summaryrefslogtreecommitdiffstats
path: root/umbrello
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello')
-rw-r--r--umbrello/AUTHORS14
-rw-r--r--umbrello/COPYING340
-rw-r--r--umbrello/ChangeLog644
-rw-r--r--umbrello/INSTALL179
-rw-r--r--umbrello/Makefile.am12
-rw-r--r--umbrello/README10
-rw-r--r--umbrello/THANKS93
-rw-r--r--umbrello/TODO22
-rw-r--r--umbrello/VERSION1
-rw-r--r--umbrello/configure.in.in112
-rwxr-xr-xumbrello/make-umbrello-release.sh60
-rw-r--r--umbrello/umbrello/Makefile.am155
-rw-r--r--umbrello/umbrello/activitywidget.cpp235
-rw-r--r--umbrello/umbrello/activitywidget.h127
-rw-r--r--umbrello/umbrello/actor.cpp40
-rw-r--r--umbrello/umbrello/actor.h66
-rw-r--r--umbrello/umbrello/actorwidget.cpp79
-rw-r--r--umbrello/umbrello/actorwidget.h78
-rw-r--r--umbrello/umbrello/aligntoolbar.cpp391
-rw-r--r--umbrello/umbrello/aligntoolbar.h224
-rw-r--r--umbrello/umbrello/artifact.cpp57
-rw-r--r--umbrello/umbrello/artifact.h97
-rw-r--r--umbrello/umbrello/artifactwidget.cpp259
-rw-r--r--umbrello/umbrello/artifactwidget.h107
-rw-r--r--umbrello/umbrello/association.cpp574
-rw-r--r--umbrello/umbrello/association.h290
-rw-r--r--umbrello/umbrello/associationwidget.cpp3614
-rw-r--r--umbrello/umbrello/associationwidget.h1045
-rw-r--r--umbrello/umbrello/associationwidgetlist.h29
-rw-r--r--umbrello/umbrello/assocrules.cpp386
-rw-r--r--umbrello/umbrello/assocrules.h106
-rw-r--r--umbrello/umbrello/attribute.cpp327
-rw-r--r--umbrello/umbrello/attribute.h157
-rw-r--r--umbrello/umbrello/autolayout/Makefile.am20
-rw-r--r--umbrello/umbrello/autolayout/_graph.h34
-rw-r--r--umbrello/umbrello/autolayout/autolayout.h45
-rw-r--r--umbrello/umbrello/autolayout/autolayoutdlg.cpp184
-rw-r--r--umbrello/umbrello/autolayout/autolayoutdlg.h63
-rw-r--r--umbrello/umbrello/autolayout/autolayouter.cpp29
-rw-r--r--umbrello/umbrello/autolayout/autolayouter.h64
-rw-r--r--umbrello/umbrello/autolayout/autolayouteradapter.cpp191
-rw-r--r--umbrello/umbrello/autolayout/autolayouteradapter.h87
-rw-r--r--umbrello/umbrello/autolayout/baseinclude.h29
-rw-r--r--umbrello/umbrello/autolayout/canvas.h34
-rw-r--r--umbrello/umbrello/autolayout/diagram.h50
-rw-r--r--umbrello/umbrello/autolayout/diagram_interface.h31
-rw-r--r--umbrello/umbrello/autolayout/dotautolayouter.cpp43
-rw-r--r--umbrello/umbrello/autolayout/dotautolayouter.h38
-rw-r--r--umbrello/umbrello/autolayout/graphvizautolayouter.cpp54
-rw-r--r--umbrello/umbrello/autolayout/graphvizautolayouter.h50
-rw-r--r--umbrello/umbrello/autolayout/graphvizgraph.cpp150
-rw-r--r--umbrello/umbrello/autolayout/graphvizgraph.h58
-rw-r--r--umbrello/umbrello/autolayout/graphviznode.cpp46
-rw-r--r--umbrello/umbrello/autolayout/graphviznode.h42
-rw-r--r--umbrello/umbrello/autolayout/newautolayoutdialog.ui554
-rw-r--r--umbrello/umbrello/autolayout/node.h37
-rw-r--r--umbrello/umbrello/autolayout/simplecanvas.cpp20
-rw-r--r--umbrello/umbrello/autolayout/simplecanvas.h39
-rw-r--r--umbrello/umbrello/boxwidget.cpp44
-rw-r--r--umbrello/umbrello/boxwidget.h60
-rw-r--r--umbrello/umbrello/classifier.cpp1023
-rw-r--r--umbrello/umbrello/classifier.h496
-rw-r--r--umbrello/umbrello/classifiercodedocument.cpp742
-rw-r--r--umbrello/umbrello/classifiercodedocument.h251
-rw-r--r--umbrello/umbrello/classifierlistitem.cpp98
-rw-r--r--umbrello/umbrello/classifierlistitem.h126
-rw-r--r--umbrello/umbrello/classifierwidget.cpp803
-rw-r--r--umbrello/umbrello/classifierwidget.h390
-rw-r--r--umbrello/umbrello/clipboard/Makefile.am6
-rw-r--r--umbrello/umbrello/clipboard/idchangelog.cpp97
-rw-r--r--umbrello/umbrello/clipboard/idchangelog.h126
-rw-r--r--umbrello/umbrello/clipboard/umlclipboard.cpp694
-rw-r--r--umbrello/umbrello/clipboard/umlclipboard.h194
-rw-r--r--umbrello/umbrello/clipboard/umldrag.cpp773
-rw-r--r--umbrello/umbrello/clipboard/umldrag.h223
-rw-r--r--umbrello/umbrello/cmdlineexportallviewsevent.cpp48
-rw-r--r--umbrello/umbrello/cmdlineexportallviewsevent.h78
-rw-r--r--umbrello/umbrello/codeaccessormethod.cpp195
-rw-r--r--umbrello/umbrello/codeaccessormethod.h118
-rw-r--r--umbrello/umbrello/codeaccessormethodlist.h23
-rw-r--r--umbrello/umbrello/codeblock.cpp143
-rw-r--r--umbrello/umbrello/codeblock.h121
-rw-r--r--umbrello/umbrello/codeblockwithcomments.cpp181
-rw-r--r--umbrello/umbrello/codeblockwithcomments.h107
-rw-r--r--umbrello/umbrello/codeclassfield.cpp617
-rw-r--r--umbrello/umbrello/codeclassfield.h237
-rw-r--r--umbrello/umbrello/codeclassfielddeclarationblock.cpp174
-rw-r--r--umbrello/umbrello/codeclassfielddeclarationblock.h112
-rw-r--r--umbrello/umbrello/codeclassfieldlist.h23
-rw-r--r--umbrello/umbrello/codecomment.cpp62
-rw-r--r--umbrello/umbrello/codecomment.h68
-rw-r--r--umbrello/umbrello/codedocument.cpp502
-rw-r--r--umbrello/umbrello/codedocument.h273
-rw-r--r--umbrello/umbrello/codedocumentlist.h23
-rw-r--r--umbrello/umbrello/codegenerationpolicy.cpp587
-rw-r--r--umbrello/umbrello/codegenerationpolicy.h384
-rw-r--r--umbrello/umbrello/codegenerator.cpp723
-rw-r--r--umbrello/umbrello/codegenerator.h416
-rw-r--r--umbrello/umbrello/codegenerators/Makefile.am38
-rw-r--r--umbrello/umbrello/codegenerators/adawriter.cpp686
-rw-r--r--umbrello/umbrello/codegenerators/adawriter.h105
-rw-r--r--umbrello/umbrello/codegenerators/aswriter.cpp775
-rw-r--r--umbrello/umbrello/codegenerators/aswriter.h80
-rw-r--r--umbrello/umbrello/codegenerators/classifierinfo.cpp140
-rw-r--r--umbrello/umbrello/codegenerators/classifierinfo.h126
-rw-r--r--umbrello/umbrello/codegenerators/codegen_utils.cpp413
-rw-r--r--umbrello/umbrello/codegenerators/codegen_utils.h42
-rw-r--r--umbrello/umbrello/codegenerators/codegenfactory.cpp360
-rw-r--r--umbrello/umbrello/codegenerators/codegenfactory.h119
-rw-r--r--umbrello/umbrello/codegenerators/codegenpolicyext.h52
-rw-r--r--umbrello/umbrello/codegenerators/cppcodeclassfield.cpp108
-rw-r--r--umbrello/umbrello/codegenerators/cppcodeclassfield.h62
-rw-r--r--umbrello/umbrello/codegenerators/cppcodecomment.cpp98
-rw-r--r--umbrello/umbrello/codegenerators/cppcodecomment.h83
-rw-r--r--umbrello/umbrello/codegenerators/cppcodedocumentation.cpp141
-rw-r--r--umbrello/umbrello/codegenerators/cppcodedocumentation.h95
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationform.cpp305
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationform.h150
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui481
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp390
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h227
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp94
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h48
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerator.cpp366
-rw-r--r--umbrello/umbrello/codegenerators/cppcodegenerator.h167
-rw-r--r--umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp160
-rw-r--r--umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h67
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp170
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h57
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp78
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h51
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodedocument.cpp813
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodedocument.h107
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp175
-rw-r--r--umbrello/umbrello/codegenerators/cppheadercodeoperation.h59
-rw-r--r--umbrello/umbrello/codegenerators/cppmakecodedocument.cpp78
-rw-r--r--umbrello/umbrello/codegenerators/cppmakecodedocument.h67
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp169
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h57
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp74
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h51
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp168
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodedocument.h73
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp193
-rw-r--r--umbrello/umbrello/codegenerators/cppsourcecodeoperation.h51
-rw-r--r--umbrello/umbrello/codegenerators/cppwriter.cpp1283
-rw-r--r--umbrello/umbrello/codegenerators/cppwriter.h293
-rw-r--r--umbrello/umbrello/codegenerators/csharpwriter.cpp725
-rw-r--r--umbrello/umbrello/codegenerators/csharpwriter.h163
-rw-r--r--umbrello/umbrello/codegenerators/dwriter.cpp970
-rw-r--r--umbrello/umbrello/codegenerators/dwriter.h276
-rw-r--r--umbrello/umbrello/codegenerators/idlwriter.cpp482
-rw-r--r--umbrello/umbrello/codegenerators/idlwriter.h74
-rw-r--r--umbrello/umbrello/codegenerators/javaantcodedocument.cpp312
-rw-r--r--umbrello/umbrello/codegenerators/javaantcodedocument.h100
-rw-r--r--umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp169
-rw-r--r--umbrello/umbrello/codegenerators/javaclassdeclarationblock.h66
-rw-r--r--umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp583
-rw-r--r--umbrello/umbrello/codegenerators/javaclassifiercodedocument.h110
-rw-r--r--umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp223
-rw-r--r--umbrello/umbrello/codegenerators/javacodeaccessormethod.h65
-rw-r--r--umbrello/umbrello/codegenerators/javacodeclassfield.cpp111
-rw-r--r--umbrello/umbrello/codegenerators/javacodeclassfield.h59
-rw-r--r--umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp118
-rw-r--r--umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h51
-rw-r--r--umbrello/umbrello/codegenerators/javacodecomment.cpp84
-rw-r--r--umbrello/umbrello/codegenerators/javacodecomment.h77
-rw-r--r--umbrello/umbrello/codegenerators/javacodedocumentation.cpp143
-rw-r--r--umbrello/umbrello/codegenerators/javacodedocumentation.h95
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerationformbase.ui277
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp188
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerationpolicy.h116
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp84
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h48
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerator.cpp339
-rw-r--r--umbrello/umbrello/codegenerators/javacodegenerator.h150
-rw-r--r--umbrello/umbrello/codegenerators/javacodeoperation.cpp132
-rw-r--r--umbrello/umbrello/codegenerators/javacodeoperation.h52
-rw-r--r--umbrello/umbrello/codegenerators/javawriter.cpp936
-rw-r--r--umbrello/umbrello/codegenerators/javawriter.h236
-rw-r--r--umbrello/umbrello/codegenerators/jswriter.cpp308
-rw-r--r--umbrello/umbrello/codegenerators/jswriter.h78
-rw-r--r--umbrello/umbrello/codegenerators/pascalwriter.cpp542
-rw-r--r--umbrello/umbrello/codegenerators/pascalwriter.h86
-rw-r--r--umbrello/umbrello/codegenerators/perlwriter.cpp716
-rw-r--r--umbrello/umbrello/codegenerators/perlwriter.h101
-rw-r--r--umbrello/umbrello/codegenerators/php5writer.cpp3418
-rw-r--r--umbrello/umbrello/codegenerators/php5writer.h95
-rw-r--r--umbrello/umbrello/codegenerators/phpwriter.cpp3339
-rw-r--r--umbrello/umbrello/codegenerators/phpwriter.h90
-rw-r--r--umbrello/umbrello/codegenerators/pythonwriter.cpp438
-rw-r--r--umbrello/umbrello/codegenerators/pythonwriter.h86
-rw-r--r--umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp147
-rw-r--r--umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h74
-rw-r--r--umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp646
-rw-r--r--umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h126
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp233
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeaccessormethod.h73
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeclassfield.cpp113
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeclassfield.h61
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp112
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h55
-rw-r--r--umbrello/umbrello/codegenerators/rubycodecomment.cpp85
-rw-r--r--umbrello/umbrello/codegenerators/rubycodecomment.h69
-rw-r--r--umbrello/umbrello/codegenerators/rubycodedocumentation.cpp145
-rw-r--r--umbrello/umbrello/codegenerators/rubycodedocumentation.h97
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui248
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp170
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h117
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp75
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h51
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerator.cpp186
-rw-r--r--umbrello/umbrello/codegenerators/rubycodegenerator.h129
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeoperation.cpp226
-rw-r--r--umbrello/umbrello/codegenerators/rubycodeoperation.h54
-rw-r--r--umbrello/umbrello/codegenerators/rubywriter.cpp448
-rw-r--r--umbrello/umbrello/codegenerators/rubywriter.h113
-rw-r--r--umbrello/umbrello/codegenerators/simplecodegenerator.cpp292
-rw-r--r--umbrello/umbrello/codegenerators/simplecodegenerator.h120
-rw-r--r--umbrello/umbrello/codegenerators/sqlwriter.cpp394
-rw-r--r--umbrello/umbrello/codegenerators/sqlwriter.h77
-rw-r--r--umbrello/umbrello/codegenerators/tclwriter.cpp951
-rw-r--r--umbrello/umbrello/codegenerators/tclwriter.h174
-rw-r--r--umbrello/umbrello/codegenerators/xmlcodecomment.cpp67
-rw-r--r--umbrello/umbrello/codegenerators/xmlcodecomment.h68
-rw-r--r--umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp166
-rw-r--r--umbrello/umbrello/codegenerators/xmlelementcodeblock.h88
-rw-r--r--umbrello/umbrello/codegenerators/xmlschemawriter.cpp809
-rw-r--r--umbrello/umbrello/codegenerators/xmlschemawriter.h249
-rw-r--r--umbrello/umbrello/codegenobjectwithtextblocks.cpp517
-rw-r--r--umbrello/umbrello/codegenobjectwithtextblocks.h192
-rw-r--r--umbrello/umbrello/codeimport/Makefile.am6
-rw-r--r--umbrello/umbrello/codeimport/adaimport.cpp588
-rw-r--r--umbrello/umbrello/codeimport/adaimport.h88
-rw-r--r--umbrello/umbrello/codeimport/classimport.cpp58
-rw-r--r--umbrello/umbrello/codeimport/classimport.h61
-rw-r--r--umbrello/umbrello/codeimport/cppimport.cpp109
-rw-r--r--umbrello/umbrello/codeimport/cppimport.h59
-rw-r--r--umbrello/umbrello/codeimport/idlimport.cpp356
-rw-r--r--umbrello/umbrello/codeimport/idlimport.h54
-rw-r--r--umbrello/umbrello/codeimport/import_utils.cpp464
-rw-r--r--umbrello/umbrello/codeimport/import_utils.h175
-rw-r--r--umbrello/umbrello/codeimport/javaimport.cpp549
-rw-r--r--umbrello/umbrello/codeimport/javaimport.h106
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/Makefile.am5
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/README56
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.cpp1183
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.h1449
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp176
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h29
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp640
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h98
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.cpp435
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.h230
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.cpp25
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.h45
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h123
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp1002
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.h791
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp113
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.h119
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.cpp4238
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.h221
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp207
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h59
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp310
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.h132
-rw-r--r--umbrello/umbrello/codeimport/nativeimportbase.cpp340
-rw-r--r--umbrello/umbrello/codeimport/nativeimportbase.h227
-rw-r--r--umbrello/umbrello/codeimport/pascalimport.cpp413
-rw-r--r--umbrello/umbrello/codeimport/pascalimport.h66
-rw-r--r--umbrello/umbrello/codeimport/pythonimport.cpp190
-rw-r--r--umbrello/umbrello/codeimport/pythonimport.h76
-rw-r--r--umbrello/umbrello/codemethodblock.cpp191
-rw-r--r--umbrello/umbrello/codemethodblock.h133
-rw-r--r--umbrello/umbrello/codeoperation.cpp177
-rw-r--r--umbrello/umbrello/codeoperation.h94
-rw-r--r--umbrello/umbrello/codeparameter.cpp287
-rw-r--r--umbrello/umbrello/codeparameter.h160
-rw-r--r--umbrello/umbrello/codeviewerstate.h38
-rw-r--r--umbrello/umbrello/component.cpp100
-rw-r--r--umbrello/umbrello/component.h86
-rw-r--r--umbrello/umbrello/componentwidget.cpp141
-rw-r--r--umbrello/umbrello/componentwidget.h74
-rw-r--r--umbrello/umbrello/configurable.cpp81
-rw-r--r--umbrello/umbrello/configurable.h118
-rw-r--r--umbrello/umbrello/cr128-mime-umbrellofile.pngbin0 -> 6767 bytes
-rw-r--r--umbrello/umbrello/cr16-mime-umbrellofile.pngbin0 -> 835 bytes
-rw-r--r--umbrello/umbrello/cr22-mime-umbrellofile.pngbin0 -> 1134 bytes
-rw-r--r--umbrello/umbrello/cr32-mime-umbrellofile.pngbin0 -> 1717 bytes
-rw-r--r--umbrello/umbrello/cr48-mime-umbrellofile.pngbin0 -> 2665 bytes
-rw-r--r--umbrello/umbrello/cr64-mime-umbrellofile.pngbin0 -> 3515 bytes
-rw-r--r--umbrello/umbrello/crsc-mime-umbrellofile.svgzbin0 -> 2860 bytes
-rw-r--r--umbrello/umbrello/datatypewidget.cpp114
-rw-r--r--umbrello/umbrello/datatypewidget.h81
-rw-r--r--umbrello/umbrello/dialog_utils.cpp60
-rw-r--r--umbrello/umbrello/dialog_utils.h63
-rw-r--r--umbrello/umbrello/dialogs/Makefile.am54
-rw-r--r--umbrello/umbrello/dialogs/activitydialog.cpp125
-rw-r--r--umbrello/umbrello/dialogs/activitydialog.h136
-rw-r--r--umbrello/umbrello/dialogs/activitypage.cpp325
-rw-r--r--umbrello/umbrello/dialogs/activitypage.h94
-rw-r--r--umbrello/umbrello/dialogs/assocgenpage.cpp131
-rw-r--r--umbrello/umbrello/dialogs/assocgenpage.h93
-rw-r--r--umbrello/umbrello/dialogs/assocpage.cpp127
-rw-r--r--umbrello/umbrello/dialogs/assocpage.h76
-rw-r--r--umbrello/umbrello/dialogs/assocpropdlg.cpp115
-rw-r--r--umbrello/umbrello/dialogs/assocpropdlg.h72
-rw-r--r--umbrello/umbrello/dialogs/assocrolepage.cpp293
-rw-r--r--umbrello/umbrello/dialogs/assocrolepage.h85
-rw-r--r--umbrello/umbrello/dialogs/classgenpage.cpp472
-rw-r--r--umbrello/umbrello/dialogs/classgenpage.h109
-rw-r--r--umbrello/umbrello/dialogs/classifierlistpage.cpp607
-rw-r--r--umbrello/umbrello/dialogs/classifierlistpage.h191
-rw-r--r--umbrello/umbrello/dialogs/classoptionspage.cpp195
-rw-r--r--umbrello/umbrello/dialogs/classoptionspage.h106
-rw-r--r--umbrello/umbrello/dialogs/classpropdlg.cpp250
-rw-r--r--umbrello/umbrello/dialogs/classpropdlg.h129
-rw-r--r--umbrello/umbrello/dialogs/classwizard.cpp107
-rw-r--r--umbrello/umbrello/dialogs/classwizard.h104
-rw-r--r--umbrello/umbrello/dialogs/codeeditor.cpp1231
-rw-r--r--umbrello/umbrello/dialogs/codeeditor.h191
-rw-r--r--umbrello/umbrello/dialogs/codegenerationoptionsbase.ui533
-rw-r--r--umbrello/umbrello/dialogs/codegenerationoptionspage.cpp188
-rw-r--r--umbrello/umbrello/dialogs/codegenerationoptionspage.h74
-rw-r--r--umbrello/umbrello/dialogs/codegenerationpolicybase.ui39
-rw-r--r--umbrello/umbrello/dialogs/codegenerationpolicypage.cpp50
-rw-r--r--umbrello/umbrello/dialogs/codegenerationpolicypage.h55
-rw-r--r--umbrello/umbrello/dialogs/codegenerationwizard.cpp258
-rw-r--r--umbrello/umbrello/dialogs/codegenerationwizard.h88
-rw-r--r--umbrello/umbrello/dialogs/codegenerationwizardbase.ui309
-rw-r--r--umbrello/umbrello/dialogs/codeviewerdialog.cpp122
-rw-r--r--umbrello/umbrello/dialogs/codeviewerdialog.h80
-rw-r--r--umbrello/umbrello/dialogs/codeviewerdialogbase.ui113
-rw-r--r--umbrello/umbrello/dialogs/codevieweroptionsbase.ui369
-rw-r--r--umbrello/umbrello/dialogs/codevieweroptionspage.cpp70
-rw-r--r--umbrello/umbrello/dialogs/codevieweroptionspage.h52
-rw-r--r--umbrello/umbrello/dialogs/defaultcodegenpolicypage.cpp41
-rw-r--r--umbrello/umbrello/dialogs/defaultcodegenpolicypage.h42
-rw-r--r--umbrello/umbrello/dialogs/diagramprintpage.cpp225
-rw-r--r--umbrello/umbrello/dialogs/diagramprintpage.h101
-rw-r--r--umbrello/umbrello/dialogs/diagrampropertiespage.ui410
-rw-r--r--umbrello/umbrello/dialogs/exportallviewsdialog.cpp55
-rw-r--r--umbrello/umbrello/dialogs/exportallviewsdialog.h72
-rw-r--r--umbrello/umbrello/dialogs/exportallviewsdialogbase.ui216
-rw-r--r--umbrello/umbrello/dialogs/notedialog.cpp53
-rw-r--r--umbrello/umbrello/dialogs/notedialog.h55
-rw-r--r--umbrello/umbrello/dialogs/overwritedialogue.cpp62
-rw-r--r--umbrello/umbrello/dialogs/overwritedialogue.h72
-rw-r--r--umbrello/umbrello/dialogs/parmpropdlg.cpp257
-rw-r--r--umbrello/umbrello/dialogs/parmpropdlg.h125
-rw-r--r--umbrello/umbrello/dialogs/pkgcontentspage.cpp127
-rw-r--r--umbrello/umbrello/dialogs/pkgcontentspage.h62
-rw-r--r--umbrello/umbrello/dialogs/selectopdlg.cpp141
-rw-r--r--umbrello/umbrello/dialogs/selectopdlg.h120
-rw-r--r--umbrello/umbrello/dialogs/settingsdlg.cpp443
-rw-r--r--umbrello/umbrello/dialogs/settingsdlg.h177
-rw-r--r--umbrello/umbrello/dialogs/statedialog.cpp147
-rw-r--r--umbrello/umbrello/dialogs/statedialog.h144
-rw-r--r--umbrello/umbrello/dialogs/umlattributedialog.cpp235
-rw-r--r--umbrello/umbrello/dialogs/umlattributedialog.h81
-rw-r--r--umbrello/umbrello/dialogs/umlentityattributedialog.cpp262
-rw-r--r--umbrello/umbrello/dialogs/umlentityattributedialog.h87
-rw-r--r--umbrello/umbrello/dialogs/umloperationdialog.cpp530
-rw-r--r--umbrello/umbrello/dialogs/umloperationdialog.h135
-rw-r--r--umbrello/umbrello/dialogs/umlroledialog.cpp63
-rw-r--r--umbrello/umbrello/dialogs/umlroledialog.h75
-rw-r--r--umbrello/umbrello/dialogs/umlroleproperties.cpp114
-rw-r--r--umbrello/umbrello/dialogs/umlroleproperties.h59
-rw-r--r--umbrello/umbrello/dialogs/umlrolepropertiesbase.ui203
-rw-r--r--umbrello/umbrello/dialogs/umltemplatedialog.cpp161
-rw-r--r--umbrello/umbrello/dialogs/umltemplatedialog.h81
-rw-r--r--umbrello/umbrello/dialogs/umlviewdialog.cpp184
-rw-r--r--umbrello/umbrello/dialogs/umlviewdialog.h119
-rw-r--r--umbrello/umbrello/dialogs/umlwidgetcolorpage.cpp114
-rw-r--r--umbrello/umbrello/dialogs/umlwidgetcolorpage.h86
-rw-r--r--umbrello/umbrello/docgenerators/Makefile.am21
-rw-r--r--umbrello/umbrello/docgenerators/common.ent19
-rw-r--r--umbrello/umbrello/docgenerators/docbook2xhtml.xsl7
-rw-r--r--umbrello/umbrello/docgenerators/docbookgenerator.cpp145
-rw-r--r--umbrello/umbrello/docgenerators/docbookgenerator.h78
-rw-r--r--umbrello/umbrello/docgenerators/main.cpp94
-rw-r--r--umbrello/umbrello/docgenerators/xhtmlgenerator.cpp171
-rw-r--r--umbrello/umbrello/docgenerators/xhtmlgenerator.h104
-rw-r--r--umbrello/umbrello/docgenerators/xmi.css170
-rw-r--r--umbrello/umbrello/docgenerators/xmi2docbook.sh9
-rw-r--r--umbrello/umbrello/docgenerators/xmi2docbook.xsl998
-rw-r--r--umbrello/umbrello/docwindow.cpp223
-rw-r--r--umbrello/umbrello/docwindow.h168
-rw-r--r--umbrello/umbrello/entity.cpp217
-rw-r--r--umbrello/umbrello/entity.h155
-rw-r--r--umbrello/umbrello/entityattribute.cpp178
-rw-r--r--umbrello/umbrello/entityattribute.h183
-rw-r--r--umbrello/umbrello/entitywidget.cpp203
-rw-r--r--umbrello/umbrello/entitywidget.h82
-rw-r--r--umbrello/umbrello/enum.cpp206
-rw-r--r--umbrello/umbrello/enum.h145
-rw-r--r--umbrello/umbrello/enumliteral.cpp74
-rw-r--r--umbrello/umbrello/enumliteral.h85
-rw-r--r--umbrello/umbrello/enumwidget.cpp218
-rw-r--r--umbrello/umbrello/enumwidget.h109
-rw-r--r--umbrello/umbrello/floatingtextwidget.cpp453
-rw-r--r--umbrello/umbrello/floatingtextwidget.h303
-rw-r--r--umbrello/umbrello/floatingtextwidgetcontroller.cpp119
-rw-r--r--umbrello/umbrello/floatingtextwidgetcontroller.h152
-rw-r--r--umbrello/umbrello/folder.cpp412
-rw-r--r--umbrello/umbrello/folder.h199
-rw-r--r--umbrello/umbrello/forkjoinwidget.cpp112
-rw-r--r--umbrello/umbrello/forkjoinwidget.h103
-rw-r--r--umbrello/umbrello/headings/Makefile.am17
-rw-r--r--umbrello/umbrello/headings/heading.adb29
-rw-r--r--umbrello/umbrello/headings/heading.ads30
-rw-r--r--umbrello/umbrello/headings/heading.as29
-rw-r--r--umbrello/umbrello/headings/heading.cpp29
-rw-r--r--umbrello/umbrello/headings/heading.cs29
-rw-r--r--umbrello/umbrello/headings/heading.d29
-rw-r--r--umbrello/umbrello/headings/heading.h29
-rw-r--r--umbrello/umbrello/headings/heading.idl29
-rw-r--r--umbrello/umbrello/headings/heading.java29
-rw-r--r--umbrello/umbrello/headings/heading.js29
-rw-r--r--umbrello/umbrello/headings/heading.php30
-rw-r--r--umbrello/umbrello/headings/heading.pm29
-rw-r--r--umbrello/umbrello/headings/heading.py29
-rw-r--r--umbrello/umbrello/headings/heading.rb29
-rw-r--r--umbrello/umbrello/headings/heading.sql28
-rw-r--r--umbrello/umbrello/headings/heading.xsd4
-rw-r--r--umbrello/umbrello/hi128-app-umbrello.pngbin0 -> 4254 bytes
-rw-r--r--umbrello/umbrello/hi16-app-umbrello.pngbin0 -> 618 bytes
-rw-r--r--umbrello/umbrello/hi16-mime-umbrellofile.pngbin0 -> 554 bytes
-rw-r--r--umbrello/umbrello/hi22-app-umbrello.pngbin0 -> 794 bytes
-rw-r--r--umbrello/umbrello/hi32-app-umbrello.pngbin0 -> 1071 bytes
-rw-r--r--umbrello/umbrello/hi32-mime-umbrellofile.pngbin0 -> 1720 bytes
-rw-r--r--umbrello/umbrello/hi48-app-umbrello.pngbin0 -> 1625 bytes
-rw-r--r--umbrello/umbrello/hi64-app-umbrello.pngbin0 -> 2132 bytes
-rw-r--r--umbrello/umbrello/hierarchicalcodeblock.cpp386
-rw-r--r--umbrello/umbrello/hierarchicalcodeblock.h155
-rw-r--r--umbrello/umbrello/hisc-app-umbrello.svgzbin0 -> 1392 bytes
-rw-r--r--umbrello/umbrello/import_rose.cpp391
-rw-r--r--umbrello/umbrello/import_rose.h35
-rw-r--r--umbrello/umbrello/kplayerslideraction.cpp412
-rw-r--r--umbrello/umbrello/kplayerslideraction.h202
-rw-r--r--umbrello/umbrello/kstartuplogo.cpp55
-rw-r--r--umbrello/umbrello/kstartuplogo.h49
-rw-r--r--umbrello/umbrello/linepath.cpp957
-rw-r--r--umbrello/umbrello/linepath.h383
-rw-r--r--umbrello/umbrello/linkwidget.cpp61
-rw-r--r--umbrello/umbrello/linkwidget.h128
-rw-r--r--umbrello/umbrello/listpopupmenu.cpp1348
-rw-r--r--umbrello/umbrello/listpopupmenu.h330
-rw-r--r--umbrello/umbrello/main.cpp208
-rw-r--r--umbrello/umbrello/messagewidget.cpp792
-rw-r--r--umbrello/umbrello/messagewidget.h401
-rw-r--r--umbrello/umbrello/messagewidgetcontroller.cpp96
-rw-r--r--umbrello/umbrello/messagewidgetcontroller.h154
-rw-r--r--umbrello/umbrello/messagewidgetlist.h22
-rw-r--r--umbrello/umbrello/model_utils.cpp1221
-rw-r--r--umbrello/umbrello/model_utils.h328
-rw-r--r--umbrello/umbrello/node.cpp43
-rw-r--r--umbrello/umbrello/node.h67
-rw-r--r--umbrello/umbrello/nodewidget.cpp132
-rw-r--r--umbrello/umbrello/nodewidget.h64
-rw-r--r--umbrello/umbrello/notewidget.cpp316
-rw-r--r--umbrello/umbrello/notewidget.h146
-rw-r--r--umbrello/umbrello/notewidgetcontroller.cpp49
-rw-r--r--umbrello/umbrello/notewidgetcontroller.h81
-rw-r--r--umbrello/umbrello/object_factory.cpp283
-rw-r--r--umbrello/umbrello/object_factory.h84
-rw-r--r--umbrello/umbrello/objectwidget.cpp403
-rw-r--r--umbrello/umbrello/objectwidget.h331
-rw-r--r--umbrello/umbrello/objectwidgetcontroller.cpp44
-rw-r--r--umbrello/umbrello/objectwidgetcontroller.h92
-rw-r--r--umbrello/umbrello/operation.cpp431
-rw-r--r--umbrello/umbrello/operation.h209
-rw-r--r--umbrello/umbrello/optionstate.cpp27
-rw-r--r--umbrello/umbrello/optionstate.h81
-rw-r--r--umbrello/umbrello/ownedcodeblock.cpp180
-rw-r--r--umbrello/umbrello/ownedcodeblock.h100
-rw-r--r--umbrello/umbrello/ownedhierarchicalcodeblock.cpp113
-rw-r--r--umbrello/umbrello/ownedhierarchicalcodeblock.h98
-rw-r--r--umbrello/umbrello/package.cpp298
-rw-r--r--umbrello/umbrello/package.h198
-rw-r--r--umbrello/umbrello/packagewidget.cpp133
-rw-r--r--umbrello/umbrello/packagewidget.h74
-rw-r--r--umbrello/umbrello/petalnode.cpp61
-rw-r--r--umbrello/umbrello/petalnode.h86
-rw-r--r--umbrello/umbrello/petaltree2uml.cpp631
-rw-r--r--umbrello/umbrello/petaltree2uml.h39
-rw-r--r--umbrello/umbrello/pics/COPYING3
-rw-r--r--umbrello/umbrello/pics/CVglobal_meth.pngbin0 -> 342 bytes
-rw-r--r--umbrello/umbrello/pics/CVglobal_var.pngbin0 -> 313 bytes
-rw-r--r--umbrello/umbrello/pics/CVimplementation_meth.pngbin0 -> 372 bytes
-rw-r--r--umbrello/umbrello/pics/CVimplementation_signal.pngbin0 -> 391 bytes
-rw-r--r--umbrello/umbrello/pics/CVimplementation_slot.pngbin0 -> 392 bytes
-rw-r--r--umbrello/umbrello/pics/CVimplementation_var.pngbin0 -> 309 bytes
-rw-r--r--umbrello/umbrello/pics/CVnamespace.pngbin0 -> 451 bytes
-rw-r--r--umbrello/umbrello/pics/CVprivate_meth.pngbin0 -> 347 bytes
-rw-r--r--umbrello/umbrello/pics/CVprivate_signal.pngbin0 -> 354 bytes
-rw-r--r--umbrello/umbrello/pics/CVprivate_slot.pngbin0 -> 356 bytes
-rw-r--r--umbrello/umbrello/pics/CVprivate_var.pngbin0 -> 314 bytes
-rw-r--r--umbrello/umbrello/pics/CVprotected_meth.pngbin0 -> 346 bytes
-rw-r--r--umbrello/umbrello/pics/CVprotected_signal.pngbin0 -> 352 bytes
-rw-r--r--umbrello/umbrello/pics/CVprotected_slot.pngbin0 -> 353 bytes
-rw-r--r--umbrello/umbrello/pics/CVprotected_var.pngbin0 -> 321 bytes
-rw-r--r--umbrello/umbrello/pics/CVpublic_meth.pngbin0 -> 320 bytes
-rw-r--r--umbrello/umbrello/pics/CVpublic_signal.pngbin0 -> 327 bytes
-rw-r--r--umbrello/umbrello/pics/CVpublic_slot.pngbin0 -> 329 bytes
-rw-r--r--umbrello/umbrello/pics/CVpublic_var.pngbin0 -> 293 bytes
-rw-r--r--umbrello/umbrello/pics/CVstruct.pngbin0 -> 355 bytes
-rw-r--r--umbrello/umbrello/pics/Makefile.am112
-rw-r--r--umbrello/umbrello/pics/actor.pngbin0 -> 1081 bytes
-rw-r--r--umbrello/umbrello/pics/aggregation.pngbin0 -> 439 bytes
-rw-r--r--umbrello/umbrello/pics/align_bottom.pngbin0 -> 247 bytes
-rw-r--r--umbrello/umbrello/pics/align_hori_distribute.pngbin0 -> 297 bytes
-rw-r--r--umbrello/umbrello/pics/align_hori_middle.pngbin0 -> 295 bytes
-rw-r--r--umbrello/umbrello/pics/align_left.pngbin0 -> 248 bytes
-rw-r--r--umbrello/umbrello/pics/align_right.pngbin0 -> 249 bytes
-rw-r--r--umbrello/umbrello/pics/align_top.pngbin0 -> 246 bytes
-rw-r--r--umbrello/umbrello/pics/align_vert_distribute.pngbin0 -> 305 bytes
-rw-r--r--umbrello/umbrello/pics/align_vert_middle.pngbin0 -> 289 bytes
-rw-r--r--umbrello/umbrello/pics/anchor.pngbin0 -> 859 bytes
-rw-r--r--umbrello/umbrello/pics/andline.pngbin0 -> 788 bytes
-rw-r--r--umbrello/umbrello/pics/arrow.pngbin0 -> 436 bytes
-rw-r--r--umbrello/umbrello/pics/artifact.pngbin0 -> 726 bytes
-rw-r--r--umbrello/umbrello/pics/association.pngbin0 -> 167 bytes
-rw-r--r--umbrello/umbrello/pics/box.pngbin0 -> 184 bytes
-rw-r--r--umbrello/umbrello/pics/branch.pngbin0 -> 863 bytes
-rw-r--r--umbrello/umbrello/pics/choice-rhomb.pngbin0 -> 894 bytes
-rw-r--r--umbrello/umbrello/pics/choice-round.pngbin0 -> 971 bytes
-rw-r--r--umbrello/umbrello/pics/class.pngbin0 -> 827 bytes
-rw-r--r--umbrello/umbrello/pics/component.pngbin0 -> 577 bytes
-rw-r--r--umbrello/umbrello/pics/composition.pngbin0 -> 540 bytes
-rw-r--r--umbrello/umbrello/pics/containment.pngbin0 -> 447 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_activity.pngbin0 -> 789 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_class.pngbin0 -> 764 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_collaboration.pngbin0 -> 799 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_component.pngbin0 -> 754 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_deployment.pngbin0 -> 815 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_sequence.pngbin0 -> 821 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_state.pngbin0 -> 816 bytes
-rw-r--r--umbrello/umbrello/pics/cr16-action-umbrello_diagram_usecase.pngbin0 -> 823 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_activity.pngbin0 -> 1211 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_class.pngbin0 -> 1124 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_collaboration.pngbin0 -> 1169 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_component.pngbin0 -> 1090 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_deployment.pngbin0 -> 1177 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_entityrelationship.pngbin0 -> 1039 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_sequence.pngbin0 -> 1225 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_state.pngbin0 -> 1258 bytes
-rw-r--r--umbrello/umbrello/pics/cr22-action-umbrello_diagram_usecase.pngbin0 -> 1247 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-actor.pngbin0 -> 1055 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-aggregation.pngbin0 -> 880 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-anchor.pngbin0 -> 1157 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-andline.pngbin0 -> 1018 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-artifact.pngbin0 -> 813 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-association.pngbin0 -> 775 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-box.pngbin0 -> 716 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-branch.pngbin0 -> 1304 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-choice-rhomb.pngbin0 -> 1179 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-choice-round.pngbin0 -> 1042 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-class.pngbin0 -> 852 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-component.pngbin0 -> 678 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-composition.pngbin0 -> 990 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-containment.pngbin0 -> 888 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-datatype.pngbin0 -> 1080 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-deep-history.pngbin0 -> 826 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-dependency.pngbin0 -> 1089 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-end_state.pngbin0 -> 1250 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-entity.pngbin0 -> 878 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-enum.pngbin0 -> 1050 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-fork.pngbin0 -> 860 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-generalisation.pngbin0 -> 890 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-initial_state.pngbin0 -> 1105 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-interface.pngbin0 -> 1056 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-join.pngbin0 -> 442 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-junction.pngbin0 -> 606 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-message-asynchronous.pngbin0 -> 1065 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-message-synchronous.pngbin0 -> 1014 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-node.pngbin0 -> 1137 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-note.pngbin0 -> 1161 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-object.pngbin0 -> 1013 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-package.pngbin0 -> 1067 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-relationship.pngbin0 -> 935 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-shallow-history.pngbin0 -> 762 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-state-fork.pngbin0 -> 390 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-text.pngbin0 -> 1049 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-uniassociation.pngbin0 -> 888 bytes
-rw-r--r--umbrello/umbrello/pics/cursor-usecase.pngbin0 -> 1189 bytes
-rw-r--r--umbrello/umbrello/pics/datatype.pngbin0 -> 752 bytes
-rw-r--r--umbrello/umbrello/pics/deep-history.pngbin0 -> 703 bytes
-rw-r--r--umbrello/umbrello/pics/dependency.pngbin0 -> 335 bytes
-rw-r--r--umbrello/umbrello/pics/end_state.pngbin0 -> 1186 bytes
-rw-r--r--umbrello/umbrello/pics/entity.pngbin0 -> 827 bytes
-rw-r--r--umbrello/umbrello/pics/enum.pngbin0 -> 999 bytes
-rw-r--r--umbrello/umbrello/pics/fork.pngbin0 -> 213 bytes
-rw-r--r--umbrello/umbrello/pics/generalisation.pngbin0 -> 346 bytes
-rw-r--r--umbrello/umbrello/pics/initial_state.pngbin0 -> 893 bytes
-rw-r--r--umbrello/umbrello/pics/interface.pngbin0 -> 883 bytes
-rw-r--r--umbrello/umbrello/pics/join.pngbin0 -> 281 bytes
-rw-r--r--umbrello/umbrello/pics/junction.pngbin0 -> 412 bytes
-rw-r--r--umbrello/umbrello/pics/message-asynchronous.pngbin0 -> 556 bytes
-rw-r--r--umbrello/umbrello/pics/message-synchronous.pngbin0 -> 594 bytes
-rw-r--r--umbrello/umbrello/pics/node.pngbin0 -> 1071 bytes
-rw-r--r--umbrello/umbrello/pics/note.pngbin0 -> 939 bytes
-rw-r--r--umbrello/umbrello/pics/object.pngbin0 -> 727 bytes
-rw-r--r--umbrello/umbrello/pics/package.pngbin0 -> 939 bytes
-rw-r--r--umbrello/umbrello/pics/relationship.pngbin0 -> 297 bytes
-rw-r--r--umbrello/umbrello/pics/shallow-history.pngbin0 -> 669 bytes
-rw-r--r--umbrello/umbrello/pics/sources/actor.svg172
-rw-r--r--umbrello/umbrello/pics/sources/aggregation.svg130
-rw-r--r--umbrello/umbrello/pics/sources/align_bottom.svg261
-rw-r--r--umbrello/umbrello/pics/sources/align_hori_distribute.svg273
-rw-r--r--umbrello/umbrello/pics/sources/align_hori_middle.svg257
-rw-r--r--umbrello/umbrello/pics/sources/align_left.svg260
-rw-r--r--umbrello/umbrello/pics/sources/align_right.svg260
-rw-r--r--umbrello/umbrello/pics/sources/align_top.svg251
-rw-r--r--umbrello/umbrello/pics/sources/align_vert_distribute.svg272
-rw-r--r--umbrello/umbrello/pics/sources/align_vert_middle.svg254
-rw-r--r--umbrello/umbrello/pics/sources/anchor.svg279
-rw-r--r--umbrello/umbrello/pics/sources/andline.svg102
-rw-r--r--umbrello/umbrello/pics/sources/artifact.svg153
-rw-r--r--umbrello/umbrello/pics/sources/association.svg115
-rw-r--r--umbrello/umbrello/pics/sources/asynchro.svg133
-rw-r--r--umbrello/umbrello/pics/sources/box.svg85
-rw-r--r--umbrello/umbrello/pics/sources/branch.svg128
-rw-r--r--umbrello/umbrello/pics/sources/choice-rhomb.svg160
-rw-r--r--umbrello/umbrello/pics/sources/choice-round.svg178
-rw-r--r--umbrello/umbrello/pics/sources/class.svg131
-rw-r--r--umbrello/umbrello/pics/sources/component.svg123
-rw-r--r--umbrello/umbrello/pics/sources/composition.svg128
-rw-r--r--umbrello/umbrello/pics/sources/containment.svg141
-rw-r--r--umbrello/umbrello/pics/sources/cursor-andline.svg496
-rw-r--r--umbrello/umbrello/pics/sources/cursor-choice-rhomb.svg439
-rw-r--r--umbrello/umbrello/pics/sources/cursor-choice-round.svg356
-rw-r--r--umbrello/umbrello/pics/sources/cursor-deep-history.svg206
-rw-r--r--umbrello/umbrello/pics/sources/cursor-join.svg289
-rw-r--r--umbrello/umbrello/pics/sources/cursor-junction.svg279
-rw-r--r--umbrello/umbrello/pics/sources/cursor-shallow-history.svg195
-rw-r--r--umbrello/umbrello/pics/sources/cursor-state-fork.svg289
-rw-r--r--umbrello/umbrello/pics/sources/datatype.svg121
-rw-r--r--umbrello/umbrello/pics/sources/deep-history.svg84
-rw-r--r--umbrello/umbrello/pics/sources/dependency.svg216
-rw-r--r--umbrello/umbrello/pics/sources/diag_activity.svg571
-rw-r--r--umbrello/umbrello/pics/sources/diag_class.svg360
-rw-r--r--umbrello/umbrello/pics/sources/diag_collaboration.svg1111
-rw-r--r--umbrello/umbrello/pics/sources/diag_component.svg732
-rw-r--r--umbrello/umbrello/pics/sources/diag_deployment.svg676
-rw-r--r--umbrello/umbrello/pics/sources/diag_entityrelationship.svg715
-rw-r--r--umbrello/umbrello/pics/sources/diag_sequence.svg729
-rw-r--r--umbrello/umbrello/pics/sources/diag_state.svg629
-rw-r--r--umbrello/umbrello/pics/sources/diag_usecase.svg489
-rw-r--r--umbrello/umbrello/pics/sources/diagbase.svg189
-rw-r--r--umbrello/umbrello/pics/sources/end_state.svg136
-rw-r--r--umbrello/umbrello/pics/sources/entity.svg151
-rw-r--r--umbrello/umbrello/pics/sources/enum.svg114
-rw-r--r--umbrello/umbrello/pics/sources/fork.svg115
-rw-r--r--umbrello/umbrello/pics/sources/generalise.svg127
-rw-r--r--umbrello/umbrello/pics/sources/initial.svg126
-rw-r--r--umbrello/umbrello/pics/sources/interface.svg130
-rw-r--r--umbrello/umbrello/pics/sources/join.svg175
-rw-r--r--umbrello/umbrello/pics/sources/junction.svg256
-rw-r--r--umbrello/umbrello/pics/sources/message-asynchronous.svg133
-rw-r--r--umbrello/umbrello/pics/sources/message-synchronous.svg169
-rw-r--r--umbrello/umbrello/pics/sources/node.svg114
-rw-r--r--umbrello/umbrello/pics/sources/note.svg164
-rw-r--r--umbrello/umbrello/pics/sources/object.svg110
-rw-r--r--umbrello/umbrello/pics/sources/package.svg121
-rw-r--r--umbrello/umbrello/pics/sources/relationship.svg243
-rw-r--r--umbrello/umbrello/pics/sources/shallow-history.svg73
-rw-r--r--umbrello/umbrello/pics/sources/state-fork.svg172
-rw-r--r--umbrello/umbrello/pics/sources/subsystem.svg135
-rw-r--r--umbrello/umbrello/pics/sources/template.svg146
-rw-r--r--umbrello/umbrello/pics/sources/text.svg91
-rw-r--r--umbrello/umbrello/pics/sources/uniassociation.svg221
-rw-r--r--umbrello/umbrello/pics/sources/usecase.svg131
-rw-r--r--umbrello/umbrello/pics/startlogo.pngbin0 -> 19738 bytes
-rw-r--r--umbrello/umbrello/pics/state-fork.pngbin0 -> 324 bytes
-rw-r--r--umbrello/umbrello/pics/subsystem.pngbin0 -> 629 bytes
-rw-r--r--umbrello/umbrello/pics/template.pngbin0 -> 577 bytes
-rw-r--r--umbrello/umbrello/pics/text.pngbin0 -> 484 bytes
-rw-r--r--umbrello/umbrello/pics/uniassociation.pngbin0 -> 307 bytes
-rw-r--r--umbrello/umbrello/pics/usecase.pngbin0 -> 751 bytes
-rw-r--r--umbrello/umbrello/plugin.cpp167
-rw-r--r--umbrello/umbrello/plugin.h163
-rw-r--r--umbrello/umbrello/pluginloader.cpp177
-rw-r--r--umbrello/umbrello/pluginloader.h132
-rw-r--r--umbrello/umbrello/refactoring/Makefile.am8
-rw-r--r--umbrello/umbrello/refactoring/refactoringassistant.cpp701
-rw-r--r--umbrello/umbrello/refactoring/refactoringassistant.h89
-rw-r--r--umbrello/umbrello/seqlinewidget.cpp124
-rw-r--r--umbrello/umbrello/seqlinewidget.h135
-rw-r--r--umbrello/umbrello/statewidget.cpp297
-rw-r--r--umbrello/umbrello/statewidget.h163
-rw-r--r--umbrello/umbrello/stereotype.cpp94
-rw-r--r--umbrello/umbrello/stereotype.h103
-rw-r--r--umbrello/umbrello/template.cpp95
-rw-r--r--umbrello/umbrello/template.h107
-rw-r--r--umbrello/umbrello/textblock.cpp320
-rw-r--r--umbrello/umbrello/textblock.h241
-rw-r--r--umbrello/umbrello/textblocklist.h23
-rw-r--r--umbrello/umbrello/tips129
-rw-r--r--umbrello/umbrello/toolbarstate.cpp260
-rw-r--r--umbrello/umbrello/toolbarstate.h365
-rw-r--r--umbrello/umbrello/toolbarstatearrow.cpp134
-rw-r--r--umbrello/umbrello/toolbarstatearrow.h158
-rw-r--r--umbrello/umbrello/toolbarstateassociation.cpp232
-rw-r--r--umbrello/umbrello/toolbarstateassociation.h168
-rw-r--r--umbrello/umbrello/toolbarstatefactory.cpp96
-rw-r--r--umbrello/umbrello/toolbarstatefactory.h53
-rw-r--r--umbrello/umbrello/toolbarstatemessages.cpp169
-rw-r--r--umbrello/umbrello/toolbarstatemessages.h187
-rw-r--r--umbrello/umbrello/toolbarstateother.cpp163
-rw-r--r--umbrello/umbrello/toolbarstateother.h83
-rw-r--r--umbrello/umbrello/toolbarstatepool.cpp30
-rw-r--r--umbrello/umbrello/toolbarstatepool.h71
-rw-r--r--umbrello/umbrello/umbrello.desktop57
-rw-r--r--umbrello/umbrello/umbrelloui.rc58
-rw-r--r--umbrello/umbrello/uml.cpp1708
-rw-r--r--umbrello/umbrello/uml.h1026
-rw-r--r--umbrello/umbrello/umlassociationlist.h23
-rw-r--r--umbrello/umbrello/umlattributelist.cpp39
-rw-r--r--umbrello/umbrello/umlattributelist.h43
-rw-r--r--umbrello/umbrello/umlcanvasobject.cpp322
-rw-r--r--umbrello/umbrello/umlcanvasobject.h249
-rw-r--r--umbrello/umbrello/umlclassifierlist.h23
-rw-r--r--umbrello/umbrello/umlclassifierlistitemlist.cpp42
-rw-r--r--umbrello/umbrello/umlclassifierlistitemlist.h45
-rw-r--r--umbrello/umbrello/umldoc.cpp2356
-rw-r--r--umbrello/umbrello/umldoc.h920
-rw-r--r--umbrello/umbrello/umlentityattributelist.cpp38
-rw-r--r--umbrello/umbrello/umlentityattributelist.h44
-rw-r--r--umbrello/umbrello/umlenumliterallist.h23
-rw-r--r--umbrello/umbrello/umllistview.cpp2703
-rw-r--r--umbrello/umbrello/umllistview.h473
-rw-r--r--umbrello/umbrello/umllistviewitem.cpp696
-rw-r--r--umbrello/umbrello/umllistviewitem.h285
-rw-r--r--umbrello/umbrello/umllistviewitemlist.h29
-rw-r--r--umbrello/umbrello/umlnamespace.cpp76
-rw-r--r--umbrello/umbrello/umlnamespace.h353
-rw-r--r--umbrello/umbrello/umlobject.cpp753
-rw-r--r--umbrello/umbrello/umlobject.h495
-rw-r--r--umbrello/umbrello/umlobjectlist.cpp42
-rw-r--r--umbrello/umbrello/umlobjectlist.h53
-rw-r--r--umbrello/umbrello/umloperationlist.h23
-rw-r--r--umbrello/umbrello/umlpackagelist.h22
-rw-r--r--umbrello/umbrello/umlrole.cpp339
-rw-r--r--umbrello/umbrello/umlrole.h128
-rw-r--r--umbrello/umbrello/umlstereotypelist.h23
-rw-r--r--umbrello/umbrello/umltemplatelist.h23
-rw-r--r--umbrello/umbrello/umlview.cpp3352
-rw-r--r--umbrello/umbrello/umlview.h1255
-rw-r--r--umbrello/umbrello/umlviewcanvas.cpp41
-rw-r--r--umbrello/umbrello/umlviewcanvas.h48
-rw-r--r--umbrello/umbrello/umlviewimageexporter.cpp128
-rw-r--r--umbrello/umbrello/umlviewimageexporter.h122
-rw-r--r--umbrello/umbrello/umlviewimageexporterall.cpp74
-rw-r--r--umbrello/umbrello/umlviewimageexporterall.h58
-rw-r--r--umbrello/umbrello/umlviewimageexportermodel.cpp366
-rw-r--r--umbrello/umbrello/umlviewimageexportermodel.h214
-rw-r--r--umbrello/umbrello/umlviewlist.h29
-rw-r--r--umbrello/umbrello/umlwidget.cpp1025
-rw-r--r--umbrello/umbrello/umlwidget.h728
-rw-r--r--umbrello/umbrello/umlwidgetcontroller.cpp540
-rw-r--r--umbrello/umbrello/umlwidgetcontroller.h476
-rw-r--r--umbrello/umbrello/umlwidgetlist.h29
-rw-r--r--umbrello/umbrello/uniqueid.cpp57
-rw-r--r--umbrello/umbrello/uniqueid.h50
-rw-r--r--umbrello/umbrello/usecase.cpp40
-rw-r--r--umbrello/umbrello/usecase.h63
-rw-r--r--umbrello/umbrello/usecasewidget.cpp72
-rw-r--r--umbrello/umbrello/usecasewidget.h74
-rw-r--r--umbrello/umbrello/widget_factory.cpp241
-rw-r--r--umbrello/umbrello/widget_factory.h41
-rw-r--r--umbrello/umbrello/widget_utils.cpp110
-rw-r--r--umbrello/umbrello/widget_utils.h52
-rw-r--r--umbrello/umbrello/widgetbase.cpp136
-rw-r--r--umbrello/umbrello/widgetbase.h201
-rw-r--r--umbrello/umbrello/worktoolbar.cpp315
-rw-r--r--umbrello/umbrello/worktoolbar.h183
-rw-r--r--umbrello/umbrello/x-umbrello.desktop53
-rw-r--r--umbrello/uml.kdevprj2154
-rw-r--r--umbrello/uml.lsm14
781 files changed, 157054 insertions, 0 deletions
diff --git a/umbrello/AUTHORS b/umbrello/AUTHORS
new file mode 100644
index 00000000..7bcc789c
--- /dev/null
+++ b/umbrello/AUTHORS
@@ -0,0 +1,14 @@
+Original author: Paul Hensgen <phensgen@sourceforge.net>
+
+Maintainer: Jonathan Riddell <jr @jriddell.org>
+
+Main Devs, in roughly chronological order
+
+* Jonathan Riddell (many areas)
+* Sebastian Stein (many areas)
+* Luis de la Parra Blum (various widgets & visuals)
+* Andrew Sutton (umbrello2)
+* Brian Thomas (advanced code generators, associations, various)
+* Oliver Kellogg (many areas)
+* Daniel Calviño Sánchez (refactoring, UI behavior)
+* Achim Spangler (countless bugfixes)
diff --git a/umbrello/COPYING b/umbrello/COPYING
new file mode 100644
index 00000000..0fc8a215
--- /dev/null
+++ b/umbrello/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/umbrello/ChangeLog b/umbrello/ChangeLog
new file mode 100644
index 00000000..5b3b6fe6
--- /dev/null
+++ b/umbrello/ChangeLog
@@ -0,0 +1,644 @@
+Version 1.5.8
+
+* Bugs/wishes from http://bugs.kde.org:
+* Cannot move text and label correctly after enabling snap to grid (137041)
+* Umbrello gratuitously appends ".xmi" to the saved file name (146061)
+* Wrong pascal code generation (146676)
+* Crash when linking to undefined xmi.id (146748)
+* End Activity Symbol gets invalid when line thickness is increased (146925)
+* The size of a fork/join is not restored (147069)
+* Crash when changing the association type to containment (147202)
+* Moving component on diagram results in absurd shape of self-association (147810)
+* Crash when changing the attribute name (147919)
+* Reads XMI exported by version 1.5 but crashes when rereading after saving (147988)
+* Patch: Correct C# constructors (no return type) (150988)
+
+Version 1.5.71
+
+* Bugs/wishes from http://bugs.kde.org:
+* Preprocessor keywords ignored which causes endless loop in code import (119125)
+* Code generator for D language (124805)
+* Unstable saves and loads, class names become dirty (145709)
+* Crash on deleting class in list view (145762)
+* Class attribute documentation not generated for python (145916)
+* Python code generator does not wrap lines properly (145918)
+* Attribute documentation not generated for 'Export to XHTML' (145972)
+* Crash when moving a class in a Java UML diagram (146058)
+* Arrowheads are not shown (146064)
+* Crash when creating a class that refers to more than one other classes/datatypes (146367)
+
+Version 1.5.7
+
+* Bugs/wishes from http://bugs.kde.org:
+* C# Code Generation and export (53368)
+* Java interface inheritance, abstract classes and generics in code generation (53376)
+* Code generation ignores unidirectional association (72042)
+* Design bug in advanced code generators (84739)
+* %date% and %time% not being parsed (96612)
+* Operations of the Interface are not implemented in the class automatically (111593)
+* Relationships for entities do not live outside of the diagram (125146)
+* Multiplicity labels often are placed incorrectly (127628)
+* Association role labels are duplicated (130172)
+* Crash on adding operation to class with Advanced Code Generators enabled (131528)
+* Javascript wrong Code Generation (135527)
+* Javascript/ActionScript Code Generation creates bad format methods (135540, 144738)
+* Sequence diagram object size incorrect after toggling "Draw as Actor" (136869)
+* Incorrect Association Properties text (139872)
+* Buttons are not displayed (139913)
+* Impossible to reuse same use case in a use case diagram (140150)
+* Java 5 generics support (140669)
+* Associations not updated during move of class on diagram (140709)
+* Crash when deleting the link between a package and a class (141602)
+* Ada95 Code Generation Errors for Aggregation (141644)
+* Unable to delete multiplicity information or label from an association (141813)
+* Reinstate code generation options for C++ (141875)
+* C++ code generator does not correctly define namespaces (141876)
+* Ada code generator generates "withs" in both directions for certain associations (141956)
+* Ada code generator always generates methods abstract even if abstract box not checked (142093)
+* Missing "with" on Ada code generation for aggregation (142392)
+* Operation Properties "Type" combo box too small (143319)
+* Support duplication of diagrams (139856, 143581)
+* Crash on changing multiplicity in an association in ERD (143909)
+* Class diagram in folder not loaded correctly from xmi (144119)
+* Sequence diagram crashes during message inserting (144293)
+* No synchronisation of comments when round-tripping (144346)
+* Crash when loading xmi with actor as object of sequence diagram (144442)
+* ActionScript/JavaScript association code generation error (144788)
+* Segmentation fault on loading corrupted file (145035)
+* Crash when moving all elements in a sequence diagram (145202)
+
+Version 1.5.61
+
+* Copy/paste of attribute or operation in list view within same class
+* Improved loading of files from older versions
+* Ada import updated for Ada2005
+* Bugs fixed from http://bugs.kde.org:
+* Crash on creating various types of associations (140693, 141073, 141106, 141277)
+* Unclickable use case diagram (140870)
+* Crash on opening xmi file produced by previous version (141279)
+
+Version 1.5.6
+
+* Fixed save/reload of association widgets for collaboration diagrams
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9825.html
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9857.html
+* Fixed crash in ToolBarStateArrow destructor
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9861.html
+* Stereotype selection list for parameter properties dialog
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9862.html
+* Note widget is now always drawn on TOP of all widgets
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9863.html
+* Optimized printer margins
+ http://www.geeksoc.org/~jr/umbrello/uml-devel/9895.html
+* Improved code import for Ada and Pascal (SVN commits: 621845, 622128, 622396, 623316,
+ 623421, and 624257)
+* Bugs/wishes from http://bugs.kde.org:
+* Association line nodes don't drag along with multiply-selected classes (57878)
+* Disappearing parameters when editing class properties (114477)
+* Umbrello saves too many copies in xmi (135606)
+* XML scheme: mixup of attribute names: *color and *colour (136061)
+* Artifacts of a component diagram are wrongly placed in Deployment View folder (137564)
+* Incorrect export to SQL (138139)
+* Parentheses do not appear around the parameters of the C++ operator() (139147)
+
+Version 1.5.52
+
+* Fixed segfault in UMLClassifier::checkOperationSignature()
+ (http://www.geeksoc.org/~jr/umbrello/uml-devel/9816.html)
+* Fixed segfault on XMI close when a class uses a template
+ (http://www.geeksoc.org/~jr/umbrello/uml-devel/9818.html)
+* Fixed crashes during Tcl code generation
+* Fixed bugs in generated code of various code generators
+* Bugs/wishes from http://bugs.kde.org:
+* Shift + Left and Shift+Right causes SIGSEGV (136288)
+* Crashes on closing/opening files created with previous umbrello versions (136940)
+* Crash when opening saved document (136998)
+* Faulty behavior when a class inside of a package is modified (137497)
+
+Version 1.5.51
+
+* This is an interim release that fixes a serious regression in version 1.5.5
+ which is detailed at http://bugs.kde.org/135749 (Crash when opening a document)
+* XMI file contains deleted associations (129859)
+* Accessor methods are private instead of public (85553)
+
+Version 1.5.5
+
+* PHP5 generator creates stub methods for all interfaces a class implements (C. Brunsdon)
+* Fix load of associations in collaboration diagram (A. Spangler)
+* Fix for single selection of an unselected widget when other widgets are selected
+* Fixes for several bugs in toolbar states
+* Fix for message widget selection
+* Fix for class association not updating the association position when being moved
+* Bugs/wishes from http://bugs.kde.org:
+* Export-to-docbook and Export-to-HTML documentation generator (54307)
+* "role A properties" should give class name (69244)
+* Sharing designs, Folders, 3rd Party imports (87252, reimplementation)
+* "Open recent" list doesn't reorder when a file is opened (111757)
+* Properties menu: move to top/bottom buttons (126467)
+* Java import - importing interfaces - absent visibility treated as package
+ instead of public (131327)
+* Python code generation not independent of diagram view (131790)
+* Java import - method parameter types not resolved correctly (131825)
+* Java import: unable to import AzareusCore (131961)
+* Java import: error on multidimensional arrays (132017)
+* Java import - array types not resolved correctly (132035)
+* Java import - "final" and comments in method declaration not parsed correctly (132174)
+* Java import: spaces in strings cause next member var to be ignored (132472)
+* Java import - static member vars ignored in interfaces (132657)
+* Header file names are lowercase in .cpp file, but mixed case on the disk (134279)
+
+Version 1.5.4
+
+* Bugs/wishes from http://bugs.kde.org:
+* Transform interface to class - fixes to some issues (79433)
+* Free Pascal code import and generator (114547)
+* Enable selection of multiple classes in "Select classes" dialog (126485)
+* Crash after single click on the "UML Model" tree window (126560/129252)
+* Fix crash when importing classes from a java file (129107, 130093)
+* Cannot insert transition/association TO fork/join node in activity diagram (129914)
+* Command line switches: graphics export to directory does not work with relative paths (130600)
+* Importing java files that reference their own class name crashes (130735)
+* Importing java class (enum pattern) cause umbrello to hang (130792)
+* Importing java subinterface before superinterface results in superinterface
+ not being treated as an interface (130793)
+* Java import: method and class visibility ignored (130794)
+* Java import - static not handled correctly (130926)
+* Java import - package visibility incorrectly represented (130932)
+* Java import - random import order can result in interface being treated as class (131006)
+* Java import - associations not setup correctly, duplicate classes created (131270)
+
+Version 1.5.3
+
+* Switch to arrow tool after association creation (http://bugs.debian.org/353344)
+* Bugs/wishes from http://bugs.kde.org:
+* "Export all views" feature contributed by Daniel Calvi� S�chez (extension of 58809)
+* Static variables in java code are not marked static (59190)
+* New alignment type "distribute horizontally/vertically" (extension of 67058)
+* Save autosave file to a more obvious place (72019)
+* Usability and responsiveness improvements to code import (93296)
+* Auto-complete in parameter properties dialog in class diagram (104477)
+* Crash on application exit (112092)
+* Memory problem when importing classes from c++ sources (122668)
+* Nestable components and subsystems in Component diagram (124326)
+* Crash loading xmi file (125331, 126968)
+* User interaction with UMLWidget improvements (126391)
+* Comments are cut short when generating PHP code (126480)
+* Freeze on C++ class import (126994)
+* Crash on importing Java 1.5 classes containing annotations (127160)
+
+Version 1.5.2
+
+* fixed problem reordering methods in classes/interfaces
+ http://bugs.debian.org/348940 , http://bugs.kde.org/119991
+* fixed problem with font size computation/word wrap in note widgets
+ http://sourceforge.net/mailarchive/forum.php?thread_id=9558795&forum_id=472
+* Automatically fill useful info into the Perl writer heading template
+* Bugs/wishes from http://bugs.kde.org:
+* Fixed connection points for associations on widgets (67223)
+* Import Rose model files (81364)
+* Documentation for association roles not saved (105661)
+* Default data types not added for old Java generator (115991)
+* Custom operations in sequence diagrams become class operations (120337)
+* Fork/join symbol appears as a black box (120455)
+* Multiplicity labels positioned incorrectly when moving entities (120598)
+* Types of entity's attributes are displayed instead of their names (120742)
+* Unable to delete entity from entity list in "UML Model" frame (120750)
+* Interface names not italicized in diagram view (120761)
+* Cannot Resize Sequence Diagram Synchronous Messages (120910)
+* Sequencediagram: messages as constructor works only properly at 100% zoom (121238)
+* drag 'n drop a class when the zoom is not 1:1 don't put the class under mouse cursor (122293)
+* Documentation for associations is not retained (121478, 122063)
+* Crash when a non existing data type is used for an argument of a new method (122497)
+* Crash when importing Python files (121952)
+* "void" is imported as class and not datatypes (122184)
+* Crash when creating a datatype with the same name as a class (122188)
+* Crash when refusing to rename a class on importing typedef (122914)
+* Java import fails at abstract methods or interfaces (123661)
+
+Version 1.5.1
+
+* fix loading of associationwidget with non-default color
+* fix moving of initial and end activity by inhibiting resize
+* fix operation parameter and return types including template expressions
+* Bugs/wishes from http://bugs.kde.org:
+* Code import for Java and Python (79648)
+* Support C++ const methods (aka queries, part of 60452)
+* Change associations, aggregations, etc. on-the-fly (109963)
+* Collaboration Diagram: labels are reset to default position after moving them (117791)
+* Imported C++ classes not saved correctly in the XMI file (117875)
+* In ER models adding associations will add blank space in the entity attributes (117990)
+* ER diagrams need to underline the attribute name of primary keys (118570)
+* Cannot anchor notes to activity elements in Activity Diagram (118719)
+
+Version 1.5
+
+* Association classes
+* Advanced code generator for Ruby
+* Code generator for Tcl
+* Externalization of folders (i.e. submodel files)
+* Change interface into class and vice versa (if abstract and no attributes)
+* Image export via command line
+* All diagram objects can be resized
+* Automatic Diagram Layout (67059, not yet closed)
+
+* Bugs fixed / wishes implemented (see http://bugs.kde.org)
+ 57588 57672 58809 66461 67120 67719 72016 79433 87252 88117
+ 97162 98368 101550 105564 107405 108223 109591 109636 110073 110216
+110231 110379 110400 110843 111088 111470 111502 111759 111768 112017
+112292 112293 112333 112531 112552 112936 112991 112992 113748 114892
+
+Version 1.4.2 (maintenance release)
+
+* Bugs fixed from http://bugs.kde.org :
+97188 103170 106183 106356 106632 106673 107101 107551 108688
+
+Version 1.4.1 (maintenance release)
+
+Bugs fixed:
+* Crash on deleting attributes / enum literals
+* Crash in UMLView::createAutoAttributeAssociations()
+* Failure to import C++ enum type with comment on last literal
+* Non-Latin1 characters in diagram names
+* Generate missing "static" keyword in new C++ code generator
+* Bugs from http://bugs.kde.org :
+ 53376 57667 57875 70924 80924 89691 95353 100290 100307 101148
+103123 103133 103728 101541 104637
+
+Version 1.4
+
+* Entity relationship diagrams
+
+* Tabbed diagrams
+
+* Object creation message in sequence diagram
+
+* Notes can contain diagram hyperlinks
+
+* Move canvas items using the keyboard (Alt + arrow keys)
+
+* Improved support for parameterized classes
+
+* CORBA IDL import
+
+* PHP 5 code generator
+
+* fixed many issues in Perl code generator
+
+* Bugs fixed / wishes implemented (see http://bugs.kde.org)
+53380 53384 54928 55058 55242 57879 61945 62321 63316 67062
+67723 69592 71978 74249 74952 75010 77645 80405 80559 82342
+83834 84515 85136 85377 86083 86828 86952 86958 87111 87537
+87956 87995 88152 88245 88415 88954 89334 89485 89553 89563
+89579 89582 89699 89860 89903 90102 90106 90206 90755 91298
+91433 91434 91494 91869 91922 92116 92123 92222 92300 92301
+92781 92995 93122 93219 93297 93298 93501 93535 93696 94173
+94728 94795 94883 95082 95247 95252 95722 95924 95951 95954
+96216 96221 96964 97155 97182 97697 97887 97984 98603 98899
+ 99697 100142
+
+Version 1.3
+
+* heavily reduced memory usage and CPU load on large projects
+
+* reserved keywords added for supported languages
+
+* new tools for aligning several objects
+
+* support added for compressed XMI files (*.xmi.tgz, *.xmi.tar.bz2)
+
+* New diagram command 'Duplicate' permits the copying of diagram
+ objects including their features
+
+* New association type: Containment (circle-plus.)
+
+* Operation parameters have a 'direction' which documents whether
+ they are input or return values (in, out, inout.)
+ The IDL and Ada generators use this in their generated code.
+
+* Ability to show only public methods/members in diagram.
+
+* Improvements to scaled printing.
+
+* Crisp new icons
+
+* Improved XMI standard conformance of the file format.
+ In principle, Umbrello's XMI parser is now capable of
+ reading foreign XMI files.
+
+* Improved compatibility with old umbrello files
+
+* Support for repeatedly importing the same C++ file(s)
+
+* Umbrello places much less demand on the X server when
+ dealing with large and complex diagrams
+
+* Umbrello is still compilable with KDE 3.1 but if you have
+ such an "ancient" KDE version the new compressed-XMI file
+ format will not work.
+
+* Bugs fixed / wishes implemented (see http://bugs.kde.org)
+53361 53381 53383 55238 56184 57664 57875 66508 67058 68441
+71281 71334 71805 71969 72016 72615 72617 72644 72801 72971
+72977 73042 73139 73274 73275 73277 73278 73418 73521 73632
+73926 73975 74432 74820 75111 75318 75380 75582 75789 75935
+76114 76209 76506 77367 77377 78192 78317 78525 78806 78910
+78912 79180 79188 79202 79631 79883 80119 80299 80824 80913
+80999 81000 81790 82236 82315 82346 82406 82685 82743 82977
+83052 83430 83432 83446 83449 83546 83553 84260 84262 84516
+84549 84656 84574 85126 85196 85434 85552 85554
+
+
+Version 1.2
+
+* Canvas zoom
+
+* Undo and redo
+
+* Clipboard now uses XMI, old binary .uml file format no longer supported
+
+* Resizeable canvas
+
+* Refactoring agent
+
+* Improved code export and many new code export languages
+
+* Datatype and enum widgets and internal representation
+
+* Component and deployment diagrams
+
+* Parameterised classes (templates in C++, generics in Java)
+
+* Stereotypes on operations, attributes, etc
+
+* Asymmetric and symmetric sequence diagram messages
+
+* Corrected placement of the diamond in aggregations/compositions,
+ the diamond is at the owning class
+
+* Can change properties of multiple items at one time
+
+* Code base is tightened up (no more WidgetData classes)
+
+* Bugs fixed / wishes implemented (see http://bugs.kde.org)
+ 53354 53356 53357 53359 53362 53363 53365 53367 53371 53379
+ 53381 53385 53387 53388 53447 53487 53652 53653 53777 54183
+ 54446 54575 54816 54817 54822 54926 54969 55051 55236 55239
+ 55243 55245 55246 55247 55283 55300 55698 55729 55731 55810
+ 56166 56519 57054 57113 57197 57199 57200 57226 57424 57475
+ 57490 57521 57665 57669 57876 57877 57878 57881 57882 57883
+ 57886 57920 58339 58349 58426 58439 58489 58852 58854 59049
+ 59155 59190 59403 59408 59774 60139 60135 60204 60685 60981
+ 61972 62201 62276 63115 63248 63316 63884 63895 63897 64201
+ 64431 64435 64501 64502 64727 64881 64884 65183 65185 65312
+ 65389 65391 65407 65410 65411 65442 65444 65450 65530
+ 65635 66185 66442 66459 66461 66847 66848 66997 67209 67277
+ 67327 67765 67770 68095 68395 69330 69332 73926
+
+Version 1.1.1
+
+* No longer crashes when printing
+
+* Capitalisation corrections in strings
+
+Version 1.1 (including 1.1 rc 2)
+
+* Activites can have multiple outgoing associations
+
+* Updated and translated tips file
+
+* New handbook help file
+
+* Slovak translation added
+
+* Updated German translation
+
+* hopefully last changes needed for the name conversion to Umbrello
+
+* i18n fixes
+
+* Many bug fixes
+
+Version 1.1 rc 1
+
+* Pasteing in sequence diagrams now works correctly
+
+* Paste operation now shows dialogue messages when it can't paste everything or at all
+
+* Cut now works
+
+* Code generation wizard checks directory exists
+
+* Code generation overwrite dialogue now lets you apply option to all remaining files
+
+* Activity widgets now have borders
+
+* Actors can be generalised from other actors
+
+* Multiple objects can now be moved at once
+
+* check for metamodel=UML when loading files
+
+* Saved files have XML header
+
+* code generation wizard gives feedback on whether the file was generated
+
+* improved RPM spec file for multiple distributions
+
+* tokenizer.l compatibility improved
+
+* Can select which language to generate to from code generation panel
+
+* User interface improvements (`new attribute' etc buttons added)
+
+* Operations and attributes can have classifier scope (static)
+
+* PHP code generation
+
+* Some menu improvements
+
+* Compiler warnings reduced
+
+* i18n() added where it was missing
+
+* Various operations which made it crash fixed
+
+* Typos fixed
+
+Version 1.1 beta 2
+
+* Name changed to Umbrello UML Modeller
+
+* Java filenames have corret capitalisation
+
+* Grid is no longer printed
+
+* Widgets now keep track of their colours and use diagram colours by default
+
+* Open and save dialogues correctly remember where they were last
+
+* Checks on saving to PNG if user really wants to save to an already existing file
+
+* Sequence and collaboration messages always update when they should
+
+* Consistant position for labels on sequence messages
+
+* Nicer looking selection box
+
+* "New operation" from sequence diagram messages will now be used automaticaly on that message
+
+* Some improvements in menu consistency
+
+* Delete selected widgets with Delete key
+
+* Select all widgets on current diagram ability
+
+* Size of left hand list view now saved
+
+* White space removed from copying to PNG
+
+* Import of file format 4 from UML version 1.0.3
+
+* Solaris compatibility with setenv(), hopefully
+
+* operations and attributes now show the correct UML syntax in class diagrams
+
+Version 1.1 beta 1
+
+* The AssocCopy, MesdsageCopy and CutCopPaste classes have been
+ replaced with CUMLDrag and CUMLClipboard.
+ It supports 5 copy&paste types:
+ -- multiple empty folders (selected from the listview)
+ -- folders and multiple umlobjects (selected from the listview)
+ -- folders, multiple umlobjects and umlviews (selected from the listview)
+ -- multiple widget selection (from a diagram)
+ -- multiple operation and attribute selection (from the listview)
+ -- PNG clipboard support when copying for a diagram.
+ currently there is no ability to cut
+
+* Assosiation can be non-streight, just double click on the line.
+
+* the ..widgetData classes abstract widget data from actual widgets so there only
+ needs to be as many widgets in memory as there are in the current diagram
+
+* listview allows folders inside folders
+
+* all UMLObjects now have associated documentation
+
+* activity and state diagrams
+
+* XMI based file system
+
+* unicode UMLObject and diagram names
+
+* QCanvas used rather than QWidget
+
+* member variables now mostly use m_... format
+
+* Code generation for C++ and Java
+
+* Code import
+
+* Fixed dos line endings and untagged binary files in CVS
+
+* New project admin (Jonathan Riddell). No thanks to Sourceforge.
+
+
+Version 1.0.3
+
+* Added rename, delete options to folders
+
+* Text now remembers state
+
+* Moving text in selection move, now moves all selected.
+
+* Diagrams now into folders
+
+* Can save/load files without diagrams (use to crash on load)
+
+Version 1.0.2
+
+* Added multiple selection of icons
+
+* mass move, delete and toggle fill color
+
+* Cut, Copy to image file of selected items or selected section of diagram
+
+* Cut, Copy, Paste between diagrams.
+
+* Correctly deletes message from sequence diagram.
+
+* Recent files list now corectly handled
+
+* Error on loading files now put Untitled corerctly in the caption.
+
+* Toolbars keep session settings
+
+* Added folders for Actors, Use Cases and Concepts to help organisation
+
+* Composition, Implemantation, unidirectional associations and realizations added to class diagrams
+
+* Generalization, dependency, and unidirectional associations added to use case diagrams.
+
+* Changing text to nothing now hides the widget
+
+Version 1.0.1
+
+* Added package and stereotype options to Classes
+
+* Added to options page package and stereotype options.
+
+* print dialog added to printer interface to allow selection of diagrams to print.
+
+* Note Box size set correctly after loading.
+
+* Sequence diagram operation lines set correctly after loading.
+
+* prefix of document files changed from kde_libs_htmldir to kde_htmldir to allow documents to be installed where you like
+
+* footnote added when printing
+
+* fixed printing so print multiple pages is now correct
+
+* popup menu co-ordinates fixes for popup menus and list view
+
+* Diagram made bigger
+
+* drag and drop now correct on large diagram
+
+
+
+
+Version 1.0 (5/09/2001)
+
+* Started maintaining ChangeLog file
+
+* Setup mime type correctly
+
+* Fixed Layout Managers on GUIs
+
+* Added scope to the Concepts on Class/Concept diagrams
+ + Public, - Private, # Protected
+
+* Fixed install so can install in the directory you wish (I hope - Let me know
+if this works)
+
+* Removed hard coding of file location from program
+
+* File Extension ".uml" added if user didn't
+
+* Removed HTML welcome screen due to loading time.
+
+* Changed the icons setup by KDevelop (someone please desing better ones)
+
+* Has i18n ready to go, just need translators (any takers?)
+
+* Text Lines e.g. messages, lines of text, etc. are printed transparently.
+
+* Association prop. Dialog now has default OK button instead of Cancel.
+
+* Added options page for UML icons
+
+* Objects set to correct background colour when not using fill colour
+
+
diff --git a/umbrello/INSTALL b/umbrello/INSTALL
new file mode 100644
index 00000000..22f48d78
--- /dev/null
+++ b/umbrello/INSTALL
@@ -0,0 +1,179 @@
+You need to be the parent directory to configure the compile,
+depending on where you got the source you may need to do the extra KDE
+step of Makefile.cvs.
+
+cd kdesdk
+make -f Makefile.cvs
+./configure --prefix=`kde-config --prefix`
+cd umbrello
+make
+sudo make install
+
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/umbrello/Makefile.am b/umbrello/Makefile.am
new file mode 100644
index 00000000..f99bedf2
--- /dev/null
+++ b/umbrello/Makefile.am
@@ -0,0 +1,12 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+
+SUBDIRS = umbrello
+
+####### kdevelop will overwrite this part!!! (end)############
+# not a GNU package. You can remove this line, if
+# have all needed files, that a GNU package needs
+AUTOMAKE_OPTIONS = foreign
+
+AM_CPPFLAGS = $(QT_INCLUDES)
+VERSION:=`cat ${PWD}/VERSION`
+
diff --git a/umbrello/README b/umbrello/README
new file mode 100644
index 00000000..2725d3a3
--- /dev/null
+++ b/umbrello/README
@@ -0,0 +1,10 @@
+Umbrello UML Modeller is a UML diagramming tool for KDE.
+
+UML lets you create models of object orientated software systems in a
+standard language.
+
+For more information on Umbrello see the website at
+http://uml.sf.net
+including the handbook which contains a tutorial on UML and Umbrello.
+
+For installation instructions read INSTALL.
diff --git a/umbrello/THANKS b/umbrello/THANKS
new file mode 100644
index 00000000..ab1462c5
--- /dev/null
+++ b/umbrello/THANKS
@@ -0,0 +1,93 @@
+Umbrello UML Modeller is the work of many people.
+Some of the contributors are listed at:
+ http://uml.sourceforge.net/developers.php
+
+If you find any problems or want features added please request or vote
+for them at http://bugs.kde.org and consider implementing the feature
+yourself, all contributions are very welcome.
+
+Some ideas for people wanting to contribute to Umbrello:
+ http://uml.sourceforge.net/junior-jobs.php
+
+---
+
+People who have contributed to Umbrello:
+(Please contact uml-devel if we have forgot you)
+
+Marcus Alanen <maalanen @ra.abo.fi>
+Danny Allen <dannya40uk @yahoo.co.uk>
+Laurent Bardi <laurent.Bardi @ipbs.fr>
+Zoltan Bartko <bartko.zoltan @pobox.sk>
+Luis De la Parra Blum <lparrab @gmx.net>
+Raymond Bosman <bosman @hetnet.nl>
+Clarke Brunsdon <clarke @vossoc.org>
+Ben Burton <bab @debian.org>
+Albert Cervera <albertca @jazzfree.com>
+Albert Astals Cid <tsdgeos @terra.es>
+Richard Dale <duke @tipitina.demon.co.uk>
+Vincent Decorges <vincent.decorges @eivd.ch>
+Antoine Dopffer <adopffer @nerdshack.com>
+Alan Ezust <alan.ezust @gmail.com>
+Jean-Remy Falleri <jr.falleri @gmail.com>
+Andi Fischer <andi.fischer @hispeed.ch>
+Pascal Fleury <fleury @users.sourceforge.net>
+JP Fournier (jfournier121 @rogers.com)
+Gregorio Guidi <g.guidi @sns.it>
+Jose Gutierrez <joseg @mapasysistemas.com.ar>
+Esben Mose Hansen <esben @despammed.com>
+Olaf Hartig <OleBowle @gmx.de>
+Marius Helf <marius.helf @gmx.de>
+Paul Hensgen <phensgen @bigpond.net.au>
+Michel Hermier <michel.hermier @wanadoo.fr>
+Harald Herres <harald.herres @control.de>
+David Hugh-Jones <hughjonesd @yahoo.co.uk>
+Pekka Jääskeläinen <pjaaskel @cs.tut.fi>
+Klas Kalass <klas.kalass @gmx.de>
+Oliver Kellogg <okellogg @users.sourceforge.net>
+Kleag (kleag @free.fr)
+Tobias Koenig <tokoe @kde.org>
+Piotr Kolaczkowski <P.Kolaczkowski @elka.pw.edu.pl>
+Matthias Kretz <kretz @kde.org>
+Thorsten Kunz <tk @bytecrash.net>
+Dmitry N. Kurashkin <dkur @nm.ru>
+Jari-Matti Mäkelä <jmjm @iki.fi>
+Gustavo Madrigal <gmadrigal @nextphere.com>
+martin <mv123q3 @hotmail.com>
+Rene Meyer <Rene.Meyer @sturmit.de>
+Laurent Montel <montel @kde.org>
+Yan Morin <yansanmo.site @gmail.com>
+Tom Morris <tfmorris @gmail.com>
+Lutz Mueller <lutz.mueller @gmx.de>
+Heiko Nardmann <heiko.nardmann @onlinehome.de>
+Dimitri Ognibene <ognibened @yahoo.it>
+Michael Palomas <mpalomas @gmail.com>
+Anthony Parent <anthony.parent @intel.com>
+Carsten Pfeiffer <pfeiffer @kde.org>
+Ivan Porres <iporres @abo.fi>
+Maciej Puzio <maciek @work.swmed.edu>
+Ruediger Ranft <kdebugs @rranft1.mail.htwm.de>
+Sharan Rao <sharanrao @gmail.com>
+John Ratke <jratke @comcast.net>
+Vincent Ricard <magic @magicninja.org>
+Daniel Richard G. <skunk @iskunk.org>
+Jonathan Riddell <jr @jriddell.org>
+Peeter Russak <pezz @tkwcy.ee>
+Paulo Roberto Rodriguez Sehn <paulo.sehn @gmail.com>
+Daniel Calviño Sánchez <danxuliu @gmail.com>
+Leo Savernik <l.savernik @aon.at>
+Peter Soetens <peter.soetens @mech.kuleuven.ac.be>
+Achim Spangler <Achim.Spangler @mnet-online.de>
+Sebastian Stein <seb.stein @gmx.de>
+Andrew Sutton <asutton @cs.kent.edu>
+Tanuj <tagrawal @hss.hns.com>
+Tonton <tonton-lists @team1664.org>
+Brian Thomas <brian.thomas @gsfc.nasa.gov>
+Ferenc Veres <lion @netngine.hu>
+Jean Vittor <jean.vittor @wanadoo.fr>
+Egbert Voigt <Egbert.Voigt @alcatel.de>
+Stefan Walter <sw @gegenunendlich.de>
+Jeremy Wickersheimer <jwickers @gmail.com>
+Yurgen Wolfgang <raptorsforever @softhome.net>
+Maciej J. Woloszyk <mat @esi.com.pl>
+Tobias Wulff <Tobias-Wulff @codeeye.de>
+
diff --git a/umbrello/TODO b/umbrello/TODO
new file mode 100644
index 00000000..06f3f78c
--- /dev/null
+++ b/umbrello/TODO
@@ -0,0 +1,22 @@
+There is always something to do for Umbrello UML Modeller. You can find an
+up-to-date list of remaining bugs in the bug tracker system at:
+
+http://bugs.kde.org/
+
+If you do not like chasing bugs you can add an incredible new feature. To get
+an idea what might be good feature look at the feature tracker system:
+
+http://bugs.kde.org/
+
+You can discuss a solution for a problem with the Umbrello developers at the
+Umbrello developer's mailing list:
+
+uml-devel@lists.sourceforge.net
+
+If you want to translate Umbrello to another language please join the relevant KDE translation team:
+
+http://i18n.kde.org/
+
+Finally, to get an overview look at the home page:
+
+http://uml.sourceforge.net/
diff --git a/umbrello/VERSION b/umbrello/VERSION
new file mode 100644
index 00000000..1cc9c180
--- /dev/null
+++ b/umbrello/VERSION
@@ -0,0 +1 @@
+1.5.8
diff --git a/umbrello/configure.in.in b/umbrello/configure.in.in
new file mode 100644
index 00000000..81e4fd59
--- /dev/null
+++ b/umbrello/configure.in.in
@@ -0,0 +1,112 @@
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+dnl Not GPL compatible
+dnl AC_PATH_PROG(DOT_FOUND, dot, no)
+dnl KDE_CHECK_HEADER(graphviz/pathgeom.h,
+dnl [kde_have_graphviz=yes],
+dnl [kde_have_graphviz=no])
+dnl
+dnl if test "$DOT_FOUND" != "no" -a "$kde_have_graphviz" = "yes"; then
+dnl CXXFLAGS="$CXXFLAGS -DHAVE_DOT"
+dnl GRAPHVIZ_LIB=`pkg-config --libs libgraph`
+dnl AUTOLAYOUT_DIR="autolayout"
+dnl AUTOLAYOUT_LIBS="autolayout/libautolayout.la $GRAPHVIZ_LIB -ldotgen -lgvc"
+dnl else
+dnl AUTOLAYOUT_DIR=""
+dnl AUTOLAYOUT_LIBS=""
+dnl fi
+dnl AC_SUBST(AUTOLAYOUT_DIR)
+dnl AC_SUBST(AUTOLAYOUT_LIBS)
+dnl End of Not GPL compatible
+
+AC_LANG_RESTORE
+
+
+AC_CHECK_FUNCS(setenv)
+
+dnl AH_BOTTOM(
+dnl [#if !defined(HAVE_SETENV)
+dnl #ifdef __cplusplus
+dnl extern "C"
+dnl #endif
+dnl int setenv(const char *name, const char *value, int overwrite);
+dnl #endif
+dnl ])
+
+HAVE_XSLT=yes
+
+KDE_FIND_PATH(xml2-config, XML_CONFIG, [${prefix}/bin ${exec_prefix}/bin], [
+ AC_MSG_WARN([Could not find libxml2 anywhere, check ftp://xmlsoft.org/ for libxml >= 2.4.8. (we also keep a version of it in kdesupport for CVS users' convience)])
+ HELP_SUBDIR=
+ DO_NOT_COMPILE="$DO_NOT_COMPILE umbrello"
+])
+
+if test -n "$XML_CONFIG"; then
+ vers=`$XML_CONFIG --version 2>/dev/null | sed -e 's/libxml //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 2004008
+ then
+ LIBXML_LIBS="`$XML_CONFIG --libs`"
+ LIBXML_RPATH=
+ for args in $LIBXML_LIBS; do
+ case $args in
+ -L*)
+ LIBXML_RPATH="$LIBXML_RPATH $args"
+ ;;
+ esac
+ done
+ LIBXML_RPATH=`echo $LIBXML_RPATH | sed -e "s/-L/-R/g"`
+ LIBXML_CFLAGS="`$XML_CONFIG --cflags`"
+
+ KDE_FIND_PATH(xmllint, XMLLINT, [${prefix}/bin ${exec_prefix}/bin], [XMLLINT=""])
+ AC_DEFINE_UNQUOTED(XMLLINT, "$XMLLINT", [Defines the executable of xmllint])
+ else
+ AC_MSG_WARN([You need at least libxml 2.4.8])
+ HAVE_XSLT=no
+ DO_NOT_COMPILE="$DO_NOT_COMPILE umbrello"
+ fi
+fi
+
+if test "$HAVE_XSLT" = yes; then
+
+ KDE_FIND_PATH(xslt-config, XSLT_CONFIG, [${prefix}/bin ${exec_prefix}/bin], [
+ AC_MSG_WARN([Could not find libxslt anywhere, check ftp://xmlsoft.org/ for libxslt >= 1.0.7. (we also keep a version of it in kdesupport for CVS users' convience)])
+ HAVE_XSLT=no
+ DO_NOT_COMPILE="$DO_NOT_COMPILE umbrello"
+ ])
+
+ if test -n "$XSLT_CONFIG"; then
+ vers=`$XSLT_CONFIG --version 2>/dev/null | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 1000007; then
+ LIBXSLT_LIBS="`$XSLT_CONFIG --libs`"
+ LIBXSLT_RPATH=
+ for args in $LIBXSLT_LIBS; do
+ case $args in
+ -L*)
+ LIBXSLT_RPATH="$LIBXSLT_RPATH $args"
+ ;;
+ esac
+ done
+ LIBXSLT_RPATH=`echo $LIBXSLT_RPATH | sed -e "s/-L/-R/g"`
+ LIBXSLT_CFLAGS="`$XSLT_CONFIG --cflags`"
+
+ else
+ AC_MSG_WARN([You need at least libxslt 1.0.7])
+ HAVE_XSLT=no
+ DO_NOT_COMPILE="$DO_NOT_COMPILE umbrello"
+ fi
+ fi
+fi
+
+if test "$have_libxslt" = "no"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE umbrello"
+fi
+
+AC_SUBST(LIBXSLT_LIBS)
+AC_SUBST(LIBXSLT_CFLAGS)
+AC_SUBST(LIBXSLT_RPATH)
+
+AC_SUBST(LIBXML_LIBS)
+AC_SUBST(LIBXML_CFLAGS)
+AC_SUBST(LIBXML_RPATH)
+
diff --git a/umbrello/make-umbrello-release.sh b/umbrello/make-umbrello-release.sh
new file mode 100755
index 00000000..84429ad0
--- /dev/null
+++ b/umbrello/make-umbrello-release.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Make a release from the current branches/KDE/3.5/kdesdk/umbrello
+#
+# Run this script as follows:
+# . make-umbrello-release.sh [BRANCH_VERSION]
+# BRANCH_VERSION defaults to 3.5.
+# @todo Create release from trunk if BRANCH_VERSION not given.
+# Note: trunk uses the cmake based build process.
+#
+# The script creates a directory, /tmp/kdesdk, which is used
+# as the work area for building the release.
+# The release tarfile will be placed in the current working dir.
+# The release version is taken from the VERSION file.
+#
+branchver=3.5
+if [ $# -gt 1 ]; then
+ branchver=$2
+fi
+origdir=`pwd`
+version=`grep "^[1-9]" VERSION`
+udir=umbrello-$version
+svnroot=svn://anonsvn.kde.org:/home/kde/branches/KDE/$branchver
+cd /tmp
+svn co -N $svnroot/kdesdk
+cd kdesdk
+svn co $svnroot/kdesdk/umbrello $udir
+svn co $svnroot/kde-common/admin $udir/admin
+svn co -N $svnroot/kdesdk/doc $udir/doc
+svn co $svnroot/kdesdk/doc/umbrello $udir/doc/umbrello
+cp -p Makefile.cvs $udir/
+cd $udir
+mv configure.in.in configure.in.in.orig
+echo '#MIN_CONFIG' > configure.in.in
+echo 'KDE_ENABLE_HIDDEN_VISIBILITY' >> configure.in.in
+echo 'CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS"' >> configure.in.in
+echo '' >> configure.in.in
+cat configure.in.in.orig >> configure.in.in
+rm configure.in.in.orig
+perl -p -e 's@umbrello/VERSION@VERSION@g' -i `find umbrello -name Makefile.am`
+cd /tmp
+log=/tmp/kdesdk/svn2dist.log
+$origdir/../scripts/svn2dist kdesdk $udir -n umbrello --admin-dir kdesdk/$udir/admin \
+ --svn-root svn://anonsvn.kde.org/home/kde/branches/stable --log=$log -o
+mv umbrello/po kdesdk/$udir/
+rm -rf umbrello
+cd kdesdk/$udir
+make -f Makefile.cvs
+cd ..
+tarfile=${udir}.tar.bz2
+tar cfvj $tarfile --exclude=.svn --exclude=autom4te.cache $udir
+mv $tarfile $origdir/
+cd $origdir
+# rm -rf /tmp/kdesdk
+
+echo upload $tarfile to upload.sf.net
+echo wput $tarfile ftp://upload.sf.net/incoming/
+echo update uml.sf.net including uploading ChangeLog
+echo advertise on freshmeat and kde-apps
+
diff --git a/umbrello/umbrello/Makefile.am b/umbrello/umbrello/Makefile.am
new file mode 100644
index 00000000..bccd738e
--- /dev/null
+++ b/umbrello/umbrello/Makefile.am
@@ -0,0 +1,155 @@
+bin_PROGRAMS = umbrello
+
+umbrello_COMPILE_FIRST = version.h
+umbrello_SOURCES = activitywidget.cpp \
+actor.cpp \
+actorwidget.cpp \
+aligntoolbar.cpp \
+artifact.cpp \
+artifactwidget.cpp \
+association.cpp \
+associationwidget.cpp \
+assocrules.cpp \
+attribute.cpp \
+boxwidget.cpp \
+classifier.cpp \
+classifiercodedocument.cpp \
+classifierlistitem.cpp \
+classifierwidget.cpp \
+cmdlineexportallviewsevent.cpp \
+codeaccessormethod.cpp \
+codeblock.cpp \
+codeblockwithcomments.cpp \
+codeclassfield.cpp \
+codeclassfielddeclarationblock.cpp \
+codecomment.cpp \
+codedocument.cpp \
+codegenerationpolicy.cpp \
+codegenerator.cpp \
+codegenobjectwithtextblocks.cpp \
+codemethodblock.cpp \
+codeoperation.cpp \
+codeparameter.cpp \
+component.cpp \
+componentwidget.cpp \
+configurable.cpp \
+datatypewidget.cpp \
+dialog_utils.cpp \
+docwindow.cpp \
+entity.cpp \
+entityattribute.cpp \
+entitywidget.cpp \
+enum.cpp \
+enumliteral.cpp \
+enumwidget.cpp \
+floatingtextwidget.cpp \
+floatingtextwidgetcontroller.cpp \
+folder.cpp \
+forkjoinwidget.cpp \
+kplayerslideraction.cpp \
+hierarchicalcodeblock.cpp \
+import_rose.cpp \
+kstartuplogo.cpp \
+linepath.cpp \
+linkwidget.cpp \
+listpopupmenu.cpp \
+main.cpp \
+messagewidget.cpp \
+messagewidgetcontroller.cpp \
+model_utils.cpp \
+node.cpp \
+nodewidget.cpp \
+notewidget.cpp \
+notewidgetcontroller.cpp \
+objectwidget.cpp \
+objectwidgetcontroller.cpp \
+object_factory.cpp \
+operation.cpp \
+optionstate.cpp \
+ownedcodeblock.cpp \
+ownedhierarchicalcodeblock.cpp \
+package.cpp \
+packagewidget.cpp \
+petalnode.cpp \
+petaltree2uml.cpp \
+plugin.cpp \
+pluginloader.cpp \
+seqlinewidget.cpp \
+statewidget.cpp \
+stereotype.cpp \
+template.cpp \
+textblock.cpp \
+toolbarstate.cpp \
+toolbarstatearrow.cpp \
+toolbarstateassociation.cpp \
+toolbarstatefactory.cpp \
+toolbarstatemessages.cpp \
+toolbarstateother.cpp \
+toolbarstatepool.cpp \
+uml.cpp \
+umlattributelist.cpp \
+umlentityattributelist.cpp \
+umlcanvasobject.cpp \
+umlclassifierlistitemlist.cpp \
+umldoc.cpp \
+umllistview.cpp \
+umllistviewitem.cpp \
+umlnamespace.cpp \
+umlobject.cpp \
+umlobjectlist.cpp \
+umlrole.cpp \
+umlview.cpp \
+umlviewcanvas.cpp \
+umlviewimageexporter.cpp \
+umlviewimageexporterall.cpp \
+umlviewimageexportermodel.cpp \
+umlwidget.cpp \
+umlwidgetcontroller.cpp \
+uniqueid.cpp \
+usecase.cpp \
+usecasewidget.cpp \
+widgetbase.cpp \
+widget_factory.cpp \
+widget_utils.cpp \
+worktoolbar.cpp
+
+#umbrello_LDADD = ./refactoring/librefactoring.la ./codeimport/libcodeimport.la ./codeimport/kdevcppparser/libkdevcppparser.la ./clipboard/libclipboard.la ./dialogs/libdialogs.la ./codegenerators/libcodegenerator.la $(AUTOLAYOUT_LIBS) $(LIB_KDEPRINT) $(LIB_KIO)
+umbrello_LDADD = ./refactoring/librefactoring.la ./codeimport/libcodeimport.la ./codeimport/kdevcppparser/libkdevcppparser.la ./clipboard/libclipboard.la ./dialogs/libdialogs.la ./codegenerators/libcodegenerator.la ./docgenerators/libdocgenerators.la $(LIB_KDEPRINT) $(LIB_KIO)
+
+## See section "dnl Not GPL compatible" in ../configure.in.in
+# SUBDIRS = $(AUTOLAYOUT_DIR) codeimport dialogs clipboard pics codegenerators headings refactoring
+SUBDIRS = codeimport dialogs docgenerators clipboard pics codegenerators headings refactoring
+
+KDE_ICON=AUTO
+
+appdir=$(kde_datadir)/umbrello
+app_DATA = tips umbrelloui.rc
+
+xdg_apps_DATA = umbrello.desktop
+
+mimedir = $(kde_mimedir)/application
+mime_DATA = x-umbrello.desktop
+
+#INCLUDES= -Idialogs -Irefactoring $(all_includes) -I/usr/include/graphviz/
+INCLUDES= -Idialogs -Irefactoring $(all_includes)
+
+METASOURCES = AUTO
+
+umbrello_LDFLAGS = $(all_libraries) $(KDE_RPATH) -export-dynamic
+
+messages: rc.cpp
+ $(PREPARETIPS) > tips.cpp
+ $(EXTRACTRC) *.rc codegenerators/*.ui dialogs/*.ui > ./rc.cpp
+ LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/umbrello.pot; \
+ fi
+ rm -f tips.cpp
+
+version.h: $(top_srcdir)/umbrello/VERSION
+ printf "#undef UMBRELLO_VERSION\n#define UMBRELLO_VERSION \"`cat $(top_srcdir)/umbrello/VERSION`\"\n" > version.h
+
+CLEANFILES = version.h
+
+noinst_HEADERS = version.h
+
diff --git a/umbrello/umbrello/activitywidget.cpp b/umbrello/umbrello/activitywidget.cpp
new file mode 100644
index 00000000..26ab29fd
--- /dev/null
+++ b/umbrello/umbrello/activitywidget.cpp
@@ -0,0 +1,235 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "activitywidget.h"
+
+// qt includes
+#include <qpainter.h>
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "docwindow.h"
+#include "umlview.h"
+#include "listpopupmenu.h"
+#include "dialogs/activitydialog.h"
+
+ActivityWidget::ActivityWidget(UMLView * view, ActivityType activityType, Uml::IDType id )
+ : UMLWidget(view, id)
+{
+ UMLWidget::setBaseType( Uml::wt_Activity );
+ setActivityType( activityType );
+ updateComponentSize();
+}
+
+ActivityWidget::~ActivityWidget() {}
+
+void ActivityWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ int w = width();
+ int h = height();
+ switch ( m_ActivityType )
+ {
+ case Normal :
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() ) {
+ p.setBrush( UMLWidget::getFillColour() );
+ }
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ //int middleX = w / 2;
+ int textStartY = (h / 2) - (fontHeight / 2);
+ p.drawRoundRect(offsetX, offsetY, w, h, (h * 60) / w, 60);
+ p.setPen(Qt::black);
+ p.setFont( UMLWidget::getFont() );
+ p.drawText(offsetX + ACTIVITY_MARGIN, offsetY + textStartY,
+ w - ACTIVITY_MARGIN * 2, fontHeight, Qt::AlignCenter, getName());
+ }
+ UMLWidget::setPen(p);
+ break;
+ case Initial :
+ p.setPen( QPen(m_LineColour, 1) );
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX, offsetY, w, h );
+ break;
+ case End :
+ p.setPen( QPen(m_LineColour, 1) );
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX, offsetY, w, h );
+ p.setBrush( Qt::white );
+ p.drawEllipse( offsetX + 1, offsetY + 1, w - 2, h - 2 );
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX + 3, offsetY + 3, w - 6, h - 6 );
+ break;
+ case Branch :
+ UMLWidget::setPen(p);
+ p.setBrush( UMLWidget::getFillColour() );
+ {
+ QPointArray array( 4 );
+ array[ 0 ] = QPoint( offsetX + w / 2, offsetY );
+ array[ 1 ] = QPoint( offsetX + w, offsetY + h / 2 );
+ array[ 2 ] = QPoint( offsetX + w / 2, offsetY + h );
+ array[ 3 ] = QPoint( offsetX, offsetY + h / 2 );
+ p.drawPolygon( array );
+ p.drawPolyline( array );
+ }
+ break;
+ }
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+void ActivityWidget::constrain(int& width, int& height) {
+ if (m_ActivityType == Normal) {
+ QSize minSize = calculateSize();
+ if (width < minSize.width())
+ width = minSize.width();
+ if (height < minSize.height())
+ height = minSize.height();
+ return;
+ }
+ if (width > height)
+ width = height;
+ else if (height > width)
+ height = width;
+ if (m_ActivityType == Branch) {
+ if (width < 20) {
+ width = 20;
+ height = 20;
+ } else if (width > 50) {
+ width = 50;
+ height = 50;
+ }
+ } else {
+ if (width < 15) {
+ width = 15;
+ height = 15;
+ } else if (width > 30) {
+ width = 30;
+ height = 30;
+ }
+ }
+}
+
+QSize ActivityWidget::calculateSize() {
+ int width, height;
+ if ( m_ActivityType == Normal ) {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(getName());
+ height = fontHeight;
+ width = textWidth > ACTIVITY_WIDTH ? textWidth : ACTIVITY_WIDTH;
+ height = height > ACTIVITY_HEIGHT ? height : ACTIVITY_HEIGHT;
+ width += ACTIVITY_MARGIN * 2;
+ height += ACTIVITY_MARGIN * 2;
+ } else {
+ width = height = 20;
+ }
+ return QSize(width, height);
+}
+
+ActivityWidget::ActivityType ActivityWidget::getActivityType() const {
+ return m_ActivityType;
+}
+
+void ActivityWidget::setActivityType( ActivityType activityType ) {
+ m_ActivityType = activityType;
+ updateComponentSize();
+ UMLWidget::m_bResizable = true;
+}
+
+void ActivityWidget::slotMenuSelection(int sel) {
+ bool done = false;
+
+ bool ok = false;
+ QString name = m_Text;
+
+ switch( sel ) {
+ case ListPopupMenu::mt_Rename:
+ name = KInputDialog::getText( i18n("Enter Activity Name"), i18n("Enter the name of the new activity:"), m_Text, &ok );
+ if( ok && name.length() > 0 )
+ m_Text = name;
+ done = true;
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ showProperties();
+ done = true;
+ break;
+ }
+
+ if( !done )
+ UMLWidget::slotMenuSelection( sel );
+}
+
+void ActivityWidget::showProperties() {
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation(false);
+
+ ActivityDialog dialog(m_pView, this);
+ if (dialog.exec() && dialog.getChangesMade()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->getDocument()->setModified(true);
+ }
+}
+
+bool ActivityWidget::isActivity(WorkToolBar::ToolBar_Buttons tbb,
+ ActivityType& resultType)
+{
+ bool status = true;
+ switch (tbb) {
+ case WorkToolBar::tbb_Initial_Activity:
+ resultType = Initial;
+ break;
+ case WorkToolBar::tbb_Activity:
+ resultType = Normal;
+ break;
+ case WorkToolBar::tbb_End_Activity:
+ resultType = End;
+ break;
+ case WorkToolBar::tbb_Branch:
+ resultType = Branch;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ return status;
+}
+
+void ActivityWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement activityElement = qDoc.createElement( "activitywidget" );
+ UMLWidget::saveToXMI( qDoc, activityElement );
+ activityElement.setAttribute( "activityname", m_Text );
+ activityElement.setAttribute( "documentation", m_Doc );
+ activityElement.setAttribute( "activitytype", m_ActivityType );
+ qElement.appendChild( activityElement );
+}
+
+bool ActivityWidget::loadFromXMI( QDomElement & qElement ) {
+ if( !UMLWidget::loadFromXMI( qElement ) )
+ return false;
+ m_Text = qElement.attribute( "activityname", "" );
+ m_Doc = qElement.attribute( "documentation", "" );
+ QString type = qElement.attribute( "activitytype", "1" );
+ setActivityType( (ActivityType)type.toInt() );
+ return true;
+}
+
+
+#include "activitywidget.moc"
+
diff --git a/umbrello/umbrello/activitywidget.h b/umbrello/umbrello/activitywidget.h
new file mode 100644
index 00000000..f23d4b65
--- /dev/null
+++ b/umbrello/umbrello/activitywidget.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ACTIVITYWIDGET_H
+#define ACTIVITYWIDGET_H
+
+#include "umlwidget.h"
+#include "worktoolbar.h"
+
+#define ACTIVITY_MARGIN 5
+#define ACTIVITY_WIDTH 30
+#define ACTIVITY_HEIGHT 10
+
+/**
+ * This class is the graphical version of a UML Activity. A ActivityWidget is created
+ * by a @ref UMLView. An ActivityWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * The ActivityWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UML Activity.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ActivityWidget : public UMLWidget {
+ Q_OBJECT
+
+public:
+ enum ActivityType
+ {
+ Initial = 0,
+ Normal,
+ End,
+ Branch
+ };
+
+ /**
+ * Creates a Activity widget.
+ *
+ * @param view The parent of the widget.
+ * @param activityType The type of activity.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ explicit ActivityWidget( UMLView * view, ActivityType activityType = Normal, Uml::IDType id = Uml::id_None );
+
+
+ /**
+ * destructor
+ */
+ virtual ~ActivityWidget();
+
+ /**
+ * Overrides the standard paint event.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Overrides Method from UMLWidget.
+ */
+ void constrain(int& width, int& height);
+
+ /**
+ * Returns the type of activity.
+ */
+ ActivityType getActivityType() const;
+
+ /**
+ * Sets the type of activity.
+ */
+ void setActivityType( ActivityType activityType );
+
+ /**
+ * Show a properties dialog for an ActivityWidget.
+ */
+ void showProperties();
+
+ /**
+ * Determines whether a toolbar button represents an Activity.
+ * CHECK: currently unused - can this be removed?
+ *
+ * @param tbb The toolbar button enum input value.
+ * @param resultType The ActivityType corresponding to tbb.
+ * This is only set if tbb is an Activity.
+ * @return True if tbb represents an Activity.
+ */
+ static bool isActivity( WorkToolBar::ToolBar_Buttons tbb,
+ ActivityType& resultType );
+
+ /**
+ * Saves the widget to the "activitywidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads the widget from the "activitywidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+protected:
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+
+ /**
+ * Type of activity.
+ */
+ ActivityType m_ActivityType;
+
+public slots:
+
+ /**
+ * Captures any popup menu signals for menus it created.
+ */
+ void slotMenuSelection(int sel);
+};
+
+#endif
diff --git a/umbrello/umbrello/actor.cpp b/umbrello/umbrello/actor.cpp
new file mode 100644
index 00000000..6e09c506
--- /dev/null
+++ b/umbrello/umbrello/actor.cpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "actor.h"
+
+UMLActor::UMLActor(const QString & name, Uml::IDType id) : UMLCanvasObject(name, id) {
+ init();
+}
+
+UMLActor::~UMLActor() {}
+
+void UMLActor::init() {
+ m_BaseType = Uml::ot_Actor;
+}
+
+UMLObject* UMLActor::clone() const {
+ UMLActor *clone = new UMLActor();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLActor::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement actorElement = UMLObject::save("UML:Actor", qDoc);
+ qElement.appendChild(actorElement);
+}
+
+bool UMLActor::load(QDomElement&) {
+ return true;
+}
+
+
+#include "actor.moc"
diff --git a/umbrello/umbrello/actor.h b/umbrello/umbrello/actor.h
new file mode 100644
index 00000000..479482e0
--- /dev/null
+++ b/umbrello/umbrello/actor.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ACTOR_H
+#define ACTOR_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML Actor.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ * The @ref UMLDoc class creates instances of this type.
+ *
+ * @short Information for a non-graphical UML Actor.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLCanvasObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLActor : public UMLCanvasObject {
+ Q_OBJECT
+public:
+ /**
+ * Constructs an Actor.
+ *
+ * @param name The name of the Actor.
+ * @param id The unique id to assign to this Actor.
+ */
+ explicit UMLActor(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~UMLActor();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates the <UML:Actor> XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Loads the <UML:Actor> XMI element (empty.)
+ */
+ bool load( QDomElement & element );
+};
+
+#endif
diff --git a/umbrello/umbrello/actorwidget.cpp b/umbrello/umbrello/actorwidget.cpp
new file mode 100644
index 00000000..0001e146
--- /dev/null
+++ b/umbrello/umbrello/actorwidget.cpp
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header file
+#include "actorwidget.h"
+
+// system includes
+#include <qpainter.h>
+
+// local includes
+#include "actor.h"
+#include "umlview.h"
+
+
+ActorWidget::ActorWidget(UMLView * view, UMLActor *a) : UMLWidget(view, a) {
+ UMLWidget::setBaseType( Uml::wt_Actor );
+}
+
+ActorWidget::~ActorWidget() {}
+
+void ActorWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if( UMLWidget::getUseFillColour() )
+ p.setBrush( UMLWidget::getFillColour() );
+ const int w = width();
+ const int h = height();
+ p.setFont( UMLWidget::getFont() );
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int textWidth = fm.width(getName());
+ const int fontHeight = fm.lineSpacing();
+ const int a_height = h - fontHeight - A_MARGIN;
+ const int h2 = a_height / 2;
+ const int w2 = w - A_MARGIN * 2;
+ const int a_width = (h2 > w2 || w > textWidth + A_MARGIN * 2 ? w2 : h2);
+ const int middleX = w / 2;
+ const int thirdY = a_height / 3;
+
+ //draw actor
+ p.drawEllipse(offsetX + middleX - a_width / 2, offsetY, a_width, thirdY); //head
+ p.drawLine(offsetX + middleX, offsetY + thirdY,
+ offsetX + middleX, offsetY + thirdY * 2); //body
+ p.drawLine(offsetX + middleX, offsetY + 2 * thirdY,
+ offsetX + middleX - a_width / 2, offsetY + a_height); //left leg
+ p.drawLine(offsetX + middleX, offsetY + 2 * thirdY,
+ offsetX + middleX + a_width / 2, offsetY + a_height); //right leg
+ p.drawLine(offsetX + middleX - a_width / 2, offsetY + thirdY + thirdY / 2,
+ offsetX + middleX + a_width / 2, offsetY + thirdY + thirdY / 2); //arms
+ //draw text
+ p.setPen(QPen(Qt::black));
+ p.drawText(offsetX + A_MARGIN, offsetY + h - fontHeight,
+ w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, getName());
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+QSize ActorWidget::calculateSize() {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(getName());
+ int width = textWidth > A_WIDTH ? textWidth : A_WIDTH;
+ int height = A_HEIGHT + fontHeight + A_MARGIN;
+ width += A_MARGIN * 2;
+ return QSize(width, height);
+}
+
+void ActorWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement actorElement = qDoc.createElement( "actorwidget" );
+ UMLWidget::saveToXMI( qDoc, actorElement );
+ qElement.appendChild( actorElement );
+}
+
diff --git a/umbrello/umbrello/actorwidget.h b/umbrello/umbrello/actorwidget.h
new file mode 100644
index 00000000..6d19290c
--- /dev/null
+++ b/umbrello/umbrello/actorwidget.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ACTORWIDGET_H
+#define ACTORWIDGET_H
+
+#include "umlwidget.h"
+
+#define A_WIDTH 20
+#define A_HEIGHT 40
+#define A_MARGIN 5
+
+class UMLActor;
+
+/**
+ * This class is the graphical version of a UML Actor.
+ * An ActorWidget is created by a @ref UMLView. An ActorWidget belongs to only
+ * one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to is destroyed, the
+ * ActorWidget will be automatically deleted.
+ *
+ * If the UMLActor class that this ActorWidget is displaying is deleted, the
+ * @ref UMLView will make sure that this instance is also deleted.
+ *
+ * The ActorWidget class inherits from the @ref UMLWidget class which adds most
+ * of the functionality to this class.
+ *
+ * @short A graphical version of a UML Actor.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * @see UMLView
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class ActorWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs an ActorWidget.
+ *
+ * @param view The parent of this ActorWidget.
+ * @param o The Actor class this ActorWidget will display.
+ */
+ ActorWidget(UMLView * view, UMLActor *o);
+
+
+ /**
+ * destructor
+ */
+ virtual ~ActorWidget();
+
+ /**
+ * Overrides the standard paint event.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Saves the widget to the "actorwidget" XMI element.
+ * Note: For loading from XMI, the inherited parent method is used.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+};
+
+#endif
diff --git a/umbrello/umbrello/aligntoolbar.cpp b/umbrello/umbrello/aligntoolbar.cpp
new file mode 100644
index 00000000..3be8689a
--- /dev/null
+++ b/umbrello/umbrello/aligntoolbar.cpp
@@ -0,0 +1,391 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "aligntoolbar.h"
+
+// system includes
+#include <algorithm>
+#include <vector>
+
+// qt includes
+#include <qmainwindow.h>
+
+// kde includes
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umlwidget.h"
+#include "umlwidgetlist.h"
+
+AlignToolBar::AlignToolBar(QMainWindow* parentWindow, const char* )
+ : KToolBar(parentWindow,Qt::DockRight,false) {
+ // load images for the buttons
+ loadPixmaps();
+
+ // create the buttons
+ insertButton(m_Pixmaps[alac_align_left], alac_align_left, true, i18n("Align Left"));
+ insertButton(m_Pixmaps[alac_align_right], alac_align_right, true, i18n("Align Right"));
+ insertButton(m_Pixmaps[alac_align_top], alac_align_top, true, i18n("Align Top"));
+ insertButton(m_Pixmaps[alac_align_bottom], alac_align_bottom, true, i18n("Align Bottom"));
+ insertButton(m_Pixmaps[alac_align_vertical_middle], alac_align_vertical_middle, true, i18n("Align Vertical Middle"));
+ insertButton(m_Pixmaps[alac_align_horizontal_middle], alac_align_horizontal_middle, true, i18n("Align Horizontal Middle"));
+ insertButton(m_Pixmaps[alac_align_vertical_distribute], alac_align_vertical_distribute, true, i18n("Align Vertical Distribute"));
+ insertButton(m_Pixmaps[alac_align_horizontal_distribute], alac_align_horizontal_distribute, true, i18n("Align Horizontal Distribute"));
+
+ setOrientation( Qt::Vertical );
+ setVerticalStretchable( true );
+
+ // gets called whenever a button in the toolbar is clicked
+ connect( this, SIGNAL( released( int ) ), this, SLOT( slotButtonChanged (int ) ) );
+}
+
+AlignToolBar::~AlignToolBar() {
+}
+
+/* ------ private functions ------ */
+
+bool AlignToolBar::hasWidgetSmallerX(const UMLWidget* widget1, const UMLWidget* widget2) {
+ return widget1->getX() < widget2->getX();
+}
+
+bool AlignToolBar::hasWidgetSmallerY(const UMLWidget* widget1, const UMLWidget* widget2) {
+ return widget1->getY() < widget2->getY();
+}
+
+void AlignToolBar::loadPixmaps() {
+ KStandardDirs* dirs = KGlobal::dirs();
+ QString dataDir = dirs->findResourceDir( "data", "umbrello/pics/object.png" );
+ dataDir += "/umbrello/pics/";
+
+ m_Pixmaps[alac_align_left].load( dataDir + "align_left.png" );
+ m_Pixmaps[alac_align_right].load( dataDir + "align_right.png" );
+ m_Pixmaps[alac_align_top].load( dataDir + "align_top.png" );
+ m_Pixmaps[alac_align_bottom].load( dataDir + "align_bottom.png" );
+ m_Pixmaps[alac_align_vertical_middle].load( dataDir + "align_vert_middle.png" );
+ m_Pixmaps[alac_align_horizontal_middle].load( dataDir + "align_hori_middle.png" );
+ m_Pixmaps[alac_align_vertical_distribute].load( dataDir + "align_vert_distribute.png" );
+ m_Pixmaps[alac_align_horizontal_distribute].load( dataDir + "align_hori_distribute.png" );
+
+ return;
+}
+
+int AlignToolBar::getSmallestX(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ int smallestX = it.toFirst()->getX();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (smallestX > widget->getX())
+ smallestX = widget->getX();
+ }
+
+ return smallestX;
+}
+
+int AlignToolBar::getSmallestY(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ int smallestY = it.toFirst()->getY();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (smallestY > widget->getY())
+ smallestY = widget->getY();
+ }
+
+ return smallestY;
+}
+
+int AlignToolBar::getBiggestX(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ int biggestX = it.toFirst()->getX();
+ biggestX += it.current()->getWidth();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (biggestX < widget->getX() + widget->getWidth())
+ biggestX = widget->getX() + widget->getWidth();
+ }
+
+ return biggestX;
+}
+
+int AlignToolBar::getBiggestY(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ int biggestY = it.toFirst()->getY();
+ biggestY += it.current()->getHeight();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (biggestY < widget->getY() + widget->getHeight())
+ biggestY = widget->getY() + widget->getHeight();
+ }
+
+ return biggestY;
+}
+
+int AlignToolBar::getHeightsSum(const UMLWidgetList &widgetList) {
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ int heightsSum = 0;
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ heightsSum += widget->getHeight();
+ }
+
+ return heightsSum;
+}
+
+int AlignToolBar::getWidthsSum(const UMLWidgetList &widgetList) {
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ int widthsSum = 0;
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widthsSum += widget->getWidth();
+ }
+
+ return widthsSum;
+}
+
+void AlignToolBar::alignLeft(UMLWidgetList &widgetList) {
+ int smallestX = getSmallestX(widgetList);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setX(smallestX);
+ }
+}
+
+void AlignToolBar::alignRight(UMLWidgetList &widgetList) {
+ int biggestX = getBiggestX(widgetList);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setX(biggestX - widget->getWidth());
+ }
+}
+
+void AlignToolBar::alignTop(UMLWidgetList &widgetList) {
+ int smallestY = getSmallestY(widgetList);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setY(smallestY);
+ }
+}
+
+void AlignToolBar::alignBottom(UMLWidgetList &widgetList) {
+ int biggestY = getBiggestY(widgetList);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setY(biggestY - widget->getHeight());
+ }
+}
+
+void AlignToolBar::alignVerticalMiddle(UMLWidgetList &widgetList) {
+ int smallestX = getSmallestX(widgetList);
+ int biggestX = getBiggestX(widgetList);
+ int middle = int((biggestX - smallestX) / 2) + smallestX;
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setX(middle - int(widget->getWidth() / 2));
+ }
+}
+
+void AlignToolBar::alignHorizontalMiddle(UMLWidgetList &widgetList) {
+ int smallestY = getSmallestY(widgetList);
+ int biggestY = getBiggestY(widgetList);
+ int middle = int((biggestY - smallestY) / 2) + smallestY;
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setY(middle - int(widget->getHeight() / 2));
+ }
+}
+
+void AlignToolBar::alignVerticalDistribute(UMLWidgetList &widgetList) {
+ int smallestY = getSmallestY(widgetList);
+ int biggestY = getBiggestY(widgetList);
+ int heightsSum = getHeightsSum(widgetList);
+ int distance = int(((biggestY - smallestY) - heightsSum) / (widgetList.count()-1.0) + 0.5);
+
+ sortWidgetList(widgetList, hasWidgetSmallerY);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it = UMLWidgetListIt(widgetList);
+
+ UMLWidget* widgetPrev = it.toFirst();
+ ++it;
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setY(widgetPrev->getY() + widgetPrev->getHeight() + distance);
+ widgetPrev = widget;
+ }
+}
+
+void AlignToolBar::alignHorizontalDistribute(UMLWidgetList &widgetList) {
+ int smallestX = getSmallestX(widgetList);
+ int biggestX = getBiggestX(widgetList);
+ int widthsSum = getWidthsSum(widgetList);
+ int distance = int(((biggestX - smallestX) - widthsSum) / (widgetList.count()-1.0) + 0.5);
+
+ sortWidgetList(widgetList, hasWidgetSmallerX);
+
+ UMLWidget* widget;
+ UMLWidgetListIt it(widgetList);
+
+ it = UMLWidgetListIt(widgetList);
+
+ UMLWidget* widgetPrev = it.toFirst();
+ ++it;
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->setX(widgetPrev->getX() + widgetPrev->getWidth() + distance);
+ widgetPrev = widget;
+ }
+}
+
+template<typename Compare>
+void AlignToolBar::sortWidgetList(UMLWidgetList &widgetList, Compare comp) {
+ std::vector<UMLWidget*> widgetVector;
+ UMLWidgetListIt it(widgetList);
+ while (it.current() != 0) {
+ widgetVector.push_back(*it);
+ ++it;
+ }
+ sort(widgetVector.begin(), widgetVector.end(), comp);
+
+ widgetList.clear();
+
+ for (std::vector<UMLWidget*>::iterator it=widgetVector.begin(); it != widgetVector.end(); ++it) {
+ widgetList.append(*it);
+ }
+}
+
+/* ------ private slots ------ */
+
+void AlignToolBar::slotButtonChanged(int btn) {
+ UMLView* view = UMLApp::app()->getCurrentView();
+ UMLWidgetList widgetList;
+ UMLWidget* widget;
+
+ // get the list with selected widgets (not associations)
+ view->getSelectedWidgets(widgetList);
+ UMLWidgetListIt it(widgetList);
+
+ // at least 2 widgets must be selected
+ if (widgetList.count() > 1) {
+ // now perform alignment according to the clicked button
+ switch (btn) {
+ case alac_align_left:
+ alignLeft(widgetList);
+ break;
+
+ case alac_align_right:
+ alignRight(widgetList);
+ break;
+
+ case alac_align_top:
+ alignTop(widgetList);
+ break;
+
+ case alac_align_bottom:
+ alignBottom(widgetList);
+ break;
+
+ case alac_align_vertical_middle:
+ alignVerticalMiddle(widgetList);
+ break;
+
+ case alac_align_horizontal_middle:
+ alignHorizontalMiddle(widgetList);
+ break;
+
+ case alac_align_vertical_distribute:
+ alignVerticalDistribute(widgetList);
+ break;
+
+ case alac_align_horizontal_distribute:
+ alignHorizontalDistribute(widgetList);
+ break;
+
+ } // switch (btn)
+
+ // update associations
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->updateWidget();
+ }
+ UMLApp::app()->getDocument()->setModified();
+ } else {
+ KMessageBox::messageBox(0, KMessageBox::Information,
+ i18n("For alignment you have to select at least 2 objects like classes or actors. You can not align associations."),
+ i18n("Information"), i18n("&OK"), QString(""),
+ "showAlignInformation");
+ } // if (widgetList.count() > 1)
+
+ return;
+}
+
+#include "aligntoolbar.moc"
diff --git a/umbrello/umbrello/aligntoolbar.h b/umbrello/umbrello/aligntoolbar.h
new file mode 100644
index 00000000..271e9c0b
--- /dev/null
+++ b/umbrello/umbrello/aligntoolbar.h
@@ -0,0 +1,224 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ALIGNTOOLBAR_H
+#define ALIGNTOOLBAR_H
+
+#include <qpixmap.h>
+#include <ktoolbar.h>
+#include "umlnamespace.h"
+#include "umlwidgetlist.h"
+
+class QMainWindow;
+class UMLWidget;
+
+/**
+ * This toolbar provides tools for alignment. Widgets can only be aligned, when
+ * there are at least 2 widgets (not associations) are selected
+ *
+ * @short Toolbar providing alignment tools.
+ * @author Sebastian Stein <seb.kde@hpfsc.de>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AlignToolBar : public KToolBar {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a bar with tools for alignment.
+ *
+ * @param parentWindow The parent of the toolbar.
+ * @param name The name of the toolbar.
+ */
+ AlignToolBar(QMainWindow* parentWindow, const char* name);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~AlignToolBar();
+
+private:
+
+ /**
+ * Returns true if the first widget's X is smaller than second's.
+ * Used for sorting the UMLWidgetList.
+ *
+ * @param widget1 The widget to compare.
+ * @param widget2 The widget to compare with.
+ */
+ static bool hasWidgetSmallerX(const UMLWidget* widget1, const UMLWidget* widget2);
+
+ /**
+ * Returns true if the first widget's Y is smaller than second's.
+ * Used for sorting the UMLWidgetList.
+ *
+ * @param widget1 The widget to compare.
+ * @param widget2 The widget to compare with.
+ */
+ static bool hasWidgetSmallerY(const UMLWidget* widget1, const UMLWidget* widget2);
+
+ /**
+ * Loads toolbar icon.
+ */
+ void loadPixmaps();
+
+ /**
+ * Looks for the smallest x-value of the given UMLWidgets.
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getSmallestX(const UMLWidgetList &widgetList);
+
+ /**
+ * Looks for the smallest y-value of the given UMLWidgets.
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getSmallestY(const UMLWidgetList &widgetList);
+
+ /**
+ * Looks for the biggest x-value of the given UMLWidgets.
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getBiggestX(const UMLWidgetList &widgetList);
+
+ /**
+ * Looks for the biggest y-value of the given UMLWidgets.
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getBiggestY(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the sum of the heights of the given UMLWidgets
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getHeightsSum(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the sum of the widths of the given UMLWidgets.
+ *
+ * @param widgetList A list with UMLWidgets.
+ */
+ int getWidthsSum(const UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the left.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignLeft(UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the right.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignRight(UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the top.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignTop(UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the bottom.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignBottom(UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the vertical middle.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignVerticalMiddle(UMLWidgetList &widgetList);
+
+ /**
+ * Aligns all the widgets in the list to the horizontal middle.
+ *
+ * @param widgetList The list with the widgets to align.
+ */
+ void alignHorizontalMiddle(UMLWidgetList &widgetList);
+
+ /**
+ * Distributes all the widgets in the list at the same vertical distance
+ * from one widget to the next.
+ *
+ * @param widgetList The list with the widgets to distribute.
+ */
+ void alignVerticalDistribute(UMLWidgetList &widgetList);
+
+ /**
+ * Distributes all the widgets in the list at the same horizontal distance
+ * from one widget to the next.
+ *
+ * @param widgetList The list with the widgets to distribute.
+ */
+ void alignHorizontalDistribute(UMLWidgetList &widgetList);
+
+ /**
+ * Sorts the given UMLWidgetList based on the Compare function.
+ * The list is cleared and all the widgets are added again in order.
+ *
+ * The comp function gets two const UMLWidget* params and returns
+ * a boolean telling if the first widget was smaller than the second,
+ * whatever the "smaller" concept is depending on the sorting to do.
+ *
+ * @param widgetList The list with the widgets to order.
+ * @param comp The comp function to compare the widgets.
+ */
+ template<typename Compare>
+ void sortWidgetList(UMLWidgetList &widgetList, Compare comp);
+
+ /**
+ * Used to identify the buttons.
+ */
+ enum AlignAction
+ {
+ alac_align_left = 0,
+ alac_align_right,
+ alac_align_top,
+ alac_align_bottom,
+ alac_align_vertical_middle,
+ alac_align_horizontal_middle,
+ alac_align_vertical_distribute,
+ alac_align_horizontal_distribute,
+ alac_none
+ };
+
+ /**
+ * Holds the number of buttons.
+ */
+ static const unsigned nrAlignButtons = (unsigned) alac_none -
+ (unsigned) alac_align_left;
+
+ /**
+ * Holds the icons for the different buttons.
+ */
+ QPixmap m_Pixmaps[nrAlignButtons];
+
+private slots:
+
+ /**
+ * Performs the alignment when a button was clicked.
+ *
+ * @param btn The clicked button.
+ */
+ void slotButtonChanged(int btn);
+};
+
+#endif
diff --git a/umbrello/umbrello/artifact.cpp b/umbrello/umbrello/artifact.cpp
new file mode 100644
index 00000000..12f77966
--- /dev/null
+++ b/umbrello/umbrello/artifact.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "artifact.h"
+#include "association.h"
+#include "clipboard/idchangelog.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+UMLArtifact::UMLArtifact(const QString & name, Uml::IDType id)
+ : UMLCanvasObject(name, id) {
+ init();
+}
+
+UMLArtifact::~UMLArtifact() {
+}
+
+void UMLArtifact::init() {
+ m_BaseType = Uml::ot_Artifact;
+ m_drawAsType = defaultDraw;
+}
+
+UMLObject* UMLArtifact::clone() const {
+ UMLArtifact *clone = new UMLArtifact();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLArtifact::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement artifactElement = UMLObject::save("UML:Artifact", qDoc);
+ artifactElement.setAttribute("drawas", m_drawAsType);
+ qElement.appendChild(artifactElement);
+}
+
+bool UMLArtifact::load(QDomElement& element) {
+ QString drawAs = element.attribute("drawas", "0");
+ m_drawAsType = (Draw_Type)drawAs.toInt();
+ return true;
+}
+
+void UMLArtifact::setDrawAsType(Draw_Type type) {
+ m_drawAsType = type;
+}
+
+UMLArtifact::Draw_Type UMLArtifact::getDrawAsType() {
+ return m_drawAsType;
+}
+
+#include "artifact.moc"
diff --git a/umbrello/umbrello/artifact.h b/umbrello/umbrello/artifact.h
new file mode 100644
index 00000000..8b76f154
--- /dev/null
+++ b/umbrello/umbrello/artifact.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ARTIFACT_H
+#define ARTIFACT_H
+
+#include "umlcanvasobject.h"
+
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Artifact.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Artifact.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLArtifact : public UMLCanvasObject {
+ Q_OBJECT
+public:
+
+ /**
+ * Artifacts can be drawn using one of several icons.
+ */
+ enum Draw_Type {
+ defaultDraw,
+ file,
+ library,
+ table
+ };
+
+ /**
+ * Sets up a Artifact.
+ *
+ * @param Name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLArtifact(const QString & Name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLArtifact();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates the UML:Artifact element including its operations,
+ * attributes and templates
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * sets m_drawAsType for which method to draw the artifact as
+ */
+ void setDrawAsType(Draw_Type type);
+
+ /**
+ * returns the value of m_drawAsType
+ */
+ Draw_Type getDrawAsType();
+
+protected:
+ /**
+ * Loads the UML:Artifact element including its operations,
+ * attributes and templates
+ */
+ bool load( QDomElement & element );
+
+private:
+ /**
+ * Artifacts can be drawn as one of several different icons,
+ * this value choosing how to draw them.
+ */
+ Draw_Type m_drawAsType;
+};
+
+#endif
diff --git a/umbrello/umbrello/artifactwidget.cpp b/umbrello/umbrello/artifactwidget.cpp
new file mode 100644
index 00000000..931f757a
--- /dev/null
+++ b/umbrello/umbrello/artifactwidget.cpp
@@ -0,0 +1,259 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "artifactwidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <qpointarray.h>
+#include <kdebug.h>
+
+// app includes
+#include "artifact.h"
+#include "umlview.h"
+
+
+ArtifactWidget::ArtifactWidget(UMLView *view, UMLArtifact *a) : UMLWidget(view, a) {
+ init();
+ setSize(100, 30);
+ updateComponentSize();
+}
+
+
+void ArtifactWidget::init() {
+ UMLWidget::setBaseType( Uml::wt_Artifact );
+ m_pMenu = 0;
+}
+
+ArtifactWidget::~ArtifactWidget() {}
+
+void ArtifactWidget::drawAsNormal(QPainter& p, int offsetX, int offsetY) {
+ int w = width();
+ int h = height();
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString name = getName();
+ QString stereotype = m_pObject->getStereotype();
+
+ p.drawRect(offsetX, offsetY, w, h);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ if (!stereotype.isEmpty()) {
+ p.drawText(offsetX + ARTIFACT_MARGIN, offsetY + (h/2) - fontHeight,
+ w, fontHeight, Qt::AlignCenter, m_pObject->getStereotype(true));
+ }
+
+ int lines;
+ if (!stereotype.isEmpty()) {
+ lines = 2;
+ } else {
+ lines = 1;
+ }
+
+ if (lines == 1) {
+ p.drawText(offsetX, offsetY + (h/2) - (fontHeight/2),
+ w, fontHeight, Qt::AlignCenter, name);
+ } else {
+ p.drawText(offsetX, offsetY + (h/2),
+ w, fontHeight, Qt::AlignCenter, name);
+ }
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void ArtifactWidget::drawAsFile(QPainter& p, int offsetX, int offsetY) {
+ const int w = width();
+ const int h = height();
+ QFont font = UMLWidget::getFont();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const QString name = getName();
+
+ int startX = offsetX + (w/2) - 25;
+ int iconHeight = h - fontHeight;
+ QPointArray pointArray(5);
+ pointArray.setPoint(0, startX, offsetY);
+ pointArray.setPoint(1, startX + 40, offsetY);
+ pointArray.setPoint(2, startX + 50, offsetY + 10);
+ pointArray.setPoint(3, startX + 50, offsetY + iconHeight);
+ pointArray.setPoint(4, startX, offsetY + iconHeight);
+ p.drawPolygon(pointArray);
+
+ p.drawLine(startX + 40, offsetY, startX + 40, offsetY + 10);
+ p.drawLine(startX + 40, offsetY + 10, startX + 50, offsetY + 10);
+ p.drawLine(startX + 40, offsetY, startX + 50, offsetY + 10);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ p.drawText(offsetX, offsetY + h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name);
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void ArtifactWidget::drawAsLibrary(QPainter& p, int offsetX, int offsetY) {
+ //FIXME this should have gears on it
+ const int w = width();
+ const int h = height();
+ const QFont font = UMLWidget::getFont();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const QString name = getName();
+
+ const int startX = offsetX + (w/2) - 25;
+ const int iconHeight = h - fontHeight;
+ QPointArray pointArray(5);
+ pointArray.setPoint(0, startX, offsetY);
+ pointArray.setPoint(1, startX + 40, offsetY);
+ pointArray.setPoint(2, startX + 50, offsetY + 10);
+ pointArray.setPoint(3, startX + 50, offsetY + iconHeight);
+ pointArray.setPoint(4, startX, offsetY + iconHeight);
+ p.drawPolygon(pointArray);
+
+ p.drawLine(startX + 40, offsetY, startX + 40, offsetY + 10);
+ p.drawLine(startX + 40, offsetY + 10, startX + 50, offsetY + 10);
+ p.drawLine(startX + 40, offsetY, startX + 50, offsetY + 10);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ p.drawText(offsetX, offsetY + h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name);
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void ArtifactWidget::drawAsTable(QPainter& p, int offsetX, int offsetY) {
+ const int w = width();
+ const int h = height();
+ const QFont font = UMLWidget::getFont();
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const QString name = getName();
+
+ const int startX = offsetX + (w/2) - 25;
+ const int iconHeight = h - fontHeight;
+
+ p.drawRect(startX, offsetY, 50, h - fontHeight + 1);
+ p.drawLine(startX + 20, offsetY, startX + 20, offsetY + iconHeight);
+ p.drawLine(startX + 30, offsetY, startX + 30, offsetY + iconHeight);
+ p.drawLine(startX + 40, offsetY, startX + 40, offsetY + iconHeight);
+ p.drawLine(startX, offsetY + (iconHeight/2), startX + 49, offsetY + (iconHeight/2));
+ p.drawLine(startX, offsetY + (iconHeight/2) + (iconHeight/4),
+ startX + 49, offsetY + (iconHeight/2) + (iconHeight/4));
+
+ QPen thickerPen = p.pen();
+ thickerPen.setWidth(2);
+ p.setPen(thickerPen);
+ p.drawLine(startX + 10, offsetY, startX + 10, offsetY + iconHeight);
+ p.drawLine(startX, offsetY + (iconHeight/4), startX + 50, offsetY + (iconHeight/4));
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ p.drawText(offsetX, offsetY + h - fontHeight,
+ w, fontHeight, Qt::AlignCenter, name);
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void ArtifactWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() ) {
+ p.setBrush( UMLWidget::getFillColour() );
+ } else {
+ p.setBrush( m_pView->viewport()->backgroundColor() );
+ }
+
+ UMLArtifact *umlart = static_cast<UMLArtifact*>(m_pObject);
+ UMLArtifact::Draw_Type drawType = umlart->getDrawAsType();
+ switch (drawType) {
+ case UMLArtifact::defaultDraw:
+ return drawAsNormal(p, offsetX, offsetY);
+ break;
+ case UMLArtifact::file:
+ return drawAsFile(p, offsetX, offsetY);
+ break;
+ case UMLArtifact::library:
+ return drawAsLibrary(p, offsetX, offsetY);
+ break;
+ case UMLArtifact::table:
+ return drawAsTable(p, offsetX, offsetY);
+ break;
+ default:
+ kWarning() << "Artifact drawn as unknown type" << endl;
+ break;
+ }
+}
+
+QSize ArtifactWidget::calculateIconSize() {
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ int width = fm.width( m_pObject->getName() );
+
+ width = width<50 ? 50 : width;
+
+ int height = 50 + fontHeight;
+
+ return QSize(width, height);
+}
+
+QSize ArtifactWidget::calculateNormalSize() {
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ int width = fm.width( m_pObject->getName() );
+
+ int tempWidth = 0;
+ if(!m_pObject->getStereotype().isEmpty()) {
+ tempWidth = fm.width( m_pObject->getStereotype(true) );
+ }
+ width = tempWidth>width ? tempWidth : width;
+ width += ARTIFACT_MARGIN * 2;
+
+ int height = (2*fontHeight) + (ARTIFACT_MARGIN * 2);
+
+ return QSize(width, height);
+}
+
+QSize ArtifactWidget::calculateSize() {
+ if ( !m_pObject) {
+ return UMLWidget::calculateSize();
+ }
+ UMLArtifact *umlart = static_cast<UMLArtifact*>(m_pObject);
+ if (umlart->getDrawAsType() == UMLArtifact::defaultDraw) {
+ return calculateNormalSize();
+ } else {
+ return calculateIconSize();
+ }
+}
+
+void ArtifactWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement conceptElement = qDoc.createElement("artifactwidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
diff --git a/umbrello/umbrello/artifactwidget.h b/umbrello/umbrello/artifactwidget.h
new file mode 100644
index 00000000..a68f3acc
--- /dev/null
+++ b/umbrello/umbrello/artifactwidget.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ARTIFACTWIDGET_H
+#define ARTIFACTWIDGET_H
+
+
+#include "umlwidget.h"
+
+class UMLView;
+class UMLArtifact;
+
+#define ARTIFACT_MARGIN 5
+
+/**
+ * Defines a graphical version of the Artifact.
+ * Most of the functionality will come from the @ref UMLArtifact class.
+ *
+ * @short A graphical version of a Artifact.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ArtifactWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a ArtifactWidget.
+ *
+ * @param view The parent of this ArtifactWidget.
+ * @param a The Artifact this widget will be representing.
+ */
+ ArtifactWidget(UMLView *view, UMLArtifact *a);
+
+ /**
+ * destructor
+ */
+ virtual ~ArtifactWidget();
+
+ /**
+ * Overrides standard method
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves the widget to the "artifactwidget" XMI element.
+ * Note: For loading from XMI, the inherited parent method is used.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * calculates the size when drawing as an icon (it's the same size for all icons)
+ */
+ QSize calculateIconSize();
+
+ /**
+ * calculates the size for drawing as a box
+ */
+ QSize calculateNormalSize();
+
+ /**
+ * draw as a file icon
+ */
+ void drawAsFile(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * draw as a library file icon
+ */
+ void drawAsLibrary(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * draw as a database table icon
+ */
+ void drawAsTable(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * draw as a box
+ */
+ void drawAsNormal(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * The right mouse button menu
+ */
+ ListPopupMenu* m_pMenu;
+};
+
+#endif
diff --git a/umbrello/umbrello/association.cpp b/umbrello/umbrello/association.cpp
new file mode 100644
index 00000000..eacc8d13
--- /dev/null
+++ b/umbrello/umbrello/association.cpp
@@ -0,0 +1,574 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "association.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <qregexp.h>
+// app includes
+#include "classifier.h"
+#include "folder.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlrole.h"
+#include "uniqueid.h"
+#include "model_utils.h"
+
+using namespace Uml;
+
+// static members
+const Uml::Association_Type UMLAssociation::atypeFirst = Uml::at_Generalization;
+const Uml::Association_Type UMLAssociation::atypeLast = Uml::at_Relationship;
+const unsigned UMLAssociation::nAssocTypes = (unsigned)atypeLast -
+ (unsigned)atypeFirst + 1;
+
+// constructor
+UMLAssociation::UMLAssociation( Uml::Association_Type type,
+ UMLObject * roleA, UMLObject * roleB )
+ : UMLObject("")
+{
+ init(type, roleA, roleB);
+
+ m_pRole[Uml::A]->setID( UniqueID::gen() );
+ m_pRole[Uml::B]->setID( UniqueID::gen() );
+}
+
+UMLAssociation::UMLAssociation( Uml::Association_Type type /* = Uml::at_Unknown */)
+ : UMLObject("", Uml::id_Reserved)
+{
+ init(type, NULL, NULL);
+}
+
+// destructor
+UMLAssociation::~UMLAssociation( ) {
+ if (m_pRole[A] == NULL) {
+ kError() << "UMLAssociation destructor: m_pRole[A] is NULL already"
+ << endl;
+ } else {
+ delete m_pRole[A];
+ m_pRole[A] = NULL;
+ }
+ if (m_pRole[B] == NULL) {
+ kError() << "UMLAssociation destructor: m_pRole[B] is NULL already"
+ << endl;
+ } else {
+ delete m_pRole[B];
+ m_pRole[B] = NULL;
+ }
+}
+
+bool UMLAssociation::operator==(UMLAssociation &rhs) {
+ if (this == &rhs) {
+ return true;
+ }
+ return ( UMLObject::operator== ( rhs ) &&
+ m_AssocType == rhs.m_AssocType &&
+ m_Name == rhs.m_Name &&
+ m_pRole[A] == rhs.m_pRole[A] &&
+ m_pRole[B] == rhs.m_pRole[B] );
+}
+
+const QString UMLAssociation::assocTypeStr[UMLAssociation::nAssocTypes] = {
+ /* The elements must be listed in the same order as in the
+ Uml::Association_Type. */
+ i18n("Generalization"), // at_Generalization
+ i18n("Aggregation"), // at_Aggregation
+ i18n("Dependency"), // at_Dependency
+ i18n("Association"), // at_Association
+ i18n("Self Association"), // at_Association_Self
+ i18n("Collaboration Message"), // at_Coll_Message
+ i18n("Sequence Message"), // at_Seq_Message
+ i18n("Collaboration Self Message"), // at_Coll_Message_Self
+ i18n("Sequence Self Message"), // at_Seq_Message_Self
+ i18n("Containment"), // at_Containment
+ i18n("Composition"), // at_Composition
+ i18n("Realization"), // at_Realization
+ i18n("Uni Association"), // at_UniAssociation
+ i18n("Anchor"), // at_Anchor
+ i18n("State Transition"), // at_State
+ i18n("Activity"), // at_Activity
+ };
+
+Uml::Association_Type UMLAssociation::getAssocType() const {
+ return m_AssocType;
+}
+
+QString UMLAssociation::toString ( ) const
+{
+ QString string;
+ if(m_pRole[A])
+ {
+ string += m_pRole[A]->getObject()->getName();
+ string += ':';
+ string += m_pRole[A]->getName();
+ }
+ string += ':' + typeAsString(m_AssocType) + ':';
+ if(m_pRole[B])
+ {
+ string += m_pRole[B]->getObject( )->getName();
+ string += ':';
+ string += m_pRole[B]->getName();
+ }
+ return string;
+}
+
+QString UMLAssociation::typeAsString (Uml::Association_Type atype)
+{
+ if (atype < atypeFirst || atype > atypeLast)
+ return "";
+ return assocTypeStr[(unsigned)atype - (unsigned)atypeFirst];
+}
+
+bool UMLAssociation::assocTypeHasUMLRepresentation(Uml::Association_Type atype)
+{
+ return (atype == Uml::at_Generalization ||
+ atype == Uml::at_Realization ||
+ atype == Uml::at_Association ||
+ atype == Uml::at_Association_Self ||
+ atype == Uml::at_UniAssociation ||
+ atype == Uml::at_Aggregation ||
+ atype == Uml::at_Relationship ||
+ atype == Uml::at_Composition ||
+ atype == Uml::at_Dependency);
+}
+
+bool UMLAssociation::resolveRef() {
+ bool successA = getUMLRole(A)->resolveRef();
+ bool successB = getUMLRole(B)->resolveRef();
+ if (successA && successB) {
+ UMLObject *objA = getUMLRole(A)->getObject();
+ UMLObject *objB = getUMLRole(B)->getObject();
+ // Check if need to change the assoc type to Realization
+ if (m_AssocType == Uml::at_Generalization &&
+ (objA && objA->getBaseType() == Uml::ot_Interface ||
+ objB && objB->getBaseType() == Uml::ot_Interface))
+ m_AssocType = Uml::at_Realization;
+ m_pUMLPackage->addAssocToConcepts(this);
+ return true;
+ }
+ return false;
+}
+
+void UMLAssociation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ if (m_AssocType == Uml::at_Generalization) {
+ QDomElement assocElement = UMLObject::save("UML:Generalization", qDoc);
+ assocElement.setAttribute( "discriminator", "" );
+ assocElement.setAttribute( "child", ID2STR(getObjectId(A)) );
+ assocElement.setAttribute( "parent", ID2STR(getObjectId(B)) );
+ qElement.appendChild( assocElement );
+ return;
+ }
+ if (m_AssocType == Uml::at_Realization) {
+ QDomElement assocElement = UMLObject::save("UML:Abstraction", qDoc);
+ assocElement.setAttribute( "client", ID2STR(getObjectId(A)) );
+ assocElement.setAttribute( "supplier", ID2STR(getObjectId(B)) );
+ qElement.appendChild( assocElement );
+ return;
+ }
+ if (m_AssocType == Uml::at_Dependency) {
+ QDomElement assocElement = UMLObject::save("UML:Dependency", qDoc);
+ assocElement.setAttribute( "client", ID2STR(getObjectId(A)) );
+ assocElement.setAttribute( "supplier", ID2STR(getObjectId(B)) );
+ qElement.appendChild( assocElement );
+ return;
+ }
+ QDomElement associationElement = UMLObject::save("UML:Association", qDoc);
+ QDomElement connElement = qDoc.createElement("UML:Association.connection");
+ getUMLRole(A)->saveToXMI (qDoc, connElement);
+ getUMLRole(B)->saveToXMI (qDoc, connElement);
+ associationElement.appendChild (connElement);
+ qElement.appendChild( associationElement );
+}
+
+bool UMLAssociation::load( QDomElement & element ) {
+ if (getID() == Uml::id_None)
+ return false; // old style XMI file. No real info in this association.
+
+ UMLDoc * doc = UMLApp::app()->getDocument();
+ UMLObject * obj[2] = { NULL, NULL };
+ if (m_AssocType == Uml::at_Generalization ||
+ m_AssocType == Uml::at_Realization ||
+ m_AssocType == Uml::at_Dependency) {
+ for (unsigned r = Uml::A; r <= Uml::B; r++) {
+ const QString fetch = (m_AssocType == Uml::at_Generalization ?
+ r == Uml::A ? "child" : "parent"
+ : r == Uml::A ? "client" : "supplier");
+ QString roleIdStr = element.attribute(fetch, "");
+ if (roleIdStr.isEmpty()) {
+ // Might be given as a child node instead - see below.
+ continue;
+ }
+
+ // set umlobject of role if possible (else defer resolution)
+ obj[r] = doc->findObjectById(STR2ID(roleIdStr));
+ Uml::Role_Type role = (Uml::Role_Type)r;
+ if (obj[r] == NULL) {
+ m_pRole[role]->setSecondaryId(roleIdStr); // defer to resolveRef()
+ } else {
+ m_pRole[role]->setObject(obj[r]);
+ if (m_pUMLPackage == NULL) {
+ Uml::Model_Type mt = Model_Utils::convert_OT_MT(obj[r]->getBaseType());
+ m_pUMLPackage = doc->getRootFolder(mt);
+ kDebug() << "UMLAssociation::load(assoctype " << m_AssocType
+ << "): setting model type " << mt << endl;
+ }
+ }
+ }
+ if (obj[A] == NULL || obj[B] == NULL) {
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(tag))
+ continue;
+ // Permitted tag names:
+ // roleA: "child" "subtype" "client"
+ // roleB: "parent" "supertype" "supplier"
+ QString idStr = tempElement.attribute( "xmi.id", "" );
+ if (idStr.isEmpty())
+ idStr = tempElement.attribute( "xmi.idref", "" );
+ if (idStr.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ idStr = tmpElem.attribute( "xmi.id", "" );
+ if (idStr.isEmpty())
+ idStr = tmpElem.attribute( "xmi.idref", "" );
+ }
+ if (idStr.isEmpty()) {
+ kError() << "UMLAssociation::load (type " << m_AssocType
+ << ", id " << ID2STR(getID()) << "): "
+ << "xmi id not given for " << tag << endl;
+ continue;
+ }
+ // Since we know for sure that we're dealing with a non
+ // umbrello file, use deferred resolution unconditionally.
+ if (tagEq(tag, "child") || tagEq(tag, "subtype") || tagEq(tag, "client")) {
+ getUMLRole(A)->setSecondaryId(idStr);
+ } else {
+ getUMLRole(B)->setSecondaryId(idStr);
+ }
+ }
+ }
+
+ // its a realization if either endpoint is an interface
+ if (m_AssocType == Uml::at_Generalization &&
+ (obj[A] && obj[A]->getBaseType() == Uml::ot_Interface ||
+ obj[B] && obj[B]->getBaseType() == Uml::ot_Interface))
+ m_AssocType = Uml::at_Realization;
+
+ return true;
+ }
+
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ // uml13.dtd compliant format (new style)
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(tag))
+ continue;
+ if (!tagEq(tag, "Association.connection") &&
+ !tagEq(tag, "Namespace.ownedElement") &&
+ !tagEq(tag, "Namespace.contents")) {
+ kWarning() << "UMLAssociation::load: "
+ << "unknown child node " << tag << endl;
+ continue;
+ }
+ // Load role A.
+ node = tempElement.firstChild();
+ while (node.isComment())
+ node = node.nextSibling();
+ tempElement = node.toElement();
+ if (tempElement.isNull()) {
+ kWarning() << "UML:Association : element (A) is Null" << endl;
+ return false;
+ }
+ tag = tempElement.tagName();
+ if (!tagEq(tag, "AssociationEndRole") &&
+ !tagEq(tag, "AssociationEnd")) {
+ kWarning() << "UMLAssociation::load: "
+ << "unknown child (A) tag " << tag << endl;
+ return false;
+ }
+ if (! getUMLRole(A)->loadFromXMI(tempElement))
+ return false;
+ // Load role B.
+ node = node.nextSibling();
+ while (node.isComment())
+ node = node.nextSibling();
+ tempElement = node.toElement();
+ if (tempElement.isNull()) {
+ kWarning() << "UML:Association : element (B) is Null" << endl;
+ return false;
+ }
+ tag = tempElement.tagName();
+ if (!tagEq(tag, "AssociationEndRole") &&
+ !tagEq(tag, "AssociationEnd")) {
+ kWarning() << "UMLAssociation::load: "
+ << "unknown child (B) tag " << tag << endl;
+ return false;
+ }
+ if (! getUMLRole(B)->loadFromXMI(tempElement))
+ return false;
+
+ if (m_pUMLPackage == NULL) {
+ Uml::Model_Type mt = Model_Utils::convert_OT_MT(getObject(B)->getBaseType());
+ m_pUMLPackage = doc->getRootFolder(mt);
+ kDebug() << "UMLAssociation::load: setting model type " << mt << endl;
+ }
+
+ // setting the association type:
+ //
+ // In the old days, we could just record this on the association,
+ // and be done with it. But thats not how the UML13.dtd does things.
+ // As a result, we are checking roleA for information about the
+ // parent association (!) which by this point in the parse, should
+ // be set. However, the information that the roles are allowed to have
+ // is not complete, so we need to finish the analysis here.
+
+ // find self-associations
+ if (m_AssocType == Uml::at_Association && getObjectId(A) == getObjectId(B))
+ m_AssocType = Uml::at_Association_Self;
+
+ // fall-back default type
+ if (m_AssocType == Uml::at_Unknown) {
+ m_AssocType = Uml::at_Association;
+ }
+
+ return true;
+ }
+
+ // From here on it's old-style stuff.
+ QString assocTypeStr = element.attribute( "assoctype", "-1" );
+ Uml::Association_Type assocType = Uml::at_Unknown;
+ if (assocTypeStr[0] >= 'a' && assocTypeStr[0] <= 'z') {
+ // In an earlier version, the natural assoctype names were saved.
+ const QString assocTypeString[nAssocTypes] = {
+ "generalization", // at_Generalization
+ "aggregation", // at_Aggregation
+ "dependency", // at_Dependency
+ "association", // at_Association
+ "associationself", // at_Association_Self
+ "collmessage", // at_Coll_Message
+ "seqmessage", // at_Seq_Message
+ "collmessageself", // at_Coll_Message_Self
+ "seqmessageself", // at_Seq_Message_Self
+ "implementation", // at_Implementation
+ "composition", // at_Composition
+ "realization", // at_Realization
+ "uniassociation", // at_UniAssociation
+ "anchor", // at_Anchor
+ "state", // at_State
+ "activity", // at_Activity
+ "relationship" // at_Relationship
+ };
+
+ unsigned index;
+ for (index = 0; index < nAssocTypes; index++)
+ if (assocTypeStr == assocTypeString[index])
+ break;
+ if (index < nAssocTypes)
+ assocType = (Uml::Association_Type)index;
+ } else {
+ int assocTypeNum = assocTypeStr.toInt();
+ if (assocTypeNum < (int)atypeFirst || assocTypeNum > (int)atypeLast) {
+ kWarning() << "bad assoctype of UML:Association "
+ << ID2STR(getID()) << endl;
+ return false;
+ }
+ assocType = (Uml::Association_Type)assocTypeNum;
+ }
+ setAssocType( assocType );
+
+ Uml::IDType roleAObjID = STR2ID(element.attribute( "rolea", "-1" ));
+ Uml::IDType roleBObjID = STR2ID(element.attribute( "roleb", "-1" ));
+ if (assocType == at_Aggregation || assocType == at_Composition) {
+ // Flip roles to compensate for changed diamond logic in LinePath.
+ // For further explanations see AssociationWidget::loadFromXMI.
+ Uml::IDType tmp = roleAObjID;
+ roleAObjID = roleBObjID;
+ roleBObjID = tmp;
+ }
+
+ UMLObject * objA = doc->findObjectById(roleAObjID);
+ UMLObject * objB = doc->findObjectById(roleBObjID);
+
+ if(objA)
+ getUMLRole(A)->setObject(objA);
+ else
+ return false;
+
+ if(objB)
+ getUMLRole(B)->setObject(objB);
+ else
+ return false;
+
+ setMulti(element.attribute( "multia", "" ), A);
+ setMulti(element.attribute( "multib", "" ), B);
+
+ setRoleName(element.attribute( "namea", "" ), A);
+ setRoleName(element.attribute( "nameb", "" ), B);
+
+ setRoleDoc(element.attribute( "doca", "" ), A);
+ setRoleDoc(element.attribute( "docb", "" ), B);
+
+ // Visibility defaults to Public if it cant set it here..
+ QString visibilityA = element.attribute( "visibilitya", "0");
+ QString visibilityB = element.attribute( "visibilityb", "0");
+ if (visibilityA.toInt() > 0)
+ setVisibility((Uml::Visibility::Value)visibilityA.toInt(), A);
+ if (visibilityB.toInt() > 0)
+ setVisibility((Uml::Visibility::Value)visibilityB.toInt(), B);
+
+ // Changeability defaults to Changeable if it cant set it here..
+ QString changeabilityA = element.attribute( "changeabilitya", "0");
+ QString changeabilityB = element.attribute( "changeabilityb", "0");
+ if (changeabilityA.toInt() > 0)
+ setChangeability ( (Uml::Changeability_Type) changeabilityA.toInt(), A);
+ if (changeabilityB.toInt() > 0)
+ setChangeability ( (Uml::Changeability_Type) changeabilityB.toInt(), B);
+
+ return true;
+}
+
+UMLObject* UMLAssociation::getObject(Uml::Role_Type role) {
+ return m_pRole[role]->getObject();
+}
+
+Uml::IDType UMLAssociation::getObjectId(Uml::Role_Type role) {
+ UMLRole *roleObj = m_pRole[role];
+ UMLObject *o = roleObj->getObject();
+ if (o == NULL) {
+ QString auxID = roleObj->getSecondaryId();
+ if (auxID.isEmpty()) {
+ kError() << "UMLAssociation::getObjectId(" << role
+ << "): getObject returns NULL" << endl;
+ return Uml::id_None;
+ } else {
+ kDebug() << "UMLAssociation::getObjectId(" << role
+ << "): using secondary ID " << auxID << endl;
+ return STR2ID(auxID);
+ }
+ }
+ return o->getID();
+}
+
+/* CURRENTLY UNUSED
+Uml::IDType UMLAssociation::getRoleId(Role_Type role) const {
+ return m_pRole[role]->getID();
+}
+ */
+
+Uml::Changeability_Type UMLAssociation::getChangeability(Uml::Role_Type role) const {
+ return m_pRole[role]->getChangeability();
+}
+
+Uml::Visibility UMLAssociation::getVisibility(Uml::Role_Type role) const {
+ return m_pRole[role]->getVisibility();
+}
+
+QString UMLAssociation::getMulti(Uml::Role_Type role) const {
+ return m_pRole[role]->getMultiplicity();
+}
+
+QString UMLAssociation::getRoleName(Uml::Role_Type role) const {
+ return m_pRole[role]->getName();
+}
+
+QString UMLAssociation::getRoleDoc(Uml::Role_Type role) const {
+ return m_pRole[role]->getDoc();
+}
+
+UMLRole * UMLAssociation::getUMLRole(Uml::Role_Type role) {
+ return m_pRole[role];
+}
+
+void UMLAssociation::setOldLoadMode(bool value /* = true */) {
+ m_bOldLoadMode = value;
+}
+
+bool UMLAssociation::getOldLoadMode() const {
+ return m_bOldLoadMode;
+}
+
+void UMLAssociation::setAssocType(Uml::Association_Type assocType) {
+ m_AssocType = assocType;
+ if(m_AssocType == at_UniAssociation)
+ {
+ // In this case we need to auto-set the multiplicity/rolenames
+ // of the roles
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << " A new uni-association has been created." << endl;
+#endif
+ }
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (! umldoc->loading())
+ emit modified();
+}
+
+void UMLAssociation::setObject(UMLObject *obj, Uml::Role_Type role) {
+ m_pRole[role]->setObject(obj);
+}
+
+void UMLAssociation::setVisibility(Uml::Visibility value, Uml::Role_Type role) {
+ m_pRole[role]->setVisibility(value);
+}
+
+void UMLAssociation::setChangeability(Uml::Changeability_Type value, Uml::Role_Type role) {
+ m_pRole[role]->setChangeability(value);
+}
+
+void UMLAssociation::setMulti(const QString &value, Uml::Role_Type role) {
+ m_pRole[role]->setMultiplicity(value);
+}
+
+void UMLAssociation::setRoleName(const QString &value, Uml::Role_Type role) {
+ m_pRole[role]->setName(value);
+}
+
+void UMLAssociation::setRoleDoc(const QString &doc, Uml::Role_Type role) {
+ m_pRole[role]->setDoc(doc);
+}
+
+QString UMLAssociation::ChangeabilityToString(Uml::Changeability_Type type) {
+ switch (type) {
+ case Uml::chg_Frozen:
+ return "frozen";
+ break;
+ case Uml::chg_AddOnly:
+ return "addOnly";
+ break;
+ case Uml::chg_Changeable:
+ default:
+ return "changeable";
+ break;
+ }
+}
+
+void UMLAssociation::init(Uml::Association_Type type, UMLObject *roleAObj, UMLObject *roleBObj) {
+ m_AssocType = type;
+ m_BaseType = ot_Association;
+ m_Name = "";
+ m_bOldLoadMode = false;
+ nrof_parent_widgets = -1;
+ if (!UMLApp::app()->getDocument()->loading())
+ m_pUMLPackage = UMLApp::app()->getDocument()->currentRoot();
+ m_pRole[Uml::A] = new UMLRole (this, roleAObj, Uml::A);
+ m_pRole[Uml::B] = new UMLRole (this, roleBObj, Uml::B);
+}
+
+
+#include "association.moc"
diff --git a/umbrello/umbrello/association.h b/umbrello/umbrello/association.h
new file mode 100644
index 00000000..3b0ef94d
--- /dev/null
+++ b/umbrello/umbrello/association.h
@@ -0,0 +1,290 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCIATION_H
+#define ASSOCIATION_H
+
+#include <qdom.h>
+#include "umlnamespace.h"
+#include "umlobject.h"
+
+class UMLRole;
+
+/**
+ * This class contains the non-graphic representation of an association.
+ * An association can be a generalization, realization, simple association,
+ * directed association, aggregation, or composition.
+ *
+ * @short Sets up association information.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLAssociation : public UMLObject {
+ Q_OBJECT
+ friend class AssociationWidget;
+public:
+ /**
+ * Sets up an association.
+ * A new unique ID is assigned internally.
+ *
+ * @param type The Uml::Association_Type to construct.
+ * @param roleA Pointer to the UMLObject in role A.
+ * @param roleB Pointer to the UMLObject in role B.
+ */
+ UMLAssociation(Uml::Association_Type type, UMLObject *roleA, UMLObject *roleB);
+
+ /**
+ * Constructs an association - for loading only.
+ * This constructor should not normally be used as it constructs
+ * an incomplete association (i.e. the role objects are missing.)
+ *
+ * @param type The Uml::Association_Type to construct.
+ * Default: Uml::at_Unknown.
+ */
+ UMLAssociation(Uml::Association_Type type = Uml::at_Unknown);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==(UMLAssociation &rhs);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLAssociation();
+
+ /**
+ * Returns a String representation of this UMLAssociation.
+ */
+ QString toString( ) const;
+
+ /**
+ * Converts a Uml::Association_Type to its string representation.
+ *
+ * @param atype The Association_Type enum value to convert.
+ * @return The string representation of the Association_Type.
+ */
+ static QString typeAsString(Uml::Association_Type atype);
+
+ /**
+ * Returns true if the given Association_Type has a representation as a
+ * UMLAssociation.
+ */
+ static bool assocTypeHasUMLRepresentation(Uml::Association_Type atype);
+
+ /**
+ * Returns the Association_Type of the UMLAssociation.
+ *
+ * @return The Association_Type of the UMLAssociation.
+ */
+ Uml::Association_Type getAssocType() const;
+
+ /**
+ * Returns the UMLObject assigned to the given role.
+ *
+ * @return Pointer to the UMLObject in the given role.
+ */
+ UMLObject* getObject(Uml::Role_Type role);
+
+ /**
+ * Returns the ID of the UMLObject assigned to the given role.
+ * Shorthand for getObject(role)->getID().
+ *
+ * @return ID of the UMLObject in the given role.
+ */
+ Uml::IDType getObjectId(Uml::Role_Type role);
+
+ /*
+ * Returns the ID of the UMLObject assigned to the given role.
+ * CURRENTLY UNUSED.
+ *
+ * @return ID of the UMLObject of the given role.
+ Uml::IDType getRoleId(Uml::Role_Type role) const;
+ */
+
+ /**
+ * Returns the Changeablity of the given role.
+ *
+ * @return Changeability_Type of the given role.
+ */
+ Uml::Changeability_Type getChangeability(Uml::Role_Type role) const;
+
+ /**
+ * Returns the Visibility of the given role.
+ *
+ * @return Visibility of the given role.
+ */
+ Uml::Visibility getVisibility(Uml::Role_Type role) const;
+
+ /**
+ * Returns the multiplicity assigned to the given role.
+ *
+ * @return The multiplicity assigned to the given role.
+ */
+ QString getMulti(Uml::Role_Type role) const;
+
+ /**
+ * Returns the name assigned to the role A.
+ *
+ * @return The name assigned to the given role.
+ */
+ QString getRoleName(Uml::Role_Type role) const;
+
+ /**
+ * Returns the documentation assigned to the given role.
+ *
+ * @return Documentation text of given role.
+ */
+ QString getRoleDoc(Uml::Role_Type role) const;
+
+ /**
+ * Sets the assocType of the UMLAssociation.
+ *
+ * @param assocType The Association_Type of the UMLAssociation.
+ */
+ void setAssocType(Uml::Association_Type assocType);
+
+ /**
+ * Sets the UMLObject playing the given role in the association.
+ *
+ * @param obj Pointer to the UMLObject of the given role.
+ * @param role The Uml::Role_Type played by the association
+ */
+ void setObject(UMLObject *obj, Uml::Role_Type role);
+
+ /**
+ * Sets the visibility of the given role of the UMLAssociation.
+ *
+ * @param value Visibility of role.
+ * @param role The Uml::Role_Type to which the visibility is being applied
+ */
+ void setVisibility(Uml::Visibility value, Uml::Role_Type role);
+
+ /**
+ * Sets the changeability of the given role of the UMLAssociation.
+ *
+ * @param value Changeability_Type of the given role.
+ * @param role The Uml::Role_Type to which the changeability is being set
+ */
+ void setChangeability(Uml::Changeability_Type value, Uml::Role_Type role);
+
+ /**
+ * Sets the multiplicity of the given role of the UMLAssociation.
+ *
+ * @param multi The multiplicity of the given role.
+ * @param role The Uml::Role_Type to which the multiplicity is being applied
+ */
+ void setMulti(const QString &multi, Uml::Role_Type role);
+
+ /**
+ * Sets the name of the given role of the UMLAssociation.
+ *
+ * @param roleName The name to set for the given role.
+ * @param role The Uml::Role_Type for which to set the name.
+ */
+ void setRoleName(const QString &roleName, Uml::Role_Type role);
+
+ /**
+ * Sets the documentation on the given role in the association.
+ *
+ * @param doc The string with the documentation.
+ * @param role The Uml::Role_Type to which the documentation is being applied
+ */
+ void setRoleDoc(const QString &doc, Uml::Role_Type role);
+
+ /**
+ * Convert Changeability_Type value into QString representation.
+ *
+ * @param type The Changeability_Type enum value to convert.
+ */
+ static QString ChangeabilityToString(Uml::Changeability_Type type);
+
+ /**
+ * Get the underlying UMLRole object for the given role.
+ *
+ * @return Pointer to the UMLRole object for the given role.
+ */
+ UMLRole * getUMLRole(Uml::Role_Type role);
+
+ /**
+ * Set backward compatibility flag for loading version 1.3.x files.
+ * This flag is necessary because the handling of the isNavigable
+ * attribute of <UML:AssociationEnd> was incorrect.
+ */
+ void setOldLoadMode(bool value = true);
+
+ /**
+ * Return the backward compatibility flag for loading files.
+ */
+ bool getOldLoadMode() const;
+
+ /**
+ * Make a clone of this object.
+ * Cloning associations is not supported yet.
+ */
+ virtual UMLObject* clone() const { return NULL; }
+
+ /**
+ * Resolve types. Required when dealing with foreign XMI files.
+ * Needs to be called after all UML objects are loaded from file.
+ * Overrides the method from UMLObject.
+ * Calls resolveRef() for each role.
+ *
+ * @return True for success.
+ */
+ virtual bool resolveRef();
+
+ /**
+ * Creates the <UML:Generalization> or <UML:Association> XMI element
+ * including its role objects.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Creates the <UML:Generalization> or <UML:Association> XMI element
+ * including its role objects.
+ */
+ bool load(QDomElement& element);
+
+ // keep track of number of parent widgets
+ int nrof_parent_widgets;
+
+ /**
+ * Common initializations at construction time.
+ *
+ * @param type The Association_Type to represent.
+ * @param roleAObj Pointer to the role A UMLObject.
+ * @param roleBObj Pointer to the role B UMLObject.
+ */
+ void init(Uml::Association_Type type, UMLObject *roleAObj, UMLObject *roleBObj);
+
+ /* If the type Uml::Association_Type is changed then also the following
+ must be changed accordingly:
+ atypeFirst, atypeLast, assocTypeStr[], toAssocType(), toString().
+ The ordering within assocTypeStr must match the enumeration
+ order of Uml::Association_Type.
+ */
+ static const Uml::Association_Type atypeFirst;
+ static const Uml::Association_Type atypeLast;
+ static const unsigned int nAssocTypes;
+ static const QString assocTypeStr[];
+
+ UMLRole * m_pRole[2];
+
+ Uml::Association_Type m_AssocType;
+ QString m_Name;
+ bool m_bOldLoadMode;
+};
+
+#endif
diff --git a/umbrello/umbrello/associationwidget.cpp b/umbrello/umbrello/associationwidget.cpp
new file mode 100644
index 00000000..3f2fe0b7
--- /dev/null
+++ b/umbrello/umbrello/associationwidget.cpp
@@ -0,0 +1,3614 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "associationwidget.h"
+// system includes
+#include <cstdlib>
+#include <cmath>
+// qt/kde includes
+#include <qcanvas.h>
+#include <qvalidator.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <kcolordialog.h>
+#include <kapplication.h>
+// app includes
+#include "activitywidget.h"
+#include "uml.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "umlwidget.h"
+#include "messagewidget.h"
+#include "umlrole.h"
+#include "listpopupmenu.h"
+#include "classifierwidget.h"
+#include "classifier.h"
+#include "entity.h"
+#include "attribute.h"
+#include "operation.h"
+#include "association.h"
+#include "assocrules.h"
+#include "floatingtextwidget.h"
+#include "objectwidget.h"
+#include "model_utils.h"
+#include "widget_utils.h"
+#include "dialogs/assocpropdlg.h"
+#include "optionstate.h"
+
+using namespace Uml;
+
+// this constructor really only for loading from XMI, otherwise it
+// is bad..and shouldn't be allowed as it creates an incomplete
+// associationwidget.
+AssociationWidget::AssociationWidget(UMLView *view)
+ : WidgetBase(view)
+{
+ init(view);
+}
+
+// the preferred constructor
+AssociationWidget::AssociationWidget(UMLView *view, UMLWidget* pWidgetA,
+ Uml::Association_Type assocType, UMLWidget* pWidgetB,
+ UMLObject *umlobject /* = NULL */)
+ : WidgetBase(view)
+{
+ init(view);
+ if (umlobject) {
+ setUMLObject(umlobject);
+ } else {
+ // set up UMLAssociation obj if assoc is represented and both roles are UML objects
+ if (UMLAssociation::assocTypeHasUMLRepresentation(assocType)) {
+ UMLObject* umlRoleA = pWidgetA->getUMLObject();
+ UMLObject* umlRoleB = pWidgetB->getUMLObject();
+ if (umlRoleA != NULL && umlRoleB != NULL) {
+ bool swap;
+
+ // THis isnt correct. We could very easily have more than one
+ // of the same type of association between the same two objects.
+ // Just create the association. This search should have been
+ // done BEFORE creation of the widget, if it mattered to the code.
+ // But lets leave check in here for the time being so that debugging
+ // output is shown, in case there is a collision with code elsewhere.
+ UMLAssociation * myAssoc = m_umldoc->findAssociation( assocType, umlRoleA, umlRoleB, &swap );
+ if (myAssoc != NULL) {
+ if (assocType == at_Generalization) {
+ kDebug() << " Ignoring second construction of same generalization"
+ << endl;
+ } else {
+ kDebug() << " constructing a similar or exact same assoc " <<
+ "as an already existing assoc (swap=" << swap << ")" << endl;
+ // now, just create a new association anyways
+ myAssoc = NULL;
+ }
+ }
+ if (myAssoc == NULL)
+ myAssoc = new UMLAssociation( assocType, umlRoleA, umlRoleB );
+ setUMLAssociation(myAssoc);
+ }
+ }
+ }
+
+ setWidget(pWidgetA, A);
+ setWidget(pWidgetB, B);
+
+ setAssocType(assocType);
+
+ calculateEndingPoints();
+
+ //The AssociationWidget is set to Activated because it already has its side widgets
+ setActivated(true);
+
+ // sync UML meta-data to settings here
+ mergeAssociationDataIntoUMLRepresentation();
+
+ // Collaboration messages need a name label because it's that
+ // which lets operator== distinguish them, which in turn
+ // permits us to have more than one message between two objects.
+ if (isCollaboration()) {
+ // Create a temporary name to bring on setName()
+ int collabID = m_pView->generateCollaborationId();
+ setName('m' + QString::number(collabID));
+ }
+}
+
+AssociationWidget::~AssociationWidget() {
+}
+
+AssociationWidget& AssociationWidget::operator=(AssociationWidget & Other) {
+ m_LinePath = Other.m_LinePath;
+
+ m_pView = Other.m_pView;
+
+ if (Other.m_pName) {
+ m_pName = new FloatingTextWidget(m_pView);
+ *m_pName = *(Other.m_pName);
+ } else {
+ m_pName = NULL;
+ }
+
+ for (unsigned r = (unsigned)A; r <= (unsigned)B; r++) {
+ WidgetRole& lhs = m_role[r];
+ const WidgetRole& rhs = Other.m_role[r];
+ lhs.m_nIndex = rhs.m_nIndex;
+ lhs.m_nTotalCount = rhs.m_nTotalCount;
+
+ if (rhs.m_pMulti) {
+ lhs.m_pMulti = new FloatingTextWidget(m_pView);
+ *(lhs.m_pMulti) = *(rhs.m_pMulti);
+ } else {
+ lhs.m_pMulti = NULL;
+ }
+
+ if (rhs.m_pRole) {
+ lhs.m_pRole = new FloatingTextWidget(m_pView);
+ *(lhs.m_pRole) = *(rhs.m_pRole);
+ } else {
+ lhs.m_pRole = NULL;
+ }
+
+ if (rhs.m_pChangeWidget) {
+ lhs.m_pChangeWidget = new FloatingTextWidget(m_pView);
+ *(lhs.m_pChangeWidget) = *(rhs.m_pChangeWidget);
+ } else {
+ lhs.m_pChangeWidget = NULL;
+ }
+
+ lhs.m_pWidget = rhs.m_pWidget;
+ lhs.m_OldCorner = rhs.m_OldCorner;
+ lhs.m_WidgetRegion = rhs.m_WidgetRegion;
+ }
+
+ m_bActivated = Other.m_bActivated;
+ m_unNameLineSegment = Other.m_unNameLineSegment;
+ m_pMenu = Other.m_pMenu;
+ setUMLAssociation(Other.getAssociation());
+ m_bSelected = Other.m_bSelected;
+ m_nMovingPoint = Other.m_nMovingPoint;
+
+ return *this;
+}
+
+bool AssociationWidget::operator==(AssociationWidget & Other) {
+ if( this == &Other )
+ return true;
+
+ if( !m_pObject || !Other.m_pObject ) {
+ if( !Other.m_pObject && m_pObject )
+ return false;
+ if( Other.m_pObject && !m_pObject )
+ return false;
+ } else if( m_pObject != Other.m_pObject )
+ return false;
+
+ if (getAssocType() != Other.getAssocType())
+ return false;
+
+ if (getWidgetID(A) != Other.getWidgetID(A))
+ return false;
+
+ if (getWidgetID(B) != Other.getWidgetID(B))
+ return false;
+
+ if (getWidget(A)->getBaseType() == Uml::wt_Object &&
+ Other.getWidget(A)->getBaseType() == Uml::wt_Object) {
+ ObjectWidget *ownA = static_cast<ObjectWidget*>(getWidget(A));
+ ObjectWidget *otherA = static_cast<ObjectWidget*>(Other.getWidget(A));
+ if (ownA->getLocalID() != otherA->getLocalID())
+ return false;
+ }
+
+ if (getWidget(B)->getBaseType() == Uml::wt_Object &&
+ Other.getWidget(B)->getBaseType() == Uml::wt_Object) {
+ ObjectWidget *ownB = static_cast<ObjectWidget*>(getWidget(B));
+ ObjectWidget *otherB = static_cast<ObjectWidget*>(Other.getWidget(B));
+ if (ownB->getLocalID() != otherB->getLocalID())
+ return false;
+ }
+
+ // Two objects in a collaboration can have multiple messages between each other.
+ // Here we depend on the messages having names, and the names must be different.
+ // That is the reason why collaboration messages have strange initial names like
+ // "m29997" or similar.
+ return (getName() == Other.getName());
+}
+
+bool AssociationWidget::operator!=(AssociationWidget & Other) {
+ return !(*this == Other);
+}
+
+UMLAssociation * AssociationWidget::getAssociation () const {
+ if (m_pObject == NULL || m_pObject->getBaseType() != ot_Association)
+ return NULL;
+ return static_cast<UMLAssociation*>(m_pObject);
+}
+
+UMLAttribute * AssociationWidget::getAttribute () const {
+ if (m_pObject == NULL)
+ return NULL;
+ Uml::Object_Type ot = m_pObject->getBaseType();
+ if (ot != ot_Attribute && ot != ot_EntityAttribute)
+ return NULL;
+ return static_cast<UMLAttribute*>(m_pObject);
+}
+
+FloatingTextWidget* AssociationWidget::getMultiWidget(Uml::Role_Type role) {
+ return m_role[role].m_pMulti;
+}
+
+QString AssociationWidget::getMulti(Uml::Role_Type role) const
+{
+ if (m_role[role].m_pMulti == NULL)
+ return "";
+ return m_role[role].m_pMulti->getText();
+}
+
+FloatingTextWidget* AssociationWidget::getNameWidget()
+{
+ return m_pName;
+}
+
+QString AssociationWidget::getName() const {
+ if (m_pName == NULL)
+ return "";
+ return m_pName->getText();
+}
+
+FloatingTextWidget* AssociationWidget::getRoleWidget(Uml::Role_Type role) {
+ return m_role[role].m_pRole;
+}
+
+FloatingTextWidget* AssociationWidget::getChangeWidget(Uml::Role_Type role) {
+ return m_role[role].m_pChangeWidget;
+}
+
+FloatingTextWidget* AssociationWidget::getTextWidgetByRole(Uml::Text_Role tr) {
+ switch (tr) {
+ case tr_MultiA:
+ return m_role[A].m_pMulti;
+ case tr_MultiB:
+ return m_role[B].m_pMulti;
+ case tr_Name:
+ case tr_Coll_Message:
+ return m_pName;
+ case tr_RoleAName:
+ return m_role[A].m_pRole;
+ case tr_RoleBName:
+ return m_role[B].m_pRole;
+ case tr_ChangeA:
+ return m_role[A].m_pChangeWidget;
+ case tr_ChangeB:
+ return m_role[B].m_pChangeWidget;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+QString AssociationWidget::getRoleName(Uml::Role_Type role) const {
+ if (m_role[role].m_pRole == NULL)
+ return "";
+ return m_role[role].m_pRole->getText();
+}
+
+QString AssociationWidget::getRoleDoc(Uml::Role_Type role) const {
+ if (m_pObject == NULL || m_pObject->getBaseType() != ot_Association)
+ return "";
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_pObject);
+ return umla->getRoleDoc(role);
+}
+
+void AssociationWidget::setName(const QString &strName) {
+ // set attribute of UMLAssociation associated with this associationwidget
+ UMLAssociation *umla = getAssociation();
+ if (umla)
+ umla->setName(strName);
+
+ bool newLabel = false;
+ if(!m_pName) {
+ // Don't construct the FloatingTextWidget if the string is empty.
+ if (! FloatingTextWidget::isTextValid(strName))
+ return;
+
+ newLabel = true;
+ m_pName = new FloatingTextWidget(m_pView, CalculateNameType(tr_Name), strName);
+ m_pName->setLink(this);
+ } else {
+ m_pName->setText(strName);
+ if (! FloatingTextWidget::isTextValid(strName)) {
+ //m_pName->hide();
+ m_pView->removeWidget(m_pName);
+ m_pName = NULL;
+ return;
+ }
+ }
+
+ setTextPosition( tr_Name );
+ if (newLabel) {
+ m_pName->setActivated();
+ m_pView->addWidget(m_pName);
+ }
+
+ m_pName->show();
+}
+
+void AssociationWidget::setFloatingText(Uml::Text_Role tr,
+ const QString &text,
+ FloatingTextWidget* &ft) {
+ if (! FloatingTextWidget::isTextValid(text)) {
+ if (ft) {
+ // Remove preexisting FloatingTextWidget
+ m_pView->removeWidget(ft); // physically deletes ft
+ ft = NULL;
+ }
+ return;
+ }
+
+ if (ft == NULL) {
+ ft = new FloatingTextWidget(m_pView, tr, text);
+ ft->setLink(this);
+ ft->activate();
+ setTextPosition(tr);
+ m_pView->addWidget(ft);
+ } else {
+ bool newLabel = ft->getText().isEmpty();
+ ft->setText(text);
+ if (newLabel)
+ setTextPosition(tr);
+ }
+
+ ft->show();
+}
+
+void AssociationWidget::setMulti(const QString &strMulti, Uml::Role_Type role) {
+ Text_Role tr = (role == A ? tr_MultiA : tr_MultiB);
+
+ setFloatingText(tr, strMulti, m_role[role].m_pMulti);
+
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ getAssociation()->setMulti(strMulti, role);
+}
+
+void AssociationWidget::setRoleName (const QString &strRole, Uml::Role_Type role) {
+ Uml::Association_Type type = getAssocType();
+ //if the association is not supposed to have a Role FloatingTextWidget
+ if (!AssocRules::allowRole(type)) {
+ return;
+ }
+
+ Text_Role tr = (role == A ? tr_RoleAName : tr_RoleBName);
+ setFloatingText(tr, strRole, m_role[role].m_pRole);
+ if (m_role[role].m_pRole) {
+ Uml::Visibility vis = getVisibility(role);
+ if (FloatingTextWidget::isTextValid(m_role[role].m_pRole->getText())) {
+ m_role[role].m_pRole->setPreText(vis.toString(true));
+ //m_role[role].m_pRole->show();
+ } else {
+ m_role[role].m_pRole->setPreText("");
+ //m_role[role].m_pRole->hide();
+ }
+ }
+
+ // set attribute of UMLAssociation associated with this associationwidget
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ getAssociation()->setRoleName(strRole, role);
+}
+
+void AssociationWidget::setRoleDoc (const QString &doc, Uml::Role_Type role) {
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ getAssociation()->setRoleDoc(doc, role);
+ else
+ m_role[role].m_RoleDoc = doc;
+}
+
+void AssociationWidget::setMessageText(FloatingTextWidget *ft) {
+ QString message;
+ if (isCollaboration()) {
+ if (m_pObject != NULL) {
+ message = getMulti(A) + ": " + getOperationText(m_pView);
+ } else {
+ message = getMulti(A) + ": " + getName();
+ }
+ } else {
+ message = getName();
+ }
+ ft->setText(message);
+}
+
+Uml::Visibility AssociationWidget::getVisibility(Uml::Role_Type role) const {
+ const UMLAssociation *assoc = getAssociation();
+ if (assoc)
+ return assoc->getVisibility(role);
+ const UMLAttribute *attr = getAttribute();
+ if (attr)
+ return attr->getVisibility();
+ return m_role[role].m_Visibility;
+}
+
+void AssociationWidget::setVisibility(Uml::Visibility value, Uml::Role_Type role)
+{
+ if (value == getVisibility(role))
+ return;
+ if (m_pObject) {
+ // update our model object
+ const Uml::Object_Type ot = m_pObject->getBaseType();
+ if (ot == ot_Association)
+ getAssociation()->setVisibility(value, role);
+ else if (ot == ot_Attribute)
+ getAttribute()->setVisibility(value);
+ }
+ m_role[role].m_Visibility = value;
+ // update role pre-text attribute as appropriate
+ if (m_role[role].m_pRole) {
+ QString scopeString = value.toString(true);
+ m_role[role].m_pRole->setPreText(scopeString);
+ }
+}
+
+Uml::Changeability_Type AssociationWidget::getChangeability(Uml::Role_Type role) const
+{
+ if (m_pObject == NULL || m_pObject->getBaseType() != ot_Association)
+ return m_role[role].m_Changeability;
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_pObject);
+ return umla->getChangeability(role);
+}
+
+void AssociationWidget::setChangeability (Uml::Changeability_Type value, Uml::Role_Type role)
+{
+ if (value == getChangeability(role))
+ return;
+ QString changeString = UMLAssociation::ChangeabilityToString(value);
+ if (m_pObject && m_pObject->getBaseType() == ot_Association) // update our model object
+ getAssociation()->setChangeability(value, role);
+ m_role[role].m_Changeability = value;
+ // update our string representation
+ setChangeWidget(changeString, role);
+}
+
+void AssociationWidget::setChangeWidget(const QString &strChangeWidget, Uml::Role_Type role) {
+ bool newLabel = false;
+ Text_Role tr = (role == A ? tr_ChangeA : tr_ChangeB);
+
+ if(!m_role[role].m_pChangeWidget) {
+ // Don't construct the FloatingTextWidget if the string is empty.
+ if (strChangeWidget.isEmpty())
+ return;
+
+ newLabel = true;
+ m_role[role].m_pChangeWidget = new FloatingTextWidget(m_pView, tr, strChangeWidget);
+ m_role[role].m_pChangeWidget->setLink(this);
+ m_pView->addWidget(m_role[role].m_pChangeWidget);
+ m_role[role].m_pChangeWidget->setPreText("{"); // all types have this
+ m_role[role].m_pChangeWidget->setPostText("}"); // all types have this
+ } else {
+ if (m_role[role].m_pChangeWidget->getText().isEmpty()) {
+ newLabel = true;
+ }
+ m_role[role].m_pChangeWidget->setText(strChangeWidget);
+ }
+ m_role[role].m_pChangeWidget->setActivated();
+
+ if (newLabel) {
+ setTextPosition( tr );
+ }
+
+ if(FloatingTextWidget::isTextValid(m_role[role].m_pChangeWidget->getText()))
+ m_role[role].m_pChangeWidget -> show();
+ else
+ m_role[role].m_pChangeWidget -> hide();
+}
+
+bool AssociationWidget::linePathStartsAt(const UMLWidget* widget) {
+ QPoint lpStart = m_LinePath.getPoint(0);
+ int startX = lpStart.x();
+ int startY = lpStart.y();
+ int wX = widget->getX();
+ int wY = widget->getY();
+ int wWidth = widget->getWidth();
+ int wHeight = widget->getHeight();
+ bool result = (startX >= wX && startX <= wX + wWidth &&
+ startY >= wY && startY <= wY + wHeight);
+ return result;
+}
+
+void AssociationWidget::setText(FloatingTextWidget *ft, const QString &text) {
+ Uml::Text_Role role = ft->getRole();
+ switch (role) {
+ case tr_Name:
+ setName(text);
+ break;
+ case tr_RoleAName:
+ setRoleName(text, A);
+ break;
+ case tr_RoleBName:
+ setRoleName(text, B);
+ break;
+ case tr_MultiA:
+ setMulti(text, A);
+ break;
+ case tr_MultiB:
+ setMulti(text, B);
+ break;
+ default:
+ break;
+ }
+}
+
+bool AssociationWidget::activate() {
+ if (m_pObject == NULL &&
+ UMLAssociation::assocTypeHasUMLRepresentation(m_AssocType)) {
+ UMLObject *myObj = m_umldoc->findObjectById(m_nId);
+ if (myObj == NULL) {
+ kError() << "AssociationWidget::activate: cannot find UMLObject "
+ << ID2STR(m_nId) << endl;
+ return false;
+ } else {
+ const Uml::Object_Type ot = myObj->getBaseType();
+ if (ot == ot_Association) {
+ UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
+ setUMLAssociation(myAssoc);
+ m_LinePath.setAssocType( myAssoc->getAssocType() );
+ } else {
+ setUMLObject(myObj);
+ setAssocType(m_AssocType);
+ }
+ }
+ }
+
+ if (m_bActivated)
+ return true;
+
+ Uml::Association_Type type = getAssocType();
+
+ if (m_role[A].m_pWidget == NULL)
+ setWidget(m_pView->findWidget(getWidgetID(A)), A);
+ if (m_role[B].m_pWidget == NULL)
+ setWidget(m_pView->findWidget(getWidgetID(B)), B);
+
+ if(!m_role[A].m_pWidget || !m_role[B].m_pWidget) {
+ kDebug() << "Can't make association" << endl;
+ return false;
+ }
+
+ calculateEndingPoints();
+ m_LinePath.activate();
+
+ if (AssocRules::allowRole(type)) {
+ for (unsigned r = A; r <= B; r++) {
+ WidgetRole& robj = m_role[r];
+ if (robj.m_pRole == NULL)
+ continue;
+ robj.m_pRole->setLink(this);
+ Text_Role tr = (r == A ? tr_RoleAName : tr_RoleBName);
+ robj.m_pRole->setRole(tr);
+ Uml::Visibility vis = getVisibility((Uml::Role_Type)r);
+ robj.m_pRole->setPreText(vis.toString(true));
+
+ if (FloatingTextWidget::isTextValid(robj.m_pRole->getText()))
+ robj.m_pRole -> show();
+ else
+ robj.m_pRole -> hide();
+ if (m_pView->getType() == dt_Collaboration)
+ robj.m_pRole->setUMLObject(robj.m_pWidget->getUMLObject());
+ robj.m_pRole->activate();
+ }
+ }
+
+ if( m_pName != NULL ) {
+ m_pName->setLink(this);
+ m_pName->setRole( CalculateNameType(tr_Name) );
+
+ if ( FloatingTextWidget::isTextValid(m_pName->getText()) ) {
+ m_pName-> show();
+ } else {
+ m_pName-> hide();
+ }
+ m_pName->activate();
+ calculateNameTextSegment();
+ }
+
+ for (unsigned r = A; r <= B; r++) {
+ WidgetRole& robj = m_role[r];
+
+ FloatingTextWidget* pMulti = robj.m_pMulti;
+ if (pMulti != NULL &&
+ AssocRules::allowMultiplicity(type, robj.m_pWidget->getBaseType())) {
+ pMulti->setLink(this);
+ Text_Role tr = (r == A ? tr_MultiA : tr_MultiB);
+ pMulti->setRole(tr);
+ if (FloatingTextWidget::isTextValid(pMulti->getText()))
+ pMulti -> show();
+ else
+ pMulti -> hide();
+ pMulti->activate();
+ }
+
+ FloatingTextWidget* pChangeWidget = robj.m_pChangeWidget;
+ if (pChangeWidget != NULL ) {
+ pChangeWidget->setLink(this);
+ Text_Role tr = (r == A ? tr_ChangeA : tr_ChangeB);
+ pChangeWidget->setRole(tr);
+ if (FloatingTextWidget::isTextValid(pChangeWidget->getText()))
+ pChangeWidget -> show();
+ else
+ pChangeWidget -> hide ();
+ pChangeWidget->activate();
+ }
+ }
+
+ // Prepare the association class line if needed.
+ if (m_pAssocClassWidget && !m_pAssocClassLine) {
+ createAssocClassLine();
+ }
+
+ m_bActivated = true;
+ return true;
+}
+
+/** This function calculates which role should be set for the m_pName FloatingTextWidget */
+Uml::Text_Role AssociationWidget::CalculateNameType(Uml::Text_Role defaultRole) {
+
+ Text_Role result = defaultRole;
+ if( m_pView -> getType() == dt_Collaboration ) {
+ if(m_role[A].m_pWidget == m_role[B].m_pWidget) {
+ result = tr_Coll_Message;//for now same as other Coll_Message
+ } else {
+ result = tr_Coll_Message;
+ }
+ } else if( m_pView -> getType() == dt_Sequence ) {
+ if(m_role[A].m_pWidget == m_role[B].m_pWidget) {
+ result = tr_Seq_Message_Self;
+ } else {
+ result = tr_Seq_Message;
+ }
+ }
+
+ return result;
+}
+
+UMLWidget* AssociationWidget::getWidget(Uml::Role_Type role) {
+ return m_role[role].m_pWidget;
+}
+
+bool AssociationWidget::setWidgets( UMLWidget* widgetA,
+ Uml::Association_Type assocType,
+ UMLWidget* widgetB) {
+ //if the association already has a WidgetB or WidgetA associated, then
+ //it cannot be changed to other widget, that would require a deletion
+ //of the association and the creation of a new one
+ if ((m_role[A].m_pWidget && (m_role[A].m_pWidget != widgetA)) ||
+ (m_role[B].m_pWidget && (m_role[B].m_pWidget != widgetB))) {
+ return false;
+ }
+ setWidget(widgetA, A);
+ setAssocType(assocType);
+ setWidget(widgetB, B);
+
+ calculateEndingPoints();
+ return true;
+}
+
+/** Returns true if this association associates WidgetA to WidgetB, otherwise it returns
+ false */
+bool AssociationWidget::checkAssoc(UMLWidget * widgetA, UMLWidget *widgetB) {
+ return (widgetA == m_role[A].m_pWidget && widgetB == m_role[B].m_pWidget);
+}
+
+/** CleansUp all the association's data in the related widgets */
+void AssociationWidget::cleanup() {
+
+ //let any other associations know we are going so they can tidy their positions up
+ if(m_role[A].m_nTotalCount > 2)
+ updateAssociations(m_role[A].m_nTotalCount - 1, m_role[A].m_WidgetRegion, A);
+ if(m_role[B].m_nTotalCount > 2)
+ updateAssociations(m_role[B].m_nTotalCount - 1, m_role[B].m_WidgetRegion, B);
+
+ for (unsigned r = A; r <= B; r++) {
+ WidgetRole& robj = m_role[r];
+
+ if(robj.m_pWidget) {
+ robj.m_pWidget->removeAssoc(this);
+ robj.m_pWidget = 0;
+ }
+ if(robj.m_pRole) {
+ m_pView->removeWidget(robj.m_pRole);
+ robj.m_pRole = 0;
+ }
+ if(robj.m_pMulti) {
+ m_pView->removeWidget(robj.m_pMulti);
+ robj.m_pMulti = 0;
+ }
+ if(robj.m_pChangeWidget) {
+ m_pView->removeWidget(robj.m_pChangeWidget);
+ robj.m_pChangeWidget = 0;
+ }
+ }
+
+ if(m_pName) {
+ m_pView->removeWidget(m_pName);
+ m_pName = 0;
+ }
+
+ if (m_pObject && m_pObject->getBaseType() == ot_Association) {
+ /*
+ We do not remove the UMLAssociation from the document.
+ Why? - Well, for example we might be in the middle of
+ a cut/paste. If the UMLAssociation is removed by the cut
+ then upon pasteing we have a problem.
+ This is not quite clean yet - there should be a way to
+ explicitly delete a UMLAssociation. The Right Thing would
+ be to have a ListView representation for UMLAssociation.
+ `
+ IF we are cut n pasting, why are we handling this association as a pointer?
+ We should be using the XMI representation for a cut and paste. This
+ allows us to be clean here, AND a choice of recreating the object
+ w/ same id IF its a "cut", or a new object if its a "copy" operation
+ (in which case we wouldnt be here, in cleanup()).
+ */
+ setUMLAssociation(0);
+ }
+
+ m_LinePath.cleanup();
+ removeAssocClassLine();
+}
+
+void AssociationWidget::setUMLAssociation (UMLAssociation * assoc)
+{
+ if (m_pObject && m_pObject->getBaseType() == ot_Association) {
+ UMLAssociation *umla = getAssociation();
+
+ // safety check. Did some num-nuts try to set the existing
+ // association again? If so, just bail here
+ if (assoc && umla == assoc)
+ return;
+
+ //umla->disconnect(this); //Qt does disconnect automatically upon destruction.
+ umla->nrof_parent_widgets--;
+
+ // we are the last "owner" of this association, so delete it
+ // from the parent UMLDoc, and as a stand-alone
+ //DISCUSS: Should we really do this?
+ // It implies that an association's existence is ONLY
+ // governed by its existence on at least one diagram.
+ // OTOH, it might be argued that an association should
+ // further exist even when it's (temporarily) not present
+ // on any diagram. This is exactly what cut and paste
+ // relies on (at least the way it's implemented now)
+ // ANSWER: yes, we *should* do this.
+ // This only implies that IF an association once 'belonged'
+ // to one or more parent associationwidgets, then it must 'die' when the
+ // last widget does. UMLAssociations which never had a parent
+ // in the first place wont be affected by this code, and can happily
+ // live on without a parent.
+ //DISCUSS: Sorry Brian, but this breaks cut/paste.
+ // In particular, cut/paste means that the UMLAssociation _does_
+ // have the assocwidget parent - the only means of doing a cut/paste
+ // on the diagram is via the widgets. I.e. in practice there is no
+ // such thing as an "orphan" UMLAssociation.
+ // BTW, IMHO the concept of a widget being the parent of a UML object
+ // is fundamentally flawed. Widgets are pure presentation - they can
+ // come and go at a whim. If at all, the widgets could be considered
+ // children of the corresponding UML object.
+ //
+ // ANSWER: This is the wrong treatment of cut and paste. Associations that
+ // are being cut/n pasted should be serialized to XMI, then reconstituted
+ // (IF a paste operation) rather than passing around object pointers. Its
+ // just too hard otherwise to prevent problems in the code. Bottom line: we need to
+ // delete orphaned associations or we well get code crashes and memory leaks.
+ if (umla->nrof_parent_widgets == 0) {
+ //umla->deleteLater();
+ }
+
+ m_pObject = NULL;
+ }
+
+ if(assoc) {
+ m_pObject = assoc;
+
+ // move counter to "0" from "-1" (which means, no assocwidgets)
+ if(assoc->nrof_parent_widgets < 0)
+ assoc->nrof_parent_widgets = 0;
+
+ assoc->nrof_parent_widgets++;
+ connect(assoc, SIGNAL(modified()), this, SLOT(syncToModel()));
+ }
+
+}
+
+
+/** Returns true if the Widget is either at the starting or ending side of the association */
+bool AssociationWidget::contains(UMLWidget* widget) {
+ return (widget == m_role[A].m_pWidget || widget == m_role[B].m_pWidget);
+}
+
+bool AssociationWidget::isCollaboration() {
+ Uml::Association_Type at = getAssocType();
+ return (at == at_Coll_Message || at == at_Coll_Message_Self);
+}
+
+Uml::Association_Type AssociationWidget::getAssocType() const {
+ if (m_pObject == NULL || m_pObject->getBaseType() != ot_Association)
+ return m_AssocType;
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_pObject);
+ return umla->getAssocType();
+}
+
+/** Sets the association's type */
+void AssociationWidget::setAssocType(Uml::Association_Type type) {
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ getAssociation()->setAssocType(type);
+ m_AssocType = type;
+ m_LinePath.setAssocType(type);
+ // If the association new type is not supposed to have Multiplicity
+ // FloatingTexts and a Role FloatingTextWidget then set the texts
+ // to empty.
+ // NB We do not physically delete the floatingtext widgets here because
+ // those widgets are also stored in the UMLView::m_WidgetList.
+ if( !AssocRules::allowMultiplicity(type, getWidget(A)->getBaseType()) ) {
+ if (m_role[A].m_pMulti) {
+ m_role[A].m_pMulti->setName("");
+ }
+ if (m_role[B].m_pMulti) {
+ m_role[B].m_pMulti->setName("");
+ }
+ }
+ if( !AssocRules::allowRole( type ) ) {
+ if (m_role[A].m_pRole) {
+ m_role[A].m_pRole->setName("");
+ }
+ if (m_role[B].m_pRole) {
+ m_role[B].m_pRole->setName("");
+ }
+ setRoleDoc("", A);
+ setRoleDoc("", B);
+ }
+}
+
+Uml::IDType AssociationWidget::getWidgetID(Uml::Role_Type role) const {
+ if (m_role[role].m_pWidget == NULL) {
+ if (m_pObject && m_pObject->getBaseType() == ot_Association) {
+ UMLAssociation *umla = static_cast<UMLAssociation*>(m_pObject);
+ return umla->getObjectId(role);
+ }
+ kError() << "AssociationWidget::getWidgetID(): m_pWidget is NULL" << endl;
+ return Uml::id_None;
+ }
+ if (m_role[role].m_pWidget->getBaseType() == Uml::wt_Object)
+ return static_cast<ObjectWidget*>(m_role[role].m_pWidget)->getLocalID();
+ Uml::IDType id = m_role[role].m_pWidget->getID();
+ return id;
+}
+
+/** Returns a QString Object representing this AssociationWidget */
+QString AssociationWidget::toString() {
+ QString string = "";
+
+ if(m_role[A].m_pWidget) {
+ string = m_role[A].m_pWidget -> getName();
+ }
+ string.append(":");
+
+ if(m_role[A].m_pRole) {
+ string += m_role[A].m_pRole -> getText();
+ }
+ string.append(":");
+ string.append( UMLAssociation::typeAsString(getAssocType()) );
+ string.append(":");
+ if(m_role[B].m_pWidget) {
+ string += m_role[B].m_pWidget -> getName();
+ }
+
+ string.append(":");
+ if(m_role[B].m_pRole) {
+ string += m_role[B].m_pRole -> getText();
+ }
+
+ return string;
+}
+
+void AssociationWidget::mouseDoubleClickEvent(QMouseEvent * me) {
+ if (me->button() != Qt::RightButton && me->button() != Qt::LeftButton)
+ return;
+ int i = m_LinePath.onLinePath(me->pos());
+ if (i == -1) {
+ m_LinePath.setSelected(false);
+ return;
+ }
+ if (me->button() != Qt::LeftButton)
+ return;
+ const QPoint mp(me->pos());
+ /* if there is no point around the mouse pointer, we insert a new one */
+ if (! m_LinePath.isPoint(i, mp, POINT_DELTA)) {
+ m_LinePath.insertPoint(i + 1, mp);
+ if (m_nLinePathSegmentIndex == i) {
+ QPoint segStart = m_LinePath.getPoint(i);
+ QPoint segEnd = m_LinePath.getPoint(i + 2);
+ const int midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2;
+ const int midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2;
+ /*
+ kDebug() << "AssociationWidget::mouseDoubleClickEvent: "
+ << "segStart=(" << segStart.x() << "," << segStart.y()
+ << "), segEnd=(" << segEnd.x() << "," << segEnd.y()
+ << "), midSeg=(" << midSegX << "," << midSegY
+ << "), mp=(" << mp.x() << "," << mp.y() << ")"
+ << endl;
+ */
+ if (midSegX > mp.x() || midSegY < mp.y()) {
+ m_nLinePathSegmentIndex++;
+ kDebug() << "AssociationWidget::mouseDoubleClickEvent: "
+ << "setting m_nLinePathSegmentIndex to "
+ << m_nLinePathSegmentIndex << endl;
+ computeAssocClassLine();
+ }
+ }
+ } else {
+ /* deselect the line path */
+ m_LinePath.setSelected( false );
+
+ /* there was a point so we remove the point */
+ if (m_LinePath.removePoint(i, mp, POINT_DELTA)) {
+ /* Maybe reattach association class connecting line
+ to different association linepath segment. */
+ const int numberOfLines = m_LinePath.count() - 1;
+ if (m_nLinePathSegmentIndex >= numberOfLines) {
+ m_nLinePathSegmentIndex = numberOfLines - 1;
+ computeAssocClassLine();
+ }
+ }
+
+ /* select the line path */
+ m_LinePath.setSelected( true );
+ }
+
+ m_LinePath.update();
+
+ calculateNameTextSegment();
+ m_umldoc->setModified(true);
+}
+
+void AssociationWidget::moveEvent(QMoveEvent* me) {
+ // 2004-04-30: Achim Spangler
+ // Simple Approach to block moveEvent during load of
+ // XMI
+ /// @todo avoid trigger of this event during load
+ if ( m_umldoc->loading() ) {
+ // hmmh - change of position during load of XMI
+ // -> there is something wrong
+ // -> avoid movement during opening
+ // -> print warn and stay at old position
+ kWarning() << "AssociationWidget::moveEvent() called during load of XMI for ViewType: " << m_pView -> getType()
+ << ", and BaseType: " << getBaseType()
+ << endl;
+ return;
+ }
+ /*to be here a line segment has moved.
+ we need to see if the three text widgets needs to be moved.
+ there are a few things to check first though:
+
+ 1) Do they exist
+ 2) does it need to move:
+ 2a) for the multi widgets only move if they changed region, otherwise they are close enough
+ 2b) for role name move if the segment it is on moves.
+ */
+ //first see if either the first or last segments moved, else no need to recalculate their point positions
+
+ QPoint oldNamePoint = calculateTextPosition(tr_Name);
+ QPoint oldMultiAPoint = calculateTextPosition(tr_MultiA);
+ QPoint oldMultiBPoint = calculateTextPosition(tr_MultiB);
+ QPoint oldChangeAPoint = calculateTextPosition(tr_ChangeA);
+ QPoint oldChangeBPoint = calculateTextPosition(tr_ChangeB);
+ QPoint oldRoleAPoint = calculateTextPosition(tr_RoleAName);
+ QPoint oldRoleBPoint = calculateTextPosition(tr_RoleBName);
+
+ m_LinePath.setPoint( m_nMovingPoint, me->pos() );
+ int pos = m_LinePath.count() - 1;//set to last point for widget b
+
+ if ( m_nMovingPoint == 1 || (m_nMovingPoint == pos-1) ) {
+ calculateEndingPoints();
+ }
+ if (m_role[A].m_pChangeWidget && (m_nMovingPoint == 1)) {
+ setTextPositionRelatively(tr_ChangeA, oldChangeAPoint);
+ }
+ if (m_role[B].m_pChangeWidget && (m_nMovingPoint == 1)) {
+ setTextPositionRelatively(tr_ChangeB, oldChangeBPoint);
+ }
+ if (m_role[A].m_pMulti && (m_nMovingPoint == 1)) {
+ setTextPositionRelatively(tr_MultiA, oldMultiAPoint);
+ }
+ if (m_role[B].m_pMulti && (m_nMovingPoint == pos-1)) {
+ setTextPositionRelatively(tr_MultiB, oldMultiBPoint);
+ }
+
+ if (m_pName) {
+ if(m_nMovingPoint == (int)m_unNameLineSegment ||
+ m_nMovingPoint - 1 == (int)m_unNameLineSegment) {
+ setTextPositionRelatively(tr_Name, oldNamePoint);
+ }
+ }
+
+ if (m_role[A].m_pRole) {
+ setTextPositionRelatively(tr_RoleAName, oldRoleAPoint);
+ }
+ if (m_role[B].m_pRole) {
+ setTextPositionRelatively(tr_RoleBName, oldRoleBPoint);
+ }
+}
+
+
+/** Calculates and sets the first and last point in the Association's LinePath
+ Each point is a middle point of its respecting UMLWidget's Bounding rectangle
+ or a corner of it
+ This method picks which sides to use for the association */
+void AssociationWidget::calculateEndingPoints() {
+ /*
+ * For each UMLWidget the diagram is divided in four regions by its diagonals
+ * as indicated below
+ * Region 2
+ * \ /
+ * \ /
+ * +--------+
+ * | \ / |
+ * Region 1 | >< | Region 3
+ * | / \ |
+ * +--------+
+ * / \
+ * / \
+ * Region 4
+ *
+ * Each diagonal is defined by two corners of the bounding rectangle
+ *
+ * To calculate the first point in the LinePath we have to find out in which
+ * Region (defined by WidgetA's diagonals) is WidgetB's center
+ * (let's call it Region M.) After that the first point will be the middle
+ * point of the rectangle's side contained in Region M.
+ *
+ * To calculate the last point in the LinePath we repeat the above but
+ * in the opposite direction (from widgetB to WidgetA)
+ */
+
+ UMLWidget *pWidgetA = m_role[A].m_pWidget;
+ UMLWidget *pWidgetB = m_role[B].m_pWidget;
+ if (!pWidgetA || !pWidgetB)
+ return;
+ m_role[A].m_OldCorner.setX( pWidgetA->getX() );
+ m_role[A].m_OldCorner.setY( pWidgetA->getY() );
+ m_role[B].m_OldCorner.setX( pWidgetB->getX() );
+ m_role[B].m_OldCorner.setY( pWidgetB->getY() );
+ uint size = m_LinePath.count();
+ if(size < 2)
+ m_LinePath.setStartEndPoints( m_role[A].m_OldCorner, m_role[B].m_OldCorner );
+
+ // See if an association to self.
+ // See if it needs to be set up before we continue:
+ // If self association/message and doesn't have the minimum 4 points
+ // then create it. Make sure no points are out of bounds of viewing area.
+ // This only happens on first time through that we are worried about.
+ if (pWidgetA == pWidgetB && size < 4) {
+ const int DISTANCE = 50;
+ int x = pWidgetA -> getX();
+ int y = pWidgetA -> getY();
+ int h = pWidgetA -> getHeight();
+ int w = pWidgetA -> getWidth();
+ //see if above widget ok to start
+ if( y - DISTANCE > 0 ) {
+ m_LinePath.setStartEndPoints( QPoint( x + w / 4, y ) , QPoint( x + w * 3 / 4, y ) );
+ m_LinePath.insertPoint( 1, QPoint( x + w / 4, y - DISTANCE ) );
+ m_LinePath.insertPoint( 2 ,QPoint( x + w * 3 / 4, y - DISTANCE ) );
+ m_role[A].m_WidgetRegion = m_role[B].m_WidgetRegion = North;
+ } else {
+ m_LinePath.setStartEndPoints( QPoint( x + w / 4, y + h ), QPoint( x + w * 3 / 4, y + h ) );
+ m_LinePath.insertPoint( 1, QPoint( x + w / 4, y + h + DISTANCE ) );
+ m_LinePath.insertPoint( 2, QPoint( x + w * 3 / 4, y + h + DISTANCE ) );
+ m_role[A].m_WidgetRegion = m_role[B].m_WidgetRegion = South;
+ }
+ return;
+ }//end a == b
+
+ // If the line has more than one segment change the values to calculate
+ // from widget to point 1.
+ int xB = pWidgetB->getX() + pWidgetB->getWidth() / 2;
+ int yB = pWidgetB->getY() + pWidgetB->getHeight() / 2;
+ if( size > 2 ) {
+ QPoint p = m_LinePath.getPoint( 1 );
+ xB = p.x();
+ yB = p.y();
+ }
+ doUpdates(xB, yB, A);
+
+ // Now do the same for widgetB.
+ // If the line has more than one segment change the values to calculate
+ // from widgetB to the last point away from it.
+ int xA = pWidgetA->getX() + pWidgetA->getWidth() / 2;
+ int yA = pWidgetA->getY() + pWidgetA->getHeight() / 2;
+ if (size > 2 ) {
+ QPoint p = m_LinePath.getPoint( size - 2 );
+ xA = p.x();
+ yA = p.y();
+ }
+ doUpdates( xA, yA, B );
+
+ computeAssocClassLine();
+}
+
+void AssociationWidget::doUpdates(int otherX, int otherY, Uml::Role_Type role) {
+ // Find widget region.
+ Region oldRegion = m_role[role].m_WidgetRegion;
+ UMLWidget *pWidget = m_role[role].m_pWidget;
+ QRect rc(pWidget->getX(), pWidget->getY(),
+ pWidget->getWidth(), pWidget->getHeight());
+ Region& region = m_role[role].m_WidgetRegion; // alias for brevity
+ region = findPointRegion( rc, otherX, otherY);
+ // Move some regions to the standard ones.
+ switch( region ) {
+ case NorthWest:
+ region = North;
+ break;
+ case NorthEast:
+ region = East;
+ break;
+ case SouthEast:
+ region = South;
+ break;
+ case SouthWest:
+ case Center:
+ region = West;
+ break;
+ default:
+ break;
+ }
+ int regionCount = getRegionCount(region, role) + 2;//+2 = (1 for this one and one to halve it)
+ int totalCount = m_role[role].m_nTotalCount;
+ if( oldRegion != region ) {
+ updateRegionLineCount( regionCount - 1, regionCount, region, role );
+ updateAssociations( totalCount - 1, oldRegion, role );
+ } else if( totalCount != regionCount ) {
+ updateRegionLineCount( regionCount - 1, regionCount, region, role );
+ } else {
+ updateRegionLineCount( m_role[role].m_nIndex, totalCount, region, role );
+ }
+ updateAssociations( regionCount, region, role );
+}
+
+/** Read property of bool m_bActivated. */
+bool AssociationWidget::isActivated() {
+ return m_bActivated;
+}
+
+/** Set the m_bActivated flag of a widget but does not perform the Activate method */
+void AssociationWidget::setActivated(bool active /*=true*/) {
+ m_bActivated = active;
+}
+
+void AssociationWidget::syncToModel()
+{
+ UMLAssociation *uml = getAssociation();
+
+ if (uml == NULL) {
+ UMLAttribute *attr = getAttribute();
+ if (attr == NULL)
+ return;
+ setVisibility(attr->getVisibility(), B);
+ setRoleName(attr->getName(), B);
+ return;
+ }
+ // block signals until finished
+ uml->blockSignals(true);
+
+ setName(uml->getName());
+ setRoleName(uml->getRoleName(A), A);
+ setRoleName(uml->getRoleName(B), B);
+ setVisibility(uml->getVisibility(A), A);
+ setVisibility(uml->getVisibility(B), B);
+ setChangeability(uml->getChangeability(A), A);
+ setChangeability(uml->getChangeability(B), B);
+ setMulti(uml->getMulti(A), A);
+ setMulti(uml->getMulti(B), B);
+
+ uml->blockSignals(false);
+}
+
+// this will synchronize UMLAssociation w/ this new Widget
+void AssociationWidget::mergeAssociationDataIntoUMLRepresentation()
+{
+ UMLAssociation *umlassoc = getAssociation();
+ UMLAttribute *umlattr = getAttribute();
+ if (umlassoc == NULL && umlattr == NULL)
+ return;
+
+ // block emit modified signal, or we get a horrible loop
+ m_pObject->blockSignals(true);
+
+ // would be desirable to do the following
+ // so that we can be sure its back to initial state
+ // in case we missed something here.
+ //uml->init();
+
+ // floating text widgets
+ FloatingTextWidget *text = getNameWidget();
+ if (text)
+ m_pObject->setName(text->getText());
+
+ text = getRoleWidget(A);
+ if (text && umlassoc)
+ umlassoc->setRoleName(text->getText(), A);
+
+ text = getRoleWidget(B);
+ if (text) {
+ if (umlassoc)
+ umlassoc->setRoleName(text->getText(), B);
+ else if (umlattr)
+ umlattr->setName(text->getText());
+ }
+
+ text = getMultiWidget(A);
+ if (text && umlassoc)
+ umlassoc->setMulti(text->getText(), A);
+
+ text = getMultiWidget(B);
+ if (text && umlassoc)
+ umlassoc->setMulti(text->getText(), B);
+
+ // unblock
+ m_pObject->blockSignals(false);
+}
+
+void AssociationWidget::saveIdealTextPositions() {
+ m_oldNamePoint = calculateTextPosition(tr_Name);
+ m_oldMultiAPoint = calculateTextPosition(tr_MultiA);
+ m_oldMultiBPoint = calculateTextPosition(tr_MultiB);
+ m_oldChangeAPoint = calculateTextPosition(tr_ChangeA);
+ m_oldChangeBPoint = calculateTextPosition(tr_ChangeB);
+ m_oldRoleAPoint = calculateTextPosition(tr_RoleAName);
+ m_oldRoleBPoint = calculateTextPosition(tr_RoleBName);
+}
+
+/** Adjusts the ending point of the association that connects to Widget */
+void AssociationWidget::widgetMoved(UMLWidget* widget, int x, int y ) {
+ // 2004-04-30: Achim Spangler
+ // Simple Approach to block moveEvent during load of
+ // XMI
+ /// @todo avoid trigger of this event during load
+ if ( m_umldoc->loading() ) {
+ // hmmh - change of position during load of XMI
+ // -> there is something wrong
+ // -> avoid movement during opening
+ // -> print warn and stay at old position
+ kDebug() << "AssociationWidget::widgetMoved() called during load of XMI for ViewType: " << m_pView -> getType()
+ << ", and BaseType: " << getBaseType()
+ << endl;
+ return;
+ }
+
+ int dx = m_role[A].m_OldCorner.x() - x;
+ int dy = m_role[A].m_OldCorner.y() - y;
+ uint size = m_LinePath.count();
+ uint pos = size - 1;
+ calculateEndingPoints();
+
+ // Assoc to self - move all points:
+ if( m_role[A].m_pWidget == m_role[B].m_pWidget ) {
+ for( int i=1 ; i < (int)pos ; i++ ) {
+ QPoint p = m_LinePath.getPoint( i );
+ int newX = p.x() - dx;
+ int newY = p.y() - dy;
+ // safety. We DON'T want to go off the screen
+ if(newX < 0)
+ newX = 0;
+ // safety. We DON'T want to go off the screen
+ if(newY < 0)
+ newY = 0;
+ newX = m_pView -> snappedX( newX );
+ newY = m_pView -> snappedY( newY );
+ p.setX( newX );
+ p.setY( newY );
+ m_LinePath.setPoint( i, p );
+ }
+
+ if ( m_pName && !m_pName->getSelected() ) {
+ setTextPositionRelatively(tr_Name, m_oldNamePoint);
+ }
+
+ }//end if widgetA = widgetB
+ else if (m_role[A].m_pWidget==widget) {
+ if (m_pName && m_unNameLineSegment == 0 && !m_pName->getSelected() ) {
+ //only calculate position and move text if the segment it is on is moving
+ setTextPositionRelatively(tr_Name, m_oldNamePoint);
+ }
+ }//end if widgetA moved
+ else if (m_role[B].m_pWidget==widget) {
+ if (m_pName && (m_unNameLineSegment == pos-1) && !m_pName->getSelected() ) {
+ //only calculate position and move text if the segment it is on is moving
+ setTextPositionRelatively(tr_Name, m_oldNamePoint);
+ }
+ }//end if widgetB moved
+
+ if ( m_role[A].m_pRole && !m_role[A].m_pRole->getSelected() ) {
+ setTextPositionRelatively(tr_RoleAName, m_oldRoleAPoint);
+ }
+ if ( m_role[B].m_pRole && !m_role[B].m_pRole->getSelected() ) {
+ setTextPositionRelatively(tr_RoleBName, m_oldRoleBPoint);
+ }
+ if ( m_role[A].m_pMulti && !m_role[A].m_pMulti->getSelected() ) {
+ setTextPositionRelatively(tr_MultiA, m_oldMultiAPoint);
+ }
+ if ( m_role[B].m_pMulti && !m_role[B].m_pMulti->getSelected() ) {
+ setTextPositionRelatively(tr_MultiB, m_oldMultiBPoint);
+ }
+ if ( m_role[A].m_pChangeWidget && !m_role[A].m_pChangeWidget->getSelected() ) {
+ setTextPositionRelatively(tr_ChangeA, m_oldChangeAPoint);
+ }
+ if ( m_role[B].m_pChangeWidget && !m_role[B].m_pChangeWidget->getSelected() ) {
+ setTextPositionRelatively(tr_ChangeB, m_oldChangeBPoint);
+ }
+}//end method widgetMoved
+
+/** Finds out in which region of rectangle Rect contains the Point (PosX, PosY) and returns the region
+ number:
+ 1 = Region 1
+ 2 = Region 2
+ 3 = Region 3
+ 4 = Region 4
+ 5 = On diagonal 2 between Region 1 and 2
+ 6 = On diagonal 1 between Region 2 and 3
+ 7 = On diagonal 2 between Region 3 and 4
+ 8 = On diagonal 1 between Region 4 and 1
+ 9 = On diagonal 1 and On diagonal 2 (the center)
+*/
+AssociationWidget::Region AssociationWidget::findPointRegion(const QRect& Rect, int PosX, int PosY) {
+ float w = (float)Rect.width();
+ float h = (float)Rect.height();
+ float x = (float)Rect.x();
+ float y = (float)Rect.y();
+ float Slope2 = w / h;
+ float Slope1 = Slope2*(float)(-1);
+ float b1 = x + w - ( Slope1* y );
+ float b2 = x - ( Slope2* y );
+
+ float eval1 = Slope1 * (float)PosY + b1;
+ float eval2 = Slope2 *(float)PosY + b2;
+
+ Region result = Error;
+ //if inside region 1
+ if(eval1 > PosX && eval2 > PosX) {
+ result = West;
+ }
+ //if inside region 2
+ else if (eval1 > PosX && eval2 < PosX) {
+ result = North;
+ }
+ //if inside region 3
+ else if (eval1 < PosX && eval2 < PosX) {
+ result = East;
+ }
+ //if inside region 4
+ else if (eval1 < PosX && eval2 > PosX) {
+ result = South;
+ }
+ //if inside region 5
+ else if (eval1 == PosX && eval2 < PosX) {
+ result = NorthWest;
+ }
+ //if inside region 6
+ else if (eval1 < PosX && eval2 == PosX) {
+ result = NorthEast;
+ }
+ //if inside region 7
+ else if (eval1 == PosX && eval2 > PosX) {
+ result = SouthEast;
+ }
+ //if inside region 8
+ else if (eval1 > PosX && eval2 == PosX) {
+ result = SouthWest;
+ }
+ //if inside region 9
+ else if (eval1 == PosX && eval2 == PosX) {
+ result = Center;
+ }
+ return result;
+}
+
+QPoint AssociationWidget::swapXY(const QPoint &p) {
+ QPoint swapped( p.y(), p.x() );
+ return swapped;
+}
+
+/* Returns the total length of the association's LinePath:
+ result = segment_1_length + segment_2_length + ..... + segment_n_length
+ */
+float AssociationWidget::totalLength() {
+ uint size = m_LinePath.count();
+ float total_length = 0;
+
+ for(uint i = 0; i < size - 1; i++) {
+ QPoint pi = m_LinePath.getPoint( i );
+ QPoint pj = m_LinePath.getPoint( i+1 );
+ int xi = pi.y();
+ int xj = pj.y();
+ int yi = pi.x();
+ int yj = pj.x();
+ total_length += sqrt( double(((xj - xi)*(xj - xi)) + ((yj - yi)*(yj - yi))) );
+ }
+
+ return total_length;
+}
+
+
+/** Calculates which point of segment P1P2 has a distance equal to Distance from P1,
+ Lets say such point is P3, the distance from P1 to P3 must be equal to Distance
+ and if P3 is not a point of the segment P1P2 then the function returns (-1,-1)
+*/
+QPoint AssociationWidget::calculatePointAtDistance(const QPoint &P1, const QPoint &P2, float Distance) {
+ /*
+ the distance D between points (x1, y1) and (x3, y3) has the following formula:
+ --- ------------------------------
+ D = \ / 2 2
+ \ / (x3 - x1) + (y3 - y1)
+
+ D, x1 and y1 are known and the point (x3, y3) is inside line (x1,y1)(x2,y2), so if the
+ that line has the formula y = mx + b
+ then y3 = m*x3 + b
+
+ 2 2 2
+ D = (x3 - x1) + (y3 - y1)
+
+ 2 2 2 2 2
+ D = x3 - 2*x3*x1 + x1 + y3 - 2*y3*y1 + y1
+
+ 2 2 2 2 2
+ D - x1 - y1 = x3 - 2*x3*x1 + y3 - 2*y3*y1
+
+ 2 2 2 2 2
+ D - x1 - y1 = x3 - 2*x3*x1 + (m*x3 + b) - 2*(m*x3 + b)*y1
+
+ 2 2 2 2 2 2
+ D - x1 - y1 + 2*b*y1 - b = (m + 1)*x3 + (-2*x1 + 2*m*b -2*m*y1)*x3
+
+ 2 2 2 2
+ C = - D + x1 + y1 - 2*b*y1 + b
+
+
+ 2
+ A = (m + 1)
+
+ B = (-2*x1 + 2*m*b -2*m*y1)
+
+ and we have
+ 2
+ A * x3 + B * x3 - C = 0
+
+ ---------------
+ -B + --- / 2
+ \/ B - 4*A*C
+ sol_1 = --------------------------------
+ 2*A
+
+
+ ---------------
+ -B - --- / 2
+ \/ B - 4*A*C
+ sol_2 = --------------------------------
+ 2*A
+
+
+ then in the distance formula we have only one variable x3 and that is easy
+ to calculate
+ */
+ int x1 = P1.y();
+ int y1 = P1.x();
+ int x2 = P2.y();
+ int y2 = P2.x();
+
+ if(x2 == x1) {
+ return QPoint(x1, y1 + (int)Distance);
+ }
+ float slope = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);
+ float b = (y1 - slope*x1);
+ float A = (slope * slope) + 1;
+ float B = (2*slope*b) - (2*x1) - (2*slope*y1);
+ float C = (b*b) - (Distance*Distance) + (x1*x1) + (y1*y1) - (2*b*y1);
+ float t = B*B - 4*A*C;
+
+ if(t < 0) {
+ return QPoint(-1, -1);
+ }
+ float sol_1 = ((-1* B) + sqrt(t) ) / (2*A);
+ float sol_2 = ((-1*B) - sqrt(t) ) / (2*A);
+
+ if(sol_1 < 0.0 && sol_2 < 0.0) {
+ return QPoint(-1, -1);
+ }
+ QPoint sol1Point((int)(slope*sol_1 + b), (int)(sol_1));
+ QPoint sol2Point((int)(slope*sol_2 + b), (int)(sol_2));
+ if(sol_1 < 0 && sol_2 >=0) {
+ if(x2 > x1) {
+ if(x1 <= sol_2 && sol_2 <= x2)
+ return sol2Point;
+ } else {
+ if(x2 <= sol_2 && sol_2 <= x1)
+ return sol2Point;
+ }
+ } else if(sol_1 >= 0 && sol_2 < 0) {
+ if(x2 > x1) {
+ if(x1 <= sol_1 && sol_1 <= x2)
+ return sol1Point;
+ } else {
+ if(x2 <= sol_1 && sol_1 <= x1)
+ return sol1Point;
+ }
+ } else {
+ if(x2 > x1) {
+ if(x1 <= sol_1 && sol_1 <= x2)
+ return sol1Point;
+ if(x1 <= sol_2 && sol_2 <= x2)
+ return sol2Point;
+ } else {
+ if(x2 <= sol_1 && sol_1 <= x1)
+ return sol1Point;
+ if(x2 <= sol_2 && sol_2 <= x1)
+ return sol2Point;
+ }
+ }
+ return QPoint(-1, -1);
+}
+
+/** Calculates which point of a perpendicular line to segment P1P2 that contains P2
+ has a distance equal to Distance from P2,
+ Lets say such point is P3, the distance from P2 to P3 must be equal to Distance
+*/
+QPoint AssociationWidget::calculatePointAtDistanceOnPerpendicular(const QPoint &P1, const QPoint &P2, float Distance) {
+ /*
+ the distance D between points (x2, y2) and (x3, y3) has the following formula:
+
+ --- ------------------------------
+ D = \ / 2 2
+ \ / (x3 - x2) + (y3 - y2)
+
+ D, x2 and y2 are known and line P2P3 is perpendicular to line (x1,y1)(x2,y2), so if the
+ line P1P2 has the formula y = m*x + b,
+ then (x1 - x2)
+ m = ----------- , because it is perpendicular to line P1P2
+ (y2 - y1)
+
+ also y2 = m*x2 + b
+ => b = y2 - m*x2
+
+ then P3 = (x3, m*x3 + b)
+
+ 2 2 2
+ D = (x3 - x2) + (y3 - y2)
+
+ 2 2 2 2 2
+ D = x3 - 2*x3*x2 + x2 + y3 - 2*y3*y2 + y2
+
+ 2 2 2 2 2
+ D - x2 - y2 = x3 - 2*x3*x2 + y3 - 2*y3*y2
+
+
+
+ 2 2 2 2 2
+ D - x2 - y2 = x3 - 2*x3*x2 + (m*x3 + b) - 2*(m*x3 + b)*y2
+
+ 2 2 2 2 2 2
+ D - x2 - y2 + 2*b*y2 - b = (m + 1)*x3 + (-2*x2 + 2*m*b -2*m*y2)*x3
+
+ 2 2 2 2
+ C = - D + x2 + y2 - 2*b*y2 + b
+
+ 2
+ A = (m + 1)
+
+ B = (-2*x2 + 2*m*b -2*m*y2)
+
+ and we have
+ 2
+ A * x3 + B * x3 - C = 0
+
+
+ ---------------
+ --- / 2
+ -B + \/ B - 4*A*C
+ sol_1 = --------------------------------
+ 2*A
+
+
+ ---------------
+ --- / 2
+ -B - \/ B - 4*A*C
+ sol_2 = --------------------------------
+ 2*A
+
+ then in the distance formula we have only one variable x3 and that is easy
+ to calculate
+ */
+ if (P1.x() == P2.x()) {
+ return QPoint((int)(P2.x() + Distance), P2.y());
+ }
+ const int x1 = P1.y();
+ const int y1 = P1.x();
+ const int x2 = P2.y();
+ const int y2 = P2.x();
+
+ float slope = ((float)x1 - (float)x2) / ((float)y2 - (float)y1);
+ float b = (y2 - slope*x2);
+ float A = (slope * slope) + 1;
+ float B = (2*slope*b) - (2*x2) - (2*slope*y2);
+ float C = (b*b) - (Distance*Distance) + (x2*x2) + (y2*y2) - (2*b*y2);
+ float t = B*B - 4*A*C;
+ if (t < 0) {
+ return QPoint(-1, -1);
+ }
+ float sol_1 = ((-1* B) + sqrt(t) ) / (2*A);
+
+ float sol_2 = ((-1*B) - sqrt(t) ) / (2*A);
+
+ if(sol_1 < 0 && sol_2 < 0) {
+ return QPoint(-1, -1);
+ }
+ QPoint sol1Point((int)(slope*sol_1 + b), (int)sol_1);
+ QPoint sol2Point((int)(slope*sol_2 + b), (int)sol_2);
+ if(sol_1 < 0 && sol_2 >=0) {
+ return sol2Point;
+ } else if(sol_1 >= 0 && sol_2 < 0) {
+ return sol1Point;
+ } else { // Choose one solution , either will work fine
+ if(slope >= 0) {
+ if(sol_1 <= sol_2)
+ return sol2Point;
+ else
+ return sol1Point;
+ } else {
+ if(sol_1 <= sol_2)
+ return sol1Point;
+ else
+ return sol2Point;
+ }
+
+ }
+ return QPoint(-1, -1); // never reached, just keep compilers happy
+}
+
+/** Calculates the intersection (PS) between line P1P2 and a perpendicular line containing
+ P3, the result is returned in ResultingPoint. and result value represents the distance
+ between ResultingPoint and P3; if this value is negative an error ocurred. */
+float AssociationWidget::perpendicularProjection(const QPoint& P1, const QPoint& P2, const QPoint& P3,
+ QPoint& ResultingPoint) {
+ //line P1P2 is Line 1 = y=slope1*x + b1
+
+ //line P3PS is Line 1 = y=slope2*x + b2
+
+ float slope2 = 0;
+ float slope1 = 0;
+ float sx = 0, sy = 0;
+ int y2 = P2.x();
+ int y1 = P1.x();
+ int x2 = P2.y();
+ int x1 = P1.y();
+ int y3 = P3.x();
+ int x3 = P3.y();
+ float distance = 0;
+ float b1 = 0;
+
+ float b2 = 0;
+
+ if(x2 == x1) {
+ sx = x2;
+ sy = y3;
+ } else if(y2 == y1) {
+ sy = y2;
+ sx = x3;
+ } else {
+ slope1 = (y2 - y1)/ (x2 - x1);
+ slope2 = (x1 - x2)/ (y2 - y1);
+ b1 = y2 - (slope1 * x2);
+ b2 = y3 - (slope2 * x3);
+ sx = (b2 - b1) / (slope1 - slope2);
+ sy = slope1*sx + b1;
+ }
+ distance = (int)( sqrt( ((x3 - sx)*(x3 - sx)) + ((y3 - sy)*(y3 - sy)) ) );
+
+ ResultingPoint.setX( (int)sy );
+ ResultingPoint.setY( (int)sx );
+
+ return distance;
+}
+
+QPoint AssociationWidget::calculateTextPosition(Uml::Text_Role role) {
+ const int SPACE = 2;
+ QPoint p(-1, -1), q(-1, -1);
+
+ // used to find out if association end point (p)
+ // is at top or bottom edge of widget.
+ bool is_top_or_bottom(false);
+ UMLWidget *pWidget(0);
+
+ if (role == tr_MultiA || role == tr_ChangeA || role == tr_RoleAName) {
+ p = m_LinePath.getPoint( 0 );
+ q = m_LinePath.getPoint( 1 );
+ pWidget = m_role[A].m_pWidget;
+ } else if (role == tr_MultiB || role == tr_ChangeB || role == tr_RoleBName) {
+ const uint lastSegment = m_LinePath.count() - 1;
+ p = m_LinePath.getPoint(lastSegment);
+ q = m_LinePath.getPoint(lastSegment - 1);
+ pWidget = m_role[B].m_pWidget;
+ } else if (role != tr_Name) {
+ kError() << "AssociationWidget::calculateTextPosition called with unsupported Text_Role "
+ << role << endl;
+ return QPoint(-1, -1);
+ }
+
+ if ( pWidget && ( pWidget->getY() == p.y() || pWidget->getY() + pWidget->height() == p.y() ))
+ is_top_or_bottom = true;
+
+ FloatingTextWidget *text = getTextWidgetByRole(role);
+ int textW = 0, textH = 0;
+ if (text) {
+ textW = text->width();
+ textH = text->height();
+ }
+
+ int x = 0, y = 0;
+
+ if (role == tr_MultiA || role == tr_MultiB) {
+ const bool isHorizontal = (p.y() == q.y());
+ const int atBottom = p.y() + SPACE;
+ const int atTop = p.y() - SPACE - textH;
+ const int atLeft = p.x() - SPACE - textW;
+ const int atRight = p.x() + SPACE;
+ y = (p.y() > q.y()) == isHorizontal ? atBottom : atTop;
+ x = (p.x() < q.x()) == isHorizontal ? atRight : atLeft;
+
+ } else if (role == tr_ChangeA || role == tr_ChangeB) {
+
+ if( p.y() > q.y() )
+ y = p.y() - SPACE - (textH * 2);
+ else
+ y = p.y() + SPACE + textH;
+
+ if( p.x() < q.x() )
+ x = p.x() + SPACE;
+ else
+ x = p.x() - SPACE - textW;
+
+ } else if (role == tr_RoleAName || role == tr_RoleBName) {
+
+ if( p.y() > q.y() )
+ y = p.y() - SPACE - textH;
+ else
+ y = p.y() + SPACE;
+
+ if( p.x() < q.x() )
+ x = p.x() + SPACE;
+ else
+ x = p.x() - SPACE - textW;
+
+ } else if (role == tr_Name) {
+
+ calculateNameTextSegment();
+ x = (int)( ( m_LinePath.getPoint(m_unNameLineSegment).x() +
+ m_LinePath.getPoint(m_unNameLineSegment + 1).x() ) / 2 );
+
+ y = (int)( ( m_LinePath.getPoint(m_unNameLineSegment).y() +
+ m_LinePath.getPoint(m_unNameLineSegment + 1).y() ) / 2 );
+ }
+
+ if (text) {
+ constrainTextPos(x, y, textW, textH, role);
+ }
+ p = QPoint( x, y );
+ return p;
+}
+
+QPoint AssociationWidget::midPoint(const QPoint& p0, const QPoint& p1) {
+ QPoint midP;
+ if (p0.x() < p1.x())
+ midP.setX(p0.x() + (p1.x() - p0.x()) / 2);
+ else
+ midP.setX(p1.x() + (p0.x() - p1.x()) / 2);
+ if (p0.y() < p1.y())
+ midP.setY(p0.y() + (p1.y() - p0.y()) / 2);
+ else
+ midP.setY(p1.y() + (p0.y() - p1.y()) / 2);
+ return midP;
+}
+
+void AssociationWidget::constrainTextPos(int &textX, int &textY,
+ int textWidth, int textHeight,
+ Uml::Text_Role tr) {
+ const int textCenterX = textX + textWidth / 2;
+ const int textCenterY = textY + textHeight / 2;
+ const uint lastSegment = m_LinePath.count() - 1;
+ QPoint p0, p1;
+ switch (tr) {
+ case tr_RoleAName:
+ case tr_MultiA:
+ case tr_ChangeA:
+ p0 = m_LinePath.getPoint(0);
+ p1 = m_LinePath.getPoint(1);
+ // If we are dealing with a single line then tie the
+ // role label to the proper half of the line, i.e.
+ // the role label must be closer to the "other"
+ // role object.
+ if (lastSegment == 1)
+ p1 = midPoint(p0, p1);
+ break;
+ case tr_RoleBName:
+ case tr_MultiB:
+ case tr_ChangeB:
+ p0 = m_LinePath.getPoint(lastSegment - 1);
+ p1 = m_LinePath.getPoint(lastSegment);
+ if (lastSegment == 1)
+ p0 = midPoint(p0, p1);
+ break;
+ case tr_Name:
+ case tr_Coll_Message: // CHECK: collab.msg texts seem to be tr_Name
+ case tr_State: // CHECK: is this used?
+ // Find the linepath segment to which the (textX,textY) is closest
+ // and constrain to the corridor of that segment (see farther below)
+ {
+ int minDistSquare = 100000; // utopian initial value
+ int lpIndex = 0;
+ for (uint i = 0; i < lastSegment; i++) {
+ p0 = m_LinePath.getPoint(i);
+ p1 = m_LinePath.getPoint(i + 1);
+ QPoint midP = midPoint(p0, p1);
+ const int deltaX = textCenterX - midP.x();
+ const int deltaY = textCenterY - midP.y();
+ const int cSquare = deltaX * deltaX + deltaY * deltaY;
+ if (cSquare < minDistSquare) {
+ minDistSquare = cSquare;
+ lpIndex = i;
+ }
+ }
+ p0 = m_LinePath.getPoint(lpIndex);
+ p1 = m_LinePath.getPoint(lpIndex + 1);
+ }
+ break;
+ default:
+ kError() << "AssociationWidget::constrainTextPos(): unexpected Text_Role "
+ << tr << endl;
+ return;
+ break;
+ }
+ /* Constraint:
+ The midpoint between p0 and p1 is taken to be the center of a circle
+ with radius D/2 where D is the distance between p0 and p1.
+ The text center needs to be within this circle else it is constrained
+ to the nearest point on the circle.
+ */
+ p0 = swapXY(p0); // go to the natural coordinate system
+ p1 = swapXY(p1); // with (0,0) in the lower left corner
+ QPoint midP = midPoint(p0, p1);
+ // If (textX,textY) is not inside the circle around midP then
+ // constrain (textX,textY) to the nearest point on that circle.
+ const int x0 = p0.x();
+ const int y0 = p0.y();
+ const int x1 = p1.x();
+ const int y1 = p1.y();
+ double r = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) / 2;
+ if (textWidth > r)
+ r = textWidth;
+ // swap textCenter{X,Y} to convert from Qt coord.system.
+ const QPoint origTextCenter(textCenterY, textCenterX);
+ const int relX = abs(origTextCenter.x() - midP.x());
+ const int relY = abs(origTextCenter.y() - midP.y());
+ const double negativeWhenInsideCircle = relX * relX + relY * relY - r * r;
+ if (negativeWhenInsideCircle <= 0.0) {
+ return;
+ }
+ /*
+ The original constraint was to snap the text position to the
+ midpoint but that creates unpleasant visual jitter:
+ textX = midP.y() - textWidth / 2; // go back to Qt coord.sys.
+ textY = midP.x() - textHeight / 2; // go back to Qt coord.sys.
+
+ Rather, we project the text position onto the closest point
+ on the circle:
+
+ Circle equation:
+ relX^2 + relY^2 - r^2 = 0 , or in other words
+ relY^2 = r^2 - relX^2 , or
+ relY = sqrt(r^2 - relX^2)
+ Line equation:
+ relY = a * relX + b
+ We can omit "b" because relX and relY are already relative to
+ the circle origin, therefore we can also write:
+ a = relY / relX
+ To obtain the point of intersection between the circle of radius r
+ and the line connecting the circle origin with the point (relX, relY),
+ we equate the relY:
+ a * x = sqrt(r^2 - x^2) , or in other words
+ a^2 * x^2 = r^2 - x^2 , or
+ x^2 * (a^2 + 1) = r^2 , or
+ x^2 = r^2 / (a^2 + 1) , or
+ x = sqrt(r^2 / (a^2 + 1))
+ and then
+ y = a * x
+ The resulting x and y are relative to the circle origin so we just add
+ the circle origin (X,Y) to obtain the constrained (textX,textY).
+ */
+ // Handle the special case, relX = 0.
+ if (relX == 0) {
+ if (origTextCenter.y() > midP.y())
+ textX = midP.y() + (int)r; // go back to Qt coord.sys.
+ else
+ textX = midP.y() - (int)r; // go back to Qt coord.sys.
+ textX -= textWidth / 2;
+ return;
+ }
+ const double a = (double)relY / (double)relX;
+ const double x = sqrt(r*r / (a*a + 1));
+ const double y = a * x;
+ if (origTextCenter.x() > midP.x())
+ textY = midP.x() + (int)x; // go back to Qt coord.sys.
+ else
+ textY = midP.x() - (int)x; // go back to Qt coord.sys.
+ textY -= textHeight / 2;
+ if (origTextCenter.y() > midP.y())
+ textX = midP.y() + (int)y; // go back to Qt coord.sys.
+ else
+ textX = midP.y() - (int)y; // go back to Qt coord.sys.
+ textX -= textWidth / 2;
+}
+
+void AssociationWidget::calculateNameTextSegment() {
+ if(!m_pName) {
+ return;
+ }
+ //changed to use the middle of the text
+ //i think this will give a better result.
+ //never know what sort of lines people come up with
+ //and text could be long to give a false reading
+ int xt = m_pName -> getX();
+ int yt = m_pName -> getY();
+ xt += m_pName -> getWidth() / 2;
+ yt += m_pName -> getHeight() / 2;
+ uint size = m_LinePath.count();
+ //sum of length(PTP1) and length(PTP2)
+ float total_length = 0;
+ float smallest_length = 0;
+ for(uint i = 0; i < size - 1; i++) {
+ QPoint pi = m_LinePath.getPoint( i );
+ QPoint pj = m_LinePath.getPoint( i+1 );
+ int xtiDiff = xt - pi.x();
+ int xtjDiff = xt - pj.x();
+ int ytiDiff = yt - pi.y();
+ int ytjDiff = yt - pj.y();
+ total_length = sqrt( double(xtiDiff * xtiDiff + ytiDiff * ytiDiff) )
+ + sqrt( double(xtjDiff * xtjDiff + ytjDiff * ytjDiff) );
+ //this gives the closest point
+ if( total_length < smallest_length || i == 0) {
+ smallest_length = total_length;
+ m_unNameLineSegment = i;
+ }
+ }
+}
+
+void AssociationWidget::setTextPosition(Uml::Text_Role role) {
+ bool startMove = false;
+ if( m_role[A].m_pMulti && m_role[A].m_pMulti->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pMulti && m_role[B].m_pMulti->getStartMove() )
+ startMove = true;
+ else if( m_role[A].m_pChangeWidget && m_role[A].m_pChangeWidget->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pChangeWidget && m_role[B].m_pChangeWidget->getStartMove() )
+ startMove = true;
+ else if( m_role[A].m_pRole && m_role[A].m_pRole->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pRole && m_role[B].m_pRole->getStartMove() )
+ startMove = true;
+ else if( m_pName && m_pName->getStartMove() )
+ startMove = true;
+
+ if (startMove) {
+ return;
+ }
+ FloatingTextWidget *ft = getTextWidgetByRole(role);
+ if (ft == NULL)
+ return;
+ QPoint pos = calculateTextPosition(role);
+ int x = pos.x();
+ int y = pos.y();
+ if ( (x < 0 || x > FloatingTextWidget::restrictPositionMax) ||
+ (y < 0 || y > FloatingTextWidget::restrictPositionMax) ) {
+ kDebug() << "AssociationWidget::setTextPosition( " << x << " , " << y << " ) "
+ << "- was blocked because at least one value is out of bounds: ["
+ << "0 ... " << FloatingTextWidget::restrictPositionMax << "]"
+ << endl;
+ return;
+ }
+ ft->setX( x );
+ ft->setY( y );
+}
+
+void AssociationWidget::setTextPositionRelatively(Uml::Text_Role role, const QPoint &oldPosition) {
+ bool startMove = false;
+ if( m_role[A].m_pMulti && m_role[A].m_pMulti->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pMulti && m_role[B].m_pMulti->getStartMove() )
+ startMove = true;
+ else if( m_role[A].m_pChangeWidget && m_role[A].m_pChangeWidget->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pChangeWidget && m_role[B].m_pChangeWidget->getStartMove() )
+ startMove = true;
+ else if( m_role[A].m_pRole && m_role[A].m_pRole->getStartMove() )
+ startMove = true;
+ else if( m_role[B].m_pRole && m_role[B].m_pRole->getStartMove() )
+ startMove = true;
+ else if( m_pName && m_pName->getStartMove() )
+ startMove = true;
+
+ if (startMove) {
+ return;
+ }
+ FloatingTextWidget *ft = getTextWidgetByRole(role);
+ if (ft == NULL)
+ return;
+ int ftX = ft->getX();
+ int ftY = ft->getY();
+ if ( (ftX < 0 || ftX > FloatingTextWidget::restrictPositionMax) ||
+ (ftY < 0 || ftY > FloatingTextWidget::restrictPositionMax) ) {
+ kDebug() << "AssociationWidget::setTextPositionRelatively: "
+ << "blocked because the FloatingTextWidget original position ("
+ << ftX << "," << ftY << " is out of bounds: [0 ... "
+ << FloatingTextWidget::restrictPositionMax << "]" << endl;
+ return;
+ }
+ QPoint pos = calculateTextPosition(role);
+ int relX = pos.x() - oldPosition.x();
+ int relY = pos.y() - oldPosition.y();
+ int ftNewX = ftX + relX;
+ int ftNewY = ftY + relY;
+ if ( (ftNewX < 0 || ftNewX > FloatingTextWidget::restrictPositionMax) ||
+ (ftNewY < 0 || ftNewY > FloatingTextWidget::restrictPositionMax) ) {
+ kDebug() << "AssociationWidget::setTextPositionRelatively: "
+ << "blocked because the FloatingTextWidget new position ("
+ << ftNewX << "," << ftNewY << " is out of bounds: [0 ... "
+ << FloatingTextWidget::restrictPositionMax << "]" << endl;
+ return;
+ }
+ bool oldIgnoreSnapToGrid = ft->getIgnoreSnapToGrid();
+ ft->setIgnoreSnapToGrid( true );
+ ft->setX( ftNewX );
+ ft->setY( ftNewY );
+ ft->setIgnoreSnapToGrid( oldIgnoreSnapToGrid );
+}
+
+void AssociationWidget::removeAssocClassLine() {
+ selectAssocClassLine(false);
+ if (m_pAssocClassLine) {
+ delete m_pAssocClassLine;
+ m_pAssocClassLine = NULL;
+ }
+ if (m_pAssocClassWidget) {
+ m_pAssocClassWidget->setClassAssocWidget(NULL);
+ m_pAssocClassWidget = NULL;
+ }
+}
+
+void AssociationWidget::createAssocClassLine() {
+ if (m_pAssocClassLine == NULL)
+ m_pAssocClassLine = new QCanvasLine(m_pView->canvas());
+ computeAssocClassLine();
+ QPen pen(getLineColor(), getLineWidth(), Qt::DashLine);
+ m_pAssocClassLine->setPen(pen);
+ m_pAssocClassLine->setVisible(true);
+}
+
+void AssociationWidget::createAssocClassLine(ClassifierWidget* classifier,
+ int linePathSegmentIndex) {
+ m_nLinePathSegmentIndex = linePathSegmentIndex;
+
+ if (m_nLinePathSegmentIndex < 0) {
+ return;
+ }
+
+ m_pAssocClassWidget = classifier;
+ m_pAssocClassWidget->setClassAssocWidget(this);
+
+ createAssocClassLine();
+}
+
+void AssociationWidget::computeAssocClassLine() {
+ if (m_pAssocClassWidget == NULL || m_pAssocClassLine == NULL)
+ return;
+ if (m_nLinePathSegmentIndex < 0) {
+ kError() << "AssociationWidget::computeAssocClassLine: "
+ << "m_nLinePathSegmentIndex is not set" << endl;
+ return;
+ }
+ QPoint segStart = m_LinePath.getPoint(m_nLinePathSegmentIndex);
+ QPoint segEnd = m_LinePath.getPoint(m_nLinePathSegmentIndex + 1);
+ const int midSegX = segStart.x() + (segEnd.x() - segStart.x()) / 2;
+ const int midSegY = segStart.y() + (segEnd.y() - segStart.y()) / 2;
+
+ QPoint segmentMidPoint(midSegX, midSegY);
+ QRect classRectangle = m_pAssocClassWidget->rect();
+ QPoint cwEdgePoint = findIntercept(classRectangle, segmentMidPoint);
+ int acwMinX = cwEdgePoint.x();
+ int acwMinY = cwEdgePoint.y();
+
+ m_pAssocClassLine->setPoints(midSegX, midSegY, acwMinX, acwMinY);
+}
+
+void AssociationWidget::selectAssocClassLine(bool sel /* =true */) {
+ if (!sel) {
+ if (m_pAssocClassLineSel0) {
+ delete m_pAssocClassLineSel0;
+ m_pAssocClassLineSel0 = NULL;
+ }
+ if (m_pAssocClassLineSel1) {
+ delete m_pAssocClassLineSel1;
+ m_pAssocClassLineSel1 = NULL;
+ }
+ return;
+ }
+ if (m_pAssocClassLine == NULL) {
+ kError() << "AssociationWidget::selectAssocClassLine: "
+ << "cannot select because m_pAssocClassLine is NULL"
+ << endl;
+ return;
+ }
+ if (m_pAssocClassLineSel0)
+ delete m_pAssocClassLineSel0;
+ m_pAssocClassLineSel0 = Widget_Utils::decoratePoint(m_pAssocClassLine->startPoint());
+ if (m_pAssocClassLineSel1)
+ delete m_pAssocClassLineSel1;
+ m_pAssocClassLineSel1 = Widget_Utils::decoratePoint(m_pAssocClassLine->endPoint());
+}
+
+void AssociationWidget::mousePressEvent(QMouseEvent * me) {
+ m_nMovingPoint = -1;
+ //make sure we should be here depending on the button
+ if(me -> button() != Qt::RightButton && me->button() != Qt::LeftButton)
+ return;
+ QPoint mep = me->pos();
+ // See if `mep' is on the connecting line to the association class
+ if (onAssocClassLine(mep)) {
+ m_bSelected = true;
+ selectAssocClassLine();
+ return;
+ }
+ // See if the user has clicked on a point to start moving the line segment
+ // from that point
+ checkPoints(mep);
+ if( me -> state() != Qt::ShiftButton )
+ m_pView -> clearSelected();
+ setSelected( !m_bSelected );
+}
+
+void AssociationWidget::mouseReleaseEvent(QMouseEvent * me) {
+ if(me -> button() != Qt::RightButton && me->button() != Qt::LeftButton) {
+ setSelected( false );
+ return;
+ }
+
+ // Check whether a point was moved and whether the moved point is
+ // located on the straight line between its neighbours.
+ // if yes, remove it
+ ///@todo: check for non-horizontal / -vertical lines
+ if (m_nMovingPoint > 0 && m_nMovingPoint < m_LinePath.count() - 1)
+ {
+ QPoint m = m_LinePath.getPoint(m_nMovingPoint);
+ QPoint b = m_LinePath.getPoint(m_nMovingPoint - 1);
+ QPoint a = m_LinePath.getPoint(m_nMovingPoint + 1);
+ if ( (b.x() == m.x() && a.x() == m.x()) ||
+ (b.y() == m.y() && a.y() == m.y()) )
+ m_LinePath.removePoint(m_nMovingPoint, m, POINT_DELTA);
+ }
+ m_nMovingPoint = -1;
+ const QPoint p = me->pos();
+
+ if (me->button() != Qt::RightButton) {
+ return;
+ }
+
+ // right button action:
+ //work out the type of menu we want
+ //work out if the association allows rolenames, multiplicity, etc
+ //also must be within a certain distance to be a multiplicity menu
+ ListPopupMenu::Menu_Type menuType = ListPopupMenu::mt_Undefined;
+ const int DISTANCE = 40;//must be within this many pixels for it to be a multi menu
+ const QPoint lpStart = m_LinePath.getPoint(0);
+ const QPoint lpEnd = m_LinePath.getPoint(m_LinePath.count() - 1);
+ const int startXDiff = lpStart.x() - p.x();
+ const int startYDiff = lpStart.y() - p.y();
+ const int endXDiff = lpEnd.x() - p.x();
+ const int endYDiff = lpEnd.y() - p.y();
+ const float lengthMAP = sqrt( double(startXDiff * startXDiff + startYDiff * startYDiff) );
+ const float lengthMBP = sqrt( double(endXDiff * endXDiff + endYDiff * endYDiff) );
+ const Uml::Association_Type type = getAssocType();
+ //allow multiplicity
+ if( AssocRules::allowMultiplicity( type, getWidget(A) -> getBaseType() ) ) {
+ if(lengthMAP < DISTANCE)
+ menuType = ListPopupMenu::mt_MultiA;
+ else if(lengthMBP < DISTANCE)
+ menuType = ListPopupMenu::mt_MultiB;
+ }
+ if( menuType == ListPopupMenu::mt_Undefined ) {
+ if (type == at_Anchor || onAssocClassLine(p))
+ menuType = ListPopupMenu::mt_Anchor;
+ else if (isCollaboration())
+ menuType = ListPopupMenu::mt_Collaboration_Message;
+ else if (getAssociation() == NULL)
+ menuType = ListPopupMenu::mt_AttributeAssociation;
+ else if (AssocRules::allowRole(type))
+ menuType = ListPopupMenu::mt_FullAssociation;
+ else
+ menuType = ListPopupMenu::mt_Association_Selected;
+ }
+ m_pMenu = new ListPopupMenu(m_pView, menuType);
+ m_pMenu->popup(me -> globalPos());
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ setSelected();
+}//end method mouseReleaseEvent
+
+bool AssociationWidget::showDialog() {
+ AssocPropDlg dlg(static_cast<QWidget*>(m_pView), this );
+ if (! dlg.exec())
+ return false;
+ QString name = getName();
+ QString doc = getDoc();
+ QString roleADoc = getRoleDoc(A), roleBDoc = getRoleDoc(B);
+ QString rnA = getRoleName(A), rnB = getRoleName(B);
+ QString ma = getMulti(A), mb = getMulti(B);
+ Uml::Visibility vA = getVisibility(A), vB = getVisibility(B);
+ Uml::Changeability_Type cA = getChangeability(A), cB = getChangeability(B);
+ //rules built into these functions to stop updating incorrect values
+ setName(name);
+ setRoleName(rnA, A);
+ setRoleName(rnB, B);
+ setDoc(doc);
+ setRoleDoc(roleADoc, A);
+ setRoleDoc(roleBDoc, B);
+ setMulti(ma, A);
+ setMulti(mb, B);
+ setVisibility(vA, A);
+ setVisibility(vB, B);
+ setChangeability(cA, A);
+ setChangeability(cB, B);
+ m_pView -> showDocumentation( this, true );
+ return true;
+}
+
+void AssociationWidget::slotMenuSelection(int sel) {
+ QString oldText, newText;
+ QFont font;
+ QRegExpValidator v(QRegExp(".*"), 0);
+ Uml::Association_Type atype = getAssocType();
+ Uml::Role_Type r = Uml::B;
+
+ //if it's a collaboration message we now just use the code in floatingtextwidget
+ //this means there's some redundant code below but that's better than duplicated code
+ if (isCollaboration() && sel != ListPopupMenu::mt_Delete) {
+ m_pName->slotMenuSelection(sel);
+ return;
+ }
+
+ switch(sel) {
+ case ListPopupMenu::mt_Properties:
+ if(atype == at_Seq_Message || atype == at_Seq_Message_Self) {
+ // show op dlg for seq. diagram here
+ // don't worry about here, I don't think it can get here as
+ // line is widget on seq. diagram
+ // here just in case - remove later after testing
+ kDebug() << "AssociationWidget::slotMenuSelection(mt_Properties): "
+ << "assoctype is " << atype << endl;
+ } else { //standard assoc dialog
+ m_pView -> updateDocumentation( false );
+ showDialog();
+ }
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ if (m_pAssocClassLineSel0)
+ removeAssocClassLine();
+ else if (getAssociation())
+ m_pView->removeAssocInViewAndDoc(this);
+ else
+ m_pView->removeAssoc(this);
+ break;
+
+ case ListPopupMenu::mt_Rename_MultiA:
+ r = Uml::A; // fall through
+ case ListPopupMenu::mt_Rename_MultiB:
+ if (m_role[r].m_pMulti)
+ oldText = m_role[r].m_pMulti->getText();
+ else
+ oldText = "";
+ newText = KInputDialog::getText(i18n("Multiplicity"),
+ i18n("Enter multiplicity:"),
+ oldText, NULL, m_pView, NULL, &v);
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setMulti(newText, r);
+ } else {
+ m_pView->removeWidget(m_role[r].m_pMulti);
+ m_role[r].m_pMulti = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Rename_Name:
+ if(m_pName)
+ oldText = m_pName->getText();
+ else
+ oldText = "";
+ newText = KInputDialog::getText(i18n("Association Name"),
+ i18n("Enter association name:"),
+ oldText, NULL, m_pView, NULL, &v);
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setName(newText);
+ } else {
+ m_pView->removeWidget(m_pName);
+ m_pName = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Rename_RoleAName:
+ r = Uml::A; // fall through
+ case ListPopupMenu::mt_Rename_RoleBName:
+ if (m_role[r].m_pRole)
+ oldText = m_role[r].m_pRole->getText();
+ else
+ oldText = "";
+ newText = KInputDialog::getText(i18n("Role Name"),
+ i18n("Enter role name:"),
+ oldText, NULL, m_pView, NULL, &v);
+ if (newText != oldText) {
+ if (FloatingTextWidget::isTextValid(newText)) {
+ setRoleName(newText, r);
+ } else {
+ m_pView->removeWidget(m_role[r].m_pRole);
+ m_role[r].m_pRole = NULL;
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ font = getFont();
+ if( KFontDialog::getFont( font, false, m_pView ) )
+ lwSetFont(font);
+ break;
+
+ case ListPopupMenu::mt_Change_Font_Selection:
+ font = getFont();
+ if( KFontDialog::getFont( font, false, m_pView ) ) {
+ m_pView -> selectionSetFont( font );
+ m_umldoc->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Line_Color:
+ case ListPopupMenu::mt_Line_Color_Selection:
+ {
+ QColor newColour;
+ if( KColorDialog::getColor(newColour) ) {
+ m_pView->selectionSetLineColor(newColour);
+ m_umldoc->setModified(true);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ m_pView->setStartedCut();
+ UMLApp::app()->slotEditCut();
+ break;
+
+ case ListPopupMenu::mt_Copy:
+ UMLApp::app()->slotEditCopy();
+ break;
+
+ case ListPopupMenu::mt_Paste:
+ UMLApp::app()->slotEditPaste();
+ break;
+
+ case ListPopupMenu::mt_Reset_Label_Positions:
+ resetTextPositions();
+ break;
+ }//end switch
+}
+
+
+void AssociationWidget::lwSetFont (QFont font) {
+ if( m_pName) {
+ m_pName->setFont( font );
+ }
+ if( m_role[A].m_pRole ) {
+ m_role[A].m_pRole->setFont( font );
+ }
+ if( m_role[B].m_pRole ) {
+ m_role[B].m_pRole->setFont( font );
+ }
+ if( m_role[A].m_pMulti ) {
+ m_role[A].m_pMulti->setFont( font );
+ }
+ if( m_role[B].m_pMulti ) {
+ m_role[B].m_pMulti->setFont( font );
+ }
+ if( m_role[A].m_pChangeWidget)
+ m_role[A].m_pChangeWidget->setFont( font );
+ if( m_role[B].m_pChangeWidget)
+ m_role[B].m_pChangeWidget->setFont( font );
+}
+
+// find a general font for the association
+QFont AssociationWidget::getFont() const {
+ QFont font;
+
+ if( m_role[A].m_pRole )
+ font = m_role[A].m_pRole -> getFont( );
+ else if( m_role[B].m_pRole)
+ font = m_role[B].m_pRole -> getFont( );
+ else if( m_role[A].m_pMulti )
+ font = m_role[A].m_pMulti -> getFont( );
+ else if( m_role[B].m_pMulti )
+ font = m_role[B].m_pMulti -> getFont( );
+ else if( m_role[A].m_pChangeWidget)
+ font = m_role[A].m_pChangeWidget-> getFont( );
+ else if( m_role[B].m_pChangeWidget)
+ font = m_role[B].m_pChangeWidget-> getFont( );
+ else if( m_pName)
+ font = m_pName-> getFont( );
+ else
+ font = m_role[A].m_pWidget -> getFont();
+
+ return font;
+}
+
+void AssociationWidget::setLineColor(const QColor &colour) {
+ WidgetBase::setLineColor(colour);
+ m_LinePath.setLineColor(colour);
+}
+
+void AssociationWidget::setLineWidth(uint width) {
+ WidgetBase::setLineWidth(width);
+ m_LinePath.setLineWidth(width);
+}
+
+void AssociationWidget::checkPoints(const QPoint &p) {
+ m_nMovingPoint = -1;
+ //only check if more than the two endpoints
+ int size = m_LinePath.count();
+ if( size <= 2 )
+ return;
+ //check all points except the end points to see if we clicked on one of them
+ QPoint tempPoint;
+ int x, y;
+ const int BOUNDARY = 4; // check for pixels around the point
+ for(int i=1;i<size-1;i++) {
+ tempPoint = m_LinePath.getPoint( i );
+ x = tempPoint.x();
+ y = tempPoint.y();
+ if( x - BOUNDARY <= p.x() && x + BOUNDARY >= p.x() &&
+ y - BOUNDARY <= p.y() && y + BOUNDARY >= p.y() ) {
+ m_nMovingPoint = i;
+ break; //no need to check the rest
+ }//end if
+ }//end for
+}
+
+void AssociationWidget::mouseMoveEvent(QMouseEvent* me) {
+ if( me->state() != Qt::LeftButton) {
+ return;
+ }
+
+ // if we have no moving point,create one
+ if (m_nMovingPoint == -1)
+ {
+ //create moving point near the mouse on the line
+ int i = m_LinePath.onLinePath(me->pos());
+
+ if (i == -1)
+ return;
+ m_LinePath.insertPoint( i + 1, me->pos() );
+ m_nMovingPoint = i + 1;
+ }
+
+ setSelected();
+ //new position for point
+ QPoint p = me->pos();
+ QPoint oldp = m_LinePath.getPoint(m_nMovingPoint);
+
+ if( m_pView -> getSnapToGrid() ) {
+ int newX = m_pView->snappedX( p.x() );
+ int newY = m_pView->snappedY( p.y() );
+ p.setX(newX);
+ p.setY(newY);
+ }
+
+ // Prevent the moving vertex from disappearing underneath a widget
+ // (else there's no way to get it back.)
+ UMLWidget *onW = m_pView->getWidgetAt(p);
+ if (onW && onW->getBaseType() != Uml::wt_Box) { // boxes are transparent
+ const int pX = p.x();
+ const int pY = p.y();
+ const int wX = onW->getX();
+ const int wY = onW->getY();
+ const int wWidth = onW->getWidth();
+ const int wHeight = onW->getHeight();
+ if (pX > wX && pX < wX + wWidth) {
+ const int midX = wX + wWidth / 2;
+ if (pX <= midX)
+ p.setX(wX);
+ else
+ p.setX(wX + wWidth);
+ }
+ if (pY > wY && pY < wY + wHeight) {
+ const int midY = wY + wHeight / 2;
+ if (pY <= midY)
+ p.setY(wY);
+ else
+ p.setY(wY + wHeight);
+ }
+ }
+
+ //move event called now
+ QMoveEvent m(p, oldp);
+ moveEvent(&m);
+ m_pView->resizeCanvasToItems();
+}
+
+AssociationWidget::Region AssociationWidget::getWidgetRegion(AssociationWidget * widget) const {
+ if(widget -> getWidget(A) == m_role[A].m_pWidget)
+ return m_role[A].m_WidgetRegion;
+ if(widget -> getWidget(B) == m_role[B].m_pWidget)
+ return m_role[B].m_WidgetRegion;
+ return Error;
+}
+
+int AssociationWidget::getRegionCount(AssociationWidget::Region region, Uml::Role_Type role) {
+ if(region == Error)
+ return 0;
+ int widgetCount = 0;
+ AssociationWidgetList list = m_pView -> getAssociationList();
+ AssociationWidgetListIt assoc_it(list);
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget = assoc_it.current())) {
+ ++assoc_it;
+ //don't count this association
+ if (assocwidget == this)
+ continue;
+ const WidgetRole& otherA = assocwidget->m_role[A];
+ const WidgetRole& otherB = assocwidget->m_role[B];
+ const UMLWidget *a = otherA.m_pWidget;
+ const UMLWidget *b = otherB.m_pWidget;
+ /*
+ //don't count associations to self if both of their end points are on the same region
+ //they are different and placement won't interfere with them
+ if( a == b && otherA.m_WidgetRegion == otherB.m_WidgetRegion )
+ continue;
+ */
+ if (m_role[role].m_pWidget == a && region == otherA.m_WidgetRegion)
+ widgetCount++;
+ else if (m_role[role].m_pWidget == b && region == otherB.m_WidgetRegion)
+ widgetCount++;
+ }//end while
+ return widgetCount;
+}
+
+QPoint AssociationWidget::findIntercept(const QRect &rect, const QPoint &point) {
+ Region region = findPointRegion(rect, point.x(), point.y());
+ /*
+ const char *regionStr[] = { "Error",
+ "West", "North", "East", "South",
+ "NorthWest", "NorthEast", "SouthEast", "SouthWest",
+ "Center"
+ };
+ kDebug() << "findPointRegion(rect(" << rect.x() << "," << rect.y()
+ << "," << rect.width() << "," << rect.height() << "), p("
+ << point.x() << "," << point.y() << ")) = " << regionStr[region]
+ << endl;
+ */
+ // Move some regions to the standard ones.
+ switch (region) {
+ case NorthWest:
+ region = North;
+ break;
+ case NorthEast:
+ region = East;
+ break;
+ case SouthEast:
+ region = South;
+ break;
+ case SouthWest:
+ case Center:
+ region = West;
+ break;
+ default:
+ break;
+ }
+ // The Qt coordinate system has (0,0) in the top left corner.
+ // In order to go to the regular XY coordinate system with (0,0)
+ // in the bottom left corner, we swap the X and Y axis.
+ // That's why the following assignments look twisted.
+ const int rectHalfWidth = rect.height() / 2;
+ const int rectHalfHeight = rect.width() / 2;
+ const int rectMidX = rect.y() + rectHalfWidth;
+ const int rectMidY = rect.x() + rectHalfHeight;
+ const int pX = point.y();
+ const int pY = point.x();
+ const int dX = rectMidX - pX;
+ const int dY = rectMidY - pY;
+ switch (region) {
+ case West:
+ region = South;
+ break;
+ case North:
+ region = East;
+ break;
+ case East:
+ region = North;
+ break;
+ case South:
+ region = West;
+ break;
+ default:
+ break;
+ }
+ // Now we have regular coordinates with the point (0,0) in the
+ // bottom left corner.
+ if (region == North || region == South) {
+ int yoff = rectHalfHeight;
+ if (region == North)
+ yoff = -yoff;
+ if (dX == 0) {
+ return QPoint(rectMidY + yoff, rectMidX); // swap back X and Y
+ }
+ if (dY == 0) {
+ kError() << "AssociationWidget::findIntercept usage error: "
+ << "North/South (dY == 0)" << endl;
+ return QPoint(0,0);
+ }
+ const float m = (float)dY / (float)dX;
+ const float b = (float)pY - m * pX;
+ const int inputY = rectMidY + yoff;
+ const float outputX = ((float)inputY - b) / m;
+ return QPoint(inputY, (int)outputX); // swap back X and Y
+ } else {
+ int xoff = rectHalfWidth;
+ if (region == East)
+ xoff = -xoff;
+ if (dY == 0)
+ return QPoint(rectMidY, rectMidX + xoff); // swap back X and Y
+ if (dX == 0) {
+ kError() << "AssociationWidget::findIntercept usage error: "
+ << "East/West (dX == 0)" << endl;
+ return QPoint(0,0);
+ }
+ const float m = (float)dY / (float)dX;
+ const float b = (float)pY - m * pX;
+ const int inputX = rectMidX + xoff;
+ const float outputY = m * (float)inputX + b;
+ return QPoint((int)outputY, inputX); // swap back X and Y
+ }
+}
+
+int AssociationWidget::findInterceptOnEdge(const QRect &rect,
+ AssociationWidget::Region region,
+ const QPoint &point)
+{
+ // The Qt coordinate system has (0,0) in the top left corner.
+ // In order to go to the regular XY coordinate system with (0,0)
+ // in the bottom left corner, we swap the X and Y axis.
+ // That's why the following assignments look twisted.
+ const int rectHalfWidth = rect.height() / 2;
+ const int rectHalfHeight = rect.width() / 2;
+ const int rectMidX = rect.y() + rectHalfWidth;
+ const int rectMidY = rect.x() + rectHalfHeight;
+ const int dX = rectMidX - point.y();
+ const int dY = rectMidY - point.x();
+ switch (region) {
+ case West:
+ region = South;
+ break;
+ case North:
+ region = West;
+ break;
+ case East:
+ region = North;
+ break;
+ case South:
+ region = East;
+ break;
+ default:
+ break;
+ }
+ // Now we have regular coordinates with the point (0,0) in the
+ // bottom left corner.
+ if (region == North || region == South) {
+ if (dX == 0)
+ return rectMidY;
+ // should be rectMidX, but we go back to Qt coord.sys.
+ if (dY == 0) {
+ kError() << "AssociationWidget::findInterceptOnEdge usage error: "
+ << "North/South (dY == 0)" << endl;
+ return -1;
+ }
+ const float m = (float)dY / (float)dX;
+ float relativeX;
+ if (region == North)
+ relativeX = (float)rectHalfHeight / m;
+ else
+ relativeX = -(float)rectHalfHeight / m;
+ return (rectMidY + (int)relativeX);
+ // should be rectMidX, but we go back to Qt coord.sys.
+ } else {
+ if (dY == 0)
+ return rectMidX;
+ // should be rectMidY, but we go back to Qt coord.sys.
+ if (dX == 0) {
+ kError() << "AssociationWidget::findInterceptOnEdge usage error: "
+ << "East/West (dX == 0)" << endl;
+ return -1;
+ }
+ const float m = (float)dY / (float)dX;
+ float relativeY = m * (float)rectHalfWidth;
+ if (region == West)
+ relativeY = -relativeY;
+ return (rectMidX + (int)relativeY);
+ // should be rectMidY, but we go back to Qt coord.sys.
+ }
+}
+
+void AssociationWidget::insertIntoLists(int position, const AssociationWidget* assoc)
+{
+ bool did_insertion = false;
+ for (int index = 0; index < m_positions_len; index++) {
+ if (position < m_positions[index]) {
+ for (int moveback = m_positions_len; moveback > index; moveback--)
+ m_positions[moveback] = m_positions[moveback - 1];
+ m_positions[index] = position;
+ m_ordered.insert(index, assoc);
+ did_insertion = true;
+ break;
+ }
+ }
+ if (! did_insertion) {
+ m_positions[m_positions_len] = position;
+ m_ordered.append(assoc);
+ }
+ m_positions_len++;
+}
+
+void AssociationWidget::updateAssociations(int totalCount,
+ AssociationWidget::Region region,
+ Uml::Role_Type role)
+{
+ if( region == Error )
+ return;
+ AssociationWidgetList list = m_pView -> getAssociationList();
+ AssociationWidgetListIt assoc_it(list);
+ AssociationWidget* assocwidget = 0;
+ UMLWidget *ownWidget = m_role[role].m_pWidget;
+ m_positions_len = 0;
+ m_ordered.clear();
+ // we order the AssociationWidget list by region and x/y value
+ while ( (assocwidget = assoc_it.current()) ) {
+ ++assoc_it;
+ WidgetRole *roleA = &assocwidget->m_role[A];
+ WidgetRole *roleB = &assocwidget->m_role[B];
+ UMLWidget *wA = roleA->m_pWidget;
+ UMLWidget *wB = roleB->m_pWidget;
+ // Skip self associations.
+ if (wA == wB)
+ continue;
+ // Now we must find out with which end the assocwidget connects
+ // to the input widget (ownWidget).
+ bool inWidgetARegion = ( ownWidget == wA &&
+ region == roleA->m_WidgetRegion );
+ bool inWidgetBRegion = ( ownWidget == wB &&
+ region == roleB->m_WidgetRegion);
+ if ( !inWidgetARegion && !inWidgetBRegion )
+ continue;
+ // Determine intercept position on the edge indicated by `region'.
+ UMLWidget * otherWidget = (inWidgetARegion ? wB : wA);
+ LinePath *linepath = assocwidget->getLinePath();
+ QPoint refpoint;
+ if (assocwidget->linePathStartsAt(otherWidget))
+ refpoint = linepath->getPoint(linepath->count() - 2);
+ else
+ refpoint = linepath->getPoint(1);
+ // The point is authoritative if we're called for the second time
+ // (i.e. role==B) or it is a waypoint on the line path.
+ bool pointIsAuthoritative = (role == B || linepath->count() > 2);
+ if (! pointIsAuthoritative) {
+ // If the point is not authoritative then we use the other
+ // widget's center.
+ refpoint.setX(otherWidget->getX() + otherWidget->getWidth() / 2);
+ refpoint.setY(otherWidget->getY() + otherWidget->getHeight() / 2);
+ }
+ int intercept = findInterceptOnEdge(ownWidget->rect(), region, refpoint);
+ if (intercept < 0) {
+ kDebug() << "updateAssociations: error from findInterceptOnEdge for"
+ << " assocType=" << assocwidget->getAssocType()
+ << " ownWidget=" << ownWidget->getName()
+ << " otherWidget=" << otherWidget->getName() << endl;
+ continue;
+ }
+ insertIntoLists(intercept, assocwidget);
+ } // while ( (assocwidget = assoc_it.current()) )
+
+ // we now have an ordered list and we only have to call updateRegionLineCount
+ int index = 1;
+ for (assocwidget = m_ordered.first(); assocwidget; assocwidget = m_ordered.next()) {
+ if (ownWidget == assocwidget->getWidget(A)) {
+ assocwidget->updateRegionLineCount(index++, totalCount, region, A);
+ } else if (ownWidget == assocwidget->getWidget(B)) {
+ assocwidget->updateRegionLineCount(index++, totalCount, region, B);
+ }
+ } // for (assocwidget = ordered.first(); ...)
+}
+
+void AssociationWidget::updateRegionLineCount(int index, int totalCount,
+ AssociationWidget::Region region,
+ Uml::Role_Type role) {
+ if( region == Error )
+ return;
+ // If the association is to self and the line ends are on the same region then
+ // use a different calculation.
+ if (m_role[A].m_pWidget == m_role[B].m_pWidget &&
+ m_role[A].m_WidgetRegion == m_role[B].m_WidgetRegion) {
+ UMLWidget * pWidget = m_role[A].m_pWidget;
+ int x = pWidget -> getX();
+ int y = pWidget -> getY();
+ int wh = pWidget -> height();
+ int ww = pWidget -> width();
+ int size = m_LinePath.count();
+ // See if above widget ok to place assoc.
+ switch( m_role[A].m_WidgetRegion ) {
+ case North:
+ m_LinePath.setPoint( 0, QPoint( x + ( ww / 4 ), y ) );
+ m_LinePath.setPoint( size - 1, QPoint(x + ( ww * 3 / 4 ), y ) );
+ break;
+
+ case South:
+ m_LinePath.setPoint( 0, QPoint( x + ( ww / 4 ), y + wh ) );
+ m_LinePath.setPoint( size - 1, QPoint( x + ( ww * 3 / 4 ), y + wh ) );
+ break;
+
+ case East:
+ m_LinePath.setPoint( 0, QPoint( x + ww, y + ( wh / 4 ) ) );
+ m_LinePath.setPoint( size - 1, QPoint( x + ww, y + ( wh * 3 / 4 ) ) );
+ break;
+
+ case West:
+ m_LinePath.setPoint( 0, QPoint( x, y + ( wh / 4 ) ) );
+ m_LinePath.setPoint( size - 1, QPoint( x, y + ( wh * 3 / 4 ) ) );
+ break;
+ default:
+ break;
+ }//end switch
+ m_role[A].m_OldCorner.setX( x );
+ m_role[A].m_OldCorner.setY( y );
+ m_role[B].m_OldCorner.setX( x );
+ m_role[B].m_OldCorner.setY( y );
+
+ return;
+ }
+
+ WidgetRole& robj = m_role[role];
+ UMLWidget * pWidget = robj.m_pWidget;
+
+ robj.m_nIndex = index;
+ robj.m_nTotalCount = totalCount;
+ int x = pWidget->getX();
+ int y = pWidget->getY();
+ robj.m_OldCorner.setX(x);
+ robj.m_OldCorner.setY(y);
+ int ww = pWidget->getWidth();
+ int wh = pWidget->getHeight();
+ const bool angular = Settings::getOptionState().generalState.angularlines;
+ int ch = 0;
+ int cw = 0;
+ if (angular) {
+ uint nind = (role == A ? 1 : m_LinePath.count() - 2);
+ QPoint neighbour = m_LinePath.getPoint(nind);
+ if (neighbour.x() < x)
+ cw = 0;
+ else if (neighbour.x() > x + ww)
+ cw = 0 + ww;
+ else
+ cw = neighbour.x() - x;
+ if (neighbour.y() < y)
+ ch = 0;
+ else if (neighbour.y() > y + wh)
+ ch = 0 + wh;
+ else
+ ch = neighbour.y() - y;
+ } else {
+ ch = wh * index / totalCount;
+ cw = ww * index / totalCount;
+ }
+
+ int snapX = m_pView->snappedX(x + cw);
+ int snapY = m_pView->snappedY(y + ch);
+
+ QPoint pt;
+ if (angular) {
+ pt = QPoint(snapX, snapY);
+ } else {
+ switch(region) {
+ case West:
+ pt.setX(x);
+ pt.setY(snapY);
+ break;
+ case North:
+ pt.setX(snapX);
+ pt.setY(y);
+ break;
+ case East:
+ pt.setX(x + ww);
+ pt.setY(snapY);
+ break;
+ case South:
+ pt.setX(snapX);
+ pt.setY(y + wh);
+ break;
+ case Center:
+ pt.setX(x + ww / 2);
+ pt.setY(y + wh / 2);
+ break;
+ default:
+ break;
+ }
+ }
+ if (role == A)
+ m_LinePath.setPoint( 0, pt );
+ else {
+ m_LinePath.setPoint( m_LinePath.count() - 1, pt );
+ LinePath::Region r = ( region == South || region == North ) ?
+ LinePath::TopBottom : LinePath::LeftRight;
+ m_LinePath.setDockRegion( r );
+ }
+}
+
+void AssociationWidget::setSelected(bool _select /* = true */) {
+ m_bSelected = _select;
+ if( m_pName)
+ m_pName-> setSelected( _select );
+ if( m_role[A].m_pRole )
+ m_role[A].m_pRole -> setSelected( _select );
+ if( m_role[B].m_pRole )
+ m_role[B].m_pRole -> setSelected( _select );
+ if( m_role[A].m_pMulti )
+ m_role[A].m_pMulti -> setSelected( _select );
+ if( m_role[B].m_pMulti )
+ m_role[B].m_pMulti -> setSelected( _select );
+ if( m_role[A].m_pChangeWidget)
+ m_role[A].m_pChangeWidget-> setSelected( _select );
+ if( m_role[B].m_pChangeWidget)
+ m_role[B].m_pChangeWidget-> setSelected( _select );
+ kapp->processEvents();
+ //Update the docwindow for this association.
+ // This is done last because each of the above setSelected calls
+ // overwrites the docwindow, but we want the main association doc
+ // to win.
+ if( _select ) {
+ if( m_pView -> getSelectCount() == 0 )
+ m_pView -> showDocumentation( this, false );
+ } else
+ m_pView -> updateDocumentation( true );
+ kapp->processEvents();
+ m_LinePath.setSelected( _select );
+ if (! _select) {
+ // For now, if _select is true we don't make the assoc class line
+ // selected. But that's certainly open for discussion.
+ // At any rate, we need to deselect the assoc class line
+ // if _select is false.
+ selectAssocClassLine(false);
+ }
+}
+
+bool AssociationWidget::onAssocClassLine(const QPoint &point) {
+ if (m_pAssocClassLine == NULL)
+ return false;
+ QCanvasItemList list = m_pView->canvas()->collisions(point);
+ QCanvasItemList::iterator end(list.end());
+ for (QCanvasItemList::iterator item_it(list.begin()); item_it != end; ++item_it) {
+ if (*item_it == m_pAssocClassLine)
+ return true;
+ }
+ return false;
+}
+
+bool AssociationWidget::onAssociation(const QPoint & point) {
+ if (m_LinePath.onLinePath(point) != -1)
+ return true;
+ return onAssocClassLine(point);
+}
+
+void AssociationWidget::slotRemovePopupMenu()
+{
+ if(m_pMenu) {
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void AssociationWidget::slotClearAllSelected() {
+ setSelected( false );
+}
+
+void AssociationWidget::moveMidPointsBy( int x, int y ) {
+ int pos = m_LinePath.count() - 1;
+ for( int i=1 ; i < (int)pos ; i++ ) {
+ QPoint p = m_LinePath.getPoint( i );
+ int newX = p.x() + x;
+ int newY = p.y() + y;
+ newX = m_pView -> snappedX( newX );
+ newY = m_pView -> snappedY( newY );
+ p.setX( newX );
+ p.setY( newY );
+ m_LinePath.setPoint( i, p );
+ }
+}
+
+void AssociationWidget::moveEntireAssoc( int x, int y ) {
+ //TODO: ADD SUPPORT FOR ASSOC. ON SEQ. DIAGRAMS WHEN NOTES BACK IN.
+ moveMidPointsBy( x, y );
+ calculateEndingPoints();
+ calculateNameTextSegment();
+ resetTextPositions();
+}
+
+QRect AssociationWidget::getAssocLineRectangle()
+{
+ QRect rectangle;
+ QPoint p;
+ uint pen_width;
+
+ /* we also want the end points connected to the other widget */
+ int pos = m_LinePath.count();
+
+ /* go through all points on the linepath */
+ for( int i=0 ; i < (int) pos; i++ )
+ {
+ p = m_LinePath.getPoint( i );
+
+ /* the first point is our starting point */
+ if (i == 0) {
+ rectangle.setRect(p.x(), p.y(), 0, 0);
+ continue;
+ }
+
+ /* the lines have the width of the pen */
+ pen_width = m_LinePath.getPen().width();
+ if (pen_width == 0)
+ pen_width = 1; // width must be at least 1
+
+ if (p.x() < rectangle.x())
+ rectangle.setX(p.x());
+ if (p.y() < rectangle.y())
+ rectangle.setY(p.y());
+ if (p.x() > rectangle.x() + rectangle.width()) {
+ int newX = p.x() - rectangle.x() + pen_width;
+ rectangle.setWidth(abs(newX));
+ }
+ if (p.y() > rectangle.y() + rectangle.height()) {
+ int newY = p.y() - rectangle.y() + pen_width;
+ rectangle.setHeight(abs(newY));
+ }
+ }
+ return rectangle;
+}
+
+void AssociationWidget::setUMLObject(UMLObject *obj) {
+ WidgetBase::setUMLObject(obj);
+ if (obj == NULL)
+ return;
+ UMLClassifier *klass = NULL;
+ UMLAttribute *attr = NULL;
+ UMLEntity *ent = NULL;
+ const Uml::Object_Type ot = obj->getBaseType();
+ switch (ot) {
+ case Uml::ot_Association:
+ setUMLAssociation(dynamic_cast<UMLAssociation*>(obj));
+ break;
+ case Uml::ot_Operation:
+ setOperation(dynamic_cast<UMLOperation *>(obj));
+ break;
+ case Uml::ot_Attribute:
+ klass = static_cast<UMLClassifier*>(obj->parent());
+ connect(klass, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotAttributeRemoved(UMLClassifierListItem*)));
+ attr = static_cast<UMLAttribute*>(obj);
+ connect(attr, SIGNAL(attributeChanged()), this, SLOT(slotAttributeChanged()));
+ break;
+ case Uml::ot_EntityAttribute:
+ ent = static_cast<UMLEntity*>(obj->parent());
+ connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(slotAttributeRemoved(UMLClassifierListItem*)));
+ break;
+ default:
+ kError() << "UMLAssociation constructor: cannot associate UMLObject of type "
+ << ot << endl;
+ }
+}
+
+void AssociationWidget::slotAttributeRemoved(UMLClassifierListItem* obj) {
+ if (obj != m_pObject)
+ kDebug() << "AssociationWidget::slotAttributeRemoved:(obj=" << obj
+ << "): m_pObject=" << m_pObject << endl;
+ m_pObject = NULL;
+ m_pView->removeAssoc(this);
+}
+
+void AssociationWidget::slotAttributeChanged() {
+ UMLAttribute *attr = getAttribute();
+ if (attr == NULL) {
+ kError() << "AssociationWidget::slotAttributeChanged: getAttribute returns NULL"
+ << endl;
+ return;
+ }
+ setVisibility(attr->getVisibility(), B);
+ setRoleName(attr->getName(), B);
+}
+
+void AssociationWidget::init (UMLView *view)
+{
+ WidgetBase::init(view, wt_Association);
+
+ // pointers to floating text widgets objects owned by this association
+ m_pName = 0;
+ m_role[A].m_pChangeWidget = 0;
+ m_role[B].m_pChangeWidget = 0;
+ m_role[A].m_pMulti = 0;
+ m_role[B].m_pMulti = 0;
+ m_role[A].m_pRole = 0;
+ m_role[B].m_pRole = 0;
+ m_role[A].m_pWidget = 0;
+ m_role[B].m_pWidget = 0;
+
+ // associationwidget attributes
+ m_role[A].m_WidgetRegion = Error;
+ m_role[B].m_WidgetRegion = Error;
+ m_role[A].m_nIndex = 0;
+ m_role[B].m_nIndex = 0;
+ m_role[A].m_nTotalCount = 0;
+ m_role[B].m_nTotalCount = 0;
+ m_role[A].m_Visibility = Uml::Visibility::Public;
+ m_role[B].m_Visibility = Uml::Visibility::Public;
+ m_role[A].m_Changeability = Uml::chg_Changeable;
+ m_role[B].m_Changeability = Uml::chg_Changeable;
+ m_positions_len = 0;
+ m_bActivated = false;
+ m_unNameLineSegment = 0;
+ m_pMenu = 0;
+ m_bSelected = false;
+ m_nMovingPoint = -1;
+ m_nLinePathSegmentIndex = -1;
+ m_pAssocClassWidget = NULL;
+ m_pAssocClassLine = NULL;
+ m_pAssocClassLineSel0 = m_pAssocClassLineSel1 = NULL;
+
+ // Initialize local members.
+ // These are only used if we don't have a UMLAssociation attached.
+ m_AssocType = Uml::at_Association;
+ m_umldoc = UMLApp::app()->getDocument();
+ m_LinePath.setAssociation( this );
+
+ connect(m_pView, SIGNAL(sigRemovePopupMenu()), this, SLOT(slotRemovePopupMenu()));
+ connect(m_pView, SIGNAL( sigClearAllSelected() ), this, SLOT( slotClearAllSelected() ) );
+}
+
+void AssociationWidget::resetTextPositions() {
+ if (m_role[A].m_pMulti) {
+ setTextPosition( tr_MultiA );
+ }
+ if (m_role[B].m_pMulti) {
+ setTextPosition( tr_MultiB );
+ }
+ if (m_role[A].m_pChangeWidget) {
+ setTextPosition( tr_ChangeA );
+ }
+ if (m_role[B].m_pChangeWidget) {
+ setTextPosition( tr_ChangeB );
+ }
+ if (m_pName) {
+ setTextPosition( tr_Name );
+ }
+ if (m_role[A].m_pRole) {
+ setTextPosition( tr_RoleAName );
+ }
+ if (m_role[B].m_pRole) {
+ setTextPosition( tr_RoleBName );
+ }
+}
+
+void AssociationWidget::setIndex(int index, Uml::Role_Type role) {
+ m_role[role].m_nIndex = index;
+}
+
+int AssociationWidget::getIndex(Uml::Role_Type role) const {
+ return m_role[role].m_nIndex;
+}
+
+void AssociationWidget::setTotalCount(int count, Uml::Role_Type role) {
+ m_role[role].m_nTotalCount = count;
+}
+
+int AssociationWidget::getTotalCount(Uml::Role_Type role) const {
+ return m_role[role].m_nTotalCount;
+}
+
+UMLOperation *AssociationWidget::getOperation() {
+ return dynamic_cast<UMLOperation*>(m_pObject);
+}
+
+void AssociationWidget::setOperation(UMLOperation *op) {
+ if (m_pObject)
+ disconnect(m_pObject, SIGNAL(modified()), m_pName, SLOT(setMessageText()));
+ m_pObject = op;
+ if (m_pObject)
+ connect(m_pObject, SIGNAL(modified()), m_pName, SLOT(setMessageText()));
+}
+
+UMLClassifier *AssociationWidget::getOperationOwner() {
+ Uml::Role_Type role = (isCollaboration() ? B : A);
+ UMLObject *o = getWidget(role)->getUMLObject();
+ if (o == NULL)
+ return NULL;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ if (c == NULL)
+ kError() << "AssociationWidget::getOperationOwner: "
+ << "getWidget(" << role << ") is not a classifier"
+ << endl;
+ return c;
+}
+
+void AssociationWidget::setSeqNumAndOp(const QString &seqNum, const QString &op) {
+ if (! op.isEmpty())
+ setName(op);
+ setMulti(seqNum, A);
+}
+
+UMLClassifier *AssociationWidget::getSeqNumAndOp(QString& seqNum, QString& op) {
+ seqNum = getMulti(A);
+ op = getName();
+ UMLObject *o = getWidget(B)->getUMLObject();
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ return c;
+}
+
+void AssociationWidget::setCustomOpText(const QString &opText) {
+ setName(opText);
+}
+
+QString AssociationWidget::getCustomOpText() {
+ return getName();
+}
+
+void AssociationWidget::setWidget( UMLWidget* widget, Uml::Role_Type role) {
+ m_role[role].m_pWidget = widget;
+ if (widget) {
+ m_role[role].m_pWidget->addAssoc(this);
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ getAssociation()->setObject(widget->getUMLObject(), role);
+ }
+}
+
+void AssociationWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement assocElement = qDoc.createElement( "assocwidget" );
+
+ WidgetBase::saveToXMI(qDoc, assocElement);
+ if (m_pObject) {
+ assocElement.setAttribute( "xmi.id", ID2STR(m_pObject->getID()) );
+ }
+ assocElement.setAttribute( "type", m_AssocType );
+ if (getAssociation() == NULL) {
+ assocElement.setAttribute( "visibilityA", m_role[A].m_Visibility);
+ assocElement.setAttribute( "visibilityB", m_role[B].m_Visibility);
+ assocElement.setAttribute( "changeabilityA", m_role[A].m_Changeability);
+ assocElement.setAttribute( "changeabilityB", m_role[B].m_Changeability);
+ if (m_pObject == NULL) {
+ assocElement.setAttribute( "roleAdoc", m_role[A].m_RoleDoc);
+ assocElement.setAttribute( "roleBdoc", m_role[B].m_RoleDoc);
+ assocElement.setAttribute( "documentation", m_Doc );
+ }
+ }
+ assocElement.setAttribute( "widgetaid", ID2STR(getWidgetID(A)) );
+ assocElement.setAttribute( "widgetbid", ID2STR(getWidgetID(B)) );
+ assocElement.setAttribute( "indexa", m_role[A].m_nIndex );
+ assocElement.setAttribute( "indexb", m_role[B].m_nIndex );
+ assocElement.setAttribute( "totalcounta", m_role[A].m_nTotalCount );
+ assocElement.setAttribute( "totalcountb", m_role[B].m_nTotalCount );
+ m_LinePath.saveToXMI( qDoc, assocElement );
+
+ if( m_pName )
+ m_pName -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[A].m_pMulti )
+ m_role[A].m_pMulti -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[B].m_pMulti )
+ m_role[B].m_pMulti -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[A].m_pRole )
+ m_role[A].m_pRole -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[B].m_pRole )
+ m_role[B].m_pRole -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[A].m_pChangeWidget )
+ m_role[A].m_pChangeWidget -> saveToXMI( qDoc, assocElement );
+
+ if( m_role[B].m_pChangeWidget )
+ m_role[B].m_pChangeWidget -> saveToXMI( qDoc, assocElement );
+
+ if (m_pAssocClassWidget) {
+ QString acid = ID2STR(m_pAssocClassWidget->getID());
+ assocElement.setAttribute("assocclass", acid);
+ assocElement.setAttribute("aclsegindex", m_nLinePathSegmentIndex);
+ }
+
+ qElement.appendChild( assocElement );
+}
+
+bool AssociationWidget::loadFromXMI( QDomElement & qElement,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* pMessages )
+{
+ WidgetBase::loadFromXMI(qElement);
+
+ // load child widgets first
+ QString widgetaid = qElement.attribute( "widgetaid", "-1" );
+ QString widgetbid = qElement.attribute( "widgetbid", "-1" );
+ Uml::IDType aId = STR2ID(widgetaid);
+ Uml::IDType bId = STR2ID(widgetbid);
+ UMLWidget *pWidgetA = Widget_Utils::findWidget( aId, widgets, pMessages );
+ if (!pWidgetA) {
+ kError() << "AssociationWidget::loadFromXMI(): "
+ << "cannot find widget for roleA id " << ID2STR(aId) << endl;
+ return false;
+ }
+ UMLWidget *pWidgetB = Widget_Utils::findWidget( bId, widgets, pMessages );
+ if (!pWidgetB) {
+ kError() << "AssociationWidget::loadFromXMI(): "
+ << "cannot find widget for roleB id " << ID2STR(bId) << endl;
+ return false;
+ }
+ setWidget(pWidgetA, A);
+ setWidget(pWidgetB, B);
+
+ QString type = qElement.attribute( "type", "-1" );
+ Uml::Association_Type aType = (Uml::Association_Type) type.toInt();
+
+ QString id = qElement.attribute( "xmi.id", "-1" );
+ bool oldStyleLoad = false;
+ if (id == "-1") {
+ // xmi.id not present, ergo either a pure widget association,
+ // or old (pre-1.2) style:
+ // Everything is loaded from the AssociationWidget.
+ // UMLAssociation may or may not be saved - if it is, it's a dummy.
+ // Create the UMLAssociation if both roles are UML objects;
+ // else load the info locally.
+
+ if (UMLAssociation::assocTypeHasUMLRepresentation(aType)) {
+ // lack of an association in our widget AND presence of
+ // both uml objects for each role clearly identifies this
+ // as reading in an old-school file. Note it as such, and
+ // create, and add, the UMLAssociation for this widget.
+ // Remove this special code when backwards compatibility
+ // with older files isn't important anymore. -b.t.
+ UMLObject* umlRoleA = pWidgetA->getUMLObject();
+ UMLObject* umlRoleB = pWidgetB->getUMLObject();
+ if (!m_pObject && umlRoleA && umlRoleB)
+ {
+ oldStyleLoad = true; // flag for further special config below
+ if (aType == at_Aggregation || aType == at_Composition) {
+ kWarning()<<" Old Style save file? swapping roles on association widget"<<this<<endl;
+ // We have to swap the A and B widgets to compensate
+ // for the long standing bug in LinePath of drawing
+ // the diamond at the wrong end which was fixed
+ // just before the 1.2 release.
+ // The logic here is that the user has understood
+ // that the diamond belongs at the SOURCE end of the
+ // the association (i.e. at the container, not at the
+ // contained), and has compensated for this anomaly
+ // by drawing the aggregations/compositions from
+ // target to source.
+ UMLWidget *tmpWidget = pWidgetA;
+ pWidgetA = pWidgetB;
+ pWidgetB = tmpWidget;
+ setWidget(pWidgetA, A);
+ setWidget(pWidgetB, B);
+ umlRoleA = pWidgetA->getUMLObject();
+ umlRoleB = pWidgetB->getUMLObject();
+ }
+
+ setUMLAssociation(m_umldoc->createUMLAssociation(umlRoleA, umlRoleB, aType));
+ }
+ }
+
+ setDoc( qElement.attribute("documentation", "") );
+ setRoleDoc( qElement.attribute("roleAdoc", ""), A );
+ setRoleDoc( qElement.attribute("roleBdoc", ""), B );
+
+ // visibilty defaults to Public if it cant set it here..
+ QString visibilityA = qElement.attribute( "visibilityA", "0");
+ if (visibilityA.toInt() > 0)
+ setVisibility( (Uml::Visibility::Value)visibilityA.toInt(), A);
+
+ QString visibilityB = qElement.attribute( "visibilityB", "0");
+ if (visibilityB.toInt() > 0)
+ setVisibility( (Uml::Visibility::Value)visibilityB.toInt(), B);
+
+ // Changeability defaults to "Changeable" if it cant set it here..
+ QString changeabilityA = qElement.attribute( "changeabilityA", "0");
+ if (changeabilityA.toInt() > 0)
+ setChangeability( (Uml::Changeability_Type)changeabilityA.toInt(), A);
+
+ QString changeabilityB = qElement.attribute( "changeabilityB", "0");
+ if (changeabilityB.toInt() > 0)
+ setChangeability( (Uml::Changeability_Type)changeabilityB.toInt(), B);
+
+ } else {
+
+ // we should disconnect any prior association (can this happen??)
+ if (m_pObject && m_pObject->getBaseType() == ot_Association)
+ {
+ UMLAssociation *umla = getAssociation();
+ umla->disconnect(this);
+ umla->nrof_parent_widgets--;
+ }
+
+ // New style: The xmi.id is a reference to the UMLAssociation.
+ // If the UMLObject is not found right now, we try again later
+ // during the type resolution pass - see activate().
+ m_nId = STR2ID(id);
+ UMLObject *myObj = m_umldoc->findObjectById(m_nId);
+ if (myObj) {
+ const Uml::Object_Type ot = myObj->getBaseType();
+ if (ot != ot_Association) {
+ setUMLObject(myObj);
+ } else {
+ UMLAssociation * myAssoc = static_cast<UMLAssociation*>(myObj);
+ setUMLAssociation(myAssoc);
+ if (type == "-1")
+ aType = myAssoc->getAssocType();
+ }
+ }
+ }
+
+ setAssocType(aType);
+
+ QString indexa = qElement.attribute( "indexa", "0" );
+ QString indexb = qElement.attribute( "indexb", "0" );
+ QString totalcounta = qElement.attribute( "totalcounta", "0" );
+ QString totalcountb = qElement.attribute( "totalcountb", "0" );
+ m_role[A].m_nIndex = indexa.toInt();
+ m_role[B].m_nIndex = indexb.toInt();
+ m_role[A].m_nTotalCount = totalcounta.toInt();
+ m_role[B].m_nTotalCount = totalcountb.toInt();
+
+ QString assocclassid = qElement.attribute("assocclass", "");
+ if (! assocclassid.isEmpty()) {
+ Uml::IDType acid = STR2ID(assocclassid);
+ UMLWidget *w = Widget_Utils::findWidget(acid, widgets);
+ if (w) {
+ m_pAssocClassWidget = static_cast<ClassifierWidget*>(w);
+ m_pAssocClassWidget->setClassAssocWidget(this);
+ // Preparation of the assoc class line is done in activate()
+ QString aclsegindex = qElement.attribute("aclsegindex", "0");
+ m_nLinePathSegmentIndex = aclsegindex.toInt();
+ } else {
+ kError() << "AssociationWidget::loadFromXMI: "
+ << "cannot find assocclass " << assocclassid
+ << endl;
+ }
+ }
+
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if( tag == "linepath" ) {
+ if( !m_LinePath.loadFromXMI( element ) )
+ return false;
+ else {
+ // set up 'old' corner from first point in line
+ // as IF this ISNT done, then the subsequent call to
+ // widgetMoved will inadvertantly think we have made a
+ // big move in the position of the association when we haven't.
+ QPoint p = m_LinePath.getPoint(0);
+ m_role[A].m_OldCorner.setX(p.x());
+ m_role[A].m_OldCorner.setY(p.y());
+ }
+ } else if (tag == "floatingtext" ||
+ tag == "UML:FloatingTextWidget") { // for bkwd compatibility
+ QString r = element.attribute( "role", "-1");
+ if( r == "-1" )
+ return false;
+ Uml::Text_Role role = (Uml::Text_Role)r.toInt();
+ FloatingTextWidget *ft = new FloatingTextWidget(m_pView, role, "", Uml::id_Reserved);
+ if( ! ft->loadFromXMI(element) ) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete ft;
+ node = element.nextSibling();
+ element = node.toElement();
+ continue;
+ }
+ // always need this
+ ft->setLink(this);
+
+ switch( role ) {
+ case Uml::tr_MultiA:
+ m_role[A].m_pMulti = ft;
+ if(oldStyleLoad)
+ setMulti(m_role[A].m_pMulti->getText(), A);
+ break;
+
+ case Uml::tr_MultiB:
+ m_role[B].m_pMulti = ft;
+ if(oldStyleLoad)
+ setMulti(m_role[B].m_pMulti->getText(), B);
+ break;
+
+ case Uml::tr_ChangeA:
+ m_role[A].m_pChangeWidget = ft;
+ break;
+
+ case Uml::tr_ChangeB:
+ m_role[B].m_pChangeWidget = ft;
+ break;
+
+ case Uml::tr_Name:
+ m_pName = ft;
+ if(oldStyleLoad)
+ setName(m_pName->getText());
+ break;
+
+ case Uml::tr_Coll_Message:
+ case Uml::tr_Coll_Message_Self:
+ m_pName = ft;
+ ft->setLink(this);
+ ft->setActivated();
+ if(FloatingTextWidget::isTextValid(ft->getText()))
+ ft -> show();
+ else
+ ft -> hide();
+ break;
+
+ case Uml::tr_RoleAName:
+ m_role[A].m_pRole = ft;
+ setRoleName( ft->getText(), A );
+ break;
+ case Uml::tr_RoleBName:
+ m_role[B].m_pRole = ft;
+ setRoleName( ft->getText(), B );
+ break;
+ default:
+ kDebug() << "AssociationWidget::loadFromXMI(): "
+ << "unexpected FloatingTextWidget (textrole "
+ << role << ")" << endl;
+ delete ft;
+ break;
+ }
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ return true;
+}
+
+bool AssociationWidget::loadFromXMI( QDomElement & qElement ) {
+ const MessageWidgetList& messages = m_pView->getMessageList();
+ return loadFromXMI( qElement, m_pView->getWidgetList(), &messages );
+}
+
+#include "associationwidget.moc"
diff --git a/umbrello/umbrello/associationwidget.h b/umbrello/umbrello/associationwidget.h
new file mode 100644
index 00000000..67739450
--- /dev/null
+++ b/umbrello/umbrello/associationwidget.h
@@ -0,0 +1,1045 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCIATIONWIDGET_H
+#define ASSOCIATIONWIDGET_H
+
+#include "widgetbase.h"
+#include "linkwidget.h"
+#include "umlwidgetlist.h"
+#include "messagewidgetlist.h"
+#include "associationwidgetlist.h"
+#include "linepath.h"
+
+class IDChangeLog;
+class ListPopupMenu;
+class QBitmap;
+class QPixmap;
+class QDataStream;
+class QCanvasLine;
+class ClassifierWidget;
+class UMLDoc;
+class UMLView;
+class UMLAssociation;
+class UMLClassifierListItem;
+class UMLAttribute;
+class UMLOperation;
+
+/**
+ * This class represents an association inside a diagram.
+ *
+ * Associations exist not only between UML objects. For example, when a Note is
+ * attached to a UML object, the Note itself is not a UML object.
+ * This class supports both kinds of associations. An association where one or
+ * both roles are not a UML object is called a "pure widget association".
+ *
+ * An AssociationWidget where both roles are UML objects has a corresponding
+ * UMLAssociation. The UMLAssociation can be retrieved using the getAssociation
+ * method.
+ * A pure widget association does not have a corresponding UMLAssociation.
+ * The getAssociation method returns NULL in this case.
+ *
+ *
+ * @author Gustavo Madrigal
+ * @short This class represents an association inside a diagram.
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssociationWidget : public WidgetBase, public LinkWidget {
+ Q_OBJECT
+public:
+ /**
+ * Enumeration used for stating where a line is on a widget.
+ */
+ enum Region {
+ Error = 0,
+ West, North, East, South,
+ NorthWest, NorthEast, SouthEast, SouthWest,
+ Center
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param view The parent view of this widget.
+ */
+ AssociationWidget(UMLView *view);
+
+ /**
+ * Constructor.
+ *
+ * @param view The parent view of this widget.
+ * @param WidgetA Pointer to the role A widget for the association.
+ * @param Type The Association_Type for this association.
+ * @param WidgetB Pointer to the role B widget for the association.
+ * @param umlobject Pointer to the underlying UMLObject (if applicable.)
+ */
+ AssociationWidget(UMLView *view, UMLWidget* WidgetA,
+ Uml::Association_Type Type, UMLWidget* WidgetB,
+ UMLObject *umlobject = NULL);
+
+ /**
+ * Deconstructor.
+ */
+ virtual ~AssociationWidget();
+
+ /**
+ * Overrides the assignment operator.
+ */
+ AssociationWidget& operator=(AssociationWidget & Other);
+
+ /**
+ * Overrides the equality test operator.
+ */
+ bool operator==(AssociationWidget & Other);
+
+ /**
+ * Overrides the != operator.
+ */
+ bool operator!=(AssociationWidget & Other);
+
+ /**
+ * Activates the AssociationWidget after a load.
+ *
+ * @return true for success
+ */
+ bool activate();
+
+ /**
+ * Set the widget of the given role.
+ *
+ * @param widget Pointer to the UMLWidget.
+ * @param role Role for which to set the widget.
+ */
+ void setWidget(UMLWidget* widget, Uml::Role_Type role);
+
+ /**
+ * Return the multiplicity FloatingTextWidget widget of the given role.
+ *
+ * @return Pointer to the multiplicity FloatingTextWidget object.
+ */
+ FloatingTextWidget* getMultiWidget(Uml::Role_Type role);
+
+ /**
+ * Return the given role's multiplicity text.
+ *
+ * @return Text of the given role's multiplicity widget.
+ */
+ QString getMulti(Uml::Role_Type role) const;
+
+ /**
+ * Read property of FloatingTextWidget* m_pName.
+ *
+ * @return Pointer to the FloatingTextWidget name widget.
+ */
+ FloatingTextWidget* getNameWidget();
+
+ /**
+ * Returns the m_pName's text.
+ *
+ * @return Text of the FloatingTextWidget name widget.
+ */
+ QString getName() const;
+
+ /**
+ * Return the given role's FloatingTextWidget object.
+ *
+ * @return Pointer to the role's FloatingTextWidget widget.
+ */
+ FloatingTextWidget* getRoleWidget(Uml::Role_Type role);
+
+ /**
+ * Return the FloatingTextWidget object indicated by the given Text_Role.
+ *
+ * @return Pointer to the text role's FloatingTextWidget widget.
+ */
+ FloatingTextWidget* getTextWidgetByRole(Uml::Text_Role tr);
+
+ /**
+ * Return the given role's FloatingTextWidget widget text.
+ *
+ * @return The name set at the FloatingTextWidget.
+ */
+ QString getRoleName(Uml::Role_Type role) const;
+
+ /**
+ * Returns the given role's documentation.
+ */
+ QString getRoleDoc(Uml::Role_Type role) const;
+
+ /**
+ * Sets the text in the FloatingTextWidget widget representing the Name
+ * of this association.
+ */
+ void setName (const QString &strRole);
+
+ /**
+ * Sets the text in the FloatingTextWidget representing the multiplicity
+ * at the given side of the association.
+ */
+ void setMulti(const QString &strMulti, Uml::Role_Type role);
+
+ /**
+ * Gets the visibility on the given role of the association.
+ */
+ Uml::Visibility getVisibility (Uml::Role_Type role) const;
+
+ /**
+ * Sets the visibility on the given role of the association.
+ */
+ void setVisibility (Uml::Visibility visibility, Uml::Role_Type role );
+
+ /**
+ * Gets the changeability on the the given end of the Association.
+ */
+ Uml::Changeability_Type getChangeability(Uml::Role_Type role) const;
+
+ /**
+ * Sets the changeability on the the given end of the Association.
+ */
+ void setChangeability (Uml::Changeability_Type value, Uml::Role_Type role);
+
+ /**
+ * Gets the ID of the given role widget.
+ */
+ Uml::IDType getWidgetID(Uml::Role_Type role) const;
+
+ /**
+ * Gets the given role widget.
+ *
+ * @return Pointer to the role's UMLWidget.
+ */
+ UMLWidget* getWidget(Uml::Role_Type role);
+
+ /**
+ * Sets the associated widgets.
+ *
+ * @param widgetA Pointer the role A widget for the association.
+ * @param assocType The Association_Type for this association.
+ * @param widgetB Pointer the role B widget for the association.
+ */
+ bool setWidgets( UMLWidget* widgetA, Uml::Association_Type assocType, UMLWidget* widgetB);
+
+ /**
+ * Returns true if this association associates widgetA to widgetB,
+ * otherwise it returns false.
+ *
+ * @param widgetA Pointer the role A widget to check.
+ * @param widgetB Pointer the role B widget to check.
+ * @return True if widgetA and widgetB are associated.
+ */
+ bool checkAssoc(UMLWidget * widgetA, UMLWidget *widgetB);
+
+ /**
+ * Returns true if the Widget is either at the starting or ending side
+ * of the association.
+ *
+ * @return True if widget plays role A or B in this assoc.
+ */
+ bool contains(UMLWidget* widget);
+
+ /**
+ * Returns true if this AssociationWidget represents a collaboration message.
+ */
+ bool isCollaboration();
+
+ /**
+ * Gets the association's type.
+ *
+ * @return This AssociationWidget's Association_Type.
+ */
+ Uml::Association_Type getAssocType() const;
+
+ /**
+ * Sets the association's type.
+ *
+ * @param type The Association_Type to set.
+ */
+ void setAssocType(Uml::Association_Type type);
+
+ /**
+ * Returns a QString object representing this AssociationWidget.
+ *
+ * @return Textual representation of the AssociationWidget.
+ */
+ QString toString();
+
+ /**
+ * Read property of bool m_bActivated.
+ *
+ * @return True if this AssociationWidget has been activated.
+ */
+ bool isActivated();
+
+ /**
+ * Set the m_bActivated flag of a widget but does not perform the
+ * activate method.
+ *
+ * @param active The flag status to set.
+ */
+ void setActivated(bool active /*=true*/);
+
+ /**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select The state of whether the widget is selected.
+ */
+ void setSelected(bool _select = true);
+
+ /**
+ * Returns the state of whether the widget is selected.
+ *
+ * @return Returns the state of whether the widget is selected.
+ */
+ bool getSelected() const {
+ return m_bSelected;
+ }
+
+ /**
+ * Returns a pointer to the association widget's line path.
+ */
+ LinePath* getLinePath() {
+ return &m_LinePath;
+ }
+
+ /**
+ * Adjusts the ending point of the association that connects to Widget
+ *
+ * @param widget Pointer to the widget that was moved.
+ * @param x New X coordinate of the widget.
+ * @param y New Y coordinate of the widget.
+ */
+ void widgetMoved(UMLWidget* widget, int x, int y);
+
+ /**
+ * Auxiliary method for widgetMoved():
+ * Saves all ideally computed floatingtext positions before doing any
+ * kind of change. This is necessary because a single invocation of
+ * calculateEndingPoints() modifies the LinePath ending points on ALL
+ * AssociationWidgets. This means that if we don't save the old ideal
+ * positions then they are irretrievably lost as soon as
+ * calculateEndingPoints() is invoked.
+ */
+ void saveIdealTextPositions();
+
+ /**
+ * Calculates the m_unNameLineSegment value according to the new
+ * NameText topleft corner PT.
+ * It iterates through all LinePath's segments and for each one
+ * calculates the sum of PT's distance to the start point + PT's
+ * distance to the end point. The segment with the smallest sum will
+ * be the RoleTextSegment (if this segment moves then the RoleText
+ * will move with it). It sets m_unNameLineSegment to the start point
+ * of the chosen segment.
+ *
+ * Overrides operation from LinkWidget (i.e. this method is also
+ * required by FloatingTextWidget.)
+ */
+ void calculateNameTextSegment();
+
+ /**
+ * Adds a break point (if left mouse button).
+ */
+ void mouseDoubleClickEvent(QMouseEvent * me);
+
+ /**
+ * Sets the association to be selected.
+ */
+ void mousePressEvent(QMouseEvent * me);
+
+ /**
+ * Displays the right mouse buttom menu if right button is pressed.
+ */
+ void mouseReleaseEvent(QMouseEvent * me);
+
+ /**
+ * Moves the break point being dragged.
+ */
+ void mouseMoveEvent(QMouseEvent * me);
+
+ /**
+ * Returns true if the given point is on the Association.
+ */
+ bool onAssociation(const QPoint & point);
+
+ /**
+ * Returns true if the given point is on the connecting line to
+ * the association class. Returns false if there is no association
+ * class attached, or if the given point is not on the connecting
+ * line.
+ */
+ bool onAssocClassLine(const QPoint & point);
+
+ /**
+ * Creates the association class connecting line.
+ */
+ void createAssocClassLine();
+
+ /**
+ * Creates the association class connecting line using the specified
+ * ClassifierWidget.
+ *
+ * @param classifierWidget The ClassifierWidget to use.
+ * @param linePathSegmentIndex The index of the segment where the
+ * association class is created.
+ */
+ void createAssocClassLine(ClassifierWidget* classifierWidget,
+ int linePathSegmentIndex);
+
+ /**
+ * Renders the association class connecting line selected.
+ */
+ void selectAssocClassLine(bool sel = true);
+
+ /**
+ * Moves all the mid points (all expcept start /end ) by the given amount.
+ */
+ void moveMidPointsBy( int x, int y );
+
+ /**
+ * Moves the entire association by the given offset.
+ */
+ void moveEntireAssoc( int x, int y );
+
+ /**
+ * Returns the bounding rectangle of all segments of the association.
+ */
+ QRect getAssocLineRectangle();
+
+ /**
+ * Return the first font found being used by any child widget. (They
+ * could be different fonts, so this is a slightly misleading method.)
+ */
+ QFont getFont () const;
+
+ /**
+ * Overrides the method from WidgetBase.
+ */
+ void setLineColor(const QColor &colour);
+
+ /**
+ * Overrides the method from WidgetBase.
+ */
+ void setLineWidth(uint width);
+
+ /**
+ * Set all 'owned' child widgets to this font.
+ */
+ void lwSetFont (QFont font);
+
+ /**
+ * Return the given role's changeability FloatingTextWidget widget.
+ */
+ FloatingTextWidget* getChangeWidget(Uml::Role_Type role);
+
+ /**
+ * Sets the text to the FloatingTextWidget that display the Role text of this
+ * association.
+ * For this function to work properly, the associated widget
+ * should already be set.
+ */
+ void setRoleName(const QString &strRole, Uml::Role_Type role);
+
+ /**
+ * Set the documentation on the given role.
+ */
+ void setRoleDoc(const QString &doc, Uml::Role_Type role);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ * @todo Move to LinkWidget.
+ */
+ UMLClassifier *getOperationOwner();
+
+ /**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+ UMLOperation *getOperation();
+
+ /**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+ void setOperation(UMLOperation *op);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ QString getCustomOpText();
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ void setCustomOpText(const QString &opText);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ */
+ void setMessageText(FloatingTextWidget *ft);
+
+ /**
+ * Returns the UMLAssociation representation of this object.
+ *
+ * @return Pointer to the UMLAssociation that is represented by
+ * this AsociationWidget.
+ */
+ UMLAssociation * getAssociation() const;
+
+ /**
+ * Returns the UMLAttribute representation of this object.
+ *
+ * @return Pointer to the UMLAttribute that is represented by
+ * this AsociationWidget.
+ */
+ UMLAttribute * getAttribute() const;
+
+ /**
+ * Sets the text of the given FloatingTextWidget.
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ void setText(FloatingTextWidget *ft, const QString &text);
+
+ /**
+ * Calls @ref setTextPosition() on all the labels.
+ * Overrides operation from LinkWidget.
+ */
+ void resetTextPositions();
+
+ /**
+ * Constrains the FloatingTextWidget X and Y values supplied.
+ * Implements the abstract operation from LinkWidget.
+ *
+ * @param textX Candidate X value (may be modified by the constraint.)
+ * @param textY Candidate Y value (may be modified by the constraint.)
+ * @param textWidth Width of the text.
+ * @param textHeight Height of the text.
+ * @param tr Uml::Text_Role of the text.
+ */
+ void constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
+ Uml::Text_Role tr);
+
+ /**
+ * Shows the association properties dialog and updates the
+ * corresponding texts if its execution is successful.
+ * Returns true for success.
+ */
+ bool showDialog();
+
+ /**
+ * Sets the Association line index for the given role.
+ */
+ void setIndex(int index, Uml::Role_Type role);
+
+ /**
+ * Returns the Association line index for the given role.
+ */
+ int getIndex(Uml::Role_Type role) const;
+
+ /**
+ * Sets the total count on the Association region.
+ */
+ void setTotalCount(int count, Uml::Role_Type role);
+
+ /**
+ * Returns the total count on the Association region.
+ */
+ int getTotalCount(Uml::Role_Type role) const;
+
+ /**
+ * Sets the total count on the Association region for widgetB.
+ */
+ void setTotalCount(int count);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param seqNum The new sequence number string to set.
+ * @param op The new operation string to set.
+ */
+ void setSeqNumAndOp(const QString &seqNum, const QString &op);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param seqNum Return this AssociationWidget's sequence number string.
+ * @param op Return this AssociationWidget's operation string.
+ */
+ UMLClassifier * getSeqNumAndOp(QString& seqNum, QString& op);
+
+ /**
+ * Calculates and sets the first and last point in the association's
+ * LinePath.
+ * Each point is a middle point of its respective UMLWidget's bounding
+ * rectangle.
+ * This method picks which sides to use for the association.
+ */
+ void calculateEndingPoints();
+
+ /**
+ * Remove dashed connecting line for association class.
+ */
+ void removeAssocClassLine();
+
+ /**
+ * Compute the end points of m_pAssocClassLine in case this
+ * association has an attached association class.
+ */
+ void computeAssocClassLine();
+
+ /**
+ * Overriding the method from WidgetBase because we need to do
+ * something extra in case this AssociationWidget represents
+ * an attribute of a classifier.
+ */
+ void setUMLObject(UMLObject *obj);
+
+ /**
+ * Saves this widget to the "assocwidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads this widget from the "assocwidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+ /**
+ * Same as above, but uses the supplied widgetList for resolving
+ * the role A and role B widgets. (The other loadFromXMI() queries
+ * the UMLView for these widgets.)
+ * Required for clipboard operations.
+ */
+ bool loadFromXMI( QDomElement & qElement, const UMLWidgetList& widgets,
+ const MessageWidgetList* pMessages = NULL);
+
+ /**
+ * Cleans up all the association's data in the related widgets.
+ */
+ void cleanup();
+
+private:
+
+ /** set our internal umlAssociation */
+ void setUMLAssociation (UMLAssociation * assoc);
+
+ /**
+ * Merges/syncs the association widget data into UML object
+ * representation.
+ * CHECK: Can we get rid of this.
+ */
+ void mergeAssociationDataIntoUMLRepresentation();
+
+ /**
+ * Finds out which region contains the point (PosX, PosY).
+ *
+ * The diagram is divided into four regions by its diagonals :
+ *
+ * Region 2
+ * \ /
+ * \ /
+ * +--------+
+ * | \ / |
+ * Region 1 | >< | Region 3
+ * | / \ |
+ * +--------+
+ * / \
+ * / \
+ * Region 4
+ *
+ *
+ * @param Rect The bounding rectangle to investigate.
+ * @param PosX X coordinate of the point to seek.
+ * @param PosY Y coordinate of the point to seek.
+ * @return The region number of the region containing the point.
+ * 1 = Region 1
+ * 2 = Region 2
+ * 3 = Region 3
+ * 4 = Region 4
+ * 5 = On diagonal 2 between Region 1 and 2
+ * 6 = On diagonal 1 between Region 2 and 3
+ * 7 = On diagonal 2 between Region 3 and 4
+ * 8 = On diagonal 1 between Region4 and 1
+ * 9 = On diagonal 1 and On diagonal 2 (the center)
+ */
+ static Region findPointRegion(const QRect& Rect, int PosX, int PosY);
+
+ /**
+ * Given a rectangle and a point, findInterceptOnEdge computes the
+ * connecting line between the middle point of the rectangle and
+ * the point, and returns the intercept of this line with the
+ * the edge of the rectangle identified by `region'.
+ * When the region is North or South, the X value is returned (Y is
+ * constant.)
+ * When the region is East or West, the Y value is returned (X is
+ * constant.)
+ * @todo This is buggy. Try replacing by findIntercept()
+ */
+ static int findInterceptOnEdge(const QRect &rect, Region region, const QPoint &point);
+
+ static QPoint findIntercept(const QRect &rect, const QPoint &point);
+
+ /**
+ * Overrides moveEvent.
+ */
+ void moveEvent(QMoveEvent *me);
+
+ /**
+ * This function calculates which role should be set for the m_pName
+ * FloatingTextWidget.
+ */
+ Uml::Text_Role CalculateNameType(Uml::Text_Role defaultRoleType);
+
+ /**
+ * Returns true if point (PosX, PosY) is close enough to any of the
+ * association's segments.
+ */
+ bool isPointInsideBoundaries(int PosX, int PosY, QPoint & SPoint,
+ uint & StartSegmentIndex, uint & EndSegmentIndex);
+
+ /**
+ * Returns a point with interchanged X and Y coordinates.
+ */
+ static QPoint swapXY(const QPoint &p);
+
+ /**
+ * Returns the total length of the association's LinePath:
+ * result = segment_1_length + segment_2_length + ... + segment_n_length
+ */
+ float totalLength();
+
+ /**
+ * Calculates which point of segment P1P2 has a distance equal to
+ * Distance from P1.
+ * Let's say such point is PX, the distance from P1 to PX must be equal
+ * to Distance and if PX is not a point of the segment P1P2 then the
+ * function returns (-1,-1).
+ */
+ static QPoint calculatePointAtDistance(const QPoint &P1, const QPoint &P2, float Distance);
+
+ /**
+ * Calculates which point of a perpendicular line to segment P1P2 that
+ * contains P2 has a distance equal to Distance from P2.
+ * Let's say such point is PX, the distance from P2 to PX must be equal
+ * to Distance.
+ */
+ static QPoint calculatePointAtDistanceOnPerpendicular(const QPoint &P1, const QPoint &P2, float Distance);
+
+ /**
+ * Calculates the intersection between line P1P2 and a perpendicular
+ * line containing P3, the result is returned in ResultingPoint.
+ * The result value represents the distance between ResultingPoint and
+ * P3. If this value is negative an error ocurred.
+ * This method is not currently used.
+ */
+ static float perpendicularProjection(const QPoint& P1, const QPoint& P2, const QPoint& P3, QPoint& ResultingPoint);
+
+ /**
+ * Return the mid point between p0 and p1
+ */
+ static QPoint midPoint(const QPoint& p0, const QPoint& p1);
+
+ /**
+ * Calculates the position of the text widget depending on the role
+ * that widget is playing.
+ * Returns the point at which to put the widget.
+ */
+ QPoint calculateTextPosition(Uml::Text_Role role);
+
+ /**
+ * Puts the text widget with the given role at the given position.
+ * This method calls @ref calculateTextPostion to get the needed position.
+ * I.e. the line segment it is on has moved and it should move the same
+ * amount as the line.
+ */
+ void setTextPosition(Uml::Text_Role role);
+
+ /**
+ * Moves the text widget with the given role by the difference between
+ * the two points.
+ */
+ void setTextPositionRelatively(Uml::Text_Role role, const QPoint &oldPosition);
+
+ /**
+ * Returns the Region the widget to line intersection is for the given
+ * widget in this Association. If the given widget is not in the
+ * Association then Region::Error is returned.
+ * Used by @ref calculateEndingPoints to work these positions out for
+ * another Association - since the number of Associations on the same
+ * region for the same widget will mean the lines will need to be
+ * spread out across the region.
+ */
+ Region getWidgetRegion(AssociationWidget * widget) const;
+
+ /**
+ * This is a pointer to the Floating Text widget which displays the
+ * name of this association.
+ */
+ FloatingTextWidget* m_pName;
+
+ /**
+ * The WidgetRole struct gathers all information pertaining to the role.
+ * The AssociationWidget class contains two WidgetRole objects, one for each
+ * side of the association (A and B).
+ */
+ struct WidgetRole {
+
+ /**
+ * This is a pointer to the Floating Text widget at the role's side
+ * of the association.
+ * This FloatingTextWidget displays the information regarding multiplicity.
+ */
+ FloatingTextWidget* m_pMulti;
+
+ /**
+ * This is a pointer to the Floating Text widget at the role's side
+ * of the association.
+ * This FloatingTextWidget displays the information regarding changeability.
+ */
+ FloatingTextWidget* m_pChangeWidget;
+
+ /**
+ * This member holds a pointer to the floating text that displays
+ * the role's label of this association.
+ */
+ FloatingTextWidget* m_pRole;
+
+ /**
+ * This member holds a pointer to the UMLWidget at this role's side
+ * of the association.
+ */
+ UMLWidget* m_pWidget;
+
+ /**
+ * This role's old top left corner before moving.
+ */
+ QPoint m_OldCorner;
+
+ /**
+ * The region of this role's widget.
+ */
+ Region m_WidgetRegion;
+
+ /**
+ * The index of where the line is on the region for this role.
+ */
+ int m_nIndex;
+
+ /**
+ * The total amount of associations on the region this role's line is on.
+ */
+ int m_nTotalCount;
+
+ // The following items are only used if m_pObject is not set.
+ Uml::Visibility m_Visibility;
+ Uml::Changeability_Type m_Changeability;
+ QString m_RoleDoc;
+
+ } m_role[2];
+
+ /**
+ * Change, create, or delete the FloatingTextWidget indicated by the given Text_Role.
+ *
+ * @param tr Text_Role of the FloatingTextWidget to change or create.
+ * @param text Text string that controls the action:
+ * If empty and ft is NULL then setFloatingText() is a no-op.
+ * If empty and ft is non-NULL then the existing ft is deleted.
+ * If non-empty and ft is NULL then a new FloatingTextWidget is created
+ * and returned in ft with the text set.
+ * If non-empty and ft is non-NULL then the existing ft text is modified.
+ * @param ft Reference to the pointer to FloatingTextWidget to change or create.
+ * On creation/deletion, the pointer value will be changed.
+ */
+ void setFloatingText(Uml::Text_Role tr, const QString &text, FloatingTextWidget* &ft);
+
+ /**
+ * Called to tell the association that another association has added
+ * a line to the region of one of its widgets. The widget is identified
+ * by its role (A or B).
+ *
+ * Called by @ref updateAssociations which is called by
+ * @ref calculateEndingPoints when required.
+ */
+ void updateRegionLineCount(int index, int totalCount,
+ AssociationWidget::Region region, Uml::Role_Type role);
+
+ /**
+ * Tells all the other view associations the new count for the
+ * given widget on a certain region. And also what index they should be.
+ */
+ void updateAssociations(int totalCount, Region region, Uml::Role_Type role);
+
+ /**
+ * Returns the number of lines there are on the given region for
+ * either widget A or B of the association.
+ */
+ int getRegionCount(Region region, Uml::Role_Type role);
+
+ /**
+ * Initialize attributes of this class at construction time.
+ */
+ void init (UMLView *view);
+
+ /**
+ * Auxiliary method for calculateEndingPoints().
+ */
+ void doUpdates(int otherX, int otherY, Uml::Role_Type role);
+
+ /**
+ * For internal purposes only.
+ * Other classes/users should use setChangeability() instead.
+ */
+ void setChangeWidget(const QString &strChangeWidget, Uml::Role_Type role);
+
+ /**
+ * Checks to see if the given point is one of the points of the line.
+ * If so will try and get the view to flag the point for moving.
+ * This is only valid if no other point id being moved and only
+ * while the left mouse button is down.
+ */
+ void checkPoints(const QPoint &p);
+
+ /**
+ * Returns true if the line path starts at the given widget.
+ */
+ bool linePathStartsAt(const UMLWidget* widget);
+
+ /**
+ * Auxiliary method for updateAssociations():
+ * Put position into m_positions and assoc into m_ordered at the
+ * correct index.
+ * m_positions and m_ordered move in parallel and are sorted by
+ * ascending position.
+ */
+ void insertIntoLists(int position, const AssociationWidget* assoc);
+
+ int m_positions[100]; ///< auxiliary variable for updateAssociations()
+ int m_positions_len; ///< auxiliary variable for updateAssociations()
+ AssociationWidgetList m_ordered; ///< auxiliary variable for updateAssociations()
+
+ /**
+ * Flag which is true if the activate method has been called for this
+ * class instance.
+ */
+ bool m_bActivated;
+
+ /**
+ * When the association has a Role Floating Text this text should move
+ * when the LinePath moves but only if the closest segment to the
+ * role text moves.
+ * This segment is:
+ * m_LinePath[m_unNameLineSegment] -- m_LinePath[m_unNameLineSegment+1]
+ */
+ uint m_unNameLineSegment;
+ UMLDoc * m_umldoc; ///< just a shorthand for UMLApp::app()->getDocument()
+ ListPopupMenu *m_pMenu;
+ bool m_bSelected;
+ int m_nMovingPoint;
+
+ /**
+ * Position of Name floatingtext saved by saveIdealTextPositions()
+ */
+ QPoint m_oldNamePoint;
+ /**
+ * Position of role A multiplicity floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldMultiAPoint;
+ /**
+ * Position of role B multiplicity floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldMultiBPoint;
+ /**
+ * Position of role A changeability floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldChangeAPoint;
+ /**
+ * Position of role B changeability floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldChangeBPoint;
+ /**
+ * Position of role A name floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldRoleAPoint;
+ /**
+ * Position of role B name floatingtext saved by
+ * saveIdealTextPositions()
+ */
+ QPoint m_oldRoleBPoint;
+
+ int m_nLinePathSegmentIndex; ///< anchor for m_pAssocClassLine
+ QCanvasLine *m_pAssocClassLine; ///< used for connecting assoc. class
+ /// selection adornment for the endpoints of the assoc. class connecting line
+ QCanvasRectangle *m_pAssocClassLineSel0, *m_pAssocClassLineSel1;
+
+ ClassifierWidget *m_pAssocClassWidget; ///< used if we have an assoc. class
+
+ /**
+ * The definition points for the association line.
+ */
+ LinePath m_LinePath;
+
+ // The following items are only used if m_pObject is not set.
+ Uml::Association_Type m_AssocType;
+
+public slots:
+ /**
+ * Handles the selection from the popup menu.
+ */
+ void slotMenuSelection(int sel);
+
+ /**
+ * This slot is entered when an event has occurred on the views display,
+ * most likely a mouse event. Before it sends out that mouse event all
+ * children should make sure that they don't have a menu active or there
+ * could be more than one popup menu displayed.
+ */
+ void slotRemovePopupMenu();
+
+ /**
+ * Handles any signals that tells everyone not to be selected.
+ */
+ void slotClearAllSelected();
+
+ /**
+ * Connected to UMLClassifier::attributeRemoved() in case this
+ * AssociationWidget is linked to a classifer's attribute type.
+ *
+ * @param obj The UMLAttribute removed.
+ */
+ void slotAttributeRemoved(UMLClassifierListItem* obj);
+
+ /**
+ * Connected to UMLObject::modified() in case this
+ * AssociationWidget is linked to a classifer's attribute type.
+ *
+ * @param obj The UMLAttribute removed.
+ */
+ void slotAttributeChanged();
+
+ /**
+ * Synchronize this widget from the UMLAssociation.
+ */
+ void syncToModel();
+};
+#endif
diff --git a/umbrello/umbrello/associationwidgetlist.h b/umbrello/umbrello/associationwidgetlist.h
new file mode 100644
index 00000000..28271b74
--- /dev/null
+++ b/umbrello/umbrello/associationwidgetlist.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ associationwidgetlist.h - description
+ -------------------
+ copyright : (C) 2003 by Oliver Kellogg
+ email : okellogg@users.sourceforge.net
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef _ASSOCIATIONWIDGETLIST_H
+#define _ASSOCIATIONWIDGETLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class AssociationWidget;
+
+typedef QPtrList<AssociationWidget> AssociationWidgetList;
+typedef QPtrListIterator<AssociationWidget> AssociationWidgetListIt;
+
+#endif
diff --git a/umbrello/umbrello/assocrules.cpp b/umbrello/umbrello/assocrules.cpp
new file mode 100644
index 00000000..9e8c9a52
--- /dev/null
+++ b/umbrello/umbrello/assocrules.cpp
@@ -0,0 +1,386 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "assocrules.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <typeinfo>
+
+// local includes
+#include "uml.h"
+#include "umlview.h"
+#include "umlwidget.h"
+#include "umlobject.h"
+#include "associationwidgetlist.h"
+#include "associationwidget.h"
+#include "statewidget.h"
+#include "activitywidget.h"
+#include "forkjoinwidget.h"
+
+
+using namespace Uml;
+
+AssocRules::AssocRules() {}
+
+AssocRules::~AssocRules() {}
+
+bool allowAssociation( Association_Type/* assocType*/, const std::type_info/* &type*/ )
+{
+ return false;
+
+}
+
+bool AssocRules::allowAssociation( Uml::Association_Type assocType, UMLWidget * widget ) {
+ Widget_Type widgetType = widget -> getBaseType();
+ bool bValid = false;
+ for (int i = 0; i < m_nNumRules; i++) {
+ if (assocType == m_AssocRules[i].assoc_type) {
+ if (widgetType == m_AssocRules[i].widgetA_type
+ || widgetType == m_AssocRules[i].widgetB_type ) {
+ bValid = true;
+ }
+ }
+ }
+ if( !bValid ) {
+ // Special case: Subsystem realizes interface in component diagram
+ UMLView *view = UMLApp::app()->getCurrentView();
+ if (view && view->getType() == dt_Component && widgetType == wt_Package &&
+ (assocType == at_Generalization || assocType == at_Realization))
+ bValid = true;
+ else
+ return false;
+ }
+ AssociationWidgetList list = widget -> getAssocList();
+ AssociationWidgetListIt it( list );
+ AssociationWidget * assoc = 0;
+ switch( assocType ) {
+ case at_Association:
+ case at_UniAssociation:
+ case at_Dependency:
+ case at_Coll_Message:
+ case at_Generalization://can have many sub/super types
+ case at_Aggregation:
+ case at_Relationship:
+ case at_Composition:
+ case at_Containment:
+ return true;//doesn't matter whats already connected to widget
+ break;
+
+ case at_Association_Self:
+ return true;// we should really check that connection is to same object
+ break;
+
+ case at_Realization: // one connected to widget only (a or b)
+ while( ( assoc = it.current() ) ) {
+ if( assoc -> getAssocType() == at_Realization )
+ return false;
+ ++it;
+ }
+ return true;
+ break;
+
+ case at_State:
+ {
+ StateWidget *pState = dynamic_cast<StateWidget*>(widget);
+ return (pState == NULL || pState->getStateType() != StateWidget::End);
+ }
+ break;
+
+ case at_Activity:
+ {
+ ActivityWidget *pActivity = dynamic_cast<ActivityWidget*>(widget);
+ return (pActivity == NULL || pActivity->getActivityType() != ActivityWidget::End);
+ }
+ break;
+
+ case at_Anchor:
+ return true;
+ break;
+ default:
+ kWarning() << "allowAssociation() on unknown type" << endl;
+ break;
+ }
+ return false;
+}
+
+// when we know what we are going to connect both ends of the association to, we can
+// use this method.
+bool AssocRules::allowAssociation( Uml::Association_Type assocType,
+ UMLWidget * widgetA, UMLWidget * widgetB,
+ bool extendedCheck ) {
+ Widget_Type widgetTypeA = widgetA->getBaseType();
+ Widget_Type widgetTypeB = widgetB->getBaseType();
+ bool bValid = false;
+ for (int i = 0; i < m_nNumRules; i++) {
+ if (assocType == m_AssocRules[i].assoc_type) {
+ if( (widgetTypeA == m_AssocRules[i].widgetA_type &&
+ widgetTypeB == m_AssocRules[i].widgetB_type) ||
+ (widgetTypeB == m_AssocRules[i].widgetA_type &&
+ widgetTypeA == m_AssocRules[i].widgetB_type ) )
+ bValid = true;
+ }
+ }
+ // we can bail here for quick checks, as occur in loading files
+ // for paste or regular creation operations, we need to go further
+ if (!extendedCheck) {
+ return bValid;
+ }
+
+ if (!bValid) {
+ return false;
+ }
+ AssociationWidgetList list = widgetB -> getAssocList();
+ AssociationWidgetListIt it( list );
+ AssociationWidget * assoc = 0;
+ switch( assocType ) {
+ case at_Association:
+ case at_Association_Self:
+ case at_UniAssociation:
+ case at_Dependency:
+ case at_Coll_Message:
+ case at_Aggregation:
+ case at_Relationship:
+ return true; // doesn't matter what's already connected to widget
+ break;
+
+ case at_Composition: // can't have mutual composition
+ case at_Containment: // can't have mutual containment
+ case at_Generalization://can have many sub/super types but can't sup/sub each
+ while( ( assoc = it.current() ) ) {
+ if( ( widgetA == assoc -> getWidget(A) || widgetA == assoc -> getWidget(B) )
+ && assoc->getAssocType() == assocType )
+ return false;
+ ++it;
+ }
+ return true;
+ break;
+
+ case at_Realization: // can only connect to abstract (interface) classes
+ while( ( assoc = it.current() ) ) {
+ if( ( widgetA == assoc->getWidget(A) || widgetA == assoc->getWidget(B) )
+ && assoc->getAssocType() == at_Realization ) {
+ return false;
+ }
+ ++it;
+ }
+ if (widgetB->getBaseType() == wt_Class) {
+ return widgetB->getUMLObject()->getAbstract();
+ } else if (widgetB->getBaseType() == wt_Interface ||
+ widgetB->getBaseType() == wt_Package) {
+ return true;
+ }
+ break;
+
+ case at_State:
+ {
+ StateWidget *stateA = dynamic_cast<StateWidget*>(widgetA);
+ StateWidget *stateB = dynamic_cast<StateWidget*>(widgetB);
+ if (stateA && stateB) {
+ if (stateB->getStateType() == StateWidget::Initial)
+ return false;
+ if (stateB->getStateType() == StateWidget::End &&
+ stateA->getStateType() != StateWidget::Normal)
+ return false;
+ }
+ }
+ return true;
+ break;
+
+ case at_Activity:
+ {
+ ActivityWidget *actA = dynamic_cast<ActivityWidget*>(widgetA);
+ ActivityWidget *actB = dynamic_cast<ActivityWidget*>(widgetB);
+ // no transitions to initial activity allowed
+ if (actB && actB->getActivityType() == ActivityWidget::Initial)
+ return false;
+ // actType -1 here means "not applicable".
+ int actTypeA = -1;
+ if (actA)
+ actTypeA = actA->getActivityType();
+ int actTypeB = -1;
+ if (actB)
+ actTypeB = actB->getActivityType();
+ // only from a normal, branch or fork activity to the end
+ if (actTypeB == ActivityWidget::End &&
+ actTypeA != ActivityWidget::Normal &&
+ actTypeA != ActivityWidget::Branch &&
+ dynamic_cast<ForkJoinWidget*>(widgetA) == NULL) {
+ return false;
+ }
+ // only Forks and Branches can have more than one "outgoing" transition
+ if (actA != NULL && actTypeA != ActivityWidget::Branch) {
+ AssociationWidgetList list = widgetA->getAssocList();
+ for (AssociationWidget* assoc = list.first(); assoc; assoc = list.next()) {
+ if (assoc->getWidget(A) == widgetA) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ break;
+
+ case at_Anchor:
+ return true;
+ break;
+
+ default:
+ kWarning() << "allowAssociation() on unknown type" << endl;
+ break;
+ }
+ return false;
+}
+
+bool AssocRules::allowRole( Uml::Association_Type assocType ) {
+ for( int i = 0; i < m_nNumRules; i++ )
+ if( assocType == m_AssocRules[ i ].assoc_type )
+ return m_AssocRules[ i ].role;
+ return false;
+}
+
+bool AssocRules::allowMultiplicity( Uml::Association_Type assocType, Uml::Widget_Type widgetType ) {
+ for( int i = 0; i < m_nNumRules; i++ )
+ if( assocType == m_AssocRules[ i ].assoc_type )
+ if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
+ return m_AssocRules[ i ].multiplicity;
+ return false;
+}
+
+bool AssocRules::allowSelf( Uml::Association_Type assocType, Uml::Widget_Type widgetType ) {
+ for( int i = 0; i < m_nNumRules; i++ )
+ if( assocType == m_AssocRules[ i ].assoc_type )
+ if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
+ return m_AssocRules[ i ].self;
+
+ return false;
+}
+
+Uml::Association_Type AssocRules::isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB) {
+ Widget_Type widgetTypeA = widgetA->getBaseType();
+ Widget_Type widgetTypeB = widgetB->getBaseType();
+ for (int i = 0; i < m_nNumRules; i++) {
+ if (m_AssocRules[i].assoc_type == at_Realization &&
+ widgetTypeA == m_AssocRules[i].widgetA_type &&
+ widgetTypeB == m_AssocRules[i].widgetB_type) {
+ return at_Realization;
+ }
+ }
+ return at_Generalization;
+}
+
+AssocRules::Assoc_Rule AssocRules::m_AssocRules []= {
+ // Association widgetA widgetB role multi directional self
+ //---------------+----------------+----------------+-------+-------+-------+---------
+ { at_Association_Self,wt_Class, wt_Class, true, true, true, true },
+ { at_Association_Self,wt_Object, wt_Object, true, true, true, true },
+ { at_Association_Self,wt_Interface, wt_Interface, true, true, true, true },
+ { at_Association, wt_Class, wt_Class, true, true, true, true },
+ { at_Association, wt_Object, wt_Object, true, true, true, true },
+ { at_Association, wt_Interface, wt_Interface, true, true, true, true },
+ { at_Association, wt_Interface, wt_Class, true, true, true, false },
+ { at_Association, wt_Class, wt_Interface, true, true, true, false },
+ { at_Association, wt_Datatype, wt_Class, true, true, true, false },
+ { at_Association, wt_Class, wt_Datatype, true, true, true, false },
+ { at_Association, wt_Enum, wt_Class, true, true, true, false },
+ { at_Association, wt_Class, wt_Enum, true, true, true, false },
+ { at_Association, wt_Actor, wt_UseCase, true, false, false, false },
+ { at_Association, wt_UseCase, wt_UseCase, true, false, false, false },
+ { at_Association, wt_Actor, wt_Actor, true, false, false, false },
+ { at_Association, wt_Actor, wt_UseCase, true, false, false, false },
+ { at_Association, wt_Component, wt_Interface, true, false, false, false },
+ { at_Association, wt_Interface, wt_Artifact, true, false, false, false },
+ { at_Association, wt_Node, wt_Node, true, false, false, false },
+ { at_UniAssociation,wt_Class, wt_Class, true, true, true, true },
+ { at_UniAssociation,wt_Object, wt_Object, true, true, true, true },
+ { at_UniAssociation,wt_Interface, wt_Interface, true, true, true, true },
+ { at_UniAssociation,wt_Interface, wt_Class, true, true, true, true },
+ { at_UniAssociation,wt_Class, wt_Interface, true, true, true, true },
+ { at_UniAssociation,wt_Class, wt_Datatype, true, true, true, true },
+ { at_UniAssociation,wt_Class, wt_Enum, true, true, true, true },
+ { at_UniAssociation,wt_Actor, wt_Actor, true, false, false, false },
+ { at_UniAssociation,wt_UseCase, wt_UseCase, true, false, false, false },
+ { at_UniAssociation,wt_UseCase, wt_Actor, true, false, false, false },
+ { at_Generalization,wt_Class, wt_Datatype, false, false, false, false },
+ { at_Generalization,wt_Class, wt_Class, false, false, false, false },
+ { at_Generalization,wt_Interface, wt_Interface, false, false, false, false },
+ { at_Generalization,wt_UseCase, wt_UseCase, false, false, false, false },
+ { at_Generalization,wt_Actor, wt_Actor, false, false, false, false },
+ { at_Generalization,wt_Component, wt_Interface, false, false, false, false },
+ { at_Aggregation, wt_Class, wt_Class, true, true, false, true },
+ { at_Aggregation, wt_Class, wt_Interface, true, true, false, false },
+ { at_Aggregation, wt_Class, wt_Enum, true, true, false, false },
+ { at_Aggregation, wt_Class, wt_Datatype, true, true, false, false },
+ { at_Dependency, wt_Class, wt_Class, true, false, false, true },
+ { at_Dependency, wt_UseCase, wt_UseCase, true, false, false, false },
+ { at_Dependency, wt_Actor, wt_Actor, true, false, false, false },
+ { at_Dependency, wt_Actor, wt_UseCase, true, false, false, false },
+ { at_Dependency, wt_Package, wt_Package, true, true, true, true },
+ { at_Dependency, wt_Package, wt_Class, true, true, true, true },
+ { at_Dependency, wt_Class, wt_Package, true, true, true, true },
+ { at_Dependency, wt_Package, wt_Interface, true, true, true, true },
+ { at_Dependency, wt_Interface, wt_Package, true, true, true, true },
+ { at_Dependency, wt_Interface, wt_Interface, true, true, true, true },
+ { at_Dependency, wt_Interface, wt_Class, true, true, true, true },
+ { at_Dependency, wt_Class, wt_Interface, true, true, true, true },
+ { at_Dependency, wt_Class, wt_Datatype, true, true, true, true },
+ { at_Dependency, wt_Class, wt_Enum, true, true, true, true },
+ { at_Dependency, wt_Component, wt_Component, true, true, true, true },
+ { at_Dependency, wt_Component, wt_Interface, true, true, true, true },
+ { at_Dependency, wt_Component, wt_Artifact, true, false, false, false },
+ { at_Dependency, wt_Node, wt_Component, true, false, false, false },
+ { at_Realization, wt_Class, wt_Interface, false, false, false, false },
+ { at_Realization, wt_Interface, wt_Package, false, false, false, false },
+ { at_Realization, wt_Interface, wt_Interface, false, false, false, false },
+ { at_Realization, wt_Component, wt_Interface, false, false, false, false },
+ { at_Realization, wt_Package, wt_Interface, false, false, false, false },
+ { at_Composition, wt_Class, wt_Class, true, true, false, true },
+ { at_Composition, wt_Class, wt_Interface, true, true, false, false },
+ { at_Composition, wt_Class, wt_Enum, true, true, false, false },
+ { at_Composition, wt_Class, wt_Datatype, false, false, false, false },
+ { at_Composition, wt_Class, wt_Class, false, false, false, false },
+ { at_Containment, wt_Package, wt_Class, false, false, true, false },
+ { at_Containment, wt_Package, wt_Interface, false, false, true, false },
+ { at_Containment, wt_Package, wt_Enum, false, false, true, false },
+ { at_Containment, wt_Package, wt_Package, false, false, true, false },
+ { at_Containment, wt_Package, wt_Component, false, false, true, false },
+ { at_Containment, wt_Class, wt_Class, false, false, true, false },
+ { at_Containment, wt_Class, wt_Interface, false, false, true, false },
+ { at_Containment, wt_Class, wt_Enum, false, false, true, false },
+ { at_Containment, wt_Interface, wt_Class, false, false, true, false },
+ { at_Containment, wt_Interface, wt_Interface, false, false, true, false },
+ { at_Containment, wt_Interface, wt_Enum, false, false, true, false },
+ { at_Containment, wt_Component, wt_Component, false, false, true, false },
+ { at_Containment, wt_Component, wt_Artifact, false, false, true, false },
+ { at_Coll_Message, wt_Object, wt_Object, true, false, true, true },
+ { at_State, wt_State, wt_State, true, false, true, true },
+ { at_State, wt_ForkJoin, wt_State, true, false, true, true },
+ { at_State, wt_State, wt_ForkJoin, true, false, true, true },
+ { at_Activity, wt_Activity, wt_Activity, true, false, true, true },
+ { at_Activity, wt_ForkJoin, wt_Activity, true, false, true, true },
+ { at_Activity, wt_Activity, wt_ForkJoin, true, false, true, true },
+ { at_Anchor, wt_Class, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Package, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Interface, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Datatype, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Enum, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Object, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Actor, wt_Note, false, false, false, false },
+ { at_Anchor, wt_UseCase, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Message, wt_Note, false, false, false, false },
+ { at_Anchor, wt_State, wt_Note, false, false, false, false },
+ { at_Anchor, wt_Activity, wt_Note, false, false, false, false },
+ { at_Relationship, wt_Entity, wt_Entity, true, true, true, true },
+};
+
+int AssocRules::m_nNumRules = sizeof( m_AssocRules ) / sizeof( AssocRules::Assoc_Rule );
+
diff --git a/umbrello/umbrello/assocrules.h b/umbrello/umbrello/assocrules.h
new file mode 100644
index 00000000..df33d6d8
--- /dev/null
+++ b/umbrello/umbrello/assocrules.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCRULES_H
+#define ASSOCRULES_H
+
+#include "umlnamespace.h"
+namespace std
+ { class type_info; }
+
+class UMLWidget;
+
+/**
+ * Used to determine rules for associations.
+ *
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssocRules {
+public:
+ /**
+ * Constructor.
+ */
+ AssocRules();
+
+ /**
+ * Deconstructor.
+ */
+ ~AssocRules();
+
+ /**
+ * Returns whether an association is going to be allowed for the given
+ * values. This method is used to test if you can start an association.
+ */
+ static bool allowAssociation( Uml::Association_Type assocType, UMLWidget * widget );
+
+ static bool allowAssociation( Uml::Association_Type assocType, const std::type_info & );
+
+ /**
+ * Returns whether an association is valid with the given variables.
+ * This method is used to finish an association.
+ */
+ static bool allowAssociation( Uml::Association_Type assocType,
+ UMLWidget * widgetA, UMLWidget * widgetB,
+ bool extendedCheck = true );
+
+ /**
+ * Returns whether to allow a role text for the given association type.
+ */
+ static bool allowRole( Uml::Association_Type assocType );
+
+ /**
+ * Returns whether to allow a multiplicity text for the given
+ * association and widget type.
+ */
+ static bool allowMultiplicity( Uml::Association_Type assocType, Uml::Widget_Type widgetType );
+
+ /**
+ * Returns whether to allow an association to self for given variables.
+ */
+ static bool allowSelf( Uml::Association_Type assocType, Uml::Widget_Type widgetType );
+
+ /**
+ * Returns whether an implements association should be a Realisation or
+ * a Generalisation.
+ * as defined in m_AssocRules.
+ */
+ static Uml::Association_Type isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB);
+
+private:
+
+ /**
+ * Structure to help determine association rules.
+ */
+ struct Assoc_Rule {
+ Uml::Association_Type assoc_type; ///< association type
+ Uml::Widget_Type widgetA_type; ///< type of role A widget
+ Uml::Widget_Type widgetB_type; ///< type of role B widget
+ bool role; ///< role text
+ bool multiplicity; ///< multipliciy text on association
+ /// can have an association of same type going between widget each way
+ bool directional;
+
+ bool self; ///< association to self
+ };
+
+ /**
+ * Container that holds all the rules.
+ */
+ static Assoc_Rule m_AssocRules[];
+
+ /**
+ * The number of rules known about.
+ */
+ static int m_nNumRules;
+};
+
+#endif
diff --git a/umbrello/umbrello/attribute.cpp b/umbrello/umbrello/attribute.cpp
new file mode 100644
index 00000000..3bdadeb7
--- /dev/null
+++ b/umbrello/umbrello/attribute.cpp
@@ -0,0 +1,327 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "attribute.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "classifier.h"
+#include "operation.h"
+#include "umlobject.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "dialogs/umlattributedialog.h"
+#include "object_factory.h"
+
+UMLAttribute::UMLAttribute( const UMLObject *parent,
+ const QString& name, Uml::IDType id,
+ Uml::Visibility s,
+ UMLObject *type, const QString& iv )
+ : UMLClassifierListItem(parent, name, id) {
+ m_InitialValue = iv;
+ m_BaseType = Uml::ot_Attribute;
+ m_Vis = s;
+ m_ParmKind = Uml::pd_In;
+ /* CHECK: Do we need this:
+ if (type == NULL) {
+ type = Object_Factory::createUMLObject(Uml::ot_Datatype, "undef");
+ }
+ */
+ m_pSecondary = type;
+}
+
+UMLAttribute::UMLAttribute(const UMLObject *parent) : UMLClassifierListItem(parent) {
+ m_BaseType = Uml::ot_Attribute;
+ m_Vis = Uml::Visibility::Private;
+ m_ParmKind = Uml::pd_In;
+}
+
+UMLAttribute::~UMLAttribute() { }
+
+void UMLAttribute::setName(const QString &name) {
+ m_Name = name;
+ emit attributeChanged();
+ UMLObject::emitModified();
+}
+
+void UMLAttribute::setVisibility(Uml::Visibility s) {
+ m_Vis = s;
+ emit attributeChanged();
+ UMLObject::emitModified();
+}
+
+QString UMLAttribute::getInitialValue() {
+ return m_InitialValue;
+}
+
+void UMLAttribute::setInitialValue(const QString &iv) {
+ if(m_InitialValue != iv) {
+ m_InitialValue = iv;
+ UMLObject::emitModified();
+ }
+}
+
+void UMLAttribute::setParmKind (Uml::Parameter_Direction pk) {
+ m_ParmKind = pk;
+}
+
+Uml::Parameter_Direction UMLAttribute::getParmKind () const {
+ return m_ParmKind;
+}
+
+QString UMLAttribute::toString(Uml::Signature_Type sig) {
+ QString s;
+
+ if(sig == Uml::st_ShowSig || sig == Uml::st_NoSig) {
+ s = m_Vis.toString(true) + ' ';
+ }
+
+ if(sig == Uml::st_ShowSig || sig == Uml::st_SigNoVis) {
+ // Determine whether the type name needs to be scoped.
+ UMLObject *owningObject = static_cast<UMLObject*>(parent());
+ if (owningObject->getBaseType() == Uml::ot_Operation) {
+ // The immediate parent() is the UMLOperation but we want
+ // the UMLClassifier:
+ owningObject = static_cast<UMLObject*>(owningObject->parent());
+ }
+ UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
+ if (ownParent == NULL) {
+ kError() << "UMLAttribute::toString: parent "
+ << owningObject->getName()
+ << " is not a UMLClassifier" << endl;
+ return "";
+ }
+ QString typeName;
+ UMLClassifier *type = UMLClassifierListItem::getType();
+ if (type) {
+ UMLPackage *typeScope = type->getUMLPackage();
+ if (typeScope != ownParent && typeScope != ownParent->getUMLPackage())
+ typeName = type->getFullyQualifiedName();
+ else
+ typeName = type->getName();
+ }
+ // The default direction, "in", is not mentioned.
+ // Perhaps we should include a pd_Unspecified in
+ // Uml::Parameter_Direction to have better control over this.
+ if (m_ParmKind == Uml::pd_InOut)
+ s += "inout ";
+ else if (m_ParmKind == Uml::pd_Out)
+ s += "out ";
+ // Construct the attribute text.
+ QString string = s + getName() + " : " + typeName;
+ if(m_InitialValue.length() > 0)
+ string += " = " + m_InitialValue;
+ return string;
+ }
+ return s + getName();
+}
+
+QString UMLAttribute::getFullyQualifiedName( const QString& separator,
+ bool includeRoot /* = false */) const {
+ UMLOperation *op = NULL;
+ UMLObject *owningObject = static_cast<UMLObject*>(parent());
+ if (owningObject->getBaseType() == Uml::ot_Operation) {
+ op = static_cast<UMLOperation*>(owningObject);
+ owningObject = static_cast<UMLObject*>(owningObject->parent());
+ }
+ UMLClassifier *ownParent = dynamic_cast<UMLClassifier*>(owningObject);
+ if (ownParent == NULL) {
+ kError() << "UMLAttribute::getFullyQualifiedName(" << m_Name
+ << "): parent " << owningObject->getName()
+ << " is not a UMLClassifier" << endl;
+ return "";
+ }
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ QString fqn = ownParent->getFullyQualifiedName(tempSeparator, includeRoot);
+ if (op)
+ fqn.append(tempSeparator + op->getName());
+ fqn.append(tempSeparator + m_Name);
+ return fqn;
+}
+
+bool UMLAttribute::operator==( UMLAttribute &rhs) {
+ if( this == &rhs )
+ return true;
+
+ if( !UMLObject::operator==( rhs ) )
+ return false;
+
+ // The type name is the only distinguishing criterion.
+ // (Some programming languages might support more, but others don't.)
+ if (m_pSecondary != rhs.m_pSecondary)
+ return false;
+
+ return true;
+}
+
+void UMLAttribute::copyInto(UMLAttribute *rhs) const
+{
+ // call the parent first.
+ UMLClassifierListItem::copyInto(rhs);
+
+ // Copy all datamembers
+ rhs->m_pSecondary = m_pSecondary;
+ rhs->m_SecondaryId = m_SecondaryId;
+ rhs->m_InitialValue = m_InitialValue;
+ rhs->m_ParmKind = m_ParmKind;
+}
+
+UMLObject* UMLAttribute::clone() const
+{
+ //FIXME: The new attribute should be slaved to the NEW parent not the old.
+ UMLAttribute *clone = new UMLAttribute( static_cast<UMLObject*>(parent()) );
+ copyInto(clone);
+
+ return clone;
+}
+
+
+void UMLAttribute::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement attributeElement = UMLObject::save("UML:Attribute", qDoc);
+ if (m_pSecondary == NULL) {
+ kDebug() << "UMLAttribute::saveToXMI(" << m_Name
+ << "): m_pSecondary is NULL, m_SecondaryId is '"
+ << m_SecondaryId << "'" << endl;
+ } else {
+ attributeElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) );
+ }
+ if (! m_InitialValue.isEmpty())
+ attributeElement.setAttribute( "initialValue", m_InitialValue );
+ qElement.appendChild( attributeElement );
+}
+
+bool UMLAttribute::load( QDomElement & element ) {
+ m_SecondaryId = element.attribute( "type", "" );
+ // We use the m_SecondaryId as a temporary store for the xmi.id
+ // of the attribute type model object.
+ // It is resolved later on, when all classes have been loaded.
+ // This deferred resolution is required because the xmi.id may
+ // be a forward reference, i.e. it may identify a model object
+ // that has not yet been loaded.
+ if (m_SecondaryId.isEmpty()) {
+ // Perhaps the type is stored in a child node:
+ QDomNode node = element.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "type")) {
+ node = node.nextSibling();
+ continue;
+ }
+ m_SecondaryId = tempElement.attribute( "xmi.id", "" );
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute( "xmi.idref", "" );
+ if (m_SecondaryId.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ m_SecondaryId = tmpElem.attribute( "xmi.id", "" );
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tmpElem.attribute( "xmi.idref", "" );
+ }
+ break;
+ }
+ if (m_SecondaryId.isEmpty()) {
+ kDebug() << "UMLAttribute::load(" << m_Name << "): "
+ << "cannot find type." << endl;
+ }
+ }
+ m_InitialValue = element.attribute( "initialValue", "" );
+ if (m_InitialValue.isEmpty()) {
+ // for backward compatibility
+ m_InitialValue = element.attribute( "value", "" );
+ }
+ return true;
+}
+
+bool UMLAttribute::showPropertiesDialog(QWidget* parent) {
+ UMLAttributeDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+
+void UMLAttribute::setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList) {
+ if (templateParam.isEmpty())
+ return;
+ QString type = templateParam.simplifyWhiteSpace();
+
+ int start = type.find(QChar('<'));
+ if (start >= 0 ) {
+ int end = start;
+ int count = 1;
+ int len = type.length();
+ while (count != 0 && ++end < len) {
+ QChar c = type.at(end);
+ if (c == QChar('<')) {
+ count++;
+ }
+ if (c == QChar('>')) {
+ count--;
+ }
+ }
+ if (count != 0) {
+ //The template is ill-formated, let's quit
+ return;
+ }
+ setTemplateParams(type.mid(start + 1, end - start - 1), templateParamList);
+ setTemplateParams(type.left(start) + type.right(len - end - 1), templateParamList);
+ } else {
+ QStringList paramsList = QStringList::split(QChar(','), type);
+ for ( QStringList::Iterator it = paramsList.begin(); it != paramsList.end(); ++it ) {
+ QString param = *it;
+ if (!param.isEmpty()) {
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLObject* obj = pDoc->findUMLObject(param);
+ if (obj == NULL ) {
+ obj = pDoc->findUMLObject(param.remove(QChar(' ')));
+ }
+ if (obj != NULL ) {
+ //We want to list only the params that already exist in this document
+ //If the param doesnt't already exist, we couldn't draw an association anyway
+ UMLClassifier* tmpClassifier = static_cast<UMLClassifier*>(obj);
+ if (templateParamList.findRef(tmpClassifier) == -1) {
+ templateParamList.append(tmpClassifier);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+UMLClassifierList UMLAttribute::getTemplateParams() {
+ UMLClassifierList templateParamList;
+ QString type = getType()->getName();
+ QString templateParam;
+ // Handle C++/D/Java template/generic parameters
+ const Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (pl == Uml::pl_Cpp || pl == Uml::pl_Java || pl == Uml::pl_D) {
+ int start = type.find(QChar('<'));
+ if (start >= 0 ) {
+ int end = type.findRev(QChar('>'));
+ if (end > start) {
+ templateParam = type.mid(start + 1, end - start - 1);
+ setTemplateParams(templateParam, templateParamList);
+ }
+ }
+ }
+ return templateParamList;
+}
+
+
+#include "attribute.moc"
diff --git a/umbrello/umbrello/attribute.h b/umbrello/umbrello/attribute.h
new file mode 100644
index 00000000..85253216
--- /dev/null
+++ b/umbrello/umbrello/attribute.h
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ATTRIBUTE_H
+#define ATTRIBUTE_H
+
+#include "classifierlistitem.h"
+#include "umlnamespace.h"
+#include "umlclassifierlist.h"
+
+/**
+ * This class is used to set up information for an attribute. This is like
+ * a programming attribute. It has a type, name, visibility and initial value.
+ *
+ * @short Sets up attribute information.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLAttribute : public UMLClassifierListItem {
+ Q_OBJECT
+public:
+ /**
+ * Sets up an attribute.
+ *
+ * @param parent The parent of this UMLAttribute.
+ * @param name The name of this UMLAttribute.
+ * @param id The unique id given to this UMLAttribute.
+ * @param s The visibility of the UMLAttribute.
+ * @param type The type of this UMLAttribute.
+ * @param iv The initial value of the attribute.
+ */
+ UMLAttribute(const UMLObject *parent, const QString& name,
+ Uml::IDType id = Uml::id_None,
+ Uml::Visibility s = Uml::Visibility::Private,
+ UMLObject *type = 0, const QString& iv = 0);
+
+ /**
+ * Sets up an attribute.
+ *
+ * @param parent The parent of this UMLAttribute.
+ */
+ UMLAttribute(const UMLObject *parent);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==( UMLAttribute &rhs);
+
+ /**
+ * destructor.
+ */
+ virtual ~UMLAttribute();
+
+ /**
+ * Copy the internal presentation of this object into the UMLAttribute
+ * object.
+ */
+ virtual void copyInto(UMLAttribute *rhs) const;
+
+ /**
+ * Reimplementation of method from UMLObject is required as
+ * an extra signal, attributeChanged(), is emitted.
+ */
+ void setName(const QString &name);
+
+ /**
+ * Reimplementation of method from UMLObject is required as
+ * an extra signal, attributeChanged(), is emitted.
+ */
+ void setVisibility(Uml::Visibility s);
+
+ /**
+ * Make a clone of the UMLAttribute.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Returns The initial value of the UMLAttribute.
+ *
+ * @return The initial value of the Atrtibute.
+ */
+ QString getInitialValue();
+
+ /**
+ * Sets the initial value of the UMLAttribute.
+ *
+ * @param iv The initial value of the UMLAttribute.
+ */
+ void setInitialValue( const QString &iv );
+
+ /**
+ * Returns a string representation of the UMLAttribute.
+ *
+ * @param sig If true will show the attribute type and
+ * initial value.
+ * @return Returns a string representation of the UMLAttribute.
+ */
+ QString toString(Uml::Signature_Type sig = Uml::st_NoSig);
+
+ /**
+ * Reimplement method from UMLObject.
+ */
+ QString getFullyQualifiedName(const QString& separator = QString::null,
+ bool includeRoot = false) const;
+
+ /**
+ * Creates the <UML:Attribute> XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Display the properties configuration dialog for the attribute.
+ */
+ virtual bool showPropertiesDialog(QWidget* parent);
+
+ void setParmKind (Uml::Parameter_Direction pk);
+ Uml::Parameter_Direction getParmKind () const;
+
+ /**
+ * Returns all the template params (if any) that are in the type of this attribute
+ */
+ virtual UMLClassifierList getTemplateParams();
+
+signals:
+ /**
+ * Required for informing AssociationWidgets representing this attribute
+ * that the attribute name or visibility has changed.
+ */
+ void attributeChanged();
+
+protected:
+ /**
+ * Loads the <UML:Attribute> XMI element.
+ */
+ bool load( QDomElement & element );
+
+ QString m_InitialValue; ///< text for the attribute's initial value.
+ Uml::Parameter_Direction m_ParmKind;
+
+private:
+ /**
+ * Puts in the param templateParamList all the template params that are in templateParam
+ */
+ void setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/autolayout/Makefile.am b/umbrello/umbrello/autolayout/Makefile.am
new file mode 100644
index 00000000..8c2a6cb3
--- /dev/null
+++ b/umbrello/umbrello/autolayout/Makefile.am
@@ -0,0 +1,20 @@
+noinst_LTLIBRARIES = libautolayout.la
+
+INCLUDES = -Idialogs -Irefactoring \
+ $(all_includes)
+#AM_CXXFLAGS = -I/usr/include/graphviz/
+
+libautolayout_la_METASOURCES = AUTO
+#noinst_HEADERS = node.h autolayout.h autolayoutdlg.h autolayouter.h canvas.h \
+# autolayouteradapter.h graphvizautolayouter.h simplecanvas.h graphvizgraph.h graphviznode.h \
+# dotautolayouter.h dotautolayouter.h baseinclude.h
+#noinst_LIBRARIES = libautolayout.la
+libautolayout_la_SOURCES = newautolayoutdialog.ui autolayoutdlg.cpp \
+ autolayouter.cpp autolayouteradapter.cpp graphvizautolayouter.cpp simplecanvas.cpp \
+ graphvizgraph.cpp graphviznode.cpp dotautolayouter.cpp neatoautolayouter.cpp \
+ circoautolayouter.cpp
+
+#libautolayout_la_LIBADD = /usr/lib/graphviz/libdotneato.la
+#libautolayout_la_LDFLAGS = -ldotneato -L/usr/lib/graphviz
+
+
diff --git a/umbrello/umbrello/autolayout/_graph.h b/umbrello/umbrello/autolayout/_graph.h
new file mode 100644
index 00000000..179a9471
--- /dev/null
+++ b/umbrello/umbrello/autolayout/_graph.h
@@ -0,0 +1,34 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTGRAPH_H
+#define AUTOLAYOUTGRAPH_H
+#include "baseinclude.h"
+namespace Autolayout {
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class Graph{
+public:
+ virtual ~Graph() {}
+ virtual void addNode(const char *name, int width,int heigt)=0;
+ virtual void addEdge(const char* nodea,const char*nodeb,int weight=100)=0;
+ virtual Node* getNode(const char*)=0;
+ virtual bool empty()=0;
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/autolayout.h b/umbrello/umbrello/autolayout/autolayout.h
new file mode 100644
index 00000000..9f34a1d8
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayout.h
@@ -0,0 +1,45 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUT_H
+#define AUTOLAYOUT_H
+
+
+#include "canvas.h"
+#include "simplecanvas.h"
+
+#include "node.h"
+
+#include "_graph.h"
+//#include "diagram.h"
+
+
+
+#include "graphviznode.h"
+#include "graphvizgraph.h"
+
+
+
+#include "autolayouter.h"
+#include "autolayouteradapter.h"
+#include "graphvizautolayouter.h"
+#include "dotautolayouter.h"
+#include "circoautolayouter.h"
+#include "neatoautolayouter.h"
+
+
+
+
+
+#endif
diff --git a/umbrello/umbrello/autolayout/autolayoutdlg.cpp b/umbrello/umbrello/autolayout/autolayoutdlg.cpp
new file mode 100644
index 00000000..2f6b1a4c
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayoutdlg.cpp
@@ -0,0 +1,184 @@
+/***************************************************************************
+ * copyright (C) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net> *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "autolayoutdlg.h"
+#include "../associationwidget.h"
+#include "../umlwidget.h"
+#include "autolayout.h"
+#include "newautolayoutdialog.h"
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qslider.h>
+#include <kdebug.h>
+
+
+AutolayoutDlg::AutolayoutDlg(KConfig* c,UMLView* v,QWidget *parent, const char *name)
+ :MyDialog1(parent, name)
+{
+ view=v;
+ readConfig(c);
+ config=c;
+}
+
+void AutolayoutDlg::slotSetAssociationWeight(int i)
+{
+ associationWeight=i;
+}
+
+
+void AutolayoutDlg::slotSetDependenciesWeight(int i)
+{
+ dependenciesWeight=i;
+}
+
+
+void AutolayoutDlg::slotSetGeneralizationWeight(int i)
+{
+ generalizationWeight=i;
+}
+void AutolayoutDlg::slotSetGenralizationAsEdges(bool b)
+{
+ genralizationAsEdges=b;
+}
+
+
+void AutolayoutDlg::slotSetDependenciesAsEdges(bool b)
+{
+ dependenciesAsEdges=b;
+}
+
+
+void AutolayoutDlg::slotSetAssociationAsEdges(bool b)
+{
+ associationAsEdges=b;
+}
+
+
+
+void AutolayoutDlg::slotSetCompressShapes(bool b)
+{
+ compressShapes=b;
+}
+
+
+void AutolayoutDlg::slotSetCenterDiagram(bool b)
+{
+ centerDiagram=b;
+}
+
+
+void AutolayoutDlg::slotSetClusterizeHierarchies(bool b)
+
+{
+ clusterizeHierarchies=b;
+}
+
+
+void AutolayoutDlg::slotSetShapeSeparation(int i)
+{
+ shapeSeparation=i;
+}
+
+void AutolayoutDlg::slotReloadSettings()
+{
+ readConfig(config);
+}
+
+
+void AutolayoutDlg::slotSaveSettings()
+{
+ writeConfig(config);
+}
+
+
+void AutolayoutDlg::slotDoAutolayout()
+{
+
+ Autolayout::Autolayouter* a=getAutolayouter();;
+
+ a->setAssociationAsEdges( associationAsEdges);
+ a->setAssociationWeight( associationWeight );
+ a->setCenterDiagram( centerDiagram);
+ a->setDependenciesAsEdges( dependenciesAsEdges);
+ a->setClusterizeHierarchies( clusterizeHierarchies);
+ a->setCompressShapes( compressShapes);
+ a->setDependenciesWeight( dependenciesWeight);
+ a->setGeneralizationAsEdges( genralizationAsEdges);
+ a->setGeneralizationWeight( generalizationWeight);
+ a->setNoteConnectionWeight( 1);
+ a->setNoteConnectionsAsEdges(true);
+ a->setShapeSeparation( shapeSeparation);
+ a->autolayout( view);
+ delete a;
+ a=0;
+ accept();
+}
+
+void AutolayoutDlg::readConfig( KConfig * conf)
+{
+ conf->setGroup("AutolayoutDlg");
+ associationEdgesCB->setChecked((bool)(conf->readBoolEntry( "associationAsEdges",false)));
+ centerDiagramCB->setChecked((bool)(conf->readBoolEntry( "centerDiagram",true)));
+ dependenciesEdgesCB->setChecked((bool)(conf->readBoolEntry( "dependenciesAsEdges",false)));
+ clusterizeHierarchiesCB->setChecked((bool)(conf->readBoolEntry( "clusterizeHierarchies",false)));
+ compressShapesCB->setChecked((bool)(conf->readBoolEntry( "compressShapes",true)));
+ dependenciedEdgesSL->setValue((int)(conf->readNumEntry( "dependenciesWeight",0)));
+ generalizationCB->setChecked((bool)(conf->readBoolEntry( "genralizationAsEdges",true)));
+ generalizationEdgessSL->setValue((int)(conf->readNumEntry( "generalizationWeight",1)));
+ associationEdgesSL->setValue((int)(conf->readNumEntry( "associationWeight",0)));
+ shapeSeparationSB->setValue((int)(conf->readNumEntry( "shapeSeparation",0)));
+ algorithmCOB->setCurrentItem((int)(conf->readNumEntry( "algorithm",0)));
+}
+
+void AutolayoutDlg::writeConfig( KConfig * conf)
+{
+ // conf=kapp->config();
+ conf->setGroup("AutolayoutDlg");
+ conf->writeEntry( "associationAsEdges",associationEdgesCB->isChecked());
+ conf->writeEntry( "centerDiagram", centerDiagramCB->isChecked());
+ conf->writeEntry("dependenciesAsEdges",dependenciesEdgesCB->isChecked());
+ conf->writeEntry("clusterizeHierarchies",clusterizeHierarchiesCB->isChecked());
+ conf->writeEntry("dependenciesWeight", dependenciedEdgesSL->value());
+ conf->writeEntry("genralizationAsEdges",generalizationCB->isChecked());
+
+ conf->writeEntry("generalizationWeight",generalizationEdgessSL->value());
+ conf->writeEntry("associationWeight",associationEdgesSL->value());
+ conf->writeEntry("shapeSeparation",shapeSeparationSB->value());
+ //conf->writeEntry("al
+
+
+ //algorithmCOB->setCurrentItem(conf->readNumEntry( "algorithm",0));
+
+}
+
+void AutolayoutDlg::slotSelectAlgorithm( const QString& _algname)
+{
+ algname=_algname;
+
+}
+
+Autolayout::Autolayouter * AutolayoutDlg::getAutolayouter( )
+{
+ const QString text = algorithmCOB->currentText();
+ kDebug() << "Autolayout Algorithm " << algname << " found " << text << endl;
+ if (text == "dot")
+ return new Autolayout::DotAutolayouter();
+ if (text == "circo")
+ return new Autolayout::CircoAutolayouter();
+ if (text == "neato")
+ return new Autolayout::NeatoAutolayouter();
+ kError() << "Autolayout Algorithm not found" << endl;
+ return new Autolayout::DotAutolayouter();
+}
+
+
+
+#include "autolayoutdlg.moc"
diff --git a/umbrello/umbrello/autolayout/autolayoutdlg.h b/umbrello/umbrello/autolayout/autolayoutdlg.h
new file mode 100644
index 00000000..2e40d736
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayoutdlg.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * copyright (C) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net> *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTDLG_H
+#define AUTOLAYOUTDLG_H
+
+#include "newautolayoutdialog.h"
+#include "../umlview.h"
+#include <qobject.h>
+#include <kconfig.h>
+#include "autolayout.h"
+
+class AutolayoutDlg : public MyDialog1
+{
+ Q_OBJECT
+ public:
+ AutolayoutDlg(KConfig* c,UMLView* v, QWidget *parent = 0, const char *name = 0);
+ public slots:
+ virtual void slotSetAssociationWeight(int i);
+ virtual void slotSetDependenciesWeight(int i);
+ virtual void slotSetGeneralizationWeight(int i);
+ virtual void slotSetGenralizationAsEdges(bool b);
+ virtual void slotSetDependenciesAsEdges(bool b);
+ virtual void slotSetAssociationAsEdges(bool b);
+ virtual void slotSetCompressShapes(bool b);
+ virtual void slotSetCenterDiagram(bool b);
+ virtual void slotSetClusterizeHierarchies(bool b);
+ virtual void slotSetShapeSeparation(int i);
+ virtual void slotReloadSettings();
+ virtual void slotSaveSettings();
+ virtual void slotDoAutolayout();
+ void readConfig(KConfig*);
+ void writeConfig(KConfig*);
+ virtual void slotSelectAlgorithm(const QString&);
+
+
+ private:
+ UMLView *view;
+ int associationWeight;
+ int dependenciesWeight;
+ int generalizationWeight;
+ bool genralizationAsEdges;
+ bool dependenciesAsEdges;
+ bool associationAsEdges;
+ bool compressShapes;
+ bool centerDiagram;
+ bool clusterizeHierarchies;
+ int shapeSeparation;
+ KConfig* config;
+ QString algname;
+ Autolayout::Autolayouter* getAutolayouter();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/autolayout/autolayouter.cpp b/umbrello/umbrello/autolayout/autolayouter.cpp
new file mode 100644
index 00000000..f70fd195
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayouter.cpp
@@ -0,0 +1,29 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "autolayouter.h"
+
+namespace Autolayout {
+
+
+
+void Autolayouter::autolayout( UMLView * v )
+{
+ setCanvas(v);
+ setGraph(v);
+ run();
+ updateView(v);
+}
+
+} // end namespace Autolayout
+
diff --git a/umbrello/umbrello/autolayout/autolayouter.h b/umbrello/umbrello/autolayout/autolayouter.h
new file mode 100644
index 00000000..a56b1ce3
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayouter.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTAUTOLAYOUTER_H
+#define AUTOLAYOUTAUTOLAYOUTER_H
+#include "baseinclude.h"
+
+namespace Autolayout {
+
+/**
+This is the super class of any class which encapsulate an autolayout algorithm
+
+
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class Autolayouter {
+public:
+ virtual ~Autolayouter() {}
+
+ virtual void setNoteConnectionWeight(int i)=0;
+ virtual void setNoteConnectionsAsEdges(bool b)=0;
+ virtual void setAssociationWeight(int i)=0;
+
+ virtual void setDependenciesWeight(int i)=0;
+
+ virtual void setGeneralizationWeight(int i)=0;
+
+ virtual void setGeneralizationAsEdges(bool b)=0;
+
+ virtual void setDependenciesAsEdges(bool b)=0;
+
+ virtual void setAssociationAsEdges(bool b)=0;
+
+ virtual void setCompressShapes(bool b)=0;
+
+ virtual void setCenterDiagram(bool b)=0;
+
+ virtual void setClusterizeHierarchies(bool b)=0;
+
+ virtual void setShapeSeparation(int i)=0;
+
+ virtual void autolayout(UMLView* v);
+protected:
+ virtual void run()=0;
+ virtual void updateView(UMLView*)=0;
+ virtual Autolayout::Canvas* getCanvas()=0;
+ virtual Autolayout::Graph* getGraph()=0;
+ virtual Autolayout::Graph* setGraph(UMLView* view)=0;
+ virtual Autolayout::Canvas* setCanvas(UMLView* view)=0;
+
+
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/autolayouteradapter.cpp b/umbrello/umbrello/autolayout/autolayouteradapter.cpp
new file mode 100644
index 00000000..0673fde1
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayouteradapter.cpp
@@ -0,0 +1,191 @@
+/***************************************************************************
+ * copyright (C) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net> *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "autolayouteradapter.h"
+
+
+namespace Autolayout
+ {
+
+ AutolayouterAdapter::AutolayouterAdapter()
+ : Autolayout::Autolayouter()
+ {}
+
+
+ AutolayouterAdapter::~AutolayouterAdapter()
+ {}}
+
+void Autolayout::AutolayouterAdapter::addRelationship( AssociationWidget * a )
+ {
+ int weight;
+ switch (a->getAssocType())
+ {
+ case Uml::at_Generalization:;
+ case Uml::at_Realization:
+ {
+ if (genralizationAsEdges)weight=generalizationWeight;
+ else return;
+ break;
+ }
+ case Uml::at_Dependency:
+ {
+ if (dependenciesAsEdges) weight=dependenciesWeight;
+ else return;
+ break;
+ }
+ case Uml::at_Anchor:
+ {
+ if (anchorsAsEdges) weight=anchorsWeight;
+ else return;
+ break;
+ }
+ case Uml::at_Aggregation:;
+ case Uml::at_Association:;
+ case Uml::at_Containment:;
+ case Uml::at_Composition:;
+ default: return;
+ /*case Uml::at_Association_Self:;
+ case Uml::at_Activity:;
+ case Uml::at_Relationship:;
+ case Uml::at_Coll_Message:;
+ case Uml::at_Seq_Message:;
+ case Uml::at_Coll_Message_Self:;
+ case Uml::at_Seq_Message_Self:;
+ case Uml::at_Containment:;
+ case Uml::at_Composition:;
+ case Uml::at_Realization:;
+ case Uml::at_UniAssociation:;
+
+ case Uml::at_State:;
+ case Uml::at_Unknown:;
+ */
+ };
+ getGraph()->addEdge(a->getWidgetID(Uml::A).c_str(),a->getWidgetID(Uml::B).c_str(),weight);
+ }
+
+void Autolayout::AutolayouterAdapter::setAssociationWeight( int i )
+ {
+ associationWeight=i;
+ }
+
+void Autolayout::AutolayouterAdapter::setDependenciesWeight( int i )
+ {
+ dependenciesWeight=i;
+ }
+
+void Autolayout::AutolayouterAdapter::setGeneralizationWeight( int i )
+ {
+ generalizationWeight=i;
+ }
+
+void Autolayout::AutolayouterAdapter::setGeneralizationAsEdges( bool b )
+ {
+ genralizationAsEdges=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setDependenciesAsEdges( bool b )
+ {
+ dependenciesAsEdges=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setAssociationAsEdges( bool b )
+ {
+ associationAsEdges=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setCompressShapes( bool b )
+ {
+ compressShapes=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setCenterDiagram( bool b )
+ {
+ centerDiagram=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setClusterizeHierarchies( bool b )
+ {
+ clusterizeHierarchies=b;
+ }
+
+void Autolayout::AutolayouterAdapter::setShapeSeparation( int i )
+ {
+ shapeSeparation=i;
+ }
+
+Autolayout::Graph * Autolayout::AutolayouterAdapter::setGraph( UMLView * view )
+ {
+ if (! view) return 0;
+ Autolayout::Graph * g=getGraph();
+ if (g&&g->empty())
+ {
+ UMLWidgetList list = view->getWidgetList();
+ UMLWidget* widget;
+ for ( widget = list.first(); widget; widget= list.next() )
+ {
+ if (widget->getBaseType() == Uml::wt_Class)
+ {
+
+
+ g->addNode(widget->getID().c_str(),widget->getWidth(),
+ widget->getHeight());
+ }
+ }
+ AssociationWidgetList as_list=view->getAssociationList();
+ AssociationWidget* assoc;
+ AssociationWidgetListIt it(as_list);
+ while ( (assoc = it.current()) != 0 )
+ {
+ ++it;
+ addRelationship(assoc);
+ }
+ }
+ return g;
+ }
+
+void Autolayout::AutolayouterAdapter::updateView( UMLView* view )
+ {
+if (! view) return ;
+UMLWidgetList list = view->getWidgetList();
+ UMLWidget* widget;
+ Graph *g=getGraph();
+ if (! view||!g) return ;
+ for ( widget = list.first(); widget; widget= list.next() )
+ if (widget->getBaseType() == Uml::wt_Class)
+ {
+ Node* n =g->getNode(widget->getID().c_str());
+ //printf("old values widgets %s x,y:%d,%d\n",widget->getID().c_str(),widget->getX(),widget->getY());
+ //int x_old=widget->getX();
+ //int x_calc=n.getX();
+ //int x_calc2=30 +n.getX()-widget->getWidth()/2;
+ widget->setX(getCanvas()->getBaseX() +n->getX()-widget->getWidth()/2);
+ //int x=widget->getX();
+ widget->setY(getCanvas()->getMaxY()/2-(n->getY()+(widget->getHeight()/2)));
+
+ widget->updateWidget();
+
+ }
+ }
+
+Autolayout::Canvas * Autolayout::AutolayouterAdapter::setCanvas( UMLView* view )
+ {
+ return canvas=new Autolayout::SimpleCanvas(view->getCanvasWidth(),view->getCanvasHeight());
+ }
+
+void Autolayout::AutolayouterAdapter::setNoteConnectionWeight( int i )
+{
+noteConnectionWeight=i;
+}
+
+void Autolayout::AutolayouterAdapter::setNoteConnectionsAsEdges( bool b )
+{
+noteConnectionAsEdges=b;
+}
diff --git a/umbrello/umbrello/autolayout/autolayouteradapter.h b/umbrello/umbrello/autolayout/autolayouteradapter.h
new file mode 100644
index 00000000..7c52e742
--- /dev/null
+++ b/umbrello/umbrello/autolayout/autolayouteradapter.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTAUTOLAYOUTERADAPTER_H
+#define AUTOLAYOUTAUTOLAYOUTERADAPTER_H
+//#include "autolayout.h"
+#include "baseinclude.h"
+#include "autolayouter.h"
+#include "../umlnamespace.h"
+
+
+namespace Autolayout
+{
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class AutolayouterAdapter : virtual public Autolayout::Autolayouter
+{
+public:
+ AutolayouterAdapter();
+
+ virtual ~AutolayouterAdapter();
+ virtual void setAssociationWeight(int i);
+
+ virtual void setDependenciesWeight(int i);
+
+ virtual void setGeneralizationWeight(int i);
+
+ virtual void setGeneralizationAsEdges(bool b);
+
+ virtual void setDependenciesAsEdges(bool b);
+
+ virtual void setAssociationAsEdges(bool b);
+
+ virtual void setCompressShapes(bool b);
+
+ virtual void setCenterDiagram(bool b);
+
+ virtual void setClusterizeHierarchies(bool b);
+
+ virtual void setShapeSeparation(int i);
+ virtual void setNoteConnectionsAsEdges(bool b);
+ virtual void setNoteConnectionWeight(int i);
+
+
+protected:
+ virtual void run()=0;
+ virtual void updateView(UMLView* view);
+ virtual Canvas* getCanvas(){return canvas;};
+ virtual Graph* getGraph()=0;
+ virtual Graph* setGraph(UMLView* view);
+ virtual void addRelationship(AssociationWidget* a);
+ virtual Canvas* setCanvas(UMLView* view);
+
+ int associationWeight;
+ int dependenciesWeight;
+ int generalizationWeight;
+ bool genralizationAsEdges;
+ bool dependenciesAsEdges;
+ bool associationAsEdges;
+ bool compressShapes;
+ bool centerDiagram;
+ bool clusterizeHierarchies;
+ int shapeSeparation;
+ int noteConnectionWeight;
+ bool noteConnectionAsEdges;
+ bool anchorsAsEdges;
+ int anchorsWeight;
+ Canvas* canvas;
+private:
+ //Graph* graph;
+
+
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/baseinclude.h b/umbrello/umbrello/autolayout/baseinclude.h
new file mode 100644
index 00000000..590c1a5c
--- /dev/null
+++ b/umbrello/umbrello/autolayout/baseinclude.h
@@ -0,0 +1,29 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTBASEINCLUDE_H
+
+#include "../umlview.h"
+#include "../associationwidget.h"
+#include "../umlwidget.h"
+
+#include "canvas.h"
+#include "simplecanvas.h"
+
+#include "node.h"
+
+#include "_graph.h"
+
+
+#endif
diff --git a/umbrello/umbrello/autolayout/canvas.h b/umbrello/umbrello/autolayout/canvas.h
new file mode 100644
index 00000000..246df8a7
--- /dev/null
+++ b/umbrello/umbrello/autolayout/canvas.h
@@ -0,0 +1,34 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTCANVAS_H
+#define AUTOLAYOUTCANVAS_H
+
+namespace Autolayout {
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class Canvas{
+public:
+ virtual int getMaxX()=0;
+ virtual int getMaxY()=0;
+ virtual int getBaseX()=0;
+ virtual int getBaseY()=0;
+ virtual ~Canvas() {}
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/diagram.h b/umbrello/umbrello/autolayout/diagram.h
new file mode 100644
index 00000000..33bda398
--- /dev/null
+++ b/umbrello/umbrello/autolayout/diagram.h
@@ -0,0 +1,50 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTABLEDIAGRAM_H
+#define AUTOLAYOUTABLEDIAGRAM_H
+#include <dotneato.h>
+#define internal_renderizer
+#include "autolayout.h"
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+Umbrello UML Modeller Authors
+*/
+namespace Autolayout{
+class Diagram//: public virtual Graph, public virtual Canvas{
+{
+private:
+ Agraph_t* g;
+ Agsym_t* a_width;
+ Agsym_t* a_height;
+ Agsym_t* a_label;
+#ifndef internal_renderizer
+ GVC_t* gvc;
+#endif
+public:
+ Diagram(int,int);
+
+ ~Diagram();
+
+ void addNode(const char *name, int width,int heigt);
+ void addEdge(const char* nodea,const char*nodeb);
+ void autolayout();
+ void save();
+ Node getNode(const char*);
+
+};
+
+
+}
+#endif
diff --git a/umbrello/umbrello/autolayout/diagram_interface.h b/umbrello/umbrello/autolayout/diagram_interface.h
new file mode 100644
index 00000000..caee5752
--- /dev/null
+++ b/umbrello/umbrello/autolayout/diagram_interface.h
@@ -0,0 +1,31 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DIAGRAM_INTERFACE_H
+#define __DIAGRAM_INTERFACE_H
+
+class DiagramInterface
+{
+public:
+ DiagramInterface() {}
+ virtual ~DiagramInterface() {}
+
+
+private:
+ DiagramInterface( const DiagramInterface& source );
+ void operator = ( const DiagramInterface& source );
+};
+
+
+#endif // __DIAGRAM_INTERFACE_H
diff --git a/umbrello/umbrello/autolayout/dotautolayouter.cpp b/umbrello/umbrello/autolayout/dotautolayouter.cpp
new file mode 100644
index 00000000..5d197845
--- /dev/null
+++ b/umbrello/umbrello/autolayout/dotautolayouter.cpp
@@ -0,0 +1,43 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "dotautolayouter.h"
+
+#include <graphviz/dotprocs.h>
+
+namespace Autolayout {
+
+DotAutolayouter::DotAutolayouter()
+ : Autolayout::GraphvizAutolayouter()
+{
+}
+
+
+DotAutolayouter::~DotAutolayouter()
+{
+ dot_cleanup(gg->_agraph);
+}
+
+
+void DotAutolayouter::run()
+{
+ //#ifndef internal_renderizer
+ /* bind graph to GV context - currently must be done before layout */
+ // gvBindContext(gvc,g);
+ //#endif
+ // do layout
+ //dot_layout();
+ dot_layout( gg->_agraph );
+}
+
+}
diff --git a/umbrello/umbrello/autolayout/dotautolayouter.h b/umbrello/umbrello/autolayout/dotautolayouter.h
new file mode 100644
index 00000000..5c6530ba
--- /dev/null
+++ b/umbrello/umbrello/autolayout/dotautolayouter.h
@@ -0,0 +1,38 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTDOTAUTOLAYOUTER_H
+#define AUTOLAYOUTDOTAUTOLAYOUTER_H
+#include "baseinclude.h"
+#include "graphvizautolayouter.h"
+
+namespace Autolayout {
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class DotAutolayouter : virtual public Autolayout::GraphvizAutolayouter
+{
+public:
+ DotAutolayouter();
+
+ virtual ~DotAutolayouter();
+
+ virtual void run();
+
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/graphvizautolayouter.cpp b/umbrello/umbrello/autolayout/graphvizautolayouter.cpp
new file mode 100644
index 00000000..8defc5ef
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphvizautolayouter.cpp
@@ -0,0 +1,54 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "graphvizautolayouter.h"
+
+#include <graphviz/graph.h>
+
+namespace Autolayout {
+
+GraphvizAutolayouter::GraphvizAutolayouter()
+ : Autolayout::AutolayouterAdapter()
+{
+ gg = new GraphvizGraph();
+}
+
+GraphvizAutolayouter::~GraphvizAutolayouter()
+{
+ agclose(gg->_agraph);
+ delete gg;
+}
+
+void GraphvizAutolayouter::setCompressShapes( bool b )
+{
+ gg->setCompressShapes(b);
+}
+
+void GraphvizAutolayouter::setCenterDiagram( bool b )
+{
+ gg->setCenterDiagram(b);
+}
+
+void GraphvizAutolayouter::setShapeSeparation( int i )
+{
+ gg->setShapeSeparation(i);
+}
+
+Autolayout::Canvas * GraphvizAutolayouter::setCanvas( UMLView * view )
+{
+ Canvas* canvas= AutolayouterAdapter::setCanvas(view);
+ gg->setCanvas(canvas);
+}
+
+} // end namespace AutoLayout
+
diff --git a/umbrello/umbrello/autolayout/graphvizautolayouter.h b/umbrello/umbrello/autolayout/graphvizautolayouter.h
new file mode 100644
index 00000000..114ae63f
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphvizautolayouter.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTGRAPHVIZAUTOLAYOUTER_H
+#define AUTOLAYOUTGRAPHVIZAUTOLAYOUTER_H
+#include "baseinclude.h"
+#include "autolayouteradapter.h"
+#include "graphvizgraph.h"
+
+namespace Autolayout
+{
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class GraphvizAutolayouter : virtual public Autolayout::AutolayouterAdapter
+{
+public:
+ GraphvizAutolayouter();
+
+
+ virtual void setCompressShapes(bool b);
+
+ virtual void setCenterDiagram(bool b);
+
+ virtual void setShapeSeparation(int i);
+
+ virtual Canvas* setCanvas(UMLView* view);
+
+ virtual ~GraphvizAutolayouter();
+
+protected:
+ virtual Graph* getGraph(){if (!gg) gg=new GraphvizGraph(); return gg;}
+
+ virtual void run()=0;
+ GraphvizGraph* gg;
+
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/graphvizgraph.cpp b/umbrello/umbrello/autolayout/graphvizgraph.cpp
new file mode 100644
index 00000000..716f9223
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphvizgraph.cpp
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "graphvizgraph.h"
+
+#include <graphviz/graph.h>
+#include <kdebug.h>
+
+#define DPI 96
+
+char* _strcpy(const char* name)
+{
+ char *a;
+ strlen(name);
+ a=new char[strlen(name)+1];
+ a=strcpy(a,name);
+ return a;
+}
+namespace Autolayout
+{
+
+/**
+ *
+ * @return
+ */
+GraphvizGraph::GraphvizGraph()
+ : Autolayout::Graph()
+{
+ aginit();
+ empty_flag=true;
+ _agraph = agopen("graph",AGDIGRAPH);
+ a_width= agnodeattr(_agraph, "width", "");;
+ a_height= agnodeattr(_agraph, "height", "");
+ a_label = agnodeattr(_agraph, "label", "");
+ a_weight= agedgeattr(_agraph,"weight","");
+ agnodeattr(_agraph, "fixedsize", "true");
+ agnodeattr(_agraph, "margin", "0.01,0.01");
+ agnodeattr(_agraph, "shape", "box");
+ agraphattr(_agraph, "dpi", "DPI/0");
+
+
+}
+
+
+GraphvizGraph::~GraphvizGraph()
+{
+ nodelist.clear();
+ agclose(_agraph);
+ /* Free graph structures */
+ //#ifndef internal_renderizer
+
+ /* Clean up output file and errors */
+ // dotneato_terminate(gvc);
+ //dotneato_eof(gvc);
+
+}
+
+
+
+
+void GraphvizGraph::addEdge(const char* nodea, const char* nodeb, int weight)
+{
+ char *a=_strcpy(nodea);
+ char *b=_strcpy(nodeb);
+ char *weight_str;
+ asprintf(&weight_str,"%d",weight);
+ Agedge_t* e= agedge(_agraph,agnode(_agraph,a),agnode(_agraph,b));
+ delete[](a);
+ delete[](b);
+ agxset(e,a_weight->index,weight_str);
+
+
+}
+
+void GraphvizGraph::addNode(const char* name, int width, int height)
+{
+ char *a =_strcpy(name);
+ char *w_str,*h_str;
+ Agnode_t* node =agnode(_agraph,a);
+ delete[](a);
+ agxset(node, a_label->index, "a");
+ asprintf(&h_str,"%f",((float)height)/DPI);
+ asprintf(&w_str,"%f",((float)width)/DPI);
+ agxset(node, a_height->index,h_str);// sprintf("%d",height));
+ free (h_str);
+ agxset(node, a_width->index, w_str);
+ free (w_str);
+ empty_flag = false;
+}
+
+
+void Autolayout::GraphvizGraph::setCompressShapes( bool b )
+{
+ if (empty())
+ {
+ if (b) agraphattr(_agraph,"ratio","compress");
+ else agraphattr(_agraph,"ratio","");
+ }
+}
+
+void Autolayout::GraphvizGraph::setCenterDiagram( bool b )
+{
+ if (empty())
+ {
+ if (b) agraphattr(_agraph,"center","true");
+ else agraphattr(_agraph,"center","false");
+ }
+}
+
+void Autolayout::GraphvizGraph::setShapeSeparation( int i )
+{
+ char* a;
+ asprintf(&a,"%f",((float) i)/10.0);
+ agraphattr(_agraph,"nodesep",a);
+ free (a);
+}
+
+bool Autolayout::GraphvizGraph::empty( )
+{
+ return empty_flag;
+}
+
+Autolayout::Node* Autolayout::GraphvizGraph::getNode( const char * arg1 )
+{
+ char *a = _strcpy(arg1);
+ Autolayout::GraphvizNode* b=
+ new Autolayout::GraphvizNode(agnode(_agraph,a));
+ delete[](a);
+ nodelist.push_back(b);
+ return b;
+}
+
+void GraphvizGraph::setCanvas( Autolayout::Canvas * canvas)
+{
+ char buf[100];
+ sprintf(buf,"%f,%f",((float)canvas->getMaxX()/DPI),((float)canvas->getMaxY()/DPI));
+ kDebug() << "size: " << buf << endl;
+ agraphattr(_agraph, "size", buf);
+ agraphattr(_agraph, "page", buf);
+}
+
+} // end namespace Autolayout
+
diff --git a/umbrello/umbrello/autolayout/graphvizgraph.h b/umbrello/umbrello/autolayout/graphvizgraph.h
new file mode 100644
index 00000000..dfbf323d
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphvizgraph.h
@@ -0,0 +1,58 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTGRAPHVIZGRAPH_H
+#define AUTOLAYOUTGRAPHVIZGRAPH_H
+
+#include "baseinclude.h"
+#include "_graph.h"
+#include "graphviznode.h"
+#include <deque>
+#include <graphviz/types.h>
+
+namespace Autolayout
+{
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class GraphvizGraph : virtual public Autolayout::Graph
+{
+public:
+ GraphvizGraph();
+
+ virtual ~GraphvizGraph();
+
+ virtual Node* getNode(const char* arg1);
+ virtual bool empty();
+ virtual void addEdge(const char* nodea, const char* nodeb, int weight=10);
+ virtual void addNode(const char* name, int width, int heigt);
+ void setCompressShapes(bool b);
+ void setCenterDiagram(bool b);
+ void setShapeSeparation(int i);
+ void setCanvas(Canvas* );
+ Agraph_t* _agraph;
+ Agsym_t* a_width;
+ Agsym_t* a_height;
+ Agsym_t* a_label;
+ Agsym_t* a_weight;
+ std::deque<Node*> nodelist;
+ GVC_t* gvc;
+ bool empty_flag;
+ friend class GraphvizAutolayouter;
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/graphviznode.cpp b/umbrello/umbrello/autolayout/graphviznode.cpp
new file mode 100644
index 00000000..ea3510cf
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphviznode.cpp
@@ -0,0 +1,46 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "graphviznode.h"
+
+#include <stdio.h>
+#include <graphviz/types.h>
+#include <graphviz/graph.h>
+
+namespace Autolayout {
+
+
+
+GraphvizNode::~GraphvizNode()
+{
+}
+
+
+int GraphvizNode::getX()
+{
+ point p = ND_coord_i(n);
+ return p.x;
+}
+
+int GraphvizNode::getY()
+{
+ point p = ND_coord_i(n);
+ return p.y;
+}
+
+}
+
+Autolayout::GraphvizNode::GraphvizNode( Agnode_t * node )
+{
+ n=node;
+}
diff --git a/umbrello/umbrello/autolayout/graphviznode.h b/umbrello/umbrello/autolayout/graphviznode.h
new file mode 100644
index 00000000..0efcb6d8
--- /dev/null
+++ b/umbrello/umbrello/autolayout/graphviznode.h
@@ -0,0 +1,42 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#ifndef AUTOLAYOUTGRAPHVIZNODE_H
+#define AUTOLAYOUTGRAPHVIZNODE_H
+
+#include "node.h"
+
+class Agnode_t;
+
+namespace Autolayout {
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class GraphvizNode : virtual public Autolayout::Node
+{
+
+ GraphvizNode (Agnode_t* n);
+ Agnode_t* n;
+ virtual ~GraphvizNode();
+public:
+
+
+ int getX();
+ int getY();
+ friend class GraphvizGraph;
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/autolayout/newautolayoutdialog.ui b/umbrello/umbrello/autolayout/newautolayoutdialog.ui
new file mode 100644
index 00000000..e6407a5c
--- /dev/null
+++ b/umbrello/umbrello/autolayout/newautolayoutdialog.ui
@@ -0,0 +1,554 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>MyDialog1</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>MyDialog1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>662</width>
+ <height>281</height>
+ </rect>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame12</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>La&amp;yout Algorithm</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>comboBox1</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>dot</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>neato</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>circo</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>algorithmCOB</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Shape separation</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>shapeSeparationSB</cstring>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>shapeSeparationSB</cstring>
+ </property>
+ <property name="prefix">
+ <string></string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>clusterizeHierarchiesCB</cstring>
+ </property>
+ <property name="text">
+ <string>Clusteri&amp;ze Hierarchies</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>centerDiagramCB</cstring>
+ </property>
+ <property name="text">
+ <string>Ce&amp;nter Diagram</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>compressShapesCB</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;mpress Shapes</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame5_2_2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter7_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>generalizationCB</cstring>
+ </property>
+ <property name="text">
+ <string>Generalization as Ed&amp;ges</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>generalizationEdgessSL</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Weight</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the weight that the autolayout algoritm must use to compare association with other relationships like Generalization and Dependence</string>
+ </property>
+ </widget>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame5_2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>associationEdgesCB</cstring>
+ </property>
+ <property name="text">
+ <string>Association as Ed&amp;ges</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>associationEdgesSL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Weight</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the weight that the autolayout algoritm must use to compare association with other relationships like Generalization and Dependence</string>
+ </property>
+ </widget>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame5</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>dependenciesEdgesCB</cstring>
+ </property>
+ <property name="text">
+ <string>Dependencies &amp;as Edges</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>dependenciedEdgesSL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Weight</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the weight that the autolayout algoritm must use to compare association with other relationships like Generalization and Dependence</string>
+ </property>
+ </widget>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer17</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>He&amp;lp</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>277</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>restoreDefaultsBTN</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Restore Default</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>saveDefaultsBTN</cstring>
+ </property>
+ <property name="text">
+ <string>Save As Defa&amp;ult</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>generalizationCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>generalizationEdgessSL</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>associationEdgesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>associationEdgesSL</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>dependenciesEdgesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>dependenciedEdgesSL</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>shapeSeparationSB</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetShapeSeparation(int)</slot>
+ </connection>
+ <connection>
+ <sender>clusterizeHierarchiesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetClusterizeHierarchies(bool)</slot>
+ </connection>
+ <connection>
+ <sender>centerDiagramCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetCenterDiagram(bool)</slot>
+ </connection>
+ <connection>
+ <sender>compressShapesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetCompressShapes(bool)</slot>
+ </connection>
+ <connection>
+ <sender>generalizationCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetGenralizationAsEdges(bool)</slot>
+ </connection>
+ <connection>
+ <sender>generalizationEdgessSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetGeneralizationWeight(int)</slot>
+ </connection>
+ <connection>
+ <sender>associationEdgesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetAssociationAsEdges(bool)</slot>
+ </connection>
+ <connection>
+ <sender>associationEdgesSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetAssociationWeight(int)</slot>
+ </connection>
+ <connection>
+ <sender>dependenciesEdgesCB</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetDependenciesAsEdges(bool)</slot>
+ </connection>
+ <connection>
+ <sender>dependenciedEdgesSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSetDependenciesWeight(int)</slot>
+ </connection>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotDoAutolayout()</slot>
+ </connection>
+ <connection>
+ <sender>restoreDefaultsBTN</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotReloadSettings()</slot>
+ </connection>
+ <connection>
+ <sender>saveDefaultsBTN</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSaveSettings()</slot>
+ </connection>
+ <connection>
+ <sender>algorithmCOB</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>slotSelectAlgorithm(const QString&amp;)</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>slotDoAutolayout()</slot>
+ <slot>slotSaveSettings()</slot>
+ <slot>slotReloadSettings()</slot>
+ <slot>slotSetClusterizeHierarchies(bool b)</slot>
+ <slot>slotSetAssociationWeight(int i)</slot>
+ <slot>slotSetDependenciesWeight(int i)</slot>
+ <slot>slotSetGeneralizationWeight(int i)</slot>
+ <slot>slotSetGenralizationAsEdges(bool b)</slot>
+ <slot>slotSetDependenciesAsEdges(bool b)</slot>
+ <slot>slotSetAssociationAsEdges(bool b)</slot>
+ <slot>slotSetCompressShapes(bool b)</slot>
+ <slot>slotSetCenterDiagram(bool b)</slot>
+ <slot>slotSetShapeSeparation(int i)</slot>
+ <slot specifier="pure virtual">slotSelectAlgorithm(const QString&amp;)</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/autolayout/node.h b/umbrello/umbrello/autolayout/node.h
new file mode 100644
index 00000000..c2532b8b
--- /dev/null
+++ b/umbrello/umbrello/autolayout/node.h
@@ -0,0 +1,37 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTNODE_H
+#define AUTOLAYOUTNODE_H
+
+namespace Autolayout {
+
+/**
+@author Umbrello UML Modeller Authors
+*/
+class Node{
+
+ //Node(Agnode_t* n);
+
+
+ //
+public:
+ virtual ~Node() {}
+ virtual int getX()=0;
+ virtual int getY()=0;
+
+
+};
+}
+#endif
diff --git a/umbrello/umbrello/autolayout/simplecanvas.cpp b/umbrello/umbrello/autolayout/simplecanvas.cpp
new file mode 100644
index 00000000..0598c15e
--- /dev/null
+++ b/umbrello/umbrello/autolayout/simplecanvas.cpp
@@ -0,0 +1,20 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include "simplecanvas.h"
+
+namespace Autolayout {
+
+
+
+}
diff --git a/umbrello/umbrello/autolayout/simplecanvas.h b/umbrello/umbrello/autolayout/simplecanvas.h
new file mode 100644
index 00000000..41865f8a
--- /dev/null
+++ b/umbrello/umbrello/autolayout/simplecanvas.h
@@ -0,0 +1,39 @@
+/*
+ * copyright (C) 2005
+ * Umbrello UML Modeller Authors <uml-devel @uml.sf.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef AUTOLAYOUTSIMPLECANVAS_H
+#define AUTOLAYOUTSIMPLECANVAS_H
+
+#include "canvas.h"
+#include <qrect.h>
+namespace Autolayout {
+
+/**
+@author Dimitri Ognibene <ognibened @yahoo.it>
+*/
+class SimpleCanvas: public Canvas
+{
+public:
+ SimpleCanvas(int i, int j):max_x(i),max_y(j){}
+ virtual ~SimpleCanvas() {}
+ virtual int getMaxX(){return max_x;}
+ virtual int getMaxY(){return max_y;}
+ virtual int getBaseX(){return 0;}
+ virtual int getBaseY(){return 0;}
+ int max_x,max_y;
+};
+
+}
+
+#endif
diff --git a/umbrello/umbrello/boxwidget.cpp b/umbrello/umbrello/boxwidget.cpp
new file mode 100644
index 00000000..e1cff3d9
--- /dev/null
+++ b/umbrello/umbrello/boxwidget.cpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "boxwidget.h"
+// qt/kde includes
+#include <qevent.h>
+#include <kdebug.h>
+
+BoxWidget::BoxWidget(UMLView * view, Uml::IDType id)
+ : UMLWidget(view, id) {
+ setSize(100,80);
+ UMLWidget::setBaseType( Uml::wt_Box );
+ WidgetBase::m_bUsesDiagramLineColour = false; // boxes be black
+ WidgetBase::m_LineColour = QColor("black");
+ setZ(m_origZ = 0);
+}
+
+BoxWidget::~BoxWidget() {
+}
+
+void BoxWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ p.drawRect( offsetX, offsetY, width(), height() );
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void BoxWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement boxElement = qDoc.createElement("boxwidget");
+ UMLWidget::saveToXMI(qDoc, boxElement);
+ qElement.appendChild(boxElement);
+}
+
diff --git a/umbrello/umbrello/boxwidget.h b/umbrello/umbrello/boxwidget.h
new file mode 100644
index 00000000..f412fee6
--- /dev/null
+++ b/umbrello/umbrello/boxwidget.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef BOXWIDGET_H
+#define BOXWIDGET_H
+//qt includes
+#include <qpainter.h>
+//app includes
+#include "umlwidget.h"
+
+// fwd decl.
+class UMLView;
+
+/**
+ * Displays a rectangular box.
+ * These widgets are diagram specific. They will still need a unique id
+ * from the @ref UMLDoc class for deletion and other purposes.
+ *
+ * @short Displays a box.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class BoxWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a BoxWidget.
+ *
+ * @param view The parent to this widget.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ explicit BoxWidget(UMLView * view, Uml::IDType id = Uml::id_None);
+
+ /**
+ * destructor
+ */
+ virtual ~BoxWidget();
+
+ /**
+ * Draws a rectangle.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Saves the widget to the "boxwidget" XMI element.
+ * Note: For loading from XMI, the inherited parent method is used.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+};
+
+#endif
diff --git a/umbrello/umbrello/classifier.cpp b/umbrello/umbrello/classifier.cpp
new file mode 100644
index 00000000..22deee10
--- /dev/null
+++ b/umbrello/umbrello/classifier.cpp
@@ -0,0 +1,1023 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+// own header
+#include "classifier.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+// app includes
+#include "association.h"
+#include "umlassociationlist.h"
+#include "operation.h"
+#include "attribute.h"
+#include "template.h"
+#include "enumliteral.h"
+#include "entityattribute.h"
+#include "enum.h"
+#include "entity.h"
+#include "stereotype.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "umllistview.h"
+#include "uniqueid.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "clipboard/idchangelog.h"
+#include "dialogs/umloperationdialog.h"
+#include "dialogs/umlattributedialog.h"
+#include "dialogs/umltemplatedialog.h"
+#include "optionstate.h"
+
+using namespace Uml;
+
+UMLClassifier::UMLClassifier(const QString & name, Uml::IDType id)
+ : UMLPackage(name, id)
+{
+ init();
+}
+
+UMLClassifier::~UMLClassifier() {
+}
+
+void UMLClassifier::init() {
+ m_BaseType = Uml::ot_Class; // default value
+ m_pClassAssoc = NULL;
+ m_isRef = false;
+}
+
+void UMLClassifier::setBaseType(Uml::Object_Type ot) {
+ m_BaseType = ot;
+ Uml::Icon_Type newIcon;
+ switch (ot) {
+ case ot_Interface:
+ UMLObject::setStereotype("interface");
+ UMLObject::m_bAbstract = true;
+ newIcon = Uml::it_Interface;
+ break;
+ case ot_Class:
+ UMLObject::setStereotype(QString());
+ UMLObject::m_bAbstract = false;
+ newIcon = Uml::it_Class;
+ break;
+ case ot_Datatype:
+ UMLObject::setStereotype("datatype");
+ UMLObject::m_bAbstract = false;
+ newIcon = Uml::it_Datatype;
+ break;
+ default:
+ kError() << "UMLClassifier::setBaseType: cannot set to type "
+ << ot << endl;
+ return;
+ }
+ // @todo get rid of direct dependencies to UMLListView
+ // (e.g. move utility methods to Model_Utils and/or use signals)
+ UMLListView *listView = UMLApp::app()->getListView();
+ listView->changeIconOf(this, newIcon);
+}
+
+bool UMLClassifier::isInterface() const {
+ return (m_BaseType == ot_Interface);
+}
+
+bool UMLClassifier::isDatatype() const {
+ return (m_BaseType == ot_Datatype);
+}
+
+UMLOperation * UMLClassifier::checkOperationSignature(
+ const QString& name,
+ UMLAttributeList opParams,
+ UMLOperation *exemptOp)
+{
+ UMLOperationList list = findOperations(name);
+ if( list.count() == 0 )
+ return NULL;
+ const int inputParmCount = opParams.count();
+
+ // there is at least one operation with the same name... compare the parameter list
+ for (UMLOperationListIt oit(list); oit.current(); ++oit)
+ {
+ UMLOperation* test = oit.current();
+ if (test == exemptOp)
+ continue;
+ UMLAttributeList testParams = test->getParmList( );
+ const int pCount = testParams.count();
+ if( pCount != inputParmCount )
+ continue;
+ int i = 0;
+ while (i < pCount) {
+ // The only criterion for equivalence is the parameter types.
+ // (Default values are not considered.)
+ if( testParams.at(i)->getTypeName() != opParams.at(i)->getTypeName() )
+ break;
+ i++;
+ }
+ if( i == pCount )
+ {//all parameters matched -> the signature is not unique
+ return test;
+ }
+ }
+ // we did not find an exact match, so the signature is unique ( acceptable )
+ return NULL;
+}
+
+UMLOperation* UMLClassifier::findOperation(const QString& name,
+ Model_Utils::NameAndType_List params) {
+ UMLOperationList list = findOperations(name);
+ if (list.count() == 0)
+ return NULL;
+ // If there are operation(s) with the same name then compare the parameter list
+ const int inputParmCount = params.count();
+ UMLOperation* test = NULL;
+ for (UMLOperationListIt oit(list); (test = oit.current()) != NULL; ++oit) {
+ UMLAttributeList testParams = test->getParmList();
+ const int pCount = testParams.count();
+ if (inputParmCount == 0 && pCount == 0)
+ break;
+ if (inputParmCount != pCount)
+ continue;
+ int i = 0;
+ for (; i < pCount; ++i) {
+ Model_Utils::NameAndType_ListIt nt(params.at(i));
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>((*nt).m_type);
+ UMLClassifier *testType = testParams.at(i)->getType();
+ if (c == NULL) { //template parameter
+ if (testType->getName() != "class")
+ break;
+ } else if (c != testType)
+ break;
+ }
+ if (i == pCount)
+ break; // all parameters matched
+ }
+ return test;
+}
+
+UMLOperation* UMLClassifier::createOperation(const QString &name /*=null*/,
+ bool *isExistingOp /*=NULL*/,
+ Model_Utils::NameAndType_List *params /*=NULL*/)
+{
+ bool nameNotSet = (name.isNull() || name.isEmpty());
+ if (! nameNotSet) {
+ Model_Utils::NameAndType_List parList;
+ if (params)
+ parList = *params;
+ UMLOperation* existingOp = findOperation(name, parList);
+ if (existingOp != NULL) {
+ if (isExistingOp != NULL)
+ *isExistingOp = true;
+ return existingOp;
+ }
+ }
+ // we did not find an exact match, so the signature is unique
+ UMLOperation *op = new UMLOperation(this, name);
+ if (params) {
+ for (Model_Utils::NameAndType_ListIt it = params->begin(); it != params->end(); ++it ) {
+ const Model_Utils::NameAndType &nt = *it;
+ UMLAttribute *par = new UMLAttribute(op, nt.m_name, Uml::id_None, Uml::Visibility::Private,
+ nt.m_type, nt.m_initialValue);
+ par->setParmKind(nt.m_direction);
+ op->addParm(par);
+ }
+ }
+ if (nameNotSet || params == NULL) {
+ if (nameNotSet)
+ op->setName( uniqChildName(Uml::ot_Operation) );
+ do {
+ UMLOperationDialog operationDialogue(0, op);
+ if( operationDialogue.exec() != QDialog::Accepted ) {
+ delete op;
+ return NULL;
+ } else if (checkOperationSignature(op->getName(), op->getParmList())) {
+ KMessageBox::information(0,
+ i18n("An operation with the same name and signature already exists. You can not add it again."));
+ } else {
+ break;
+ }
+ } while(1);
+ }
+
+ // operation name is ok, formally add it to the classifier
+ if (! addOperation(op)) {
+ delete op;
+ return NULL;
+ }
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(op);
+ return op;
+}
+
+bool UMLClassifier::addOperation(UMLOperation* op, int position )
+{
+ if (m_List.findRef(op) != -1) {
+ kDebug() << "UMLClassifier::addOperation: findRef("
+ << op->getName() << ") finds op (bad)"
+ << endl;
+ return false;
+ }
+ if (checkOperationSignature(op->getName(), op->getParmList()) ) {
+ kDebug() << "UMLClassifier::addOperation: checkOperationSignature("
+ << op->getName() << ") op is non-unique" << endl;
+ return false;
+ }
+
+ if( position >= 0 && position <= (int)m_List.count() ) {
+ kDebug() << "UMLClassifier::addOperation(" << op->getName()
+ << "): inserting at position " << position << endl;
+ m_List.insert(position,op);
+ UMLClassifierListItemList itemList = getFilteredList(Uml::ot_Operation);
+ UMLClassifierListItem* currentAtt;
+ QString buf;
+ for (UMLClassifierListItemListIt it0(itemList); (currentAtt = it0.current()); ++it0)
+ buf.append(' ' + currentAtt->getName());
+ kDebug() << " UMLClassifier::addOperation list after change: " << buf << endl;
+ } else
+ m_List.append( op );
+ emit operationAdded(op);
+ UMLObject::emitModified();
+ connect(op,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+}
+
+bool UMLClassifier::addOperation(UMLOperation* Op, IDChangeLog* Log) {
+ if( addOperation( Op, -1 ) )
+ return true;
+ else if( Log ) {
+ Log->removeChangeByNewID( Op -> getID() );
+ }
+ return false;
+}
+
+int UMLClassifier::removeOperation(UMLOperation *op) {
+ if (op == NULL) {
+ kDebug() << "UMLClassifier::removeOperation called on NULL op"
+ << endl;
+ return -1;
+ }
+ if(!m_List.remove(op)) {
+ kDebug() << "UMLClassifier::removeOperation: can't find op "
+ << op->getName() << " in list" << endl;
+ return -1;
+ }
+ // disconnection needed.
+ // note that we don't delete the operation, just remove it from the Classifier
+ disconnect(op,SIGNAL(modified()),this,SIGNAL(modified()));
+ emit operationRemoved(op);
+ UMLObject::emitModified();
+ return m_List.count();
+}
+
+UMLObject* UMLClassifier::createTemplate(const QString& currentName /*= QString()*/) {
+ QString name = currentName;
+ bool goodName = !name.isEmpty();
+ if (!goodName)
+ name = uniqChildName(Uml::ot_Template);
+ UMLTemplate* newTemplate = new UMLTemplate(this, name);
+
+ int button = QDialog::Accepted;
+
+ while (button==QDialog::Accepted && !goodName) {
+ UMLTemplateDialog templateDialogue(0, newTemplate);
+ button = templateDialogue.exec();
+ name = newTemplate->getName();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if ( findChildObject(name) != NULL ) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ }
+
+ if (button != QDialog::Accepted) {
+ return NULL;
+ }
+
+ addTemplate(newTemplate);
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(newTemplate);
+ return newTemplate;
+}
+
+int UMLClassifier::attributes() {
+ UMLClassifierListItemList atts = getFilteredList(Uml::ot_Attribute);
+ return atts.count();
+}
+
+UMLAttributeList UMLClassifier::getAttributeList() const{
+ UMLAttributeList attributeList;
+ for (UMLObjectListIt lit(m_List); lit.current(); ++lit) {
+ UMLObject *listItem = lit.current();
+ if (listItem->getBaseType() == Uml::ot_Attribute) {
+ attributeList.append(static_cast<UMLAttribute*>(listItem));
+ }
+ }
+ return attributeList;
+}
+
+UMLOperationList UMLClassifier::findOperations(const QString &n) {
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ UMLOperationList list;
+ for (UMLObjectListIt lit(m_List); lit.current(); ++lit) {
+ UMLObject* obj = lit.current();
+ if (obj->getBaseType() != Uml::ot_Operation)
+ continue;
+ UMLOperation *op = static_cast<UMLOperation*>(obj);
+ if (caseSensitive) {
+ if (obj->getName() == n)
+ list.append(op);
+ } else if (obj->getName().lower() == n.lower()) {
+ list.append(op);
+ }
+ }
+ return list;
+}
+
+UMLObject* UMLClassifier::findChildObjectById(Uml::IDType id, bool considerAncestors /* =false */) {
+ UMLObject *o = UMLCanvasObject::findChildObjectById(id);
+ if (o)
+ return o;
+ if (considerAncestors) {
+ UMLClassifierList ancestors = findSuperClassConcepts();
+ for (UMLClassifier *anc = ancestors.first(); anc; anc = ancestors.next()) {
+ UMLObject *o = anc->findChildObjectById(id);
+ if (o)
+ return o;
+ }
+ }
+ return NULL;
+}
+
+UMLClassifierList UMLClassifier::findSubClassConcepts (ClassifierType type) {
+ UMLClassifierList list = getSubClasses();
+ UMLAssociationList rlist = getRealizations();
+
+ UMLClassifierList inheritingConcepts;
+ Uml::IDType myID = getID();
+ for (UMLClassifier *c = list.first(); c; c = list.next())
+ {
+ if (type == ALL || (!c->isInterface() && type == CLASS)
+ || (c->isInterface() && type == INTERFACE))
+ inheritingConcepts.append(c);
+ }
+
+ for (UMLAssociation *a = rlist.first(); a; a = rlist.next())
+ {
+ if (a->getObjectId(A) != myID)
+ {
+ UMLObject* obj = a->getObject(A);
+ UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
+ if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ && (inheritingConcepts.findRef(concept) == -1))
+ inheritingConcepts.append(concept);
+ }
+ }
+
+ return inheritingConcepts;
+}
+
+UMLClassifierList UMLClassifier::findSuperClassConcepts (ClassifierType type) {
+ UMLClassifierList list = getSuperClasses();
+ UMLAssociationList rlist = getRealizations();
+
+ UMLClassifierList parentConcepts;
+ Uml::IDType myID = getID();
+ for (UMLClassifier *concept = list.first(); concept; concept = list.next())
+ {
+ if (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ parentConcepts.append(concept);
+ }
+
+ for (UMLAssociation *a = rlist.first(); a; a = rlist.next())
+ {
+ if (a->getObjectId(A) == myID)
+ {
+ UMLObject* obj = a->getObject(B);
+ UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
+ if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
+ || (concept->isInterface() && type == INTERFACE))
+ && (parentConcepts.findRef(concept) == -1))
+ parentConcepts.append(concept);
+ }
+ }
+
+ return parentConcepts;
+}
+
+bool UMLClassifier::operator==( UMLClassifier & rhs ) {
+ /*
+ if ( m_List.count() != rhs.m_List.count() ) {
+ return false;
+ }
+ if ( &m_List != &(rhs.m_List) ) {
+ return false;
+ }
+ */
+ return UMLCanvasObject::operator==(rhs);
+}
+
+
+void UMLClassifier::copyInto(UMLClassifier *rhs) const
+{
+ UMLCanvasObject::copyInto(rhs);
+ rhs->setBaseType(m_BaseType);
+ // CHECK: association property m_pClassAssoc is not copied
+ m_List.copyInto(&(rhs->m_List));
+}
+
+UMLObject* UMLClassifier::clone() const {
+ UMLClassifier *clone = new UMLClassifier();
+ copyInto(clone);
+ return clone;
+}
+
+bool UMLClassifier::resolveRef() {
+ bool success = UMLPackage::resolveRef();
+ // Using reentrant iteration is a bare necessity here:
+ for (UMLObjectListIt oit(m_List); oit.current(); ++oit) {
+ UMLObject* obj = oit.current();
+ /**** For reference, here is the non-reentrant iteration scheme -
+ DO NOT USE THIS !
+ for (UMLObject *obj = m_List.first(); obj; obj = m_List.next())
+ { .... }
+ ****/
+ if (obj->resolveRef()) {
+ UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
+ switch (cli->getBaseType()) {
+ case Uml::ot_Attribute:
+ emit attributeAdded(cli);
+ break;
+ case Uml::ot_Operation:
+ emit operationAdded(cli);
+ break;
+ case Uml::ot_Template:
+ emit templateAdded(cli);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return success;
+}
+
+bool UMLClassifier::acceptAssociationType(Uml::Association_Type type)
+{
+ switch(type)
+ {
+ case at_Generalization:
+ case at_Aggregation:
+ case at_Relationship:
+ case at_Dependency:
+ case at_Association:
+ case at_Association_Self:
+ case at_Containment:
+ case at_Composition:
+ case at_Realization:
+ case at_UniAssociation:
+ return true;
+ default:
+ return false;
+ }
+ return false; //shutup compiler warning
+}
+
+UMLAttribute* UMLClassifier::createAttribute(const QString &name,
+ UMLObject *type,
+ Uml::Visibility vis,
+ const QString &init) {
+ Uml::IDType id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(Uml::ot_Attribute);
+ } else {
+ currentName = name;
+ }
+ UMLAttribute* newAttribute = new UMLAttribute(this, currentName, id, vis, type, init);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button == QDialog::Accepted && !goodName && name.isNull()) {
+ UMLAttributeDialog attributeDialogue(0, newAttribute);
+ button = attributeDialogue.exec();
+ QString name = newAttribute->getName();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if ( findChildObject(name) != NULL ) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ }
+
+ if (button != QDialog::Accepted) {
+ delete newAttribute;
+ return NULL;
+ }
+
+ addAttribute(newAttribute);
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(newAttribute);
+ return newAttribute;
+}
+
+UMLAttribute* UMLClassifier::addAttribute(const QString &name, Uml::IDType id /* = Uml::id_None */) {
+ for (UMLObjectListIt lit(m_List); lit.current(); ++lit) {
+ UMLObject *obj = lit.current();
+ if (obj->getBaseType() == Uml::ot_Attribute && obj->getName() == name)
+ return static_cast<UMLAttribute*>(obj);
+ }
+ Uml::Visibility scope = Settings::getOptionState().classState.defaultAttributeScope;
+ UMLAttribute *a = new UMLAttribute(this, name, id, scope);
+ m_List.append(a);
+ emit attributeAdded(a);
+ UMLObject::emitModified();
+ connect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ return a;
+}
+
+UMLAttribute* UMLClassifier::addAttribute(const QString &name, UMLObject *type, Uml::Visibility scope) {
+ UMLAttribute *a = new UMLAttribute(this);
+ a->setName(name);
+ a->setVisibility(scope);
+ a->setID(UniqueID::gen());
+ if (type)
+ a->setType(type);
+ m_List.append(a);
+ emit attributeAdded(a);
+ UMLObject::emitModified();
+ connect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ return a;
+}
+
+bool UMLClassifier::addAttribute(UMLAttribute* att, IDChangeLog* Log /* = 0 */,
+ int position /* = -1 */) {
+ if (findChildObject(att->getName()) == NULL) {
+ att->parent()->removeChild( att );
+ this->insertChild( att );
+ if (position >= 0 && position < (int)m_List.count())
+ m_List.insert(position, att);
+ else
+ m_List.append(att);
+ emit attributeAdded(att);
+ UMLObject::emitModified();
+ connect(att, SIGNAL(modified()), this, SIGNAL(modified()));
+ return true;
+ } else if (Log) {
+ Log->removeChangeByNewID(att->getID());
+ delete att;
+ }
+ return false;
+}
+
+int UMLClassifier::removeAttribute(UMLAttribute* a) {
+ if (!m_List.remove(a)) {
+ kDebug() << "can't find att given in list" << endl;
+ return -1;
+ }
+ emit attributeRemoved(a);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ delete a;
+ return m_List.count();
+}
+
+
+void UMLClassifier::setClassAssoc(UMLAssociation *assoc) {
+ m_pClassAssoc = assoc;
+}
+
+UMLAssociation *UMLClassifier::getClassAssoc() const{
+ return m_pClassAssoc;
+}
+
+bool UMLClassifier::hasAbstractOps () {
+ UMLOperationList opl( getOpList() );
+ for(UMLOperation *op = opl.first(); op ; op = opl.next())
+ if(op->getAbstract())
+ return true;
+ return false;
+}
+
+int UMLClassifier::operations() {
+ return getOpList().count();
+}
+
+UMLOperationList UMLClassifier::getOpList(bool includeInherited) {
+ UMLOperationList ops;
+ for (UMLObjectListIt lit(m_List); lit.current(); ++lit) {
+ UMLObject *li = lit.current();
+ if (li->getBaseType() == ot_Operation)
+ ops.append(static_cast<UMLOperation*>(li));
+ }
+ if (includeInherited) {
+ UMLClassifierList parents = findSuperClassConcepts();
+ UMLClassifier *c;
+ for (UMLClassifierListIt pit(parents); (c = pit.current()) != NULL; ++pit) {
+ if (c == this) {
+ kError() << "UMLClassifier::getOpList: class " << c->getName()
+ << " is parent of itself ?!?" << endl;
+ continue;
+ }
+ // get operations for each parent by recursive call
+ UMLOperationList pops = c->getOpList(true);
+ // add these operations to operation list, but only if unique.
+ for (UMLOperation *po = pops.first(); po; po = pops.next()) {
+ QString po_as_string(po->toString(Uml::st_SigNoVis));
+ UMLOperation *o = NULL;
+ for (o = ops.first(); o; o = ops.next())
+ if (o->toString(Uml::st_SigNoVis) == po_as_string)
+ break;
+ if (!o)
+ ops.append(po);
+ }
+ }
+ }
+ return ops;
+}
+
+UMLClassifierListItemList UMLClassifier::getFilteredList(Uml::Object_Type ot) const {
+ UMLClassifierListItemList resultList;
+ UMLObject *o;
+ for (UMLObjectListIt lit(m_List); (o = lit.current()) != NULL; ++lit) {
+ if (o->getBaseType() == Uml::ot_Association)
+ continue;
+ UMLClassifierListItem *listItem = static_cast<UMLClassifierListItem*>(o);
+ if (ot == Uml::ot_UMLObject || listItem->getBaseType() == ot)
+ resultList.append(listItem);
+ }
+ return resultList;
+}
+
+UMLTemplate* UMLClassifier::addTemplate(const QString &name, Uml::IDType id) {
+ UMLTemplate *t = findTemplate(name);
+ if (t)
+ return t;
+ t = new UMLTemplate(this, name, id);
+ m_List.append(t);
+ emit templateAdded(t);
+ UMLObject::emitModified();
+ connect(t, SIGNAL(modified()), this, SIGNAL(modified()));
+ return t;
+}
+
+bool UMLClassifier::addTemplate(UMLTemplate* newTemplate, IDChangeLog* log /* = 0*/) {
+ QString name = newTemplate->getName();
+ if (findChildObject(name) == NULL) {
+ newTemplate->parent()->removeChild(newTemplate);
+ this->insertChild(newTemplate);
+ m_List.append(newTemplate);
+ emit templateAdded(newTemplate);
+ UMLObject::emitModified();
+ connect(newTemplate,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ } else if (log) {
+ log->removeChangeByNewID( newTemplate->getID() );
+ delete newTemplate;
+ }
+ return false;
+}
+
+bool UMLClassifier::addTemplate(UMLTemplate* Template, int position)
+{
+ QString name = Template->getName();
+ if (findChildObject(name) == NULL) {
+ Template->parent()->removeChild(Template);
+ this->insertChild(Template);
+ if( position >= 0 && position <= (int)m_List.count() )
+ m_List.insert(position,Template);
+ else
+ m_List.append(Template);
+ emit templateAdded(Template);
+ UMLObject::emitModified();
+ connect(Template,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ }
+ //else
+ return false;
+}
+
+int UMLClassifier::removeTemplate(UMLTemplate* umltemplate) {
+ if ( !m_List.remove(umltemplate) ) {
+ kWarning() << "can't find att given in list" << endl;
+ return -1;
+ }
+ emit templateRemoved(umltemplate);
+ UMLObject::emitModified();
+ disconnect(umltemplate,SIGNAL(modified()),this,SIGNAL(modified()));
+ return m_List.count();
+}
+
+
+UMLTemplate *UMLClassifier::findTemplate(const QString& name) {
+ UMLTemplateList templParams = getTemplateList();
+ for (UMLTemplate *t = templParams.first(); t; t = templParams.next()) {
+ if (t->getName() == name)
+ return t;
+ }
+ return NULL;
+}
+
+int UMLClassifier::templates() {
+ UMLClassifierListItemList tempList = getFilteredList(Uml::ot_Template);
+ return tempList.count();
+}
+
+UMLTemplateList UMLClassifier::getTemplateList() const {
+ UMLTemplateList templateList;
+ for (UMLObjectListIt lit(m_List); lit.current(); ++lit) {
+ UMLObject *listItem = lit.current();
+ if (listItem->getBaseType() == Uml::ot_Template) {
+ templateList.append(static_cast<UMLTemplate*>(listItem));
+ }
+ }
+ return templateList;
+}
+
+int UMLClassifier::takeItem(UMLClassifierListItem *item) {
+ UMLObject* currentAtt;
+ QString buf;
+ for (UMLObjectListIt it0(m_List);
+ (currentAtt = it0.current()); ++it0) {
+ QString txt = currentAtt->getName();
+ if (txt.isEmpty())
+ txt = "Type-" + QString::number((int) currentAtt->getBaseType());
+ buf.append(' ' + currentAtt->getName());
+ }
+ kDebug() << " UMLClassifier::takeItem (before): m_List is " << buf << endl;
+ int index = m_List.findRef(item);
+ if (index == -1)
+ return -1;
+ switch (item->getBaseType()) {
+ case Uml::ot_Operation: {
+ if (removeOperation(dynamic_cast<UMLOperation*>(item)) < 0)
+ index = -1;
+ break;
+ }
+ case Uml::ot_Attribute: {
+ UMLAttribute *retval = dynamic_cast<UMLAttribute*>(m_List.take());
+ if (retval) {
+ emit attributeRemoved(retval);
+ emit modified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case Uml::ot_Template: {
+ UMLTemplate *t = dynamic_cast<UMLTemplate*>(m_List.take());
+ if (t) {
+ emit templateRemoved(t);
+ emit modified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case Uml::ot_EnumLiteral: {
+ UMLEnumLiteral *el = dynamic_cast<UMLEnumLiteral*>(m_List.take());
+ if (el) {
+ UMLEnum *e = static_cast<UMLEnum*>(this);
+ e->signalEnumLiteralRemoved(el);
+ emit modified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ case Uml::ot_EntityAttribute: {
+ UMLEntityAttribute* el = dynamic_cast<UMLEntityAttribute*>(m_List.take());
+ if (el) {
+ UMLEntity *e = static_cast<UMLEntity*>(this);
+ e->signalEntityAttributeRemoved(el);
+ emit modified();
+ } else {
+ index = -1;
+ }
+ break;
+ }
+ default:
+ index = -1;
+ break;
+ }
+ return index;
+}
+
+void UMLClassifier::setOriginType(UMLClassifier *origType) {
+ m_pSecondary = origType;
+}
+
+UMLClassifier * UMLClassifier::originType() const{
+ return static_cast<UMLClassifier*>(m_pSecondary);
+}
+
+void UMLClassifier::setIsReference(bool isRef) {
+ m_isRef = isRef;
+}
+
+bool UMLClassifier::isReference() const{
+ return m_isRef;
+}
+
+UMLAssociationList UMLClassifier::getUniAssociationToBeImplemented() {
+ UMLAssociationList associations = getSpecificAssocs(Uml::at_UniAssociation);
+ UMLAssociationList uniAssocListToBeImplemented;
+
+ for(UMLAssociation *a = associations.first(); a; a = associations.next()) {
+ if (a->getObjectId(Uml::B) == getID())
+ continue; // we need to be at the A side
+
+ QString roleNameB = a->getRoleName(Uml::B);
+ if (!roleNameB.isEmpty()) {
+ UMLAttributeList atl = getAttributeList();
+ bool found = false;
+ //make sure that an attribute with the same name doesn't already exist
+ for (UMLAttribute *at = atl.first(); at ; at = atl.next()) {
+ if (at->getName() == roleNameB) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ uniAssocListToBeImplemented.append(a);
+ }
+ }
+ }
+ return uniAssocListToBeImplemented;
+}
+
+void UMLClassifier::saveToXMI(QDomDocument & qDoc, QDomElement & qElement) {
+ QString tag;
+ switch (m_BaseType) {
+ case Uml::ot_Class:
+ tag = "UML:Class";
+ break;
+ case Uml::ot_Interface:
+ tag = "UML:Interface";
+ break;
+ case Uml::ot_Datatype:
+ tag = "UML:DataType";
+ break;
+ default:
+ kError() << "UMLClassifier::saveToXMI() internal error: basetype is "
+ << m_BaseType << endl;
+ return;
+ }
+ QDomElement classifierElement = UMLObject::save(tag, qDoc);
+ if (m_BaseType == Uml::ot_Datatype && m_pSecondary != NULL)
+ classifierElement.setAttribute( "elementReference",
+ ID2STR(m_pSecondary->getID()) );
+
+ //save templates
+ UMLClassifierListItemList list = getFilteredList(Uml::ot_Template);
+ if (list.count()) {
+ QDomElement tmplElement = qDoc.createElement( "UML:ModelElement.templateParameter" );
+ for (UMLClassifierListItem *tmpl = list.first(); tmpl; tmpl = list.next() ) {
+ tmpl->saveToXMI(qDoc, tmplElement);
+ }
+ classifierElement.appendChild( tmplElement );
+ }
+
+ //save generalizations (we are the subclass, the other end is the superclass)
+ UMLAssociationList generalizations = getSpecificAssocs(Uml::at_Generalization);
+ if (generalizations.count()) {
+ QDomElement genElement = qDoc.createElement("UML:GeneralizableElement.generalization");
+ for (UMLAssociation *a = generalizations.first(); a; a = generalizations.next()) {
+ // We are the subclass if we are at the role A end.
+ if (m_nId != a->getObjectId(Uml::A))
+ continue;
+ QDomElement gElem = qDoc.createElement("UML:Generalization");
+ gElem.setAttribute( "xmi.idref", ID2STR(a->getID()) );
+ genElement.appendChild(gElem);
+ }
+ if (genElement.hasChildNodes())
+ classifierElement.appendChild( genElement );
+ }
+
+ // save attributes
+ QDomElement featureElement = qDoc.createElement( "UML:Classifier.feature" );
+ UMLClassifierListItemList attList = getFilteredList(Uml::ot_Attribute);
+ for (UMLClassifierListItem *pAtt = attList.first(); pAtt; pAtt = attList.next() )
+ pAtt -> saveToXMI( qDoc, featureElement );
+
+ // save operations
+ UMLOperationList opList = getOpList();
+ for (UMLOperation *pOp = opList.first(); pOp; pOp = opList.next() )
+ pOp -> saveToXMI( qDoc, featureElement );
+ if (featureElement.hasChildNodes())
+ classifierElement.appendChild( featureElement );
+
+ // save contained objects
+ if (m_objects.count()) {
+ QDomElement ownedElement = qDoc.createElement( "UML:Namespace.ownedElement" );
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ obj->saveToXMI (qDoc, ownedElement);
+ }
+ classifierElement.appendChild( ownedElement );
+ }
+ qElement.appendChild( classifierElement );
+}
+
+UMLClassifierListItem* UMLClassifier::makeChildObject(const QString& xmiTag) {
+ UMLClassifierListItem* pObject = NULL;
+ if (tagEq(xmiTag, "Operation")) {
+ pObject = new UMLOperation(this);
+ } else if (tagEq(xmiTag, "Attribute")) {
+ if (getBaseType() != Uml::ot_Class)
+ return NULL;
+ pObject = new UMLAttribute(this);
+ } else if (tagEq(xmiTag, "TemplateParameter")) {
+ pObject = new UMLTemplate(this);
+ }
+ return pObject;
+}
+
+bool UMLClassifier::load(QDomElement& element) {
+ UMLClassifierListItem *child = NULL;
+ m_SecondaryId = element.attribute( "elementReference", "" );
+ if (!m_SecondaryId.isEmpty()) {
+ // @todo We do not currently support composition.
+ m_isRef = true;
+ }
+ bool totalSuccess = true;
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ element = node.toElement();
+ QString tag = element.tagName();
+ if (tagEq(tag, "ModelElement.templateParameter") ||
+ tagEq(tag, "Classifier.feature") ||
+ tagEq(tag, "Namespace.ownedElement") ||
+ tagEq(tag, "Namespace.contents")) {
+ load(element);
+ // Not evaluating the return value from load()
+ // because we want a best effort.
+
+ } else if ((child = makeChildObject(tag)) != NULL) {
+ if (child->loadFromXMI(element)) {
+ switch (child->getBaseType()) {
+ case Uml::ot_Template:
+ addTemplate( static_cast<UMLTemplate*>(child) );
+ break;
+ case Uml::ot_Operation:
+ if (! addOperation(static_cast<UMLOperation*>(child)) ) {
+ kError() << "UMLClassifier::load: error from addOperation(op)"
+ << endl;
+ delete child;
+ totalSuccess = false;
+ }
+ break;
+ case Uml::ot_Attribute:
+ addAttribute( static_cast<UMLAttribute*>(child) );
+ break;
+ default:
+ break;
+ }
+ } else {
+ kWarning() << "UMLClassifier::load: failed to load " << tag << endl;
+ delete child;
+ totalSuccess = false;
+ }
+ } else if (!Model_Utils::isCommonXMIAttribute(tag)) {
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(tag);
+ if (pObject == NULL) {
+ // Not setting totalSuccess to false
+ // because we want a best effort.
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (! pObject->loadFromXMI(element)) {
+ removeObject(pObject);
+ delete pObject;
+ totalSuccess = false;
+ }
+ }
+ }
+ return totalSuccess;
+}
+
+
+
+#include "classifier.moc"
diff --git a/umbrello/umbrello/classifier.h b/umbrello/umbrello/classifier.h
new file mode 100644
index 00000000..c599fe16
--- /dev/null
+++ b/umbrello/umbrello/classifier.h
@@ -0,0 +1,496 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIER__H
+#define CLASSIFIER__H
+
+#include "package.h"
+#include "umlattributelist.h"
+#include "umloperationlist.h"
+#include "umlclassifierlistitemlist.h"
+#include "classifierlistitem.h"
+#include "umltemplatelist.h"
+#include "model_utils.h"
+
+// forward declarations
+class UMLAssociation;
+class IDChangeLog;
+
+/**
+ * This class defines the non-graphical information required for a
+ * UML Classifier (ie a class or interface).
+ * This class inherits from @ref UMLPackage which allows classifiers
+ * to also act as namespaces, i.e. it allows classifiers to nest.
+ *
+ * @short Information for a non-graphical Concept/Class.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLClassifier : public UMLPackage {
+ Q_OBJECT
+public:
+
+ /**
+ * Enumeration identifying the type of classifier.
+ */
+ enum ClassifierType { ALL = 0, CLASS, INTERFACE, DATATYPE };
+
+
+ /**
+ * Sets up a Concept.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLClassifier(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLClassifier();
+
+ /**
+ * Overloaded '==' operator.
+ */
+ bool operator==( UMLClassifier & rhs );
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLClassifier *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ UMLObject* clone() const;
+
+ /**
+ * Creates an attribute for the class.
+ *
+ * @param name An optional name, used by when creating through UMLListView
+ * @param type An optional type, used by when creating through UMLListView
+ * @param vis An optional visibility, used by when creating through UMLListView
+ * @param init An optional initial value, used by when creating through UMLListView
+ * @return The UMLAttribute created
+ */
+ virtual UMLAttribute* createAttribute(const QString &name = QString::null,
+ UMLObject *type = 0,
+ Uml::Visibility vis = Uml::Visibility::Private,
+ const QString &init = QString::null);
+
+ /**
+ * Adds an attribute to the class.
+ * If an attribute of the given name already exists, then
+ * returns the existing attribute instead of creating a new one.
+ *
+ * @param name The name of the attribute.
+ * @param id The id of the attribute (optional.)
+ * If not given, and the attribute name
+ * does not already exist, then the method
+ * will internally assign a new ID.
+ * @return Pointer to the UMLAttribute created or found.
+ */
+ UMLAttribute* addAttribute(const QString &name, Uml::IDType id = Uml::id_None);
+
+ UMLAttribute* addAttribute(const QString &name, UMLObject *type, Uml::Visibility scope);
+
+ /**
+ * Adds an already created attribute.
+ * The attribute object must not belong to any other concept.
+ *
+ * @param Att Pointer to the UMLAttribute.
+ * @param Log Pointer to the IDChangeLog (optional.)
+ * @param position Position index for the insertion (optional.)
+ * If the position is omitted, or if it is
+ * negative or too large, the attribute is added
+ * to the end of the list.
+ * @return True if the attribute was successfully added.
+ */
+ bool addAttribute(UMLAttribute* Att, IDChangeLog* Log = 0,
+ int position = -1);
+
+ /**
+ * Removes an attribute from the class.
+ *
+ * @param a The attribute to remove.
+ * @return Count of the remaining attributes after removal.
+ * Returns -1 if the given attribute was not found.
+ */
+ int removeAttribute(UMLAttribute *a);
+
+ /**
+ * Returns the number of attributes for the class.
+ *
+ * @return The number of attributes for the class.
+ */
+ int attributes() ;
+
+ /**
+ * Returns the attributes.
+ * Same as UMLClassifier::getFilteredList(ot_Attribute) but
+ * return type is a true UMLAttributeList.
+ *
+ * @return List of true attributes for the class.
+ */
+ UMLAttributeList getAttributeList() const;
+
+ /**
+ * Creates an operation in the current document.
+ * The new operation is initialized with name, id, etc.
+ * If a method with the given profile already exists in the classifier,
+ * no new method is created and the existing operation is returned.
+ * If no name is provided, or if the params are NULL, an Operation
+ * Dialog is shown to ask the user for a name and parameters.
+ * The operation's signature is checked for validity within the parent
+ * classifier.
+ *
+ * @param name The operation name (will be chosen internally if
+ * none given.)
+ * @param isExistingOp Optional pointer to bool. If supplied, the bool is
+ * set to true if an existing operation is returned.
+ * @param params Optional list of parameter names and types.
+ * If supplied, new operation parameters are
+ * constructed using this list.
+ * @return The new operation, or NULL if the operation could not be
+ * created because for example, the user canceled the dialog
+ * or no appropriate name can be found.
+ */
+ UMLOperation* createOperation( const QString &name = QString::null,
+ bool *isExistingOp = NULL,
+ Model_Utils::NameAndType_List *params = NULL);
+
+ /**
+ * Adds an operation to the classifier, at the given position.
+ * If position is negative or too large, the attribute is added
+ * to the end of the list.
+ * The Classifier first checks and only adds the Operation if the
+ * signature does not conflict with exising operations
+ *
+ * @param Op Pointer to the UMLOperation to add.
+ * @param position Index at which to insert into the list.
+ * @return true if the Operation could be added to the Classifier.
+ */
+ bool addOperation(UMLOperation* Op, int position = -1);
+
+ /**
+ * Appends an operation to the classifier.
+ * @see bool addOperation(UMLOperation* Op, int position = -1)
+ * This function is mainly intended for the clipboard.
+ *
+ * @param Op Pointer to the UMLOperation to add.
+ * @param Log Pointer to the IDChangeLog.
+ * @return True if the operation was added successfully.
+ */
+ bool addOperation(UMLOperation* Op, IDChangeLog* Log);
+
+ /**
+ * Checks whether an operation is valid based on its signature -
+ * An operation is "valid" if the operation's name and parameter list
+ * are unique in the classifier.
+ *
+ * @param name Name of the operation to check.
+ * @param opParams The operation's argument list.
+ * @param exemptOp Pointer to the exempt method (optional.)
+ * @return NULL if the signature is valid (ok), else return a pointer
+ * to the existing UMLOperation that causes the conflict.
+ */
+ UMLOperation * checkOperationSignature( const QString& name,
+ UMLAttributeList opParams,
+ UMLOperation *exemptOp = NULL);
+
+ /**
+ * Remove an operation from the Classifier.
+ * The operation is not deleted so the caller is responsible for what
+ * happens to it after this.
+ *
+ * @param op The operation to remove.
+ * @return Count of the remaining operations after removal, or
+ * -1 if the given operation was not found.
+ */
+ int removeOperation(UMLOperation *op);
+
+ /**
+ * counts the number of operations in the Classifier.
+ *
+ * @return The number of operations for the Classifier.
+ */
+ int operations() ;
+
+ /**
+ * Return a list of operations for the Classifier.
+ * @param includeInherited Includes operations from superclasses.
+ *
+ * @return The list of operations for the Classifier.
+ */
+ UMLOperationList getOpList(bool includeInherited = false);
+
+ /**
+ * Creates a template for the concept.
+ *
+ * @return The UMLTemplate created
+ */
+ UMLObject* createTemplate(const QString& name = QString::null);
+
+ /**
+ * Adds a template to the class if it is not there yet.
+ *
+ * @param name The name of the template.
+ * @param id The id of the template.
+ * @return Pointer to the UMLTemplate object created.
+ */
+ UMLTemplate* addTemplate(const QString &name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Adds an already created template.
+ * The template object must not belong to any other concept.
+ *
+ * @param newTemplate Pointer to the UMLTemplate object to add.
+ * @param log Pointer to the IDChangeLog.
+ * @return True if the template was successfully added.
+ */
+ bool addTemplate(UMLTemplate* newTemplate, IDChangeLog* log = 0);
+
+ /**
+ * Adds an template to the class.
+ * The template object must not belong to any other class.
+ *
+ * @param Template Pointer to the UMLTemplate to add.
+ * @param position The position of the template in the list.
+ * A value of -1 will add the template at the end.
+ * @return True if the template was successfully added.
+ */
+ //TODO: if the param IDChangeLog from the method above is not being used,
+ // give position a default value of -1 and the method can replace the above one
+ bool addTemplate(UMLTemplate* Template, int position);
+
+ /**
+ * Removes a template from the class.
+ *
+ * @param umltemplate The template to remove.
+ * @return Count of the remaining templates after removal.
+ * Returns -1 if the given template was not found.
+ */
+ int removeTemplate(UMLTemplate* umltemplate);
+
+ /**
+ * Seeks the template parameter of the given name.
+ */
+ UMLTemplate *findTemplate(const QString& name);
+
+ /**
+ * Returns the number of templates for the class.
+ *
+ * @return The number of templates for the class.
+ */
+ int templates();
+
+ /**
+ * Returns the templates.
+ * Same as UMLClassifier::getFilteredList(ot_Template) but
+ * return type is a true UMLTemplateList.
+ *
+ * @return Pointer to the list of true templates for the class.
+ */
+ UMLTemplateList getTemplateList() const;
+
+ /**
+ * Take and return a subordinate item from this classifier.
+ * Ownership of the item is passed to the caller.
+ *
+ * @param item Subordinate item to take.
+ * @return Index in m_List of the item taken.
+ * Return -1 if the item is not found in m_List.
+ */
+ int takeItem(UMLClassifierListItem* item);
+
+ /**
+ * Returns the entries in m_List that are of the requested type.
+ * If the requested type is Uml::ot_UMLObject then all entries
+ * are returned.
+ *
+ * @return The list of true operations for the Concept.
+ */
+ virtual UMLClassifierListItemList getFilteredList(Uml::Object_Type ot) const;
+
+ /**
+ * Needs to be called after all UML objects are loaded from file.
+ * Calls the parent resolveRef(), and calls resolveRef() on all
+ * UMLClassifierListItems.
+ * Overrides the method from UMLObject.
+ *
+ * @return true for success.
+ */
+ virtual bool resolveRef();
+
+ /**
+ * Find a list of operations with the given name.
+ *
+ * @param n The name of the operation to find.
+ * @return The list of objects found; will be empty if none found.
+ */
+ UMLOperationList findOperations(const QString &n);
+
+ /**
+ * Find an attribute, operation, association or template.
+ *
+ * @param id The id of the object to find.
+ *
+ * @return The object found. Will return 0 if none found.
+ */
+ virtual UMLObject* findChildObjectById(Uml::IDType id, bool considerAncestors = false);
+
+ /**
+ * Find an operation of the given name and parameter signature.
+ *
+ * @param name The name of the operation to find.
+ * @param params The parameter descriptors of the operation to find.
+ *
+ * @return The operation found. Will return 0 if none found.
+ */
+ UMLOperation* findOperation(const QString& name,
+ Model_Utils::NameAndType_List params);
+
+ /**
+ * Returns a list of concepts which this concept inherits from.
+ *
+ * @param type The ClassifierType to seek.
+ * @return List of UMLClassifiers we inherit from.
+ */
+ UMLClassifierList findSuperClassConcepts(ClassifierType type = ALL);
+
+ /**
+ * Returns a list of concepts which inherit from this concept.
+ *
+ * @param type The ClassifierType to seek.
+ * @return List of UMLClassifiers that inherit from us.
+ */
+ UMLClassifierList findSubClassConcepts(ClassifierType type = ALL);
+
+ /** reimplemented from UMLObject */
+ virtual bool acceptAssociationType(Uml::Association_Type);
+
+ /**
+ * Sets the UMLAssociation for which this class shall act as an
+ * association class.
+ */
+ void setClassAssoc(UMLAssociation *assoc);
+
+ /**
+ * Returns the UMLAssociation for which this class acts as an
+ * association class. Returns NULL if this class does not act
+ * as an association class.
+ */
+ UMLAssociation *getClassAssoc() const;
+
+ /**
+ * Reimplementation of method from class UMLObject for controlling the
+ * exact type of this classifier: class, interface, or datatype.
+ */
+ void setBaseType(Uml::Object_Type ot);
+
+ /**
+ * Returns true if this classifier represents an interface.
+ */
+ bool isInterface() const;
+
+ /**
+ * Returns true if this classifier represents a datatype.
+ */
+ bool isDatatype() const;
+
+ /**
+ * Set the origin type (in case of e.g. typedef)
+ */
+ void setOriginType(UMLClassifier *origType);
+
+ /**
+ * Get the origin type (in case of e.g. typedef)
+ */
+ UMLClassifier * originType() const;
+
+ /**
+ * Set the m_isRef flag (true when dealing with a pointer type)
+ */
+ void setIsReference(bool isRef = true);
+
+ /**
+ * Get the m_isRef flag.
+ */
+ bool isReference() const;
+
+ /**
+ * Return true if this classifier has abstract operations.
+ */
+ bool hasAbstractOps ();
+
+ /**
+ * Create a new ClassifierListObject (attribute, operation, template)
+ * according to the given XMI tag.
+ * Returns NULL if the string given does not contain one of the tags
+ * <UML:Attribute>, <UML:Operation>, or <UML:TemplateParameter>.
+ * Used by the clipboard for paste operation.
+ */
+ UMLClassifierListItem* makeChildObject(const QString& xmiTag);
+
+ /**
+ * Return the list of unidirectional association that should show up in the code
+ */
+ virtual UMLAssociationList getUniAssociationToBeImplemented();
+
+signals:
+ /** Signals that a new UMLOperation has been added to the classifer.
+ */
+ void operationAdded(UMLClassifierListItem *);
+
+ /** Signals that a UMLOperation has been removed from the classifer.
+ */
+ void operationRemoved(UMLClassifierListItem *);
+
+ void templateAdded(UMLClassifierListItem*);
+ void templateRemoved(UMLClassifierListItem*);
+
+ // only applies when (m_Type == ot_Class)
+ void attributeAdded(UMLClassifierListItem*);
+ void attributeRemoved(UMLClassifierListItem*);
+
+private:
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ UMLAssociation *m_pClassAssoc;
+
+ bool m_isRef;
+
+protected:
+
+ /**
+ * Auxiliary to saveToXMI of inheriting classes:
+ * Saves template parameters to the given QDomElement.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Auxiliary to loadFromXMI:
+ * The loading of operations is implemented here.
+ * Calls loadSpecialized() for any other tag.
+ * Child classes can override the loadSpecialized method
+ * to load its additional tags.
+ */
+ virtual bool load(QDomElement& element);
+
+};
+
+#endif // CONCEPT_H
diff --git a/umbrello/umbrello/classifiercodedocument.cpp b/umbrello/umbrello/classifiercodedocument.cpp
new file mode 100644
index 00000000..a2d2f9fc
--- /dev/null
+++ b/umbrello/umbrello/classifiercodedocument.cpp
@@ -0,0 +1,742 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+// own header
+#include "classifiercodedocument.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <qregexp.h>
+
+// local includes
+#include "association.h"
+#include "attribute.h"
+#include "operation.h"
+#include "classifierlistitem.h"
+#include "classifier.h"
+#include "codegenerator.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlrole.h"
+#include "umlattributelist.h"
+#include "umloperationlist.h"
+#include "codegenerators/codegenfactory.h"
+
+// Constructors/Destructors
+//
+
+ClassifierCodeDocument::ClassifierCodeDocument ( UMLClassifier * parent )
+{
+ init (parent);
+}
+
+ClassifierCodeDocument::~ClassifierCodeDocument ( )
+{
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ delete cf;
+ }
+ m_classfieldVector.clear();
+}
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ */
+CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType)
+{
+ CodeClassFieldList list;
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if (cf->getClassFieldType() == cfType)
+ list.append(cf);
+ }
+ return list;
+}
+
+/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ */
+CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic)
+{
+ CodeClassFieldList list;
+ list.setAutoDelete(false);
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if (cf->getClassFieldType() == cfType && cf->getStatic() == isStatic)
+ list.append(cf);
+ }
+ return list;
+}
+
+/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ */
+CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, Uml::Visibility visibility)
+{
+ CodeClassFieldList list;
+ list.setAutoDelete(false);
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility)
+ list.append(cf);
+ }
+ return list;
+}
+
+/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ */
+CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic, Uml::Visibility visibility)
+{
+ CodeClassFieldList list;
+ list.setAutoDelete(false);
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility && cf->getStatic() == isStatic )
+ list.append(cf);
+ }
+ return list;
+}
+
+// do we have accessor methods for lists of objects?
+// (as opposed to lists of primitive types like 'int' or 'float', etc)
+bool ClassifierCodeDocument::hasObjectVectorClassFields() {
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if(cf->getClassFieldType() != CodeClassField::Attribute)
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject());
+ QString multi = role->getMultiplicity();
+ if (
+ multi.contains(QRegExp("[23456789\\*]")) ||
+ multi.contains(QRegExp("1\\d"))
+ )
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ClassifierCodeDocument::hasClassFields() {
+ if(m_classfieldVector.count() > 0 )
+ return true;
+ return false;
+}
+
+/**
+ * Tell if one or more codeclassfields are derived from associations.
+ */
+bool ClassifierCodeDocument::hasAssociationClassFields() {
+ CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
+ return (m_classfieldVector.count() - list.count()) > 0 ? true : false;
+}
+
+/**
+ * Tell if one or more codeclassfields are derived from attributes.
+ */
+bool ClassifierCodeDocument::hasAttributeClassFields() {
+ CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
+ return list.count() > 0 ? true : false;
+}
+
+/**
+ * Add a CodeClassField object to the m_classfieldVector List
+ * @return boolean true if successful in adding
+ */
+// We DON'T add methods of the code classfield here because we need to allow
+// the codegenerator writer the liberty to organize their document as they desire.
+bool ClassifierCodeDocument::addCodeClassField ( CodeClassField * add_object ) {
+ UMLObject * umlobj = add_object->getParentObject();
+ if(!(m_classFieldMap.contains(umlobj)))
+ {
+ m_classfieldVector.append(add_object);
+ m_classFieldMap.insert(umlobj,add_object);
+
+ return true;
+ }
+ return false;
+}
+
+// this is a slot..should only be called from a signal
+void ClassifierCodeDocument::addAttributeClassField (UMLClassifierListItem *obj, bool syncToParentIfAdded) {
+ UMLAttribute *at = (UMLAttribute*)obj;
+ CodeClassField * cf = CodeGenFactory::newCodeClassField(this, at);
+ if(cf)
+ if (addCodeClassField(cf) && syncToParentIfAdded)
+ updateContent();
+}
+
+/**
+ * Remove a CodeClassField object from m_classfieldVector List
+ */
+bool ClassifierCodeDocument::removeCodeClassField ( CodeClassField * remove_object ) {
+ UMLObject * umlobj = remove_object->getParentObject();
+ if(m_classFieldMap.contains(umlobj))
+ {
+ if (m_classfieldVector.removeRef(remove_object))
+ {
+ // remove from our classfield map
+ m_classFieldMap.remove(umlobj);
+ delete remove_object;
+ return true;
+ }
+ }
+ return false;
+}
+
+void ClassifierCodeDocument::removeAttributeClassField(UMLClassifierListItem *obj)
+{
+ CodeClassField * remove_object = m_classFieldMap[obj];
+ if(remove_object)
+ removeCodeClassField(remove_object);
+}
+
+void ClassifierCodeDocument::removeAssociationClassField (UMLAssociation *assoc )
+{
+
+ // the object could be either (or both!) role a or b. We should check
+ // both parts of the association.
+ CodeClassField * remove_object = m_classFieldMap[assoc->getUMLRole(Uml::A)];
+ if(remove_object)
+ removeCodeClassField(remove_object);
+
+ // check role b
+ remove_object = m_classFieldMap[assoc->getUMLRole(Uml::B)];
+ if(remove_object)
+ removeCodeClassField(remove_object);
+
+}
+
+/**
+ * Get the list of CodeClassField objects held by m_classfieldVector
+ * @return CodeClassFieldList list of CodeClassField objects held by
+ * m_classfieldVector
+ */
+CodeClassFieldList * ClassifierCodeDocument::getCodeClassFieldList ( ) {
+ return &m_classfieldVector;
+}
+
+/**
+ * Get the value of m_parentclassifier
+ * @return the value of m_parentclassifier
+ */
+UMLClassifier * ClassifierCodeDocument::getParentClassifier ( ) {
+ return m_parentclassifier;
+}
+
+/**
+ * @return QPtrList<CodeOperation>
+ */
+QPtrList<CodeOperation> ClassifierCodeDocument::getCodeOperations ( ) {
+
+ QPtrList<CodeOperation> list;
+ list.setAutoDelete(false);
+
+ TextBlockList * tlist = getTextBlockList();
+ for (TextBlock *tb = tlist->first(); tb; tb=tlist->next())
+ {
+ CodeOperation * cop = dynamic_cast<CodeOperation*>(tb);
+ if(cop)
+ list.append(cop);
+ }
+ return list;
+}
+
+/**
+ * @param o The Operation to add
+ */
+void ClassifierCodeDocument::addOperation (UMLClassifierListItem * o) {
+ UMLOperation *op = dynamic_cast<UMLOperation*>(o);
+ if (op == NULL) {
+ kError() << "ClassifierCodeDocument::addOperation: arg is not a UMLOperation"
+ << endl;
+ }
+ QString tag = CodeOperation::findTag(op);
+ CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
+ bool createdNew = false;
+
+ // create the block, if it doesn't already exist
+ if(!codeOp)
+ {
+ codeOp = CodeGenFactory::newCodeOperation(this, op);
+ createdNew = true;
+ }
+
+ // now try to add it. This may fail because it (or a block with
+ // the same tag) is already in the document somewhere. IF we
+ // created this new, then we need to delete our object.
+ if(!addCodeOperation(codeOp)) // wont add if already present
+ if(createdNew)
+ delete codeOp;
+
+}
+
+/**
+ * @param op
+ */
+void ClassifierCodeDocument::removeOperation (UMLClassifierListItem * op ) {
+
+ QString tag = CodeOperation::findTag((UMLOperation*)op);
+ TextBlock *tb = findTextBlockByTag(tag, true);
+ if(tb)
+ {
+ if(removeTextBlock(tb)) // wont add if already present
+ delete tb; // delete unused operations
+ else
+ kError()<<"Cant remove CodeOperation from ClassCodeDocument!"<<endl;
+
+ }
+ else
+ kError()<<"Cant Find codeOperation for deleted operation!"<<endl;
+}
+
+// Other methods
+//
+
+void ClassifierCodeDocument::addCodeClassFieldMethods(CodeClassFieldList &list )
+{
+
+ for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * field = ccflit.current();
+ CodeAccessorMethodList list = field->getMethodList();
+ CodeAccessorMethod * method;
+ for (CodeAccessorMethodListIt it(list); (method = it.current()) != NULL; ++it)
+ {
+ /*
+ QString tag = method->getTag();
+ if(tag.isEmpty())
+ {
+ tag = getUniqueTag();
+ method->setTag(tag);
+ }
+ */
+ addTextBlock(method); // wont add if already exists in document, will add a tag if missing;
+
+ }
+
+ }
+
+}
+
+// add declaration blocks for the passed classfields
+void ClassifierCodeDocument::declareClassFields (CodeClassFieldList & list ,
+ CodeGenObjectWithTextBlocks * parent )
+{
+
+ for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * field = ccflit.current();
+ CodeClassFieldDeclarationBlock * declBlock = field->getDeclarationCodeBlock();
+
+ /*
+ // if it has a tag, check
+ if(!declBlock->getTag().isEmpty())
+ {
+ // In C++, because we may shift the declaration to a different parent
+ // block for a change in scope, we need to track down any pre-existing
+ // location, and remove FIRST before adding to new parent
+ CodeGenObjectWithTextBlocks * oldParent = findParentObjectForTaggedTextBlock (declBlock->getTag());
+ if(oldParent) {
+ if(oldParent != parent)
+ oldParent->removeTextBlock(declBlock);
+ }
+ }
+ */
+
+ parent->addTextBlock(declBlock); // wont add it IF its already present. Will give it a tag if missing
+
+ }
+}
+
+bool ClassifierCodeDocument::parentIsClass() {
+ return (m_parentclassifier->getBaseType() == Uml::ot_Class);
+}
+
+bool ClassifierCodeDocument::parentIsInterface() {
+ return (m_parentclassifier->getBaseType() == Uml::ot_Interface);
+}
+
+/**
+ * Init from a UMLClassifier object.
+ * @param classifier
+ * @param package
+ */
+void ClassifierCodeDocument::init (UMLClassifier * c )
+{
+
+ m_parentclassifier = c;
+ m_classfieldVector.setAutoDelete(false);
+
+ updateHeader();
+ syncNamesToParent();
+ // initCodeClassFields(); // cant call here?..newCodeClassField is pure virtual
+
+ // slots
+ if (parentIsClass()) {
+ connect(c,SIGNAL(attributeAdded(UMLClassifierListItem*)),this,SLOT(addAttributeClassField(UMLClassifierListItem*)));
+ connect(c,SIGNAL(attributeRemoved(UMLClassifierListItem*)),this,SLOT(removeAttributeClassField(UMLClassifierListItem*)));
+ }
+
+ connect(c,SIGNAL(sigAssociationEndAdded(UMLAssociation*)),this,SLOT(addAssociationClassField(UMLAssociation*)));
+ connect(c,SIGNAL(sigAssociationEndRemoved(UMLAssociation*)),this,SLOT(removeAssociationClassField(UMLAssociation*)));
+ connect(c,SIGNAL(operationAdded(UMLClassifierListItem*)),this,SLOT(addOperation(UMLClassifierListItem*)));
+ connect(c,SIGNAL(operationRemoved(UMLClassifierListItem*)),this,SLOT(removeOperation(UMLClassifierListItem*)));
+ connect(c,SIGNAL(modified()),this,SLOT(syncToParent()));
+
+}
+
+// IF the classifier object is modified, this will get called.
+// @todo we cannot make this virtual as long as the
+// ClassifierCodeDocument constructor calls it because that gives
+// a call-before-construction error.
+// Example of the problem: CPPSourceCodeDocument reimplementing syncNamesToParent()
+// CPPCodeGenerator::initFromParentDocument()
+// CodeDocument * codeDoc = new CPPSourceCodeDocument(c);
+// CPPSourceCodeDocument::CPPSourceCodeDocument(UMLClassifier * concept)
+// : ClassifierCodeDocument(concept)
+// ClassifierCodeDocument::ClassifierCodeDocument(concept)
+// init(concept);
+// syncNamesToParent();
+// dispatches to CPPSourceCodeDocument::syncNamesToParent()
+// but that object is not yet constructed.
+//
+void ClassifierCodeDocument::syncNamesToParent( ) {
+ QString fileName = CodeGenerator::cleanName(getParentClassifier()->getName());
+ if (!UMLApp::app()->activeLanguageIsCaseSensitive()) {
+ // @todo let the user decide about mixed case file names (codegen setup menu)
+ fileName = fileName.lower();
+ }
+ setFileName(fileName);
+ setPackage(m_parentclassifier->getUMLPackage());
+}
+
+void ClassifierCodeDocument::synchronize( ) {
+
+ updateHeader(); // doing this insures time/date stamp is at the time of this call
+ syncNamesToParent();
+ updateContent();
+ syncClassFields();
+ updateOperations();
+
+}
+
+void ClassifierCodeDocument::syncClassFields( )
+{
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ cf->synchronize();
+ }
+}
+
+void ClassifierCodeDocument::updateOperations( ) {
+
+ UMLOperationList opList(getParentClassifier()->getOpList());
+ for (UMLOperation *op = opList.first(); op; op = opList.next())
+ {
+ QString tag = CodeOperation::findTag(op);
+ CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
+ bool createdNew = false;
+
+ if(!codeOp)
+ {
+ codeOp = CodeGenFactory::newCodeOperation(this, op);
+ createdNew = true;
+ }
+
+ // now try to add it. This may fail because it (or a block with
+ // the same tag) is already in the document somewhere. IF we
+ // created this new, then we need to delete our object.
+ if(!addCodeOperation(codeOp)) // wont add if already present
+ if(createdNew)
+ delete codeOp;
+
+ // synchronize all non-new operations
+ if(!createdNew)
+ codeOp->syncToParent();
+ }
+
+}
+
+void ClassifierCodeDocument::syncToParent( ) {
+ synchronize();
+}
+
+/**
+ * add codeclassfields to this classifiercodedocument. IF a codeclassfield
+ * already exists, it is not added.
+ */
+void ClassifierCodeDocument::initCodeClassFields ( ) {
+
+ UMLClassifier * c = getParentClassifier();
+ // first, do the code classifields that arise from attributes
+ if (parentIsClass()) {
+ UMLAttributeList alist = c->getAttributeList();
+ for(UMLAttribute * at = alist.first(); at; at = alist.next())
+ {
+ CodeClassField * field = CodeGenFactory::newCodeClassField(this, at);
+ addCodeClassField(field);
+ }
+
+ }
+
+ // now, do the code classifields that arise from associations
+ UMLAssociationList ap = c->getSpecificAssocs(Uml::at_Association);
+ UMLAssociationList ag = c->getAggregations();
+ UMLAssociationList ac = c->getCompositions();
+ UMLAssociationList selfAssoc = c->getSpecificAssocs(Uml::at_Association_Self);
+
+ updateAssociationClassFields(ap);
+ updateAssociationClassFields(ag);
+ updateAssociationClassFields(ac);
+ updateAssociationClassFields(selfAssoc);
+
+}
+
+void ClassifierCodeDocument::updateAssociationClassFields ( UMLAssociationList &assocList )
+{
+ CodeClassFieldList list;
+ for(UMLAssociation * a=assocList.first(); a; a=assocList.next())
+ addAssociationClassField(a, false); // syncToParent later
+}
+
+void ClassifierCodeDocument::addAssociationClassField (UMLAssociation * a, bool syncToParentIfAdded)
+{
+
+ Uml::IDType cid = getParentClassifier()->getID(); // so we know who 'we' are
+ bool printRoleA = false, printRoleB = false, shouldSync = false;
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == cid)
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == cid)
+ printRoleA = true;
+
+ // grab RoleB decl
+ if (printRoleB)
+ {
+
+ UMLRole * role = a->getUMLRole(Uml::B);
+ if(!m_classFieldMap.contains((UMLObject*)role))
+ {
+ CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
+ if( addCodeClassField(classfield))
+ shouldSync = true;
+ }
+ }
+
+ // print RoleA decl
+ if (printRoleA)
+ {
+ UMLRole * role = a->getUMLRole(Uml::A);
+ if(!m_classFieldMap.contains((UMLObject*)role))
+ {
+ CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
+ if( addCodeClassField(classfield))
+ shouldSync = true;
+ }
+ }
+
+ if (shouldSync && syncToParentIfAdded)
+ syncToParent(); // needed for a slot add
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void ClassifierCodeDocument::setAttributesFromNode ( QDomElement & elem )
+{
+
+ // NOTE: we DON'T set the parent here as we ONLY get to this point
+ // IF the parent codegenerator could find a matching parent classifier
+ // that already has a code document.
+
+ // We FIRST set code class field stuff..check re-linnking with
+ // accessor methods by looking for our particular child element
+ QDomNode node = elem.firstChild();
+ QDomElement childElem = node.toElement();
+ while( !childElem.isNull() ) {
+ QString tag = childElem.tagName();
+ if( tag == "classfields" ) {
+ // load classfields
+ loadClassFieldsFromXMI(childElem);
+ break;
+ }
+ node = childElem.nextSibling();
+ childElem= node.toElement();
+ }
+
+ // call super-class after. THis will populate the text blocks (incl
+ // the code accessor methods above) as is appropriate
+ CodeDocument::setAttributesFromNode(elem);
+
+}
+
+// look at all classfields currently in document.. match up
+// by parent object ID and Role ID (needed for self-association CF's)
+CodeClassField *
+ClassifierCodeDocument::findCodeClassFieldFromParentID (Uml::IDType id,
+ int role_id)
+{
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ if(role_id == -1) { // attribute-based
+ if (STR2ID(cf->getID()) == id)
+ return cf;
+ } else { // association(role)-based
+ const Uml::Role_Type r = (Uml::Role_Type)role_id;
+ UMLRole * role = dynamic_cast<UMLRole *>(cf->getParentObject());
+ if(role && STR2ID(cf->getID()) == id && role->getRole() == r)
+ return cf;
+ }
+ }
+
+ // shouldn't happen..
+ kError() << "Failed to find codeclassfield for parent uml id:"
+ << ID2STR(id) << " (role id:" << role_id
+ << ") Do you have a corrupt classifier code document?"
+ << endl;
+
+ return (CodeClassField*) NULL; // not found
+}
+
+void ClassifierCodeDocument::loadClassFieldsFromXMI( QDomElement & elem) {
+
+ QDomNode node = elem.firstChild();
+ QDomElement childElem = node.toElement();
+ while( !childElem.isNull() ) {
+ QString nodeName = childElem.tagName();
+ if( nodeName == "codeclassfield")
+ {
+ QString id = childElem.attribute("parent_id","-1");
+ int role_id = childElem.attribute("role_id","-1").toInt();
+ CodeClassField * cf = findCodeClassFieldFromParentID(STR2ID(id), role_id);
+ if(cf)
+ {
+ // Because we just may change the parent object here,
+ // we need to yank it from the map of umlobjects
+ m_classFieldMap.remove(cf->getParentObject());
+
+ // configure from XMI
+ cf->loadFromXMI(childElem);
+
+ // now add back in
+ m_classFieldMap.insert(cf->getParentObject(),cf);
+
+ } else
+ kError()<<" LoadFromXMI: can't load classfield parent_id:"<<id<<" do you have a corrupt savefile?"<<endl;
+ }
+ node = childElem.nextSibling();
+ childElem= node.toElement();
+ }
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void ClassifierCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+#if 0
+ // avoid the creation of primitive data type
+ QString strType;
+ if (getParentClassifier()->getBaseType() == Uml::ot_Datatype) {
+ strType = getParentClassifier()->getName();
+ // lets get the default code generator to check if it is a primitive data type
+ // there's a reason to create files for int/boolean and so ?
+ if (getParentGenerator()->isReservedKeyword(strType))
+ return;
+ }
+#endif
+ QDomElement docElement = doc.createElement( "classifiercodedocument" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void ClassifierCodeDocument::loadFromXMI ( QDomElement & root ) {
+
+ // set attributes/fields
+ setAttributesFromNode(root);
+
+ // now sync our doc, needed?
+ // synchronize();
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void ClassifierCodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement)
+{
+
+ // do super-class first
+ CodeDocument::setAttributesOnNode(doc, docElement);
+
+ // cache local attributes/fields
+ docElement.setAttribute("parent_class", ID2STR(getParentClassifier()->getID()));
+
+ // (code) class fields
+ // which we will store in its own separate child node block
+ QDomElement fieldsElement = doc.createElement( "classfields" );
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * field = ccflit.current();
+ field->saveToXMI(doc, fieldsElement);
+ }
+ docElement.appendChild( fieldsElement);
+
+}
+
+TextBlock * ClassifierCodeDocument::findCodeClassFieldTextBlockByTag (const QString &tag)
+{
+
+ for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * cf = ccflit.current();
+ CodeClassFieldDeclarationBlock * decl = cf->getDeclarationCodeBlock();
+ if(decl && decl->getTag() == tag)
+ return decl;
+ // well, if not in the decl block, then in the methods perhaps?
+ CodeAccessorMethodList mlist = cf->getMethodList();
+ CodeAccessorMethod *m;
+ for (CodeAccessorMethodListIt it(mlist); (m = it.current()) != NULL; ++it)
+ if(m->getTag() == tag)
+ return m;
+ }
+
+ // if we get here, we failed.
+ return (TextBlock*) NULL;
+
+}
+
+
+#include "classifiercodedocument.moc"
diff --git a/umbrello/umbrello/classifiercodedocument.h b/umbrello/umbrello/classifiercodedocument.h
new file mode 100644
index 00000000..2e103034
--- /dev/null
+++ b/umbrello/umbrello/classifiercodedocument.h
@@ -0,0 +1,251 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+
+
+#ifndef CLASSIFIERCODEDOCUMENT_H
+#define CLASSIFIERCODEDOCUMENT_H
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include "classifier.h"
+#include "codeaccessormethod.h"
+#include "codedocument.h"
+#include "codeoperation.h"
+#include "codeclassfield.h"
+#include "codeclassfieldlist.h"
+#include "umlassociationlist.h"
+
+class UMLRole;
+
+/**
+ * class ClassifierCodeDocument
+ * A CodeDocument which represents a UMLClassifier (e.g. a Class or Interface)
+ */
+
+class ClassifierCodeDocument : public CodeDocument
+{
+ friend class HierarchicalCodeBlock;
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Empty Constructor
+ */
+ ClassifierCodeDocument ( UMLClassifier * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~ClassifierCodeDocument ( );
+
+ /**
+ * Add a CodeClassField object to the m_classfieldVector List
+ */
+ bool addCodeClassField ( CodeClassField * add_object );
+
+ /**
+ * Remove a CodeClassField object from m_classfieldVector List
+ */
+ bool removeCodeClassField ( CodeClassField * remove_object );
+
+ /**
+ * Get the list of CodeClassField objects held by m_classfieldVector
+ * @return CodeClassFieldList list of CodeClassField objects held by
+ * m_classfieldVector
+ */
+ CodeClassFieldList * getCodeClassFieldList ( );
+
+ // some Utility methods
+
+ /**
+ * Return if the parent classifier is an interface
+ */
+ bool parentIsInterface();
+
+ /**
+ * Return if the parent classifier is a class
+ */
+ bool parentIsClass();
+
+ /**
+ * Tell if one or more codeclassfields are derived from any kind of association.
+ */
+ bool hasAssociationClassFields();
+ /**
+ * Tell if one or more codeclassfields are derived from attributes.
+ */
+ bool hasAttributeClassFields();
+
+ /**
+ * Tell if any of the accessor classfields will be of lists of objects.
+ */
+ bool hasObjectVectorClassFields();
+
+ /**
+ * Does this object have any classfields declared?
+ */
+ bool hasClassFields();
+
+ /**
+ * Get a list of codeoperation objects held by this classifiercodedocument.
+ * @return QPtrList<CodeOperation>
+ */
+ QPtrList<CodeOperation> getCodeOperations ( );
+
+ /** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ * @return CodeClassFieldList
+ */
+ CodeClassFieldList getSpecificClassFields (CodeClassField::ClassFieldType cfType);
+
+ /** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ * @return CodeClassFieldList
+ */
+ CodeClassFieldList getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic);
+
+ /** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ * @return CodeClassFieldList
+ */
+ CodeClassFieldList getSpecificClassFields (CodeClassField::ClassFieldType cfType, Uml::Visibility visibility);
+
+ /** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
+ * @return CodeClassFieldList
+ */
+ CodeClassFieldList getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic, Uml::Visibility visibility);
+
+ /** Using the parent object's UML ID, find the corresponding
+ * codeclassfield object in this classifiercodedocument. Returns
+ * NULL if no such codeclassfield object exists in this document.
+ *
+ * @param id ID of the parent object
+ * @param role_id 0 for role A of the asssociation
+ * 1 for role B of the asssociation
+ * -1 if this is an attribute.
+ */
+ CodeClassField * findCodeClassFieldFromParentID (Uml::IDType id, int role_id = -1);
+
+ /**
+ * Get the value of m_parentclassifier
+ * @return the value of m_parentclassifier
+ */
+ UMLClassifier * getParentClassifier ( );
+
+ // a utility method that allows user to easily add classfield methods to this document
+ void addCodeClassFieldMethods(CodeClassFieldList &list );
+
+ /**
+ * Utility method to appropriately populate the code classfields for this document.
+ */
+ virtual void initCodeClassFields ( );
+
+ // cause this classifier code document to synchronize to current policy
+ virtual void synchronize();
+
+ /** Will add the code operation in the correct place in the document.
+ * @return bool which is true IF the code operation was added successfully
+ */
+ virtual bool addCodeOperation (CodeOperation *opBlock) = 0;
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+protected:
+
+ /**
+ * Load CodeClassFields from XMI element node.
+ */
+ void loadClassFieldsFromXMI( QDomElement & childElem);
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ // find a specific textblock held by any code class field in this document
+ // by its tag
+ TextBlock * findCodeClassFieldTextBlockByTag (const QString &tag);
+
+ // add the declaration text blocks for various classfields
+ void declareClassFields (CodeClassFieldList & list , CodeGenObjectWithTextBlocks * parent);
+
+ virtual void updateContent( ) = 0;
+
+ // force syncronization of child classfields to their parent objects
+ void syncClassFields( );
+
+ // IF the classifier object is modified, this will get called.
+ // @fixme We cannot make this virtual because the ClassifierCodeDocument
+ // constructor calls it.
+ void syncNamesToParent( );
+
+private:
+
+ CodeClassFieldList m_classfieldVector;
+ UMLClassifier* m_parentclassifier;
+
+ // using the passed list, update our inventory of CodeClassFields which are
+ // based on UMLRoles (e.g. derived from associations with other classifiers).
+ void updateAssociationClassFields ( UMLAssociationList &assocList );
+
+ // update code operations in this document using the parent classifier
+ void updateOperations( );
+
+ /**
+ * Maps CodeClassFields to UMLObjects. Used to prevent re-adding a class
+ * field.
+ */
+ QMap<UMLObject *,CodeClassField *> m_classFieldMap;
+
+ /**
+ * Init from a UMLClassifier object.
+ * @param classifier
+ */
+ void init ( UMLClassifier * classifier );
+
+public slots:
+
+ /**
+ * Synchronize this document to the attributes/associations of the parent classifier.
+ */
+ void addAttributeClassField(UMLClassifierListItem *at, bool syncToParentIfAdded = true);
+ void addAssociationClassField (UMLAssociation * assoc, bool syncToParentIfAdded = true);
+ void removeAttributeClassField(UMLClassifierListItem *at);
+ void removeAssociationClassField(UMLAssociation *assoc);
+ void addOperation (UMLClassifierListItem * obj);
+ void removeOperation (UMLClassifierListItem * obj);
+ void syncToParent( );
+
+};
+
+#endif // CLASSIFIERCODEDOCUMENT_H
diff --git a/umbrello/umbrello/classifierlistitem.cpp b/umbrello/umbrello/classifierlistitem.cpp
new file mode 100644
index 00000000..888f3da7
--- /dev/null
+++ b/umbrello/umbrello/classifierlistitem.cpp
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classifierlistitem.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+
+// local includes
+#include "classifier.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "model_utils.h"
+#include "object_factory.h"
+
+UMLClassifierListItem::UMLClassifierListItem(const UMLObject *parent,
+ const QString& name, Uml::IDType id)
+ : UMLObject(parent, name, id) {
+ UMLObject *parentObj = const_cast<UMLObject*>(parent);
+ UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
+ if (pc)
+ UMLObject::setUMLPackage(pc);
+}
+
+UMLClassifierListItem::UMLClassifierListItem(const UMLObject *parent)
+ : UMLObject(parent) {
+ UMLObject *parentObj = const_cast<UMLObject*>(parent);
+ UMLClassifier *pc = dynamic_cast<UMLClassifier*>(parentObj);
+ if (pc)
+ UMLObject::setUMLPackage(pc);
+}
+
+UMLClassifierListItem::~UMLClassifierListItem() {
+}
+
+void UMLClassifierListItem::copyInto(UMLClassifierListItem *rhs) const
+{
+ // Call the parent.
+ UMLObject::copyInto(rhs);
+}
+
+QString UMLClassifierListItem::toString(Uml::Signature_Type /*sig*/) {
+ return getName();
+}
+
+UMLClassifier * UMLClassifierListItem::getType() const{
+ return static_cast<UMLClassifier*>(m_pSecondary);
+}
+
+QString UMLClassifierListItem::getTypeName() const{
+ if (m_pSecondary == NULL)
+ return m_SecondaryId;
+ const UMLPackage *typePkg = m_pSecondary->getUMLPackage();
+ if (typePkg != NULL && typePkg != m_pUMLPackage)
+ return m_pSecondary->getFullyQualifiedName();
+ return m_pSecondary->getName();
+}
+
+void UMLClassifierListItem::setType(UMLObject *type) {
+ if (m_pSecondary != type) {
+ m_pSecondary = type;
+ UMLObject::emitModified();
+ }
+}
+
+void UMLClassifierListItem::setTypeName(const QString &type) {
+ if (type.isEmpty() || type == "void") {
+ m_pSecondary = NULL;
+ m_SecondaryId = QString();
+ return;
+ }
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ m_pSecondary = pDoc->findUMLObject(type);
+ if (m_pSecondary == NULL) {
+ // Make data type for easily identified cases
+ if (Model_Utils::isCommonDataType(type) || type.contains('*')) {
+ m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+ kDebug() << "UMLClassifierListItem::setTypeName: "
+ << "created datatype for " << type << endl;
+ } else {
+ m_SecondaryId = type;
+ }
+ }
+ UMLObject::emitModified();
+}
+
+
+#include "classifierlistitem.moc"
diff --git a/umbrello/umbrello/classifierlistitem.h b/umbrello/umbrello/classifierlistitem.h
new file mode 100644
index 00000000..fd68fdf3
--- /dev/null
+++ b/umbrello/umbrello/classifierlistitem.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERLISTITEM_H
+#define CLASSIFIERLISTITEM_H
+
+#include "umlobject.h"
+
+// forward declaration
+class UMLClassifier;
+
+/**
+ * Classifiers (classes, interfaces) have lists of operations,
+ * attributes, templates and others. This is a base class for
+ * the items in this list. This abstraction should remove
+ * duplication of dialogs and allow for stereotypes in lists.
+ *
+ * @short A base class for classifier list items (e.g. attributes)
+ * @author Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLClassifierListItem : public UMLObject {
+ Q_OBJECT
+public:
+ /**
+ * Constructor. Empty.
+ *
+ * @param parent The parent to this operation.
+ * At first sight it would appear that the type of the
+ * parent should be UMLClassifier. However, the class
+ * UMLAttribute is also used for the parameters of
+ * operations, and in this case the UMLOperation is the
+ * parent.
+ * @param name The name of the operation.
+ * @param id The id of the operation.
+ */
+ UMLClassifierListItem(const UMLObject *parent,
+ const QString& name,
+ Uml::IDType id = Uml::id_None);
+
+ /**
+ * Constructor. Empty.
+ *
+ * @param parent The parent to this operation.
+ * At first sight it would appear that the type of the
+ * parent should be UMLClassifier. However, the class
+ * UMLAttribute is also used for the parameters of
+ * operations, and in this case the UMLOperation is the
+ * parent.
+ */
+ UMLClassifierListItem(const UMLObject *parent);
+
+ /**
+ * Destructor. Empty.
+ */
+ virtual ~UMLClassifierListItem();
+
+ /**
+ * Returns the type of the UMLClassifierListItem.
+ *
+ * @return The type of the UMLClassifierListItem.
+ */
+ UMLClassifier * getType() const;
+
+ /**
+ * Returns the type name of the UMLClassifierListItem.
+ *
+ * @return The type name of the UMLClassifierListItem.
+ */
+ virtual QString getTypeName() const;
+
+ /**
+ * Sets the type name of the UMLClassifierListItem.
+ * DEPRECATED - use setType() instead.
+ *
+ * @param type The type name of the UMLClassifierListItem.
+ */
+ void setTypeName( const QString &type );
+
+ /**
+ * Sets the type of the UMLAttribute.
+ *
+ * @param type Pointer to the UMLObject of the type.
+ */
+ virtual void setType(UMLObject *type);
+
+ /**
+ * Returns a string representation of the list item.
+ *
+ * @param sig What type of operation string to show.
+ * @return The string representation of the operation.
+ */
+ virtual QString toString(Uml::Signature_Type sig = Uml::st_NoSig);
+
+ /**
+ * Display the properties configuration dialog for the list item.
+ *
+ * @param parent The parent widget.
+ * @return True for success of this operation.
+ */
+ virtual bool showPropertiesDialog(QWidget* parent) = 0;
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLClassifierListItem *rhs) const;
+
+ /**
+ * The abstract method UMLObject::clone() must be implemented
+ * by the classes inheriting from UMLClassifierListItem.
+ */
+ virtual UMLObject* clone() const = 0;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/classifierwidget.cpp b/umbrello/umbrello/classifierwidget.cpp
new file mode 100644
index 00000000..4d4c1eb8
--- /dev/null
+++ b/umbrello/umbrello/classifierwidget.cpp
@@ -0,0 +1,803 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classifierwidget.h"
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+// app includes
+#include "classifier.h"
+#include "operation.h"
+#include "template.h"
+#include "associationwidget.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "listpopupmenu.h"
+#include "object_factory.h"
+
+ClassifierWidget::ClassifierWidget(UMLView * view, UMLClassifier *c)
+ : UMLWidget(view, c) {
+ init();
+ if (c != NULL && c->isInterface()) {
+ WidgetBase::setBaseType(Uml::wt_Interface);
+ m_bShowStereotype = true;
+ m_bShowAttributes = false;
+ updateSigs();
+ }
+}
+
+ClassifierWidget::~ClassifierWidget() {
+ if (m_pAssocWidget)
+ m_pAssocWidget->removeAssocClassLine();
+}
+
+const int ClassifierWidget::MARGIN = 5;
+const int ClassifierWidget::CIRCLE_SIZE = 30;
+
+void ClassifierWidget::init() {
+ WidgetBase::setBaseType(Uml::wt_Class);
+
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ m_bShowAccess = ops.classState.showVisibility;
+ m_bShowOperations = ops.classState.showOps;
+ m_bShowPublicOnly = false;
+ m_bShowPackage = ops.classState.showPackage;
+ m_ShowAttSigs = Uml::st_ShowSig;
+ /* setShowOpSigs( ops.classState.showOpSig );
+ Cannot do that because we get "pure virtual method called". Open code:
+ */
+ if( !ops.classState.showOpSig ) {
+ if (m_bShowAccess)
+ m_ShowOpSigs = Uml::st_NoSig;
+ else
+ m_ShowOpSigs = Uml::st_NoSigNoVis;
+
+ } else if (m_bShowAccess)
+ m_ShowOpSigs = Uml::st_ShowSig;
+ else
+ m_ShowOpSigs = Uml::st_SigNoVis;
+
+ m_bShowAttributes = ops.classState.showAtts;
+ m_bShowStereotype = ops.classState.showStereoType;
+ m_bDrawAsCircle = false;
+ m_pAssocWidget = NULL;
+ setShowAttSigs( ops.classState.showAttSig );
+}
+
+void ClassifierWidget::updateSigs() {
+ //turn on scope
+ if (m_bShowAccess) {
+ if (m_ShowOpSigs == Uml::st_NoSigNoVis) {
+ m_ShowOpSigs = Uml::st_NoSig;
+ } else if (m_ShowOpSigs == Uml::st_SigNoVis) {
+ m_ShowOpSigs = Uml::st_ShowSig;
+ }
+ } else { //turn off scope
+ if (m_ShowOpSigs == Uml::st_ShowSig) {
+ m_ShowOpSigs = Uml::st_SigNoVis;
+ } else if (m_ShowOpSigs == Uml::st_NoSig) {
+ m_ShowOpSigs = Uml::st_NoSigNoVis;
+ }
+ }
+ if (m_bShowAccess) {
+ if (m_ShowAttSigs == Uml::st_NoSigNoVis)
+ m_ShowAttSigs = Uml::st_NoSig;
+ else if (m_ShowAttSigs == Uml::st_SigNoVis)
+ m_ShowAttSigs = Uml::st_ShowSig;
+ } else {
+ if (m_ShowAttSigs == Uml::st_ShowSig)
+ m_ShowAttSigs = Uml::st_SigNoVis;
+ else if(m_ShowAttSigs == Uml::st_NoSig)
+ m_ShowAttSigs = Uml::st_NoSigNoVis;
+ }
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowStereotype()
+{
+ m_bShowStereotype = !m_bShowStereotype;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+bool ClassifierWidget::getShowOps() const {
+ return m_bShowOperations;
+}
+
+void ClassifierWidget::setShowOps(bool _show) {
+ m_bShowOperations = _show;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowOps() {
+ m_bShowOperations = !m_bShowOperations;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+bool ClassifierWidget::getShowPublicOnly() const {
+ return m_bShowPublicOnly;
+}
+
+void ClassifierWidget::setShowPublicOnly(bool _status) {
+ m_bShowPublicOnly = _status;
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowPublicOnly() {
+ m_bShowPublicOnly = !m_bShowPublicOnly;
+ updateComponentSize();
+ update();
+}
+
+bool ClassifierWidget::getShowVisibility() const {
+ return m_bShowAccess;
+}
+
+void ClassifierWidget::setShowVisibility(bool _visibility) {
+ m_bShowAccess = _visibility;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowVisibility() {
+ m_bShowAccess = !m_bShowAccess;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+Uml::Signature_Type ClassifierWidget::getShowOpSigs() const {
+ return m_ShowOpSigs;
+}
+
+void ClassifierWidget::setShowOpSigs(bool _status) {
+ if( !_status ) {
+ if (m_bShowAccess)
+ m_ShowOpSigs = Uml::st_NoSig;
+ else
+ m_ShowOpSigs = Uml::st_NoSigNoVis;
+ } else if (m_bShowAccess)
+ m_ShowOpSigs = Uml::st_ShowSig;
+ else
+ m_ShowOpSigs = Uml::st_SigNoVis;
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowOpSigs() {
+ if (m_ShowOpSigs == Uml::st_ShowSig || m_ShowOpSigs == Uml::st_SigNoVis) {
+ if (m_bShowAccess) {
+ m_ShowOpSigs = Uml::st_NoSig;
+ } else {
+ m_ShowOpSigs = Uml::st_NoSigNoVis;
+ }
+ } else if (m_bShowAccess) {
+ m_ShowOpSigs = Uml::st_ShowSig;
+ } else {
+ m_ShowOpSigs = Uml::st_SigNoVis;
+ }
+ updateComponentSize();
+ update();
+}
+
+bool ClassifierWidget::getShowPackage() const {
+ return m_bShowPackage;
+}
+
+void ClassifierWidget::setShowPackage(bool _status) {
+ m_bShowPackage = _status;
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowPackage() {
+ m_bShowPackage = !m_bShowPackage;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::setOpSignature(Uml::Signature_Type sig) {
+ m_ShowOpSigs = sig;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::setShowAtts(bool _show) {
+ m_bShowAttributes = _show;
+ updateSigs();
+
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::setAttSignature(Uml::Signature_Type sig) {
+ m_ShowAttSigs = sig;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::setShowAttSigs(bool _status) {
+ if( !_status ) {
+ if (m_bShowAccess)
+ m_ShowAttSigs = Uml::st_NoSig;
+ else
+ m_ShowAttSigs = Uml::st_NoSigNoVis;
+ }
+ else if (m_bShowAccess)
+ m_ShowAttSigs = Uml::st_ShowSig;
+ else
+ m_ShowAttSigs = Uml::st_SigNoVis;
+ if (UMLApp::app()->getDocument()->loading())
+ return;
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowAtts()
+{
+ m_bShowAttributes = !m_bShowAttributes;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::toggleShowAttSigs()
+{
+ if (m_ShowAttSigs == Uml::st_ShowSig ||
+ m_ShowAttSigs == Uml::st_SigNoVis) {
+ if (m_bShowAccess) {
+ m_ShowAttSigs = Uml::st_NoSig;
+ } else {
+ m_ShowAttSigs = Uml::st_NoSigNoVis;
+ }
+ } else if (m_bShowAccess) {
+ m_ShowAttSigs = Uml::st_ShowSig;
+ } else {
+ m_ShowAttSigs = Uml::st_SigNoVis;
+ }
+ updateComponentSize();
+ update();
+}
+
+int ClassifierWidget::displayedMembers(Uml::Object_Type ot) {
+ int count = 0;
+ UMLClassifierListItemList list = getClassifier()->getFilteredList(ot);
+ for (UMLClassifierListItem *m = list.first(); m; m = list.next()) {
+ if (!(m_bShowPublicOnly && m->getVisibility() != Uml::Visibility::Public))
+ count++;
+ }
+ return count;
+}
+
+int ClassifierWidget::displayedOperations() {
+ if (!m_bShowOperations)
+ return 0;
+ return displayedMembers(Uml::ot_Operation);
+}
+
+QSize ClassifierWidget::calculateSize() {
+ if (!m_pObject) {
+ return UMLWidget::calculateSize();
+ }
+ if (getClassifier()->isInterface() && m_bDrawAsCircle) {
+ return calculateAsCircleSize();
+ }
+
+ const QFontMetrics &fm = getFontMetrics(UMLWidget::FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ // width is the width of the longest 'word'
+ int width = 0, height = 0;
+
+ // consider stereotype
+ if (m_bShowStereotype && !m_pObject->getStereotype().isEmpty()) {
+ height += fontHeight;
+ // ... width
+ const QFontMetrics &bfm = UMLWidget::getFontMetrics(UMLWidget::FT_BOLD);
+ const int stereoWidth = bfm.size(0,m_pObject->getStereotype(true)).width();
+ if (stereoWidth > width)
+ width = stereoWidth;
+ }
+
+ // consider name
+ height += fontHeight;
+ // ... width
+ QString displayedName;
+ if (m_bShowPackage)
+ displayedName = m_pObject->getFullyQualifiedName();
+ else
+ displayedName = m_pObject->getName();
+ const UMLWidget::FontType nft = (m_pObject->getAbstract() ? FT_BOLD_ITALIC : FT_BOLD);
+ //const int nameWidth = getFontMetrics(nft).boundingRect(displayName).width();
+ const int nameWidth = UMLWidget::getFontMetrics(nft).size(0,displayedName).width();
+ if (nameWidth > width)
+ width = nameWidth;
+
+ // consider attributes
+ const int numAtts = displayedAttributes();
+ if (numAtts == 0) {
+ height += fontHeight / 2; // no atts, so just add a bit of space
+ } else {
+ height += fontHeight * numAtts;
+ // calculate width of the attributes
+ UMLClassifierListItemList list = getClassifier()->getFilteredList(Uml::ot_Attribute);
+ for (UMLClassifierListItem *a = list.first(); a; a = list.next()) {
+ if (m_bShowPublicOnly && a->getVisibility() != Uml::Visibility::Public)
+ continue;
+ const int attWidth = fm.size(0,a->toString(m_ShowAttSigs)).width();
+ if (attWidth > width)
+ width = attWidth;
+ }
+ }
+
+ // consider operations
+ const int numOps = displayedOperations();
+ if (numOps == 0) {
+ height += fontHeight / 2; // no ops, so just add a bit of space
+ } else {
+ height += numOps * fontHeight;
+ // ... width
+ UMLOperationList list(getClassifier()->getOpList());
+ for (UMLOperation* op = list.first(); op; op = list.next()) {
+ if (m_bShowPublicOnly && op->getVisibility() != Uml::Visibility::Public)
+ continue;
+ const QString displayedOp = op->toString(m_ShowOpSigs);
+ UMLWidget::FontType oft;
+ oft = (op->getAbstract() ? UMLWidget::FT_ITALIC : UMLWidget::FT_NORMAL);
+ const int w = UMLWidget::getFontMetrics(oft).size(0,displayedOp).width();
+ if (w > width)
+ width = w;
+ }
+ }
+
+ // consider template box _as last_ !
+ QSize templatesBoxSize = calculateTemplatesBoxSize();
+ if (templatesBoxSize.width() != 0) {
+ // add width to largest 'word'
+ width += templatesBoxSize.width() / 2;
+ }
+ if (templatesBoxSize.height() != 0) {
+ height += templatesBoxSize.height() - MARGIN;
+ }
+
+
+ // allow for height margin
+ if (!m_bShowOperations && !m_bShowAttributes && !m_bShowStereotype) {
+ height += MARGIN * 2;
+ }
+
+ // allow for width margin
+ width += MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void ClassifierWidget::slotMenuSelection(int sel) {
+ ListPopupMenu::Menu_Type mt = (ListPopupMenu::Menu_Type)sel;
+ switch (mt) {
+ case ListPopupMenu::mt_Attribute:
+ case ListPopupMenu::mt_Operation:
+ case ListPopupMenu::mt_Template:
+ {
+ Uml::Object_Type ot = ListPopupMenu::convert_MT_OT(mt);
+ if (Object_Factory::createChildObject(getClassifier(), ot)) {
+ updateComponentSize();
+ update();
+ UMLApp::app()->getDocument()->setModified();
+ }
+ break;
+ }
+ case ListPopupMenu::mt_Show_Operations:
+ case ListPopupMenu::mt_Show_Operations_Selection:
+ toggleShowOps();
+ break;
+
+ case ListPopupMenu::mt_Show_Attributes:
+ case ListPopupMenu::mt_Show_Attributes_Selection:
+ toggleShowAtts();
+ break;
+
+ case ListPopupMenu::mt_Show_Public_Only:
+ case ListPopupMenu::mt_Show_Public_Only_Selection:
+ toggleShowPublicOnly();
+ break;
+
+ case ListPopupMenu::mt_Show_Operation_Signature:
+ case ListPopupMenu::mt_Show_Operation_Signature_Selection:
+ toggleShowOpSigs();
+ break;
+
+ case ListPopupMenu::mt_Show_Attribute_Signature:
+ case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
+ toggleShowAttSigs();
+ break;
+
+ case ListPopupMenu::mt_Visibility:
+ case ListPopupMenu::mt_Visibility_Selection:
+ toggleShowVisibility();
+ break;
+
+ case ListPopupMenu::mt_Show_Packages:
+ case ListPopupMenu::mt_Show_Packages_Selection:
+ toggleShowPackage();
+ break;
+
+ case ListPopupMenu::mt_Show_Stereotypes:
+ case ListPopupMenu::mt_Show_Stereotypes_Selection:
+ toggleShowStereotype();
+ break;
+
+ case ListPopupMenu::mt_DrawAsCircle:
+ case ListPopupMenu::mt_DrawAsCircle_Selection:
+ toggleDrawAsCircle();
+ break;
+
+ case ListPopupMenu::mt_ChangeToClass:
+ case ListPopupMenu::mt_ChangeToClass_Selection:
+ changeToClass();
+ break;
+
+ case ListPopupMenu::mt_ChangeToInterface:
+ case ListPopupMenu::mt_ChangeToInterface_Selection:
+ changeToInterface();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(sel);
+ break;
+ }
+}
+
+QSize ClassifierWidget::calculateTemplatesBoxSize() {
+ UMLTemplateList list = getClassifier()->getTemplateList();
+ int count = list.count();
+ if (count == 0) {
+ return QSize(0, 0);
+ }
+
+ int width, height;
+ height = width = 0;
+
+ QFont font = UMLWidget::getFont();
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setBold(false);
+ const QFontMetrics fm(font);
+
+ height = count * fm.lineSpacing() + (MARGIN*2);
+
+ for (UMLTemplate *t = list.first(); t; t = list.next()) {
+ int textWidth = fm.size(0, t->toString() ).width();
+ if (textWidth > width)
+ width = textWidth;
+ }
+
+ width += (MARGIN*2);
+ return QSize(width, height);
+}
+
+int ClassifierWidget::displayedAttributes() {
+ if (!m_bShowAttributes)
+ return 0;
+ return displayedMembers(Uml::ot_Attribute);
+}
+
+void ClassifierWidget::setClassAssocWidget(AssociationWidget *assocwidget) {
+ m_pAssocWidget = assocwidget;
+ UMLAssociation *umlassoc = NULL;
+ if (assocwidget)
+ umlassoc = assocwidget->getAssociation();
+ getClassifier()->setClassAssoc(umlassoc);
+}
+
+AssociationWidget *ClassifierWidget::getClassAssocWidget() {
+ return m_pAssocWidget;
+}
+
+UMLClassifier *ClassifierWidget::getClassifier() {
+ return static_cast<UMLClassifier*>(m_pObject);
+}
+
+void ClassifierWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() )
+ p.setBrush( UMLWidget::getFillColour() );
+ else
+ p.setBrush( m_pView->viewport()->backgroundColor() );
+
+ if (getClassifier()->isInterface() && m_bDrawAsCircle) {
+ drawAsCircle(p, offsetX, offsetY);
+ return;
+ }
+
+ // Draw the bounding rectangle
+ QSize templatesBoxSize = calculateTemplatesBoxSize();
+ m_bodyOffsetY = offsetY;
+ if (templatesBoxSize.height() > 0)
+ m_bodyOffsetY += templatesBoxSize.height() - MARGIN;
+ int w = width();
+ if (templatesBoxSize.width() > 0)
+ w -= templatesBoxSize.width() / 2;
+ int h = height();
+ if (templatesBoxSize.height() > 0)
+ h -= templatesBoxSize.height() - MARGIN;
+ p.drawRect(offsetX, m_bodyOffsetY, w, h);
+
+ QFont font = UMLWidget::getFont();
+ font.setUnderline(false);
+ font.setItalic(false);
+ const QFontMetrics fm = UMLWidget::getFontMetrics(UMLWidget::FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ //If there are any templates then draw them
+ UMLTemplateList tlist = getClassifier()->getTemplateList();
+ if ( tlist.count() > 0 ) {
+ UMLWidget::setPen(p);
+ QPen pen = p.pen();
+ pen.setStyle(Qt::DotLine);
+ p.setPen(pen);
+ p.drawRect( offsetX + width() - templatesBoxSize.width(), offsetY,
+ templatesBoxSize.width(), templatesBoxSize.height() );
+ p.setPen( QPen(Qt::black) );
+ font.setBold(false);
+ p.setFont(font);
+ const int x = offsetX + width() - templatesBoxSize.width() + MARGIN;
+ int y = offsetY + MARGIN;
+ for ( UMLTemplate *t = tlist.first(); t; t = tlist.next() ) {
+ QString text = t->toString();
+ p.drawText(x, y, fm.size(0,text).width(), fontHeight, Qt::AlignVCenter, text);
+ y += fontHeight;
+ }
+ }
+
+ const int textX = offsetX + MARGIN;
+ const int textWidth = w - MARGIN * 2;
+
+ p.setPen(QPen(Qt::black));
+
+ // draw stereotype
+ font.setBold(true);
+ QString stereo = m_pObject->getStereotype();
+ /* if no stereotype is given we don't want to show the empty << >> */
+ const bool showStereotype = (m_bShowStereotype && !stereo.isEmpty());
+ const bool showNameOnly = (!m_bShowOperations && !m_bShowAttributes && !showStereotype);
+ int nameHeight = fontHeight;
+ if (showNameOnly) {
+ nameHeight = h;
+ } else if (showStereotype) {
+ p.setFont(font);
+ stereo = m_pObject->getStereotype(true);
+ p.drawText(textX, m_bodyOffsetY, textWidth, fontHeight, Qt::AlignCenter, stereo);
+ m_bodyOffsetY += fontHeight;
+ }
+
+ // draw name
+ QString name;
+ if (m_bShowPackage) {
+ name = m_pObject->getFullyQualifiedName();
+ } else {
+ name = this->getName();
+ }
+ font.setItalic( m_pObject->getAbstract() );
+ p.setFont(font);
+ p.drawText(textX, m_bodyOffsetY, textWidth, nameHeight, Qt::AlignCenter, name);
+ if (!showNameOnly) {
+ m_bodyOffsetY += fontHeight;
+ UMLWidget::setPen(p);
+ p.drawLine(offsetX, m_bodyOffsetY, offsetX + w - 1, m_bodyOffsetY);
+ p.setPen(QPen(Qt::black));
+ }
+ font.setBold(false);
+ font.setItalic(false);
+ p.setFont(font);
+
+ // draw attributes
+ const int numAtts = displayedAttributes();
+ if (m_bShowAttributes) {
+ drawMembers(p, Uml::ot_Attribute, m_ShowAttSigs, textX,
+ m_bodyOffsetY, fontHeight);
+ }
+
+ // draw dividing line between attributes and operations
+ if (!showNameOnly) {
+ if (numAtts == 0)
+ m_bodyOffsetY += fontHeight / 2; // no atts, so just add a bit of space
+ else
+ m_bodyOffsetY += fontHeight * numAtts;
+ UMLWidget::setPen(p);
+ p.drawLine(offsetX, m_bodyOffsetY, offsetX + w - 1, m_bodyOffsetY);
+ p.setPen(QPen(Qt::black));
+ }
+
+ // draw operations
+ if (m_bShowOperations) {
+ drawMembers(p, Uml::ot_Operation, m_ShowOpSigs, textX,
+ m_bodyOffsetY, fontHeight);
+ }
+
+ if (UMLWidget::m_bSelected)
+ UMLWidget::drawSelected(&p, offsetX, offsetY);
+}
+
+void ClassifierWidget::drawAsCircle(QPainter& p, int offsetX, int offsetY) {
+ int w = width();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString name;
+ if ( m_bShowPackage ) {
+ name = m_pObject->getFullyQualifiedName();
+ } else {
+ name = this -> getName();
+ }
+
+ p.drawEllipse(offsetX + w/2 - CIRCLE_SIZE/2, offsetY, CIRCLE_SIZE, CIRCLE_SIZE);
+ p.setPen( QPen(Qt::black) );
+
+ QFont font = UMLWidget::getFont();
+ p.setFont(font);
+ p.drawText(offsetX, offsetY + CIRCLE_SIZE, w, fontHeight, Qt::AlignCenter, name);
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize ClassifierWidget::calculateAsCircleSize() {
+ const QFontMetrics &fm = UMLWidget::getFontMetrics(UMLWidget::FT_ITALIC_UNDERLINE);
+ const int fontHeight = fm.lineSpacing();
+
+ int height = CIRCLE_SIZE + fontHeight;
+
+ int width = CIRCLE_SIZE;
+ QString displayedName;
+ if (m_bShowPackage) {
+ displayedName = m_pObject->getFullyQualifiedName();
+ } else {
+ displayedName = m_pObject->getName();
+ }
+ const int nameWidth = fm.size(0,displayedName).width();
+ if (nameWidth > width)
+ width = nameWidth;
+ width += MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void ClassifierWidget::drawMembers(QPainter & p, Uml::Object_Type ot, Uml::Signature_Type sigType,
+ int x, int y, int fontHeight) {
+ QFont f = UMLWidget::getFont();
+ f.setBold(false);
+ UMLClassifierListItemList list = getClassifier()->getFilteredList(ot);
+ for (UMLClassifierListItem *obj = list.first(); obj; obj = list.next()) {
+ if (m_bShowPublicOnly && obj->getVisibility() != Uml::Visibility::Public)
+ continue;
+ QString text = obj->toString(sigType);
+ f.setItalic( obj->getAbstract() );
+ f.setUnderline( obj->getStatic() );
+ p.setFont( f );
+ QFontMetrics fontMetrics(f);
+ p.drawText(x, y, fontMetrics.size(0,text).width(), fontHeight, Qt::AlignVCenter, text);
+ f.setItalic(false);
+ f.setUnderline(false);
+ p.setFont(f);
+ y += fontHeight;
+ }
+}
+
+void ClassifierWidget::setDrawAsCircle(bool drawAsCircle) {
+ m_bDrawAsCircle = drawAsCircle;
+ updateComponentSize();
+ update();
+}
+
+bool ClassifierWidget::getDrawAsCircle() const {
+ return m_bDrawAsCircle;
+}
+
+void ClassifierWidget::toggleDrawAsCircle() {
+ m_bDrawAsCircle = !m_bDrawAsCircle;
+ updateSigs();
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::changeToClass() {
+ WidgetBase::setBaseType(Uml::wt_Class);
+ getClassifier()->setBaseType(Uml::ot_Class);
+
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ m_bShowAttributes = ops.classState.showAtts;
+ m_bShowStereotype = ops.classState.showStereoType;
+
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::changeToInterface() {
+ WidgetBase::setBaseType(Uml::wt_Interface);
+ getClassifier()->setBaseType(Uml::ot_Interface);
+
+ m_bShowAttributes = false;
+ m_bShowStereotype = true;
+
+ updateComponentSize();
+ update();
+}
+
+void ClassifierWidget::adjustAssocs(int x, int y) {
+ UMLWidget::adjustAssocs(x, y);
+
+ if (m_pDoc->loading() || m_pAssocWidget == 0) {
+ return;
+ }
+
+ m_pAssocWidget->computeAssocClassLine();
+}
+
+void ClassifierWidget::saveToXMI(QDomDocument & qDoc, QDomElement & qElement) {
+ QDomElement conceptElement;
+ UMLClassifier *umlc = getClassifier();
+ if (umlc->isInterface())
+ conceptElement = qDoc.createElement("interfacewidget");
+ else
+ conceptElement = qDoc.createElement("classwidget");
+ UMLWidget::saveToXMI( qDoc, conceptElement );
+ conceptElement.setAttribute( "showoperations", m_bShowOperations );
+ conceptElement.setAttribute( "showpubliconly", m_bShowPublicOnly );
+ conceptElement.setAttribute( "showopsigs", m_ShowOpSigs );
+ conceptElement.setAttribute( "showpackage", m_bShowPackage );
+ conceptElement.setAttribute( "showscope", m_bShowAccess );
+ if (! umlc->isInterface()) {
+ conceptElement.setAttribute("showattributes", m_bShowAttributes);
+ conceptElement.setAttribute("showattsigs", m_ShowAttSigs);
+ }
+ if (umlc->isInterface() || umlc->getAbstract())
+ conceptElement.setAttribute("drawascircle", m_bDrawAsCircle);
+ qElement.appendChild( conceptElement );
+}
+
+bool ClassifierWidget::loadFromXMI(QDomElement & qElement) {
+ if (!UMLWidget::loadFromXMI(qElement))
+ return false;
+ QString showatts = qElement.attribute( "showattributes", "0" );
+ QString showops = qElement.attribute( "showoperations", "1" );
+ QString showpubliconly = qElement.attribute( "showpubliconly", "0" );
+ QString showattsigs = qElement.attribute( "showattsigs", "600" );
+ QString showopsigs = qElement.attribute( "showopsigs", "600" );
+ QString showpackage = qElement.attribute( "showpackage", "0" );
+ QString showscope = qElement.attribute( "showscope", "0" );
+ QString drawascircle = qElement.attribute("drawascircle", "0");
+
+ m_bShowAttributes = (bool)showatts.toInt();
+ m_bShowOperations = (bool)showops.toInt();
+ m_bShowPublicOnly = (bool)showpubliconly.toInt();
+ m_ShowAttSigs = (Uml::Signature_Type)showattsigs.toInt();
+ m_ShowOpSigs = (Uml::Signature_Type)showopsigs.toInt();
+ m_bShowPackage = (bool)showpackage.toInt();
+ m_bShowAccess = (bool)showscope.toInt();
+ m_bDrawAsCircle = (bool)drawascircle.toInt();
+
+ return true;
+}
+
diff --git a/umbrello/umbrello/classifierwidget.h b/umbrello/umbrello/classifierwidget.h
new file mode 100644
index 00000000..17172460
--- /dev/null
+++ b/umbrello/umbrello/classifierwidget.h
@@ -0,0 +1,390 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERWIDGET_H
+#define CLASSIFIERWIDGET_H
+
+#include "umlwidget.h"
+
+class QPainter;
+class UMLClassifier;
+class AssociationWidget;
+
+/**
+ * @short Common implementation for class widget and interface widget
+ * @author Oliver Kellogg
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassifierWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a ClassifierWidget.
+ *
+ * @param view The parent of this ClassifierWidget.
+ * @param o The UMLObject to represent.
+ */
+ ClassifierWidget(UMLView * view, UMLClassifier * o);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ClassifierWidget();
+
+ /**
+ * Toggles the status of whether to show StereoType.
+ */
+ void toggleShowStereotype();
+
+ /**
+ * Return the status of showing operations.
+ *
+ * @return Return the status of showing operations.
+ */
+ bool getShowOps() const;
+
+ /**
+ * Set the status of whether to show Operations
+ *
+ * @param _show True if operations shall be shown.
+ */
+ void setShowOps(bool _show);
+
+ /**
+ * Toggles the status of showing operations.
+ */
+ void toggleShowOps();
+
+ /**
+ * Return true if public operations/attributes are shown only.
+ */
+ bool getShowPublicOnly() const;
+
+ /**
+ * Set whether to show public operations/attributes only.
+ */
+ void setShowPublicOnly(bool _status);
+
+ /**
+ * Toggle whether to show public operations/attributes only.
+ */
+ void toggleShowPublicOnly();
+
+ /**
+ * Returns the status of whether to show visibility.
+ *
+ * @return True if visibility is shown.
+ */
+ bool getShowVisibility() const;
+
+ /**
+ * Set the status of whether to show visibility
+ *
+ * @param _visibility True if visibility shall be shown.
+ */
+ void setShowVisibility(bool _visibility);
+
+ /**
+ * Toggles the status of whether to show visibility
+ */
+ void toggleShowVisibility();
+
+ /**
+ * Return the status of showing operation signatures.
+ *
+ * @return Status of showing operation signatures.
+ */
+ Uml::Signature_Type getShowOpSigs() const;
+
+ /**
+ * Set the status of whether to show Operation signature
+ *
+ * @param _show True if operation signatures shall be shown.
+ */
+ void setShowOpSigs(bool _show);
+
+ /**
+ * Toggles the status of showing operation signatures.
+ */
+ void toggleShowOpSigs();
+
+ /**
+ * Returns the status of whether to show Package.
+ *
+ * @return True if package is shown.
+ */
+ bool getShowPackage() const;
+
+ /**
+ * Set the status of whether to show Package.
+ *
+ * @param _status True if package shall be shown.
+ */
+ void setShowPackage(bool _status);
+
+ /**
+ * Toggles the status of whether to show package.
+ */
+ void toggleShowPackage();
+
+ /**
+ * Set the type of signature to display for an Operation
+ *
+ * @param sig Type of signature to display for an operation.
+ */
+ void setOpSignature(Uml::Signature_Type sig);
+
+ /**
+ * Return the number of displayed attributes.
+ */
+ int displayedAttributes();
+
+ /**
+ * Return the number of displayed operations.
+ */
+ int displayedOperations();
+
+ /**
+ * Returns whether to show attributes.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ *
+ * @return True if attributes are shown.
+ */
+ bool getShowAtts() const {
+ return m_bShowAttributes;
+ }
+
+ /**
+ * Toggles whether to show attributes.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ */
+ void toggleShowAtts();
+
+ /**
+ * Returns whether to show attribute signatures.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ *
+ * @return Status of how attribute signatures are shown.
+ */
+ Uml::Signature_Type getShowAttSigs() {
+ return m_ShowAttSigs;
+ }
+
+ /**
+ * Toggles whether to show attribute signatures.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ */
+ void toggleShowAttSigs();
+
+ /**
+ * Sets whether to show attributes.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ *
+ * @param _show True if attributes shall be shown.
+ */
+ void setShowAtts(bool _show);
+
+ /**
+ * Sets whether to show attribute signature
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ *
+ * @param _show True if attribute signatures shall be shown.
+ */
+ void setShowAttSigs(bool _show);
+
+ /**
+ * Sets the type of signature to display for an attribute.
+ * Only applies when m_pObject->getBaseType() is ot_Class.
+ *
+ * @param sig Type of signature to display for an attribute.
+ */
+ void setAttSignature(Uml::Signature_Type sig);
+
+ /**
+ * Returns whether to draw as circle.
+ * Only applies when m_pObject->getBaseType() is ot_Interface.
+ *
+ * @return True if widget is drawn as circle.
+ */
+ bool getDrawAsCircle() const;
+
+ /**
+ * Toggles whether to draw as circle.
+ * Only applies when m_pObject->getBaseType() is ot_Interface.
+ */
+ void toggleDrawAsCircle();
+
+ /**
+ * Sets whether to draw as circle.
+ * Only applies when m_pObject->getBaseType() is ot_Interface.
+ *
+ * @param drawAsCircle True if widget shall be drawn as circle.
+ */
+ void setDrawAsCircle(bool drawAsCircle);
+
+ /**
+ * Changes this classifier from an interface to a class.
+ * Attributes and stereotype visibility is got from the view OptionState.
+ * This widget is also updated.
+ */
+ void changeToClass();
+
+ /**
+ * Changes this classifier from a class to an interface.
+ * Attributes are hidden and stereotype is shown.
+ * This widget is also updated.
+ */
+ void changeToInterface();
+
+ /**
+ * Set the AssociationWidget when this ClassWidget acts as
+ * an association class.
+ */
+ void setClassAssocWidget(AssociationWidget *assocwidget);
+
+ /**
+ * Return the AssociationWidget when this classifier acts as
+ * an association class (else return NULL.)
+ */
+ AssociationWidget *getClassAssocWidget();
+
+ /**
+ * Return the UMLClassifier which this ClassifierWidget
+ * represents.
+ */
+ UMLClassifier *getClassifier();
+
+ /**
+ * Overrides standard method.
+ * Auxiliary to reimplementations in the derived classes.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Extends base method to adjust also the association of a class
+ * association.
+ * Executes the base method and then, if file isn't loading and the
+ * classifier acts as a class association, the association position is
+ * updated.
+ *
+ * @param x The x-coordinate.
+ * @param y The y-coordinate.
+ */
+ virtual void adjustAssocs(int x, int y);
+
+ /**
+ * Creates the "classwidget" or "interfacewidget" XML element.
+ */
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+ /**
+ * Loads the "classwidget" or "interfacewidget" XML element.
+ */
+ bool loadFromXMI(QDomElement & qElement);
+
+public slots:
+ /**
+ * Will be called when a menu selection has been made from the
+ * popup menu.
+ *
+ * @param sel The selection id that has been selected.
+ */
+ void slotMenuSelection(int sel);
+
+protected:
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Calculcates the size of the templates box in the top left
+ * if it exists, returns QSize(0,0) if it doesn't.
+ *
+ * @return QSize of the templates flap.
+ */
+ QSize calculateTemplatesBoxSize();
+
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+ /**
+ * Draws the interface as a circle with name underneath.
+ * Only applies when m_pObject->getBaseType() is ot_Interface.
+ */
+ void drawAsCircle(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Calculates the size of the object when drawn as a circle.
+ * Only applies when m_pObject->getBaseType() is ot_Interface.
+ */
+ QSize calculateAsCircleSize();
+
+ /**
+ * Updates m_ShowOpSigs to match m_bShowVisibility.
+ */
+ void updateSigs();
+
+ /**
+ * Return the number of displayed members of the given Object_Type.
+ * Takes into consideration m_bShowPublicOnly but not other settings,
+ */
+ int displayedMembers(Uml::Object_Type ot);
+
+ /**
+ * Auxiliary method for draw() of child classes:
+ * Draw the attributes or operations.
+ *
+ * @param p QPainter to paint to.
+ * @param ot Object type to draw, either ot_Attribute or ot_Operation.
+ * @param sigType Governs details of the member display.
+ * @param x X coordinate at which to draw the texts.
+ * @param y Y coordinate at which text drawing commences.
+ * @param fontHeight The font height.
+ */
+ void drawMembers(QPainter & p, Uml::Object_Type ot, Uml::Signature_Type sigType,
+ int x, int y, int fontHeight);
+
+ bool m_bShowOperations; ///< Loaded/saved item.
+ bool m_bShowPublicOnly; ///< Loaded/saved item.
+ bool m_bShowAccess; ///< Loaded/saved item.
+ bool m_bShowPackage; ///< Loaded/saved item.
+ bool m_bShowAttributes; ///< Loaded/saved item.
+ bool m_bDrawAsCircle; ///< Loaded/saved item.
+ Uml::Signature_Type m_ShowAttSigs; ///< Loaded/saved item.
+ Uml::Signature_Type m_ShowOpSigs; ///< Loaded/saved item.
+
+ /**
+ * Text width margin
+ */
+ static const int MARGIN;
+
+ /**
+ * Size of circle when interface is rendered as such
+ */
+ static const int CIRCLE_SIZE;
+
+ /// Auxiliary variable for size calculations and drawing
+ int m_bodyOffsetY;
+
+ /**
+ * The related AssociationWidget in case this classifier
+ * acts as an association class
+ */
+ AssociationWidget *m_pAssocWidget;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/clipboard/Makefile.am b/umbrello/umbrello/clipboard/Makefile.am
new file mode 100644
index 00000000..91dc58f7
--- /dev/null
+++ b/umbrello/umbrello/clipboard/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I$(top_builddir)/umbrello/umbrello/dialogs $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libclipboard.la
+libclipboard_la_SOURCES = umldrag.cpp umlclipboard.cpp idchangelog.cpp
diff --git a/umbrello/umbrello/clipboard/idchangelog.cpp b/umbrello/umbrello/clipboard/idchangelog.cpp
new file mode 100644
index 00000000..1521c1cc
--- /dev/null
+++ b/umbrello/umbrello/clipboard/idchangelog.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "idchangelog.h"
+
+#include <kdebug.h>
+
+IDChangeLog::IDChangeLog() {}
+
+IDChangeLog::IDChangeLog(const IDChangeLog& Other) {
+ m_LogArray = Other.m_LogArray;
+}
+
+IDChangeLog::~IDChangeLog() {}
+
+IDChangeLog& IDChangeLog::operator=(const IDChangeLog& Other) {
+ m_LogArray = Other.m_LogArray;
+
+ return *this;
+}
+
+bool IDChangeLog::operator==(const IDChangeLog& /*Other*/) {
+ /*It needs to be Implemented*/
+ return false;
+}
+
+Uml::IDType IDChangeLog::findNewID(Uml::IDType OldID) {
+ uint count = m_LogArray.size();
+ for(uint i = 0; i < count; i++) {
+ if((m_LogArray.point(i)).y() == OldID) {
+ return (m_LogArray.point(i)).x();
+ }
+ }
+
+ return Uml::id_None;
+}
+
+IDChangeLog& IDChangeLog::operator+=(const IDChangeLog& Other) {
+ //m_LogArray.putpoints(m_LogArray.size(), Other.m_LogArray.size(), Other)
+ uint count = Other.m_LogArray.size();
+ for(uint i = 0; i < count; i++) {
+ addIDChange((Other.m_LogArray.point(i)).y(), (Other.m_LogArray.point(i)).x());
+ }
+
+ return *this;
+}
+
+void IDChangeLog::addIDChange(Uml::IDType OldID, Uml::IDType NewID) {
+ uint pos;
+ if(!findIDChange(OldID, NewID, pos)) {
+ pos = m_LogArray.size();
+ m_LogArray.resize(pos + 1);
+ m_LogArray.setPoint(pos, NewID, OldID);
+ } else {
+ m_LogArray.setPoint(pos, NewID, OldID);
+ }
+}
+
+Uml::IDType IDChangeLog::findOldID(Uml::IDType NewID) {
+ uint count = m_LogArray.size();
+ for(uint i = 0; i < count; i++) {
+ if((m_LogArray.point(i)).x() == NewID) {
+ return (m_LogArray.point(i)).y();
+ }
+ }
+
+ return Uml::id_None;
+}
+
+bool IDChangeLog::findIDChange(Uml::IDType OldID, Uml::IDType NewID, uint& pos) {
+ uint count = m_LogArray.size();
+ for(uint i = 0; i < count; i++) {
+ if(((m_LogArray.point(i)).y() == OldID) && ((m_LogArray.point(i)).x() == NewID)) {
+ pos = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void IDChangeLog::removeChangeByNewID(Uml::IDType OldID) {
+ uint count = m_LogArray.size();
+ for(uint i = 0; i < count; i++) {
+ if((m_LogArray.point(i)).y() == OldID) {
+ m_LogArray.setPoint(i, Uml::id_None, OldID);
+ }
+ }
+}
diff --git a/umbrello/umbrello/clipboard/idchangelog.h b/umbrello/umbrello/clipboard/idchangelog.h
new file mode 100644
index 00000000..1d92cd0d
--- /dev/null
+++ b/umbrello/umbrello/clipboard/idchangelog.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IDCHANGELOG_H
+#define IDCHANGELOG_H
+
+
+/**
+ * This class contains all the ID translations done for each
+ * UMLObject pasted. It contains for each old id its new
+ * assigned id.
+ *
+ * @author Gustavo Madrigal
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+#include <qstring.h>
+#include <qvaluevector.h>
+
+#include "../umlnamespace.h"
+
+class IDChangeLog {
+public:
+ /**
+ * Constructor.
+ */
+ IDChangeLog();
+
+ /**
+ * Copy constructor.
+ */
+ IDChangeLog(const IDChangeLog& Other);
+
+ /**
+ * Deconstructor.
+ */
+ ~IDChangeLog();
+
+ /**
+ * Overloaded '=' operator.
+ */
+ IDChangeLog& operator=(const IDChangeLog& Other);
+
+ /**
+ * Overloaded '==' operator.
+ */
+ bool operator==(const IDChangeLog& Other);
+
+ /**
+ * Adds a new ID Change to the log.
+ */
+ void addIDChange(Uml::IDType OldID, Uml::IDType NewID);
+
+ /**
+ * Appends another IDChangeLog to this instance of IDChangeLog and
+ * returns a reference to itself.
+ */
+ IDChangeLog& operator+=(const IDChangeLog& Other);
+
+ /**
+ * Returns the new assigned ID of the object that had OldID as its
+ * previous id.
+ */
+ Uml::IDType findNewID(Uml::IDType OldID);
+
+ /**
+ * Returns the old ID of an UMLobject given its new one.
+ */
+ Uml::IDType findOldID(Uml::IDType NewID);
+
+ /**
+ * Removes a change giving an New ID.
+ */
+ void removeChangeByNewID( Uml::IDType OldID);
+
+ enum SpecialIDs
+ {
+ NullID = -1000 ///< An impossible id value.
+ };
+
+private:
+ /**
+ * Each change is a Point (x=newID, y=oldID)
+ */
+ class Point {
+ public:
+ Point()
+ {}
+ Point(const Uml::IDType &x, const Uml::IDType &y)
+ : m_x(x), m_y(y)
+ {}
+ virtual ~Point() {}
+ void setX(const Uml::IDType &x) { m_x = x; }
+ Uml::IDType x() const { return m_x; }
+ void setY(const Uml::IDType &y) { m_y = y; }
+ Uml::IDType y() const { return m_y; }
+ private:
+ Uml::IDType m_x, m_y;
+ };
+class PointArray : QValueVector<Point> {
+ public:
+ void setPoint(uint i, const Uml::IDType &x, const Uml::IDType &y) {
+ Point point(x, y);
+ QValueVector<Point>::at(i) = point;
+ }
+ const Point& point( uint i ) const { return QValueVector<Point>::at(i); }
+ uint size() const { return QValueVector<Point>::size(); }
+ bool resize( uint size ) { QValueVector<Point>::resize(size); return true; }
+ };
+ PointArray m_LogArray;
+
+ /**
+ * Finds a specific change in the log.
+ */
+ bool findIDChange(Uml::IDType OldID, Uml::IDType NewID, uint& pos);
+};
+
+#endif
diff --git a/umbrello/umbrello/clipboard/umlclipboard.cpp b/umbrello/umbrello/clipboard/umlclipboard.cpp
new file mode 100644
index 00000000..c65c576e
--- /dev/null
+++ b/umbrello/umbrello/clipboard/umlclipboard.cpp
@@ -0,0 +1,694 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlclipboard.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+// local includes
+#include "umldrag.h"
+#include "idchangelog.h"
+#include "../associationwidget.h"
+#include "../attribute.h"
+#include "../classifier.h"
+#include "../floatingtextwidget.h"
+#include "../operation.h"
+#include "../umldoc.h"
+#include "../umllistview.h"
+#include "../umllistviewitem.h"
+#include "../umlobjectlist.h"
+#include "../umlview.h"
+#include "../umlwidget.h"
+#include "../uml.h"
+#include "../model_utils.h"
+
+UMLClipboard::UMLClipboard() {
+ m_type = clip1;
+}
+
+UMLClipboard::~UMLClipboard() {
+}
+
+QMimeSource* UMLClipboard::copy(bool fromView/*=false*/) {
+ //Clear previous copied data
+ m_AssociationList.clear();
+ m_ItemList.clear();
+ m_ObjectList.clear();
+ m_ViewList.clear();
+
+ UMLDrag *data = 0;
+ QPixmap* png = 0;
+
+ UMLListView * listView = UMLApp::app()->getListView();
+ UMLListViewItemList selectedItems;
+ selectedItems.setAutoDelete(false);
+
+ if(fromView) {
+ m_type = clip4;
+ UMLView *view = UMLApp::app()->getCurrentView();
+ view->checkSelections();
+ if(!view->getSelectedWidgets(m_WidgetList)) {
+ return 0;
+ }
+ //if there is no selected widget then there is no copy action
+ if(!m_WidgetList.count()) {
+ return 0;
+ }
+ m_AssociationList = view->getSelectedAssocs();
+ view->copyAsImage(png);
+
+ } else { //if the copy action is being performed from the ListView
+ if(!listView->getSelectedItems(selectedItems)) {
+ return 0;
+ }
+ //Set What type of copy operation are we performing and
+ //also fill m_ViewList with all the selected Diagrams
+ setCopyType(selectedItems);
+
+ //if we are copying a diagram or part of a diagram, select the items
+ //on the ListView that correspond to a UseCase, Actor or Concept
+ //in the Diagram
+ if(m_type == clip2) {
+ //Fill the member lists with all the object and stuff to be copied
+ //to the clipboard
+ selectedItems.clear();
+ //For each selected view select all the Actors, USe Cases and Concepts
+ //widgets in the ListView
+ for (UMLViewListIt vit(m_ViewList); vit.current(); ++vit) {
+ UMLObjectList objects = vit.current()->getUMLObjects();
+ for (UMLObjectListIt oit(objects); oit.current(); ++oit) {
+ UMLObject *o = oit.current();
+ UMLListViewItem *item = listView->findUMLObject(o);
+ if(item) {
+ listView->setSelected(item, true);
+ }
+ }
+ }
+ if(!listView->getSelectedItems(selectedItems)) {
+ return 0;
+ }
+ }
+ if(!fillSelectionLists(selectedItems)) {
+ return 0;
+ }
+ }
+ int i =0;
+ switch(m_type) {
+ case clip1:
+ data = new UMLDrag(m_ObjectList);
+ break;
+ case clip2:
+ data = new UMLDrag(m_ObjectList, m_ItemList, m_ViewList);
+ break;
+ case clip3:
+ data = new UMLDrag(m_ItemList);
+ break;
+ case clip4:
+ if(png) {
+ UMLView *view = UMLApp::app()->getCurrentView();
+ data = new UMLDrag(m_ObjectList, m_WidgetList,
+ m_AssociationList, *png, view->getType());
+ } else {
+ return 0;
+ }
+ break;
+ case clip5:
+ data = new UMLDrag(m_ObjectList, i);
+ // The int i is used to differentiate
+ // which UMLDrag constructor gets called.
+ break;
+ }
+
+ return (QMimeSource*)data;
+}
+
+bool UMLClipboard::paste(QMimeSource* data) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ bool result = false;
+ doc->beginPaste();
+ switch(UMLDrag::getCodingType(data)) {
+ case 1:
+ result = pasteClip1(data);
+ break;
+ case 2:
+ result = pasteClip2(data);
+ break;
+ case 3:
+ result = pasteClip3(data);
+ break;
+ case 4:
+ result = pasteClip4(data);
+ break;
+ case 5:
+ result = pasteClip5(data);
+ break;
+ default:
+ break;
+ }
+ doc->endPaste();
+ return result;
+}
+
+bool UMLClipboard::fillSelectionLists(UMLListViewItemList& SelectedItems) {
+ UMLListViewItemListIt it(SelectedItems);
+ UMLListViewItem* item = 0;
+ Uml::ListView_Type type;
+ switch(m_type) {
+ case clip4:
+ break;
+ case clip3:
+ for ( ; it.current(); ++it ) {
+ item = (UMLListViewItem*)it.current();
+ type = item->getType();
+ if ( !Model_Utils::typeIsClassifierList(type) ) {
+ m_ItemList.append(item);
+ insertItemChildren(item, SelectedItems);
+ //Because it is being called when m_type is 3
+ //it will insert only child empty folders of other folders.
+ //If a child folder
+ //is not empty that means m_type wouldn't be 3 because if a folder is
+ //selected then its complete contents are treated as if
+ //they were selected
+ }
+ }
+ break;
+ case clip2:
+ case clip1:
+ for ( ; it.current(); ++it ) {
+ item = (UMLListViewItem*)it.current();
+ type = item->getType();
+ if ( !Model_Utils::typeIsClassifierList(type) ) {
+
+ m_ItemList.append(item);
+
+ if ( Model_Utils::typeIsCanvasWidget(type) ) {
+ m_ObjectList.append(item->getUMLObject());
+ }
+ insertItemChildren(it.current(), SelectedItems);
+ }
+ }
+ break;
+ case clip5:
+ for ( ; it.current(); ++it ) {
+ item = (UMLListViewItem*)it.current();
+ type = item->getType();
+ if( Model_Utils::typeIsClassifierList(type) ) {
+ m_ItemList.append(item);
+ m_ObjectList.append(item->getUMLObject());
+
+ } else {
+ return false;
+ }
+ }
+ break;
+ }
+
+ return true;
+}
+
+void UMLClipboard::setCopyType(UMLListViewItemList& SelectedItems) {
+ bool withDiagrams = false; //If the selection includes diagrams
+ bool withObjects = false; //If the selection includes objects
+ bool onlyAttsOps = false; //If the selection only includes Attributes and/or Operations
+ UMLListViewItemListIt it(SelectedItems);
+ for ( ; it.current(); ++it ) {
+ checkItemForCopyType(it.current(), withDiagrams, withObjects, onlyAttsOps);
+ }
+ if(onlyAttsOps) {
+ m_type = clip5;
+ } else if(withDiagrams) {
+ m_type = clip2;
+ } else if(withObjects) {
+ m_type = clip1;
+ } else {
+ m_type = clip3;
+ }
+}
+
+void UMLClipboard::checkItemForCopyType(UMLListViewItem* Item, bool & WithDiagrams, bool &WithObjects,
+ bool &OnlyAttsOps) {
+ if(!Item) {
+ return;
+ }
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ OnlyAttsOps = true;
+ UMLView * view = 0;
+ UMLListViewItem * child = 0;
+ Uml::ListView_Type type = Item->getType();
+ if ( Model_Utils::typeIsCanvasWidget(type) ) {
+ WithObjects = true;
+ OnlyAttsOps = false;
+ } else if ( Model_Utils::typeIsDiagram(type) ) {
+ WithDiagrams = true;
+ OnlyAttsOps = false;
+ view = doc->findView( Item->getID() );
+ m_ViewList.append( view );
+ } else if ( Model_Utils::typeIsFolder(type) ) {
+ OnlyAttsOps = false;
+ if(Item->childCount()) {
+ child = (UMLListViewItem*)Item->firstChild();
+ while(child) {
+ checkItemForCopyType(child, WithDiagrams, WithObjects, OnlyAttsOps);
+ child = (UMLListViewItem*)child->nextSibling();
+ }
+ }
+ }
+}
+
+/** Adds the children of a UMLListViewItem to m_ItemList */
+bool UMLClipboard::insertItemChildren(UMLListViewItem * Item, UMLListViewItemList& SelectedItems) {
+ if(Item->childCount()) {
+ UMLListViewItem * child = (UMLListViewItem*)Item->firstChild();
+ int type;
+ while(child) {
+ m_ItemList.append(child);
+ type = child->getType();
+ if(type == Uml::lvt_Actor || type == Uml::lvt_UseCase || type == Uml::lvt_Class) {
+ m_ObjectList.append(child->getUMLObject());
+ }
+ // If the child is selected, remove it from the list of selected items
+ // otherwise it will be inserted twice in m_ObjectList.
+ if(child->isSelected()) {
+ SelectedItems.remove(SelectedItems.find(child) );
+ }
+ insertItemChildren(child, SelectedItems);
+ child = (UMLListViewItem*)child->nextSibling();
+ }
+ }
+ return true;
+}
+
+bool UMLClipboard::pasteChildren(UMLListViewItem *parent, IDChangeLog *chgLog) {
+ if (!parent) {
+ kWarning() << "Paste Children Error, parent missing" << endl;
+ return false;
+ }
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *childItem = static_cast<UMLListViewItem*>(parent->firstChild());
+ while (childItem) {
+ Uml::IDType oldID = childItem->getID();
+ Uml::IDType newID = chgLog->findNewID(oldID);
+ UMLListViewItem *shouldNotExist = listView->findItem(newID);
+ if (shouldNotExist) {
+ kError() << "UMLClipboard::pasteChildren: new list view item " << ID2STR(newID)
+ << " already exists (internal error)" << endl;
+ childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
+ continue;
+ }
+ UMLObject *newObj = doc->findObjectById(newID);
+ if (newObj) {
+ kDebug() << "UMLClipboard::pasteChildren: adjusting lvitem(" << ID2STR(oldID)
+ << ") to new UMLObject(" << ID2STR(newID) << ")" << endl;
+ childItem->setUMLObject(newObj);
+ childItem->setText(newObj->getName());
+ } else {
+ kDebug() << "UMLClipboard::pasteChildren: no UMLObject found for lvitem "
+ << ID2STR(newID) << endl;
+ }
+ childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
+ }
+ return true;
+}
+
+/** Cleans the list of associations taking out the ones that point to an object
+ not in m_ObjectList. */
+void UMLClipboard::CleanAssociations(AssociationWidgetList& associations) {
+ AssociationWidgetListIt it(associations);
+ AssociationWidget* assoc = it.current();
+
+ while (assoc) {
+ ++it;
+ assoc = it.current();
+ }
+}
+
+/** If clipboard has mime type application/x-uml-clip1,
+Pastes the data from the clipboard into the current Doc */
+bool UMLClipboard::pasteClip1(QMimeSource* data) {
+ UMLObjectList objects;
+ if (! UMLDrag::decodeClip1(data, objects)) {
+ return false;
+ }
+ UMLListView *lv = UMLApp::app()->getListView();
+ if ( !lv->startedCopy() )
+ return true;
+ lv->setStartedCopy(false);
+ /* If we get here we are pasting after a Copy and need to
+ // paste possible children.
+ UMLListViewItem* itemdata = 0;
+ UMLListViewItemListIt it(itemdatalist);
+ while ( (itemdata=it.current()) != 0 ) {
+ if(itemdata -> childCount()) {
+ if(!pasteChildren(itemdata, idchanges)) {
+ return false;
+ }
+ }
+ ++it;
+ }
+ */
+ return true;
+}
+
+/** If clipboard has mime type application/x-uml-clip2,
+Pastes the data from the clipboard into the current Doc */
+bool UMLClipboard::pasteClip2(QMimeSource* data) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ UMLListViewItemList itemdatalist;
+ UMLObjectList objects;
+ objects.setAutoDelete(false);
+ UMLViewList views;
+ IDChangeLog* idchanges = 0;
+
+ bool result = UMLDrag::decodeClip2(data, objects, itemdatalist, views);
+ if(!result) {
+ return false;
+ }
+ UMLObject *obj = 0;
+ UMLObjectListIt object_it(objects);
+ idchanges = doc->getChangeLog();
+ if(!idchanges) {
+ return false;
+ }
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+ if(!doc->assignNewIDs(obj)) {
+ kDebug()<<"UMLClipboard: error adding umlobject"<<endl;
+ return false;
+ }
+ }
+
+ UMLView * pView = 0;
+ UMLViewListIt view_it( views );
+ while ( ( pView =view_it.current()) != 0 ) {
+ ++view_it;
+ if( !doc->addUMLView( pView ) ) {
+ return false;
+ }
+ }
+
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem* item = 0;
+ UMLListViewItem* itemdata = 0;
+ UMLListViewItemListIt it(itemdatalist);
+ while ( (itemdata=it.current()) != 0 ) {
+ item = listView->createItem(*itemdata, *idchanges);
+ if(!item) {
+ return false;
+ }
+ if(itemdata -> childCount()) {
+ if(!pasteChildren(item, idchanges)) {
+ return false;
+ }
+ }
+ ++it;
+ }
+
+ return result;
+}
+
+/** If clipboard has mime type application/x-uml-clip3,
+Pastes the data from the clipboard into the current Doc */
+bool UMLClipboard::pasteClip3(QMimeSource* data) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ UMLListViewItemList itemdatalist;
+ UMLListViewItem* item = 0;
+ UMLListViewItem* itemdata = 0;
+ IDChangeLog* idchanges = doc->getChangeLog();
+
+ if(!idchanges) {
+ return false;
+ }
+
+ UMLListView *listView = UMLApp::app()->getListView();
+ bool result = UMLDrag::decodeClip3(data, itemdatalist, listView);
+ if(!result) {
+ return false;
+ }
+ UMLListViewItemListIt it(itemdatalist);
+ while ( (itemdata=it.current()) != 0 ) {
+ item = listView->createItem(*itemdata, *idchanges);
+ if(itemdata -> childCount()) {
+ if(!pasteChildren(item, idchanges)) {
+ return false;
+ }
+ }
+ ++it;
+ }
+
+ return result;
+}
+
+/** If clipboard has mime type application/x-uml-clip4,
+Pastes the data from the clipboard into the current Doc */
+bool UMLClipboard::pasteClip4(QMimeSource* data) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+
+ UMLObjectList objects;
+ objects.setAutoDelete(false);
+
+
+ UMLWidgetList widgets;
+ widgets.setAutoDelete(false);
+
+ AssociationWidgetList assocs;
+ assocs.setAutoDelete(false);
+
+ IDChangeLog* idchanges = 0;
+
+ Uml::Diagram_Type diagramType;
+
+ if( !UMLDrag::decodeClip4(data, objects, widgets, assocs, diagramType) ) {
+ return false;
+ }
+
+ if( diagramType != UMLApp::app()->getCurrentView()->getType() ) {
+ if( !checkPasteWidgets(widgets) ) {
+ assocs.setAutoDelete(true);
+ assocs.clear();
+ return false;
+ }
+ }
+ UMLObjectListIt object_it(objects);
+ idchanges = doc->getChangeLog();
+ if(!idchanges) {
+ return false;
+ }
+ //make sure the file we are pasting into has the objects
+ //we need if there are widgets to be pasted
+ UMLObject* obj = 0;
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+
+ if(!doc->assignNewIDs(obj)) {
+ return false;
+ }
+
+ }
+
+ //now add any widget we are want to paste
+ bool objectAlreadyExists = false;
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ currentView->beginPartialWidgetPaste();
+ UMLWidget* widget =0;
+ UMLWidgetListIt widget_it(widgets);
+ while ( (widget=widget_it.current()) != 0 ) {
+ ++widget_it;
+
+ Uml::IDType oldId = widget->getID();
+ Uml::IDType newId = idchanges->findNewID(oldId);
+ if (currentView->findWidget(newId)) {
+ kError() << "UMLClipboard::pasteClip4: widget (oldID=" << ID2STR(oldId)
+ << ", newID=" << ID2STR(newId) << ") already exists in target view."
+ << endl;
+ widgets.remove(widget);
+ delete widget;
+ objectAlreadyExists = true;
+ } else if (! currentView->addWidget(widget, true)) {
+ currentView->endPartialWidgetPaste();
+ return false;
+ }
+ }
+
+ //now paste the associations
+ AssociationWidget* assoc;
+ AssociationWidgetListIt assoc_it(assocs);
+ while ( (assoc=assoc_it.current()) != 0 ) {
+ ++assoc_it;
+ if (!currentView->addAssociation(assoc, true)) {
+ currentView->endPartialWidgetPaste();
+ return false;
+ }
+ }
+
+ //Activate all the pasted associations and widgets
+ currentView->activate();
+ currentView->endPartialWidgetPaste();
+
+ /*
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem* item = 0;
+ UMLListViewItem* itemdata = 0;
+ UMLListViewItemListIt it(itemdatalist);
+ while ( (itemdata=it.current()) != 0 ) {
+ item = listView->createItem(*itemdata, *idchanges);
+ if(!item) {
+ return false;
+ }
+ if(itemdata -> childCount()) {
+ if(!pasteChildren(item, idchanges)) {
+ return false;
+ }
+ }
+ ++it;
+ }*/
+
+ if (objectAlreadyExists) {
+ pasteItemAlreadyExists();
+ }
+ return true;
+}
+
+/** If clipboard has mime type application/x-uml-clip5,
+Pastes the data from the clipboard into the current Doc */
+bool UMLClipboard::pasteClip5(QMimeSource* data) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem* lvitem = dynamic_cast<UMLListViewItem *>( listView->currentItem() );
+ if (!lvitem ||
+ (lvitem->getType() != Uml::lvt_Class && lvitem->getType() != Uml::lvt_Interface)) {
+ return false;
+ }
+ UMLClassifier *parent = dynamic_cast<UMLClassifier *>(lvitem->getUMLObject());
+ if (parent == NULL) {
+ kError() << "UMLClipboard::pasteClip5: parent is not a UMLClassifier"
+ << endl;
+ return false;
+ }
+
+ UMLObjectList objects;
+ objects.setAutoDelete(false);
+ IDChangeLog* idchanges = 0;
+ bool result = UMLDrag::decodeClip5(data, objects, parent);
+
+ if(!result) {
+ return false;
+ }
+
+ UMLObject *obj = 0;
+ doc->setModified(true);
+ idchanges = doc->getChangeLog();
+ // Assume success if at least one child object could be pasted
+ if (objects.count())
+ result = false;
+
+ for (UMLObjectListIt it(objects); (obj = it.current()) != NULL; ++it) {
+ obj->setID(doc->assignNewID(obj->getID()));
+ switch(obj->getBaseType()) {
+ case Uml::ot_Attribute :
+ {
+ UMLObject *exist = parent->findChildObject(obj->getName(), Uml::ot_Attribute);
+ if (exist) {
+ QString newName = parent->uniqChildName(Uml::ot_Attribute, obj->getName());
+ obj->setName(newName);
+ }
+ UMLAttribute *att = static_cast<UMLAttribute*>(obj);
+ if (parent->addAttribute(att, idchanges)) {
+ result = true;
+ } else {
+ kError() << "UMLClipboard::pasteClip5: " << parent->getName()
+ << "->addAttribute(" << att->getName() << ") failed" << endl;
+ }
+ break;
+ }
+ case Uml::ot_Operation :
+ {
+ UMLOperation *op = static_cast<UMLOperation*>(obj);
+ UMLOperation *exist = parent->checkOperationSignature(op->getName(), op->getParmList());
+ if (exist) {
+ QString newName = parent->uniqChildName(Uml::ot_Operation, obj->getName());
+ op->setName(newName);
+ }
+ if (parent->addOperation(op, idchanges)) {
+ result = true;
+ } else {
+ kError() << "UMLClipboard::pasteClip5: " << parent->getName()
+ << "->addOperation(" << op->getName() << ") failed" << endl;
+ }
+ break;
+ }
+ default :
+ kWarning() << "pasting unknown children type in clip type 5" << endl;
+ return false;
+ }
+ }
+
+ return result;
+}
+
+bool UMLClipboard::insertItemChildren( UMLListViewItem * item ) {
+ if( item -> childCount() ) {
+ UMLListViewItem * child =dynamic_cast<UMLListViewItem *>( item -> firstChild() );
+ while( child ) {
+ m_ItemList.append( child );
+ insertItemChildren( child );
+ child = dynamic_cast<UMLListViewItem *>( child->nextSibling() );
+ }
+ }
+ return true;
+}
+
+bool UMLClipboard::checkPasteWidgets( UMLWidgetList & widgetList ) {
+ bool retval = true;
+ UMLWidget * p = 0;
+ UMLWidgetListIt it( widgetList );
+ while ( ( p = it.current()) != 0 ) {
+ ++it;
+ switch( p -> getBaseType() ) {
+ case Uml::wt_Note:
+ break;
+
+ case Uml::wt_Text:
+ {
+ FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(p);
+ if (ft->getRole() != Uml::tr_Floating) {
+ widgetList.remove(p);
+ delete ft;
+ retval = false;
+ }
+ }
+ break;
+
+ default:
+ widgetList.remove(p);
+ delete p;
+ retval = false;
+ break;
+ }
+ }
+ return retval;
+}
+
+void UMLClipboard::pasteItemAlreadyExists() {
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ KMessageBox::sorry( currentView,
+ i18n("At least one of the items in the clipboard "
+ "could not be pasted because an item of the "
+ "same name already exists. Any other items "
+ "have been pasted."),
+ i18n("Paste Error") );
+}
+
+#include "umlclipboard.moc"
diff --git a/umbrello/umbrello/clipboard/umlclipboard.h b/umbrello/umbrello/clipboard/umlclipboard.h
new file mode 100644
index 00000000..9be92111
--- /dev/null
+++ b/umbrello/umbrello/clipboard/umlclipboard.h
@@ -0,0 +1,194 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLCLIPBOARD_H
+#define UMLCLIPBOARD_H
+
+#include "../associationwidgetlist.h"
+#include "../umlobjectlist.h"
+#include "../umllistviewitemlist.h"
+#include "../umllistviewitem.h"
+#include "../umlviewlist.h"
+#include "../umlwidgetlist.h"
+
+class IDChangeLog;
+class QMimeSource;
+
+/**
+ * This class manages the uml's interaction with the KDE
+ * Clipboard. It makes possible to copy stuff from one uml
+ * instance to another one.
+ *
+ * @short Clipboard management class
+ * @author Gustavo Madrigal
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLClipboard : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Constructor.
+ */
+ UMLClipboard();
+
+ /**
+ * Deconstructor.
+ */
+ virtual ~UMLClipboard();
+
+ /**
+ * Inserts the clipboard's contents.
+ *
+ * @param Data Pointer to the MIME format clipboard data.
+ * @return True for successful operation.
+ */
+ bool paste(QMimeSource* Data);
+
+ /**
+ * Copies the selected stuff from the list view or current diagram
+ * to a QMimeSource ready to be put in the clipboard.
+ *
+ * @return Pointer to the created clipboard data.
+ */
+ QMimeSource* copy(bool fromView = false);
+
+ /// Enumeration that codes the different types of UML clips.
+ enum UMLCopyType
+ {
+ clip1 = 1, ///<UMLObjects (not diagrams)
+ clip2 = 2, ///<UMLObjects, UMLListViewItems (not diagrams) and diagrams
+ clip3 = 3, ///<UMLListViewItems (not diagrams)
+ clip4 = 4, ///<UMLObjects, Associations and UMLWidgets
+ clip5 = 5 ///<Only Attributes and Operations
+ };
+
+private:
+ /**
+ * Cleans the list of associations taking out the ones
+ * that point to an object not in m_ObjectList.
+ *
+ * @param associations The list of associations to process.
+ */
+ void CleanAssociations(AssociationWidgetList& associations);
+
+ /**
+ * If clipboard has mime type application/x-uml-clip1,
+ * pastes the data from the clipboard.
+ *
+ * @param data Pointer to the source clip.
+ * @return True for successful operation.
+ */
+ bool pasteClip1(QMimeSource* data);
+
+ /**
+ * If clipboard has mime type application/x-uml-clip2,
+ * pastes the data from the clipboard.
+ *
+ * @param data Pointer to the source clip.
+ * @return True for successful operation.
+ */
+ bool pasteClip2(QMimeSource* data);
+
+ /**
+ * If clipboard has mime type application/x-uml-clip3,
+ * pastes the data from the clipboard.
+ *
+ * @param data Pointer to the source clip.
+ * @return True for successful operation.
+ */
+ bool pasteClip3(QMimeSource* data);
+
+ /**
+ * If clipboard has mime type application/x-uml-clip4,
+ * pastes the data from the clipboard.
+ *
+ * @param data Pointer to the source clip.
+ * @return True for successful operation.
+ */
+ bool pasteClip4(QMimeSource* data);
+
+ /**
+ * If clipboard has mime type application/x-uml-clip5,
+ * pastes the data from the clipboard.
+ *
+ * @param data Pointer to the source clip.
+ * @return True for successful operation.
+ */
+ bool pasteClip5(QMimeSource* data);
+
+ /**
+ * When pasting widgets see if they can be pasted on
+ * different diagram types. Will return true if all the
+ * widgets to be pasted can be. At the moment this only
+ * includes NoteWidgets and lines of text.
+ *
+ * @param widgetList List of widgets to examine.
+ * @return True if all widgets can be put on different diagrams.
+ */
+ bool checkPasteWidgets(UMLWidgetList & widgetList);
+
+ UMLObjectList m_ObjectList;
+ UMLListViewItemList m_ItemList;
+ UMLWidgetList m_WidgetList;
+ AssociationWidgetList m_AssociationList;
+ UMLViewList m_ViewList;
+ UMLCopyType m_type; ///< Type of copy operation to perform.
+
+private:
+ /**
+ * Fills the member lists with all the objects and other
+ * stuff to be copied to the clipboard.
+ */
+ bool fillSelectionLists(UMLListViewItemList& SelectedItems);
+
+ /**
+ * Checks the whole list to determine the copy action
+ * type to be * performed, sets the type in the m_type
+ * member variable.
+ */
+ void setCopyType(UMLListViewItemList& SelectedItems);
+
+ /**
+ * Searches the child items of a UMLListViewItem to
+ * establish which Copy type is to be perfomed.
+ */
+ void checkItemForCopyType(UMLListViewItem* Item,
+ bool& WithDiagrams,
+ bool& WithObjects,
+ bool& OnlyAttsOps);
+
+ /**
+ * Adds the children of a UMLListViewItem to m_ItemList.
+ */
+ bool insertItemChildren(UMLListViewItem* Item,
+ UMLListViewItemList& SelectedItems);
+
+ /**
+ * Inserts the data of the children of the given item
+ * into the item data list. Used for clip type 4. Used
+ * to make * sure classes have all the attributes and
+ * operations saved.
+ */
+ bool insertItemChildren(UMLListViewItem* item);
+
+ /**
+ * Pastes the children of a UMLListViewItem (The Parent)
+ */
+ bool pasteChildren(UMLListViewItem* parent, IDChangeLog *chgLog);
+
+ /**
+ * Gives a `sorry' message box if you're pasting an item which
+ * already exists and can't be duplicated.
+ */
+ void pasteItemAlreadyExists();
+};
+
+#endif
diff --git a/umbrello/umbrello/clipboard/umldrag.cpp b/umbrello/umbrello/clipboard/umldrag.cpp
new file mode 100644
index 00000000..f9fa6629
--- /dev/null
+++ b/umbrello/umbrello/clipboard/umldrag.cpp
@@ -0,0 +1,773 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umldrag.h"
+
+// qt/kde includes
+#include <qdom.h>
+#include <kdebug.h>
+
+// local includes
+#include "idchangelog.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlview.h"
+#include "../umlobject.h"
+#include "../folder.h"
+#include "../classifier.h"
+#include "../umlwidget.h"
+#include "../umllistview.h"
+#include "../umllistviewitem.h"
+#include "../associationwidget.h"
+#include "../object_factory.h"
+#include "../model_utils.h"
+
+#define nfmt 4
+class UMLDragPrivate {
+public:
+ QCString fmt[nfmt];
+ QCString subtype;
+ QByteArray enc[nfmt];
+
+ UMLDragPrivate() {
+ setSubType("clip1", 0);
+ }
+
+ void setType(const QCString& st, int index) {
+ if (index < nfmt) {
+ fmt[index] = st.lower();
+ }
+ }
+
+ void setSubType(const QCString& st, int index) {
+ if (index < nfmt) {
+ subtype = st.lower();
+ fmt[index] = "application/x-uml-";
+ fmt[index].append(subtype);
+ }
+ }
+
+ const char* format(int i) const {
+ if(i < nfmt) {
+ return fmt[i];
+ }
+ return 0;
+ }
+};
+
+UMLDrag::UMLDrag(UMLObjectList& objects, QWidget* dragSource /*= 0*/, const char* name /*= 0*/)
+ : QDragObject(dragSource, name) {
+ data = new UMLDragPrivate;
+ setUMLDataClip1(objects);
+}
+
+UMLDrag::UMLDrag(UMLObjectList& objects, UMLListViewItemList& umlListViewItems, UMLViewList& diagrams,
+ QWidget* dragSource /*= 0*/, const char* name /*= 0*/ ): QDragObject(dragSource, name) {
+ data = new UMLDragPrivate;
+ setUMLDataClip2(objects, umlListViewItems, diagrams);
+}
+
+UMLDrag::UMLDrag(UMLListViewItemList& umlListViewItems, QWidget* dragSource /*= 0*/,
+ const char* name /*= 0*/ ): QDragObject(dragSource, name) {
+ data = new UMLDragPrivate;
+ setUMLDataClip3(umlListViewItems);
+}
+
+UMLDrag::UMLDrag(UMLObjectList& objects,
+ UMLWidgetList& widgets, AssociationWidgetList& associationDatas,
+ QPixmap& pngImage, Uml::Diagram_Type dType, QWidget * dragSource /*= 0*/,
+ const char * name /*= 0*/ ): QDragObject(dragSource, name) {
+ data = new UMLDragPrivate;
+ setUMLDataClip4(objects, widgets, associationDatas, pngImage, dType);
+}
+
+UMLDrag::UMLDrag(UMLObjectList& objects, int,
+ QWidget* /*dragSource = 0*/, const char* /*name = 0*/ ) {
+ data = new UMLDragPrivate;
+ setUMLDataClip5(objects);
+}
+
+UMLDrag::UMLDrag(QWidget* dragSource /*= 0*/, const char * name /*= 0*/ ): QDragObject(dragSource, name) {
+ data = new UMLDragPrivate;
+}
+
+UMLDrag::~UMLDrag() {
+ delete data;
+}
+
+void UMLDrag::setSubType(const QCString& string, int index) {
+ data->setSubType(string, index);
+}
+
+void UMLDrag::setEncodedData(const QByteArray& encodedData, int index) {
+ data->enc[index] = encodedData.copy();
+}
+
+QByteArray UMLDrag::encodedData(const char* dataName) const {
+ QString str(dataName);
+ for (int i = 0; i < 4; i++) {
+ if ( !qstricmp(dataName,data->fmt[i]) ) {
+ return data->enc[i];
+ }
+ }
+ return QByteArray();
+}
+
+const char* UMLDrag::format(int index) const {
+ char* result = (char*)data->format(index);
+ return result;
+}
+
+void UMLDrag::setUMLDataClip1(UMLObjectList& objects) {
+ setSubType("clip1", 0);
+
+ QDomDocument domDoc;
+ QDomElement xmiclip = domDoc.createElement("xmiclip");
+ domDoc.appendChild(xmiclip);
+ QDomElement objectsTag = domDoc.createElement("umlobjects");
+ xmiclip.appendChild(objectsTag);
+
+ UMLObjectListIt object_it(objects);
+ UMLObject* obj = 0;
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+ obj->saveToXMI(domDoc, objectsTag);
+ }
+
+ QDomElement itemsTag = domDoc.createElement("umllistviewitems");
+ xmiclip.appendChild(itemsTag);
+
+ setEncodedData(domDoc.toString().utf8(), 0);
+}
+
+void UMLDrag::setUMLDataClip2(UMLObjectList& objects, UMLListViewItemList& umlListViewItems,
+ UMLViewList& diagrams) {
+ setSubType("clip2", 0);
+
+ QDomDocument domDoc;
+ QDomElement xmiclip = domDoc.createElement("xmiclip");
+ domDoc.appendChild(xmiclip);
+ QDomElement objectsTag = domDoc.createElement("umlobjects");
+ xmiclip.appendChild(objectsTag);
+
+ UMLObjectListIt object_it(objects);
+ UMLObject* obj = 0;
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+ obj->saveToXMI(domDoc, objectsTag);
+ }
+
+ QDomElement viewsTag = domDoc.createElement("umlviews");
+ xmiclip.appendChild(viewsTag);
+
+ UMLViewListIt diagram_it(diagrams);
+ UMLView* view = 0;
+ while ( (view=diagram_it.current()) != 0 ) {
+ ++diagram_it;
+ view->saveToXMI(domDoc, viewsTag);
+ }
+
+ QDomElement itemsTag = domDoc.createElement("umllistviewitems");
+ xmiclip.appendChild(itemsTag);
+
+ UMLListViewItemListIt item_it2(umlListViewItems);
+ UMLListViewItem* item = 0;
+ while ( (item=item_it2.current()) != 0 ) {
+ ++item_it2;
+ item->saveToXMI(domDoc, itemsTag);
+ }
+ setEncodedData(domDoc.toString().utf8(), 0);
+}
+
+void UMLDrag::setUMLDataClip3(UMLListViewItemList& umlListViewItems) {
+ setSubType("clip3", 0);
+
+ QDomDocument domDoc;
+ QDomElement xmiclip = domDoc.createElement("xmiclip");
+ domDoc.appendChild(xmiclip);
+
+ QDomElement itemsTag = domDoc.createElement("umllistviewitems");
+ xmiclip.appendChild(itemsTag);
+
+ UMLListViewItemListIt item_it2(umlListViewItems);
+ UMLListViewItem* item = 0;
+ while ( (item=item_it2.current()) != 0 ) {
+ ++item_it2;
+ item->saveToXMI(domDoc, itemsTag);
+ }
+ setEncodedData(domDoc.toString().utf8(), 0);
+}
+
+void UMLDrag::setUMLDataClip4(UMLObjectList& objects, UMLWidgetList& widgets, AssociationWidgetList& associations,
+ QPixmap& pngImage, Uml::Diagram_Type dType ) {
+ setSubType("clip4", 0);
+
+ QDomDocument domDoc;
+ QDomElement xmiclip = domDoc.createElement("xmiclip");
+ xmiclip.setAttribute("diagramtype", dType);
+ domDoc.appendChild(xmiclip);
+ QDomElement objectsTag = domDoc.createElement("umlobjects");
+ xmiclip.appendChild(objectsTag);
+
+ UMLObjectListIt object_it(objects);
+ UMLObject* obj = 0;
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+ obj->saveToXMI(domDoc, objectsTag);
+ }
+
+ QDomElement widgetsTag = domDoc.createElement("widgets");
+ xmiclip.appendChild(widgetsTag);
+
+ UMLWidgetListIt widget_it(widgets);
+ UMLWidget* widget = 0;
+ while ( (widget=widget_it.current()) != 0 ) {
+ ++widget_it;
+ widget->saveToXMI(domDoc, widgetsTag);
+ }
+
+ QDomElement associationWidgetsTag = domDoc.createElement("associations");
+ xmiclip.appendChild(associationWidgetsTag);
+
+ AssociationWidgetListIt associations_it(associations);
+ AssociationWidget* association;
+ while ( (association=associations_it.current()) != 0 ) {
+ ++associations_it;
+ association->saveToXMI(domDoc, associationWidgetsTag);
+ }
+
+ QDomElement itemsTag = domDoc.createElement("umllistviewitems");
+ xmiclip.appendChild(itemsTag);
+
+ setEncodedData(domDoc.toString().utf8(), 0);
+
+ data->setType("image/PNG", 1);
+ long l_size = (pngImage.convertToImage()).numBytes();
+ QByteArray clipdata;
+ clipdata.resize(l_size);
+ QDataStream clipstream(clipdata, IO_WriteOnly);
+ clipstream << pngImage;
+ setEncodedData(clipdata, 1);
+}
+
+void UMLDrag::setUMLDataClip5(UMLObjectList& objects) {
+ setSubType("clip5", 0);
+
+ QDomDocument domDoc;
+ QDomElement xmiclip = domDoc.createElement("xmiclip");
+ domDoc.appendChild(xmiclip);
+ QDomElement objectsTag = domDoc.createElement("umlobjects");
+ xmiclip.appendChild(objectsTag);
+
+ UMLObjectListIt object_it(objects);
+ UMLObject* obj = 0;
+ while ( (obj=object_it.current()) != 0 ) {
+ ++object_it;
+ obj->saveToXMI(domDoc, objectsTag);
+ }
+
+ QDomElement itemsTag = domDoc.createElement("umllistviewitems");
+ xmiclip.appendChild(itemsTag);
+
+ setEncodedData(domDoc.toString().utf8(), 0);
+}
+
+bool UMLDrag::decodeClip1(const QMimeSource* mimeSource, UMLObjectList& objects) {
+ UMLDoc* doc = UMLApp::app()->getDocument();
+ if ( !mimeSource->provides("application/x-uml-clip1") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip1");
+ if ( !payload.size() ) {
+ return false;
+ }
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if ( root.tagName() != "xmiclip" ) {
+ return false;
+ }
+
+ UMLListView *listView = UMLApp::app()->getListView();
+
+ //UMLObjects
+ QDomNode objectsNode = xmiClipNode.firstChild();
+ QDomNode objectElement = objectsNode.firstChild();
+ QDomElement element = objectElement.toElement();
+ if ( element.isNull() ) {
+ return false;//return ok as it means there is no umlobjects
+ }
+ UMLObject* pObject = 0;
+ while ( !element.isNull() ) {
+ pObject = 0;
+ QString type = element.tagName();
+ if (type == "UML:Association") {
+ objectElement = objectElement.nextSibling();
+ element = objectElement.toElement();
+ continue;
+ }
+ pObject = Object_Factory::makeObjectFromXMI(type);
+
+ if( !pObject ) {
+ kWarning() << "UMLDrag::decodeClip1: Given wrong type of umlobject to create: "
+ << type << endl;
+ return false;
+ }
+ pObject->setInPaste( true );
+ if( !pObject->loadFromXMI( element ) ) {
+ kWarning() << "UMLDrag::decodeClip1: failed to load object of type "
+ << type << " from XMI" << endl;
+ delete pObject;
+ return false;
+ }
+ pObject->setInPaste( false );
+ if (listView->startedCopy()) {
+ /****************************************************************
+ * If the clone() methods called IDChangeLog::addIDChange(),
+ * we could do the following:
+ UMLObject *newObj = pObject->clone();
+ delete pObject;
+ pObject = newObj;
+ * but since that's not currently the case we do: */
+ if(!doc->assignNewIDs(pObject)) {
+ return false;
+ }
+ Uml::Object_Type type = pObject->getBaseType();
+ QString newName = Model_Utils::uniqObjectName(type, pObject->getUMLPackage(),
+ pObject->getName());
+ pObject->setName(newName);
+ /****************************************************************/
+ }
+
+ pObject->resolveRef();
+
+ objects.append(pObject);
+ objectElement = objectElement.nextSibling();
+ element = objectElement.toElement();
+ }
+
+ return true;
+}
+
+bool UMLDrag::decodeClip2(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLListViewItemList& umlListViewItems, UMLViewList& diagrams) {
+
+ if ( !mimeSource->provides("application/x-uml-clip2") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip2");
+ if ( !payload.size() ) {
+ return false;
+ }
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if ( root.tagName() != "xmiclip" ) {
+ return false;
+ }
+
+ //UMLObjects
+ QDomNode objectsNode = xmiClipNode.firstChild();
+ QDomNode objectElement = objectsNode.firstChild();
+ QDomElement element = objectElement.toElement();
+ if ( element.isNull() ) {
+ return false;//return ok as it means there is no umlobjects
+ }
+ UMLObject* pObject = 0;
+ while ( !element.isNull() ) {
+ pObject = 0;
+ QString type = element.tagName();
+ if (type != "UML:Association") {
+ pObject = Object_Factory::makeObjectFromXMI(type);
+
+ if( !pObject ) {
+ kWarning() << "Given wrong type of umlobject to create:" << type << endl;
+ return false;
+ }
+ if( !pObject->loadFromXMI(element) ) {
+ kWarning() << "failed to load object from XMI" << endl;
+ return false;
+ }
+ objects.append(pObject);
+ }
+ objectElement = objectElement.nextSibling();
+ element = objectElement.toElement();
+ }
+
+ //UMLViews (diagrams)
+ QDomNode umlviewsNode = objectsNode.nextSibling();
+ QDomNode diagramNode = umlviewsNode.firstChild();
+ QDomElement diagramElement = diagramNode.toElement();
+ if ( diagramElement.isNull() ) {
+ kWarning() << "no diagrams in XMI clip" << endl;
+ return false;
+ }
+ UMLListView *listView = UMLApp::app()->getListView();
+ while ( !diagramElement.isNull() ) {
+ QString type = diagramElement.attribute("type", "0");
+ Uml::Diagram_Type dt = (Uml::Diagram_Type)type.toInt();
+ UMLListViewItem *parent = listView->findFolderForDiagram(dt);
+ if (parent == NULL)
+ return false;
+ UMLObject *po = parent->getUMLObject();
+ if (po == NULL || po->getBaseType() != Uml::ot_Folder) {
+ kError() << "UMLDrag::decodeClip2: bad parent for view" << endl;
+ return false;
+ }
+ UMLFolder *f = static_cast<UMLFolder*>(po);
+ UMLView* view = new UMLView(f);
+ view->loadFromXMI(diagramElement);
+ diagrams.append(view);
+ diagramNode = diagramNode.nextSibling();
+ diagramElement = diagramNode.toElement();
+ }
+
+ //listviewitems
+ QDomNode listItemNode = umlviewsNode.nextSibling();
+ QDomNode listItems = listItemNode.firstChild();
+ QDomElement listItemElement = listItems.toElement();
+ if ( listItemElement.isNull() ) {
+ kWarning() << "no listitems in XMI clip" << endl;
+ return false;
+ }
+ UMLListViewItem *currentItem = (UMLListViewItem*)listView->currentItem();
+ while ( !listItemElement.isNull() ) {
+ UMLListViewItem* itemData;
+ if (currentItem)
+ itemData = new UMLListViewItem( currentItem );
+ else
+ itemData = new UMLListViewItem( listView );
+ if ( itemData->loadFromXMI(listItemElement) )
+ umlListViewItems.append(itemData);
+ else
+ delete itemData;
+ listItems = listItems.nextSibling();
+ listItemElement = listItems.toElement();
+ }
+ return true;
+}
+
+bool UMLDrag::getClip3TypeAndID(const QMimeSource* mimeSource,
+ LvTypeAndID_List& typeAndIdList)
+{
+ if ( !mimeSource->provides("application/x-uml-clip3") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip3");
+ if ( !payload.size() ) {
+ return false;
+ }
+ QTextStream clipdata(payload, IO_ReadOnly);
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "getClip3Type: Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if (root.tagName() != "xmiclip") {
+ return false;
+ }
+
+ QDomNode listItemNode = xmiClipNode.firstChild();
+ QDomNode listItems = listItemNode.firstChild();
+ QDomElement listItemElement = listItems.toElement();
+ if ( listItemElement.isNull() ) {
+ kWarning() << "getClip3Type: no listitems in XMI clip" << endl;
+ return false;
+ }
+ while ( !listItemElement.isNull() ) {
+ QString typeStr = listItemElement.attribute( "type", "-1" );
+ if (typeStr == "-1") {
+ kDebug() << "getClip3Type: bad type" << endl;
+ return false;
+ }
+ QString idStr = listItemElement.attribute( "id", "-1" );
+ if (idStr == "-1") {
+ kDebug() << "getClip3Type: bad id" << endl;
+ return false;
+ }
+ LvTypeAndID * pData = new LvTypeAndID;
+ pData->type = (Uml::ListView_Type)(typeStr.toInt());
+ pData->id = STR2ID(idStr);
+ typeAndIdList.append(pData);
+ listItems = listItems.nextSibling();
+ listItemElement = listItems.toElement();
+ }
+ return true;
+}
+
+bool UMLDrag::decodeClip3(const QMimeSource* mimeSource, UMLListViewItemList& umlListViewItems,
+ const UMLListView* parentListView){
+ if ( !mimeSource->provides("application/x-uml-clip3") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip3");
+ if ( !payload.size() ) {
+ return false;
+ }
+ QTextStream clipdata(payload, IO_ReadOnly);
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if (root.tagName() != "xmiclip") {
+ return false;
+ }
+
+ //listviewitems
+ QDomNode listItemNode = xmiClipNode.firstChild();
+ QDomNode listItems = listItemNode.firstChild();
+ QDomElement listItemElement = listItems.toElement();
+ if ( listItemElement.isNull() ) {
+ kWarning() << "no listitems in XMI clip" << endl;
+ return false;
+ }
+ while ( !listItemElement.isNull() ) {
+ // Get the ListView_Type beforehand so that we can construct an
+ // UMLListViewItem instance.
+ QString type = listItemElement.attribute( "type", "-1" );
+ if (type == "-1") {
+ kDebug() << "Pech gehabt" << endl;
+ continue;
+ }
+ Uml::ListView_Type t = (Uml::ListView_Type)(type.toInt());
+ UMLListViewItem* parent = parentListView->determineParentItem(t);
+ UMLListViewItem* itemData = new UMLListViewItem(parent);
+ if ( itemData->loadFromXMI(listItemElement) )
+ umlListViewItems.append(itemData);
+ else
+ delete itemData;
+ listItems = listItems.nextSibling();
+ listItemElement = listItems.toElement();
+ }
+ return true;
+}
+
+bool UMLDrag::decodeClip4(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLWidgetList& widgets,
+ AssociationWidgetList& associations, Uml::Diagram_Type & dType) {
+ if ( !mimeSource->provides("application/x-uml-clip4") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip4");
+ if ( !payload.size() ) {
+ return false;
+ }
+
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if ( root.tagName() != "xmiclip" ) {
+ return false;
+ }
+
+ dType = (Uml::Diagram_Type)(root.attribute("diagramtype", "0").toInt());
+
+ //UMLObjects
+ QDomNode objectsNode = xmiClipNode.firstChild();
+ QDomNode objectElement = objectsNode.firstChild();
+ QDomElement element = objectElement.toElement();
+ while ( !element.isNull() ) {
+ UMLObject* pObject = 0;
+ QString type = element.tagName();
+ //FIXME associations don't load
+ if (type == "UML:Association")
+ continue;
+ pObject = Object_Factory::makeObjectFromXMI(type);
+
+ if ( !pObject ) {
+ kWarning() << "Given wrong type of umlobject to create: " << type << endl;
+ return false;
+ }
+
+ if ( !pObject->loadFromXMI( element ) ) {
+ kWarning() << "failed to load object from XMI" << endl;
+ return false;
+ }
+
+ objects.append(pObject);
+ objectElement = objectElement.nextSibling();
+ element = objectElement.toElement();
+ }
+
+ //widgets
+ QDomNode widgetsNode = objectsNode.nextSibling();
+ QDomNode widgetNode = widgetsNode.firstChild();
+ QDomElement widgetElement = widgetNode.toElement();
+ if ( widgetElement.isNull() ) {
+ kWarning() << "no widgets in XMI clip" << endl;
+ return false;
+ }
+
+ UMLView *view = UMLApp::app()->getCurrentView();
+ while ( !widgetElement.isNull() ) {
+
+ UMLWidget* widget = view->loadWidgetFromXMI(widgetElement);
+ if (widget)
+ widgets.append(widget);
+
+ widgetNode = widgetNode.nextSibling();
+ widgetElement = widgetNode.toElement();
+ }
+
+ //AssociationWidgets
+ QDomNode associationWidgetsNode = widgetsNode.nextSibling();
+ QDomNode associationWidgetNode = associationWidgetsNode.firstChild();
+ QDomElement associationWidgetElement = associationWidgetNode.toElement();
+ while ( !associationWidgetElement.isNull() ) {
+ AssociationWidget* associationWidget = new AssociationWidget(view);
+ if (associationWidget->loadFromXMI(associationWidgetElement, widgets))
+ associations.append(associationWidget);
+ else {
+ //associationWidget->cleanup();
+ delete associationWidget;
+ }
+ associationWidgetNode = associationWidgetNode.nextSibling();
+ associationWidgetElement = associationWidgetNode.toElement();
+ }
+
+ return true;
+}
+
+bool UMLDrag::decodeClip5(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLClassifier* newParent) {
+ if ( !mimeSource->provides("application/x-uml-clip5") ) {
+ return false;
+ }
+ QByteArray payload = mimeSource->encodedData("application/x-uml-clip5");
+ if ( !payload.size() ) {
+ return false;
+ }
+ QString xmiClip = QString::fromUtf8(payload);
+
+ QString error;
+ int line;
+ QDomDocument domDoc;
+ if( !domDoc.setContent(xmiClip, false, &error, &line) ) {
+ kWarning() << "Can't set content:" << error << " Line:" << line << endl;
+ return false;
+ }
+ QDomNode xmiClipNode = domDoc.firstChild();
+ QDomElement root = xmiClipNode.toElement();
+ if ( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI clip
+ if (root.tagName() != "xmiclip") {
+ return false;
+ }
+
+ //UMLObjects
+ QDomNode objectsNode = xmiClipNode.firstChild();
+ QDomNode objectElement = objectsNode.firstChild();
+ QDomElement element = objectElement.toElement();
+ if ( element.isNull() ) {
+ return false;//return ok as it means there is no umlobjects
+ }
+ while ( !element.isNull() ) {
+ QString type = element.tagName();
+ UMLClassifierListItem *pObject = newParent->makeChildObject(type);
+ if( !pObject ) {
+ kWarning() << "Given wrong type of umlobject to create:" << type << endl;
+ return false;
+ }
+ if( !pObject->loadFromXMI( element ) ) {
+ kWarning() << "failed to load object from XMI" << endl;
+ return false;
+ }
+ pObject->resolveRef();
+ objects.append(pObject);
+ objectElement = objectElement.nextSibling();
+ element = objectElement.toElement();
+ }
+
+ return true;
+}
+
+int UMLDrag::getCodingType(const QMimeSource* mimeSource) {
+ int result = 0;
+ if (mimeSource->provides("application/x-uml-clip1") ) {
+ result = 1;
+ }
+ if (mimeSource->provides("application/x-uml-clip2") ) {
+ result = 2;
+ }
+ if (mimeSource->provides("application/x-uml-clip3") ) {
+ result = 3;
+ }
+ if (mimeSource->provides("application/x-uml-clip4") ) {
+ result = 4;
+ }
+ if (mimeSource->provides("application/x-uml-clip5") ) {
+ result = 5;
+ }
+
+ return result;
+}
+
+#include "umldrag.moc"
diff --git a/umbrello/umbrello/clipboard/umldrag.h b/umbrello/umbrello/clipboard/umldrag.h
new file mode 100644
index 00000000..a56a138e
--- /dev/null
+++ b/umbrello/umbrello/clipboard/umldrag.h
@@ -0,0 +1,223 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLDRAG_H
+#define UMLDRAG_H
+
+#include <qdragobject.h>
+#include <qobject.h>
+#include <qptrlist.h>
+
+#include "../umllistviewitemlist.h"
+#include "../associationwidgetlist.h"
+#include "../umlobjectlist.h"
+#include "../umlviewlist.h"
+#include "../umlwidgetlist.h"
+#include "../umlnamespace.h"
+
+/**
+ * This class provides encoding and decoding for the uml data that will be used
+ * in a drag and drop operation or in a copy or paste operation.
+ *
+ * @author Gustavo Madrigal, Jonathan Riddell (XMI conversion)
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLListView;
+class UMLDragPrivate;
+class UMLClassifier;
+
+class Q_EXPORT UMLDrag : public QDragObject {
+ Q_OBJECT
+ UMLDragPrivate* data;
+public:
+
+ /**
+ * For use when the user selects only UML Objects from
+ * the ListView but no diagrams to be copied, Mime type =
+ * "application/x-uml-clip1
+ */
+ explicit UMLDrag(UMLObjectList& Objects,QWidget* dragSource = 0, const char* name = 0 );
+
+ /**
+ * For use when the user selects UML Object and Diagrams
+ * from the ListView to be copied, Mime type =
+ * "application/x-uml-clip2
+ */
+ UMLDrag(UMLObjectList &Objects, UMLListViewItemList& UMLListViewItems,
+ UMLViewList& Diagrams, QWidget * dragSource = 0, const char * name = 0 );
+
+ /**
+ * For use when the user selects only empty folders from
+ * the ListView to be copied, Mime type =
+ * "application/x-uml-clip3
+ */
+ explicit UMLDrag(UMLListViewItemList& UMLListViewItems, QWidget* dragSource = 0,
+ const char* name = 0 );
+
+ /*
+ * For use when the user selects UMLObjects from a
+ * Diagram. The Selected widegets and the relationships *
+ * between only selected widgets will be copied and also
+ * its respective ListView Items, Mime type =
+ * "application/x-uml-clip4
+ */
+ UMLDrag(UMLObjectList& Objects, UMLWidgetList& Widgets, AssociationWidgetList& Associations,
+ QPixmap& PngImage, Uml::Diagram_Type dType, QWidget* dragSource = 0,
+ const char* name = 0 );
+
+ /**
+ * For use when the user selects only Operations and/or
+ * Attributes from the ListView, Mime type =
+ * "application/x-uml-clip5
+ */
+ UMLDrag(UMLObjectList& Objects, int, QWidget* dragSource = 0, const char* name = 0);
+
+ /**
+ * Constructor
+ */
+ explicit UMLDrag(QWidget* dragSource = 0, const char* name = 0);
+
+ /**
+ * Deconstructor
+ */
+ ~UMLDrag();
+
+ /**
+ * For use when the user selects only UMLObjects from the
+ * ListView but no diagrams to be copied
+ */
+ void setUMLDataClip1(UMLObjectList& Objects);
+
+ /**
+ * For use when the user selects UML Object and Diagrams
+ * from the ListView to be copied
+ */
+ void setUMLDataClip2(UMLObjectList& Objects, UMLListViewItemList& UMLListViewItems,
+ UMLViewList& Diagrams);
+
+ /**
+ * For use when the user selects only empty folders from the ListView
+ * to be copied.
+ */
+ void setUMLDataClip3(UMLListViewItemList& UMLListViewItems);
+
+ /**
+ * For use when the user selects UML Objects from a
+ * Diagram. The Selected widegets and the relationships
+ * between only selected widgets will be copied and also
+ * its respective ListView Items
+ */
+ void setUMLDataClip4(UMLObjectList& Objects,
+ UMLWidgetList& WidgetDatas,
+ AssociationWidgetList& Associations, QPixmap& PngImage,
+ Uml::Diagram_Type dType);
+
+ /**
+ * For use when the user selects only Attirbutes and/or
+ * Operation from the ListView
+ */
+ void setUMLDataClip5(UMLObjectList& Objects);
+
+ /**
+ * Sets the type of the clip to "application/x-uml-" + sub
+ * sub should be clip[1-5]
+ */
+ virtual void setSubType(const QCString& sub, int index);
+
+ /**
+ * Sets the data in the clip
+ */
+ virtual void setEncodedData(const QByteArray&, int index);
+
+ /**
+ * Returns the type set by setSubType
+ */
+ const char* format(int index) const;
+
+ /**
+ * Returns the encoded data of the given type
+ *
+ * @param dataName the name of the data type to return
+ */
+ virtual QByteArray encodedData(const char* dataName) const;
+
+ /**
+ * For use when the user selects only UML Objects
+ * from the ListView but no diagrams to be
+ * copied, decodes Mime type =
+ * "application/x-uml-clip1
+ */
+ static bool decodeClip1(const QMimeSource* mimeSource, UMLObjectList& objects);
+
+ /**
+ * For use when the user selects UML Object and Diagrams
+ * from the ListView to be copied, decodes Mime type =
+ * "application/x-uml-clip2
+ */
+ static bool decodeClip2(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLListViewItemList& umlListViewItems,
+ UMLViewList& diagrams);
+
+ /**
+ * For use when the user selects UMLObjects from
+ * the ListView to be copied, decodes Mime * type =
+ * "application/x-uml-clip3
+ */
+ static bool decodeClip3(const QMimeSource* mimeSource,
+ UMLListViewItemList& umlListViewItems,
+ const UMLListView* parentListView=0);
+
+ struct LvTypeAndID {
+ Uml::ListView_Type type;
+ Uml::IDType id;
+ };
+ typedef QPtrList<LvTypeAndID> LvTypeAndID_List;
+ typedef QPtrListIterator<LvTypeAndID> LvTypeAndID_It;
+
+ /**
+ * Return just the LvTypeAndID of a Clip3.
+ *
+ * @param mimeSource The encoded source.
+ * @param typeAndIdList The LvTypeAndID_List decoded from the source.
+ * @return True if decoding was successful.
+ */
+ static bool getClip3TypeAndID(const QMimeSource* mimeSource,
+ LvTypeAndID_List& typeAndIdList);
+
+ /**
+ * For use when the user selects UML Objects from a
+ * Diagram. The Selected widegets and the relationships
+ * between only * selected widgets will be copied and
+ * also its respective ListView Items, * decodes Mime
+ * type = "application/x-uml-clip4
+ */
+ static bool decodeClip4(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLWidgetList& widgets,
+ AssociationWidgetList& associations,
+ Uml::Diagram_Type & dType);
+
+ /**
+ * For use when the user selects only Attributes and/or
+ * Operations from the ListView * copied, decodes Mime
+ * type = "application/x-uml-clip5
+ */
+ static bool decodeClip5(const QMimeSource* mimeSource, UMLObjectList& objects,
+ UMLClassifier *newParent);
+
+ /**
+ * Converts application/x-uml-clip[1-5] clip type to an integer
+ */
+ static int getCodingType(const QMimeSource* mimeSource);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/cmdlineexportallviewsevent.cpp b/umbrello/umbrello/cmdlineexportallviewsevent.cpp
new file mode 100644
index 00000000..7c4b3caa
--- /dev/null
+++ b/umbrello/umbrello/cmdlineexportallviewsevent.cpp
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cmdlineexportallviewsevent.h"
+
+// qt includes
+#include <qstringlist.h>
+
+// kde includes
+#include <kapplication.h>
+#include <kdebug.h>
+
+// app includes
+#include "uml.h"
+#include "umlviewimageexportermodel.h"
+
+
+int CmdLineExportAllViewsEvent::getType() {
+ return QEvent::User + 1;
+}
+
+CmdLineExportAllViewsEvent::CmdLineExportAllViewsEvent(const QString &imageType, const KURL &directory, const bool useFolders)
+ : QCustomEvent(CmdLineExportAllViewsEvent::getType()) {
+ m_imageType = imageType;
+ m_directory = directory;
+ m_useFolders = useFolders;
+}
+
+void CmdLineExportAllViewsEvent::exportAllViews() {
+ QStringList errors = UMLViewImageExporterModel().exportAllViews(m_imageType, m_directory, m_useFolders);
+ if (!errors.isEmpty()) {
+ kError() << "Errors while exporting:" << endl;
+ for (QStringList::Iterator it = errors.begin(); it != errors.end(); ++it) {
+ kError() << *it << endl;
+ }
+ }
+
+ kapp->sendEvent(UMLApp::app(), new QCloseEvent());
+}
diff --git a/umbrello/umbrello/cmdlineexportallviewsevent.h b/umbrello/umbrello/cmdlineexportallviewsevent.h
new file mode 100644
index 00000000..8c613bee
--- /dev/null
+++ b/umbrello/umbrello/cmdlineexportallviewsevent.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CMDLINEEXPORTALLVIEWSEVENT_H
+#define CMDLINEEXPORTALLVIEWSEVENT_H
+
+#include <qevent.h>
+#include <kurl.h>
+
+/**
+ * This class provides an event that is posted to the UMLApp when the "export all views"
+ * option was set in the command line. Once the QT main loop begins, the event is processed.
+ *
+ * The processing made in UMLApp is execute the exportAllViews method in the event.
+ * This method exports all the views using UMLViewImageExporterModel and then finishes
+ * the application using a close event.
+ *
+ * @see UMLViewImageExporterModel
+ */
+class CmdLineExportAllViewsEvent : public QCustomEvent {
+public:
+
+ /**
+ * Returns the type of the event.
+ */
+ static int getType();
+
+ /**
+ * Constructor for CmdLineExportAllViewsEvent.
+ *
+ * @param imageType The type of the images the views will be exported to.
+ * @param directory The url of the directory where the images will be saved.
+ * @param useFolders If the tree structure of the views in the document must be created
+ * in the target directory.
+ */
+ CmdLineExportAllViewsEvent(const QString &imageType, const KURL &directory, const bool useFolders);
+
+ /**
+ * Destructor for CmdLineExportAllViewsEvent
+ */
+ virtual ~CmdLineExportAllViewsEvent() {
+ }
+
+ /**
+ * Exports all the views using UMLViewImageExporterModel, prints the errors
+ * occurred in the error output and sends a close event to the application to finish it.
+ * To export the views, it uses the attributes set when the event was created.
+ */
+ void exportAllViews();
+
+private:
+
+ /**
+ * The type of the images the views will be exported to.
+ */
+ QString m_imageType;
+
+ /**
+ * The url of the directory where the images will be saved.
+ */
+ KURL m_directory;
+
+ /**
+ * If the tree structure of the views in the document must be created
+ * in the target directory.
+ */
+ bool m_useFolders;
+};
+
+#endif
diff --git a/umbrello/umbrello/codeaccessormethod.cpp b/umbrello/umbrello/codeaccessormethod.cpp
new file mode 100644
index 00000000..329bef51
--- /dev/null
+++ b/umbrello/umbrello/codeaccessormethod.cpp
@@ -0,0 +1,195 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jul 1 2003
+ */
+
+// own header
+#include "codeaccessormethod.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "classifiercodedocument.h"
+#include "codeclassfield.h"
+#include "attribute.h"
+#include "umlobject.h"
+#include "umlrole.h"
+
+// Constructors/Destructors
+//
+
+CodeAccessorMethod::CodeAccessorMethod ( CodeClassField * parentCF )
+ : CodeMethodBlock ( parentCF->getParentDocument(), parentCF->getParentObject() )
+{
+ initFields(parentCF);
+}
+
+CodeAccessorMethod::~CodeAccessorMethod ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+/**
+ * Get the value of m_parentclassfield
+ * @return the value of m_parentclassfield
+ */
+CodeClassField * CodeAccessorMethod::getParentClassField ( ) {
+ return m_parentclassfield;
+}
+
+bool CodeAccessorMethod::parentIsAttribute( ) {
+ return getParentClassField()->parentIsAttribute();
+}
+
+/**
+ * Utility method to get the value of the parent object of the parent classifield.
+ * @return the value of the parent of the parent classfield
+ */
+/*
+UMLObject * CodeAccessorMethod::getParentObject ( ) {
+ return getParentClassField()->getParentObject();
+}
+*/
+
+/** return the type of accessor method this is
+ */
+CodeAccessorMethod::AccessorType CodeAccessorMethod::getType( ) {
+ return m_accessorType;
+}
+
+/** Set the type of accessor method this is
+ */
+void CodeAccessorMethod::setType ( CodeAccessorMethod::AccessorType atype) {
+ m_accessorType = atype;
+}
+
+// Other methods
+//
+
+
+// this type of textblock is special
+// we DON'T release it when resetTextBlocks is
+// called because we re-use it over and over
+// until the codeclassfield is released.
+void CodeAccessorMethod::release () {
+ // do nothing
+}
+
+// ok, a method so the parent can force it to release
+void CodeAccessorMethod::forceRelease () {
+ if(m_parentclassfield)
+ m_parentclassfield->disconnect(this);
+ CodeMethodBlock::release();
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeAccessorMethod::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeAccessorMethod::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement docElement = doc.createElement( "codeaccessormethod" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void CodeAccessorMethod::setAttributesOnNode ( QDomDocument & doc, QDomElement & elem)
+{
+
+ // set super-class attributes
+ CodeMethodBlock::setAttributesOnNode(doc, elem);
+
+ // set local class attributes
+ elem.setAttribute("accessType",getType());
+ elem.setAttribute("classfield_id",getParentClassField()->getID());
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeAccessorMethod::setAttributesFromNode ( QDomElement & root) {
+
+ // set attributes from the XMI
+ CodeMethodBlock::setAttributesFromNode(root); // superclass load
+
+ /*
+ // I don't believe this is needed for a load from XMI. We never delete
+ // accessor methods from the parent classfield.. they are essentially
+ // in composition with the parent class and are arent meant to be out
+ // on their own. Well, this is fine for now, but IF we start allowing
+ // clipping and pasting of these methods between classes/ classfields
+ // then we may have problems (ugh.. I cant imagine allowing this, but
+ // perhaps someone will see a need to allow it. -b.t.)
+ QString id = root.attribute("classfield_id","-1");
+ CodeClassField * newCF = 0;
+ ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ if(cdoc)
+ newCF = cdoc->findCodeClassFieldFromParentID (STR2ID(id));
+
+ m_parentclassfield->disconnect(this); // always disconnect
+ if(newCF)
+ initFields(newCF);
+ else
+ kError()<<"ERROR: code accessor method cant load parent codeclassfield, corrupt file?"<<endl;
+
+ */
+ // now load/set other local attributes
+ setType((AccessorType) root.attribute("accessType","0").toInt());
+
+}
+
+void CodeAccessorMethod::setAttributesFromObject(TextBlock * obj)
+{
+
+ CodeMethodBlock::setAttributesFromObject(obj);
+
+ CodeAccessorMethod * mb = dynamic_cast<CodeAccessorMethod*>(obj);
+ if(mb)
+ {
+ m_parentclassfield->disconnect(this); // always disconnect
+
+ initFields(mb->getParentClassField());
+
+ setType(mb->getType());
+ }
+
+}
+
+void CodeAccessorMethod::initFields(CodeClassField * parentClassField ) {
+
+ m_parentclassfield = parentClassField;
+ m_accessorType = GET;
+ m_canDelete = false; // we cant delete these with the codeeditor, delete the UML operation instead.
+
+ connect(m_parentclassfield,SIGNAL(modified()),this,SLOT(syncToParent()));
+}
+
+#include "codeaccessormethod.moc"
diff --git a/umbrello/umbrello/codeaccessormethod.h b/umbrello/umbrello/codeaccessormethod.h
new file mode 100644
index 00000000..03e8ff67
--- /dev/null
+++ b/umbrello/umbrello/codeaccessormethod.h
@@ -0,0 +1,118 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jul 1 2003
+ */
+
+
+
+#ifndef CODEACCESSORMETHOD_H
+#define CODEACCESSORMETHOD_H
+
+#include <qstring.h>
+#include "codemethodblock.h"
+
+class CodeClassField;
+
+class CodeAccessorMethod : public CodeMethodBlock
+{
+ friend class CodeClassField;
+ Q_OBJECT
+public:
+
+ // some types of accessor methods that are possible:
+ // "GET" is to retrieve single-valued (primative or Object) fields
+ // "SET" is to set single-valued (primative or Object) fields
+ // "ADD" is to add a value to a multiple-valued field of either primative or Object items
+ // "REMOVE" is to remove a value to a multiple-valued field of either primative or Object items
+ // "LIST" is to retrive the entire list of items in a multiple-valued field
+ enum AccessorType {GET=0, SET, ADD, REMOVE, LIST};
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ CodeAccessorMethod ( CodeClassField * field );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeAccessorMethod ( );
+
+ /**
+ * Get the value of m_parentclassfield
+ * @return the value of m_parentclassfield
+ */
+ CodeClassField * getParentClassField ( );
+
+ /** return the type of accessor method this is
+ */
+ AccessorType getType( );
+
+ /** Set the type of accessor method this is
+ */
+ void setType ( AccessorType type);
+
+ /** Utility method to get the value of the parent object of the parent classifield.
+ */
+ // virtual UMLObject * getParentObject();
+
+ bool parentIsAttribute();
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+protected:
+
+ virtual void release ();
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ virtual void updateMethodDeclaration() = 0;
+
+ virtual void updateContent() = 0;
+
+ // a method so the parent code classfield can force code block to release
+ void forceRelease ();
+
+private:
+
+ CodeClassField * m_parentclassfield;
+ AccessorType m_accessorType;
+
+ void initFields(CodeClassField * parentCF );
+
+};
+
+#endif // CODEACCESSORMETHOD_H
diff --git a/umbrello/umbrello/codeaccessormethodlist.h b/umbrello/umbrello/codeaccessormethodlist.h
new file mode 100644
index 00000000..96693f2f
--- /dev/null
+++ b/umbrello/umbrello/codeaccessormethodlist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef _CODEACCESSORMETHODLIST_H
+#define _CODEACCESSORMETHODLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class CodeAccessorMethod;
+
+typedef QPtrList<CodeAccessorMethod> CodeAccessorMethodList;
+typedef QPtrListIterator<CodeAccessorMethod> CodeAccessorMethodListIt;
+
+#endif
diff --git a/umbrello/umbrello/codeblock.cpp b/umbrello/umbrello/codeblock.cpp
new file mode 100644
index 00000000..d1705348
--- /dev/null
+++ b/umbrello/umbrello/codeblock.cpp
@@ -0,0 +1,143 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+#include "codeblock.h"
+#include "codedocument.h"
+
+#include "hierarchicalcodeblock.h"
+
+// Constructors/Destructors
+//
+
+CodeBlock::CodeBlock ( HierarchicalCodeBlock * hblock , const QString & body )
+ : TextBlock ( hblock->getParentDocument(), body )
+{
+ initFields ( );
+}
+
+CodeBlock::CodeBlock ( CodeDocument * doc, const QString & body )
+ : TextBlock ( doc, body )
+{
+ initFields( );
+}
+
+CodeBlock::~CodeBlock ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+
+/**
+ * Set the value of m_contentType
+ * specifies whether the content (text) of this object was generated by the code
+ * generator or was supplied by the user.
+ * @param new_var the new value of m_contentType
+ */
+void CodeBlock::setContentType ( ContentType new_var ) {
+ m_contentType = new_var;
+}
+
+/**
+ * Get the value of m_contentType
+ * specifies whether the content (text) of this object was generated by the code
+ * generator or was supplied by the user.
+ * @return the value of m_contentType
+ */
+CodeBlock::ContentType CodeBlock::getContentType ( ) {
+ return m_contentType;
+}
+
+/**
+ * Get the value of m_dialog
+ * @return the value of m_dialog
+ */
+/*
+CodeBlockDialog * CodeBlock::getDialog ( ) {
+ return m_dialog;
+}
+*/
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "codeblock" );
+
+ // set attributes
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+void CodeBlock::setAttributesOnNode( QDomDocument & doc, QDomElement & blockElement)
+{
+
+ // call super-class
+ TextBlock::setAttributesOnNode(doc, blockElement);
+
+ // local attributes
+ if(m_contentType != AutoGenerated)
+ blockElement.setAttribute("contentType",getContentType());
+
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeBlock::loadFromXMI ( QDomElement & root ) {
+
+ setAttributesFromNode(root);
+
+}
+
+void CodeBlock::setAttributesFromNode (QDomElement & elem) {
+
+ // set attributes from the XMI in super-class
+ TextBlock::setAttributesFromNode(elem);
+
+ // set local fields now
+ setContentType(((ContentType) elem.attribute("contentType","0").toInt()));
+
+}
+
+void CodeBlock::setAttributesFromObject(TextBlock * obj)
+{
+
+ TextBlock::setAttributesFromObject(obj);
+
+ CodeBlock * cb = dynamic_cast<CodeBlock*>(obj);
+ if(cb)
+ setContentType(cb->getContentType());
+
+}
+
+void CodeBlock::initFields ( ) {
+ m_contentType = AutoGenerated;
+ // m_dialog = new CodeBlockDialog( );
+}
+
+#include "codeblock.moc"
diff --git a/umbrello/umbrello/codeblock.h b/umbrello/umbrello/codeblock.h
new file mode 100644
index 00000000..c01b6c9f
--- /dev/null
+++ b/umbrello/umbrello/codeblock.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+
+#ifndef CODEBLOCK_H
+#define CODEBLOCK_H
+
+
+#include "textblock.h"
+
+class HierarchicalCodeBlock;
+
+
+/**
+ * class CodeBlock
+ * A "chunk" of code within the code document.
+ */
+
+class CodeBlock : public TextBlock
+{
+ Q_OBJECT
+public:
+
+ enum ContentType {AutoGenerated=0, UserGenerated };
+
+ // Constructors/Destructors
+ //
+
+ /** constructor with QString so we can create & populate it in
+ * one step.
+ */
+ explicit CodeBlock ( CodeDocument * parent, const QString & body = "");
+ explicit CodeBlock ( HierarchicalCodeBlock * parent, const QString & body = "" );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeBlock ( );
+
+ // Public attributes
+ //
+
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_contentType
+ * specifies whether the content (text) of this object was generated by the code
+ * generator or was supplied by the user.
+ * @param new_var the new value of m_contentType
+ */
+ void setContentType ( ContentType new_var );
+
+ /**
+ * Get the value of m_contentType
+ * specifies whether the content (text) of this object was generated by the code
+ * generator or was supplied by the user.
+ * @return the value of m_contentType
+ */
+ ContentType getContentType ( );
+
+ /**
+ * Get the value of m_dialog
+ * @return the value of m_dialog
+ */
+ // CodeBlockDialog getDialog ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+private:
+
+ // CodeBlockDialog * m_dialog;
+
+ // specifies whether the content (text) of this object
+ // was generated by the code generator or was supplied by the user (or some other way).
+ ContentType m_contentType;
+
+ void initFields ( );
+
+};
+
+#endif // CODEBLOCK_H
diff --git a/umbrello/umbrello/codeblockwithcomments.cpp b/umbrello/umbrello/codeblockwithcomments.cpp
new file mode 100644
index 00000000..0e94001f
--- /dev/null
+++ b/umbrello/umbrello/codeblockwithcomments.cpp
@@ -0,0 +1,181 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+// own header
+#include "codeblockwithcomments.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "codedocument.h"
+#include "hierarchicalcodeblock.h"
+#include "codegenerators/codegenfactory.h"
+
+// Constructors/Destructors
+//
+
+CodeBlockWithComments::CodeBlockWithComments ( HierarchicalCodeBlock * hb, const QString & body, const QString & comment)
+ : CodeBlock (hb, body)
+{
+ initFields(hb->getParentDocument(), comment);
+}
+
+CodeBlockWithComments::CodeBlockWithComments ( CodeDocument * parent , const QString & body, const QString & comment)
+ : CodeBlock (parent, body)
+{
+ initFields(parent, comment);
+}
+
+CodeBlockWithComments::~CodeBlockWithComments ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+/**
+ * Set the comment on this code block.
+ */
+void CodeBlockWithComments::setComment ( CodeComment * object ) {
+ m_comment = object;
+}
+
+/**
+ * Remove a Comment object from m_commentVector List
+ */
+CodeComment * CodeBlockWithComments::getComment ( ) {
+ return m_comment;
+}
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeBlockWithComments::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "codeblockwithcomments" );
+
+ // set attributes
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+void CodeBlockWithComments::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement)
+{
+
+ // set super-class attributes
+ CodeBlock::setAttributesOnNode(doc, blockElement);
+
+ // set local attributes now..e.g. a comment
+ // which we will store in its own separate child node block
+ QDomElement commElement = doc.createElement( "header" );
+ getComment()->saveToXMI(doc, commElement); // comment
+ blockElement.appendChild( commElement);
+
+}
+
+void CodeBlockWithComments::setAttributesFromObject(TextBlock * obj)
+{
+
+ CodeBlock::setAttributesFromObject(obj);
+
+ CodeBlockWithComments * cb = dynamic_cast<CodeBlockWithComments*>(obj);
+ if(cb)
+ getComment()->setAttributesFromObject((TextBlock*)cb->getComment());
+
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeBlockWithComments::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+void CodeBlockWithComments::setAttributesFromNode( QDomElement & root)
+{
+
+ // set attributes from superclass method the XMI
+ CodeBlock::setAttributesFromNode(root);
+
+ // load comment now
+ // by looking for our particular child element
+ QDomNode node = root.firstChild();
+ QDomElement element = node.toElement();
+ bool gotComment = false;
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if( tag == "header" ) {
+ QDomNode cnode = element.firstChild();
+ QDomElement celem = cnode.toElement();
+ getComment()->loadFromXMI(celem);
+ gotComment = true;
+ break;
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ if(!gotComment)
+ kWarning()<<" loadFromXMI : Warning: unable to initialize CodeComment in block:"<<getTag()<<endl;
+
+}
+
+/**
+ * @return QString
+ */
+QString CodeBlockWithComments::toString ( ) {
+
+ QString string = QString();
+
+ if(getWriteOutText()) {
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ QString body = formatMultiLineText (getText(), indent, endLine);
+ QString comment = getComment()->toString();
+
+ if(!comment.isEmpty() && getComment()->getWriteOutText())
+ string.append(comment);
+ if(!body.isEmpty())
+ string.append(body);
+ }
+
+ return string;
+}
+
+// slave indentation level for both the header and text body
+void CodeBlockWithComments::setOverallIndentationLevel ( int level )
+{
+ setIndentationLevel(level);
+ m_comment->setIndentationLevel(level);
+}
+
+void CodeBlockWithComments::initFields(CodeDocument *parent, const QString& comment)
+{
+ CodeComment * codecomment = CodeGenFactory::newCodeComment(parent);
+ codecomment->setText(comment);
+ m_comment = codecomment;
+}
+
+#include "codeblockwithcomments.moc"
diff --git a/umbrello/umbrello/codeblockwithcomments.h b/umbrello/umbrello/codeblockwithcomments.h
new file mode 100644
index 00000000..85226077
--- /dev/null
+++ b/umbrello/umbrello/codeblockwithcomments.h
@@ -0,0 +1,107 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+
+#ifndef CODEBLOCKWITHCOMMENTS_H
+#define CODEBLOCKWITHCOMMENTS_H
+
+
+#include "codeblock.h"
+#include "codecomment.h"
+
+class HierarchicalCodeBlock;
+
+/**
+ * class CodeBlockWithComments
+ * A very common type of text block in any type of code.
+ */
+
+class CodeBlockWithComments : public CodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Basic Constructor
+ */
+ explicit CodeBlockWithComments ( CodeDocument * doc , const QString & body = "", const QString & comment = "");
+ explicit CodeBlockWithComments ( HierarchicalCodeBlock * hblock, const QString & body = "", const QString & comment = "" );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeBlockWithComments ( );
+
+
+ /**
+ * Set the Comment object
+ */
+ void setComment ( CodeComment * object );
+
+ /**
+ * Get the Comment object
+ */
+ CodeComment * getComment ( );
+
+ /**
+ * @return QString
+ */
+ virtual QString toString ( );
+
+ /** A utility method that causes the comment and body of the code block
+ * to have the same indentation level.
+ */
+ void setOverallIndentationLevel ( int level );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode (QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+private:
+
+ CodeComment * m_comment;
+
+ void initFields(CodeDocument *parent, const QString& comment);
+
+};
+
+#endif // CODEBLOCKWITHCOMMENTS_H
diff --git a/umbrello/umbrello/codeclassfield.cpp b/umbrello/umbrello/codeclassfield.cpp
new file mode 100644
index 00000000..a19e664d
--- /dev/null
+++ b/umbrello/umbrello/codeclassfield.cpp
@@ -0,0 +1,617 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+// own header
+#include "codeclassfield.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "association.h"
+#include "classifiercodedocument.h"
+#include "codegenerator.h"
+#include "attribute.h"
+#include "umlobject.h"
+#include "umlrole.h"
+#include "uml.h"
+#include "codegenerators/codegenfactory.h"
+
+// Constructors/Destructors
+//
+
+CodeClassField::CodeClassField ( ClassifierCodeDocument * doc , UMLRole * role)
+ : CodeParameter ( doc , (UMLObject*) role)
+{
+
+ setParentUMLObject(role);
+ initFields(true);
+
+}
+
+CodeClassField::CodeClassField ( ClassifierCodeDocument * doc , UMLAttribute * attrib)
+ : CodeParameter ( doc , (UMLObject*) attrib )
+{
+
+ setParentUMLObject(attrib);
+ initFields(true);
+
+}
+
+CodeClassField::~CodeClassField ( ) {
+
+ // remove methods from parent document
+ CodeAccessorMethodList list = m_methodVector;
+ for(CodeAccessorMethod * m = list.first(); m ; m=list.next())
+ {
+ getParentDocument()->removeTextBlock(m);
+ m->forceRelease();
+ }
+ list.clear();
+
+ // clear the decl block from parent text block list too
+ if(m_declCodeBlock)
+ {
+ getParentDocument()->removeTextBlock(m_declCodeBlock);
+ m_declCodeBlock->forceRelease();
+ delete m_declCodeBlock;
+ }
+
+}
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+void CodeClassField::setParentUMLObject (UMLObject * obj) {
+ UMLRole *role = dynamic_cast<UMLRole*>(obj);
+ if(role) {
+ UMLAssociation * parentAssoc = role->getParentAssociation();
+ Uml::Association_Type atype = parentAssoc->getAssocType();
+ m_parentIsAttribute = false;
+
+ if ( atype == Uml::at_Association || atype == Uml::at_Association_Self)
+ m_classFieldType = PlainAssociation; // Plain == Self + untyped associations
+ else if (atype == Uml::at_Aggregation)
+ m_classFieldType = Aggregation;
+ else if (atype == Uml::at_Composition)
+ m_classFieldType = Composition;
+ } else {
+ m_classFieldType = Attribute;
+ m_parentIsAttribute = true;
+ }
+}
+
+// Public attribute accessor methods
+//
+
+QString CodeClassField::getTypeName ( ) {
+
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = (UMLAttribute*) getParentObject();
+ return at->getTypeName();
+ } else {
+ UMLRole * role = (UMLRole*) getParentObject();
+ if(fieldIsSingleValue()) {
+ return getUMLObjectName(role->getObject());
+ } else {
+ return role->getName();
+ }
+ }
+}
+
+// get the type of object that will be added/removed from lists
+// of objects (as per specification of associations)
+QString CodeClassField::getListObjectType() {
+ QString type = QString ("");
+ if (!parentIsAttribute())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ type = getUMLObjectName(role->getObject());
+ }
+ return type;
+}
+
+/**
+ * Get the value of m_isAbstract
+ * @return the value of m_isAbstract
+ */
+bool CodeClassField::parentIsAttribute ( ) {
+ return m_parentIsAttribute;
+ // return (m_classFieldType == Attribute) ? true : false;
+}
+
+/**
+ * Get the type of classfield this is.
+ */
+CodeClassField::ClassFieldType CodeClassField::getClassFieldType() {
+ return m_classFieldType;
+}
+
+/**
+ * Get the value of m_dialog
+ * @return the value of m_dialog
+ */
+/*
+CodeClassFieldDialog * CodeClassField::getDialog ( ) {
+ return m_dialog;
+}
+*/
+
+// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
+QString CodeClassField::getUMLObjectName(UMLObject *obj)
+{
+ return (obj!=0)?obj->getName():QString("NULL");
+}
+
+/**
+ * Add a Method object to the m_methodVector List
+ */
+bool CodeClassField::addMethod ( CodeAccessorMethod * add_object ) {
+
+ CodeAccessorMethod::AccessorType type = add_object->getType();
+
+ if(findMethodByType(type))
+ return false;
+ /*
+ // this wont work as the key for QMap needs to inherit from QObject
+ if(m_methodMap->contains(type))
+ return false; // return false, we already have some object with this tag in the list
+ else
+ m_methodMap->insert(type, add_object);
+ */
+
+ m_methodVector.append(add_object);
+ return true;
+}
+
+/**
+ * Remove a Method object from m_methodVector List
+ */
+bool CodeClassField::removeMethod ( CodeAccessorMethod * remove_object ) {
+ // m_methodMap->erase(remove_object->getType());
+ m_methodVector.removeRef(remove_object);
+ getParentDocument()->removeTextBlock(remove_object);
+ return true;
+}
+
+/**
+ * Get the list of Method objects held by m_methodVector
+ * @return QPtrList<CodeMethodBlock *> list of Method objects held by
+ * m_methodVector
+ */
+CodeAccessorMethodList CodeClassField::getMethodList() {
+ return m_methodVector;
+}
+
+/** determine if we will *allow* methods to be viewable.
+ * this flag is often used to toggle autogeneration of accessor
+ * methods in the code class field.
+ */
+bool CodeClassField::getWriteOutMethods ()
+{
+ return m_writeOutMethods;
+}
+
+void CodeClassField::setWriteOutMethods ( bool val )
+{
+ m_writeOutMethods = val;
+ updateContent();
+}
+
+/**
+ * return the declaration statement for this class field object.
+ * will be empty until this (abstract) class is inherited in elsewhere.
+ */
+CodeClassFieldDeclarationBlock * CodeClassField::getDeclarationCodeBlock( )
+{
+ return m_declCodeBlock;
+}
+
+// Other methods
+//
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeClassField::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void CodeClassField::setAttributesOnNode ( QDomDocument & doc, QDomElement & cfElem)
+{
+
+ // super class
+ CodeParameter::setAttributesOnNode(doc,cfElem);
+
+ // now set local attributes/fields
+ cfElem.setAttribute("field_type",m_classFieldType);
+ cfElem.setAttribute("listClassName",m_listClassName);
+ cfElem.setAttribute("writeOutMethods",getWriteOutMethods()?"true":"false");
+
+ // record tag on declaration codeblock
+ // which we will store in its own separate child node block
+ m_declCodeBlock->saveToXMI(doc, cfElem);
+
+ // now record the tags on our accessormethods
+ CodeAccessorMethod *method;
+ for (CodeAccessorMethodListIt it(m_methodVector); (method = it.current()) != NULL; ++it)
+ {
+ method->saveToXMI(doc,cfElem);
+ }
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeClassField::setAttributesFromNode ( QDomElement & root) {
+
+ // always disconnect
+ getParentObject()->disconnect(this);
+
+ // superclass call.. may reset the parent object
+ CodeParameter::setAttributesFromNode(root);
+
+ // make AFTER super-class call. This will reconnect to the parent
+ // and re-check we have all needed child accessor methods and decl blocks
+ initFields( );
+
+ setWriteOutMethods(root.attribute("writeOutMethods","true") == "true" ? true : false);
+ m_listClassName = root.attribute("listClassName","");
+ m_classFieldType = (ClassFieldType) root.attribute("field_type","0").toInt();
+
+ // load accessor methods now
+ // by looking for our particular child element
+ QDomNode node = root.firstChild();
+ QDomElement element = node.toElement();
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if( tag == "ccfdeclarationcodeblock" ) {
+ m_declCodeBlock->loadFromXMI(element);
+ } else
+ if( tag == "codeaccessormethod" ) {
+ int type = element.attribute("accessType","0").toInt();
+ int role_id = element.attribute("role_id","-1").toInt();
+ CodeAccessorMethod * method = findMethodByType((CodeAccessorMethod::AccessorType) type, role_id);
+ if(method)
+ method->loadFromXMI(element);
+ else
+ kError()<<"Cant load code accessor method for type:"<<type<<" which doesn't exist in this codeclassfield. Is XMI out-dated or corrupt?"<<endl;
+
+ } else
+ if( tag == "header" ) {
+ // this is treated in parent.. skip over here
+ } else
+ kWarning()<<"ERROR: bad savefile? code classfield loadFromXMI got child element with unknown tag:"<<tag<<" ignoring node."<<endl;
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeClassField::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement docElement = doc.createElement( "codeclassfield" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+int CodeClassField::minimumListOccurances( ) {
+ if (!parentIsAttribute())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ QString multi = role->getMultiplicity();
+ // ush. IF we had a multiplicty object, this would be much easier.
+ if(!multi.isEmpty())
+ {
+ QString lowerBoundString = multi.remove(QRegExp("\\.\\.\\d+$"));
+ if(!lowerBoundString.isEmpty() &&lowerBoundString.contains(QRegExp("^\\d+$")))
+ return lowerBoundString.toInt();
+ }
+
+ }
+ return 0;
+}
+
+int CodeClassField::maximumListOccurances( ) {
+ if (!parentIsAttribute())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ QString multi = role->getMultiplicity();
+ // ush. IF we had a multiplicty object, this would be much easier.
+ if(!multi.isEmpty())
+ {
+ QString upperBoundString = multi.section(QRegExp("(\\.\\.)"),1);
+ if(!upperBoundString.isEmpty() && upperBoundString.contains(QRegExp("^\\d+$")))
+ return upperBoundString.toInt();
+ else
+ return -1; // unbounded
+ } else
+ return -1; // unbounded
+
+ }
+ return 1;
+}
+
+QString CodeClassField::cleanName ( const QString &name ) {
+ return getParentDocument()->cleanName(name);
+}
+
+QString CodeClassField::fixInitialStringDeclValue(const QString& val, const QString &type)
+{
+ QString value = val;
+ // check for strings only<F2>String value = val;
+ if (!value.isEmpty() && type == "String") {
+ if (!value.startsWith("\""))
+ value.prepend("\"");
+ if (!value.endsWith("\""))
+ value.append("\"");
+ }
+ return value;
+}
+
+void CodeClassField::synchronize ()
+{
+ updateContent();
+ CodeAccessorMethod *method;
+ for (CodeAccessorMethodListIt it(m_methodVector); (method = it.current()) != NULL; ++it)
+ method->syncToParent();
+
+ if(m_declCodeBlock)
+ m_declCodeBlock->syncToParent();
+}
+
+CodeAccessorMethod * CodeClassField::findMethodByType ( CodeAccessorMethod::AccessorType type, int role_id)
+{
+ //if we already know to which file this class was written/should be written, just return it.
+ /*
+ // argh. this wont work because "accessorType' doesn't inherit from QObject.
+ if(m_methodMap->contains(type))
+ return ((*m_methodMap)[type]);
+ CodeAccessorMethod * obj = NULL;
+ */
+ if(role_id > 1 || role_id < 0)
+ {
+ for (CodeAccessorMethod * m = m_methodVector.first(); m ; m= m_methodVector.next())
+ if( m->getType() == type)
+ return m;
+ } else {
+ // ugh. forced into this underperforming algorithm because of bad association
+ // design.
+ for (CodeAccessorMethod * m = m_methodVector.first(); m ; m= m_methodVector.next())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(m->getParentObject());
+ if(!role)
+ kError()<<" FindMethodByType() cant create role for method type:"<<m->getType()<<endl;
+ if( role && m->getType() == type && role->getRole() == role_id)
+ return m;
+ }
+
+ }
+
+ return (CodeAccessorMethod *) NULL;
+}
+
+void CodeClassField::initAccessorMethods()
+{
+
+ // everything gets potential get/set method
+ //if(!m_methodMap->contains(CodeAccessorMethod::GET))
+ if(!findMethodByType(CodeAccessorMethod::GET))
+ {
+ CodeAccessorMethod * method = CodeGenFactory::newCodeAccessorMethod (getParentDocument(), this, CodeAccessorMethod::GET);
+ if(method)
+ {
+ method->setType(CodeAccessorMethod::GET);
+ addMethod(method);
+ }
+ }
+
+ if(!findMethodByType(CodeAccessorMethod::SET))
+ {
+ CodeAccessorMethod * method = CodeGenFactory::newCodeAccessorMethod (getParentDocument(), this, CodeAccessorMethod::SET);
+ if(method) {
+ method->setType(CodeAccessorMethod::SET);
+ addMethod(method);
+ }
+ }
+
+ // add in the add,remove and list methods for things which are role based.
+ // (and only used if the role specifies a 'list' type object
+ if (!parentIsAttribute()) {
+
+ if(!findMethodByType(CodeAccessorMethod::ADD))
+ {
+ CodeAccessorMethod * method = CodeGenFactory::newCodeAccessorMethod (getParentDocument(), this, CodeAccessorMethod::ADD);
+ if(method) {
+ method->setType(CodeAccessorMethod::ADD);
+ addMethod(method);
+ }
+ }
+
+ if(!findMethodByType(CodeAccessorMethod::REMOVE))
+ {
+ CodeAccessorMethod * method = CodeGenFactory::newCodeAccessorMethod (getParentDocument(), this, CodeAccessorMethod::REMOVE);
+ if(method) {
+ method->setType(CodeAccessorMethod::REMOVE);
+ addMethod(method);
+ }
+ }
+
+ if(!findMethodByType(CodeAccessorMethod::LIST))
+ {
+ CodeAccessorMethod * method = CodeGenFactory::newCodeAccessorMethod (getParentDocument(), this, CodeAccessorMethod::LIST);
+ if(method) {
+ method->setType(CodeAccessorMethod::LIST);
+ addMethod(method);
+ }
+ }
+
+ }
+
+
+}
+
+void CodeClassField::updateContent()
+{
+
+ // Set properties for writing out the various methods derived from UMLRoles.
+ // I suppose this could be supported under individual accessor method synctoparent
+ // calls, but its going to happen again and again for many languages. Why not a catch
+ // all here? -b.t.
+ if (parentIsAttribute())
+ {
+ for ( CodeAccessorMethod *method = m_methodVector.first(); method;
+ method = m_methodVector.next() )
+ method->setWriteOutText( m_writeOutMethods );
+ return;
+ }
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ Uml::Changeability_Type changeType = role->getChangeability();
+ bool isSingleValue = fieldIsSingleValue();
+ bool isEmptyRole = role->getName().isEmpty() ? true : false;
+
+ for (CodeAccessorMethod * method = m_methodVector.first(); method; method=m_methodVector.next())
+ {
+
+ CodeAccessorMethod::AccessorType type = method->getType();
+
+ // for role-based accessors, we DON'T write ourselves out when
+ // the name of the role is not defined OR when the global flag
+ // to not show ANY methods is set.
+ if(!m_writeOutMethods || isEmptyRole)
+ {
+ method->setWriteOutText(false);
+ continue;
+ }
+
+ // not to change if no tag (don't know what it is, OR its not an AutoGenerated method
+ if(method->getContentType() != CodeBlock::AutoGenerated)
+ continue;
+
+ // first off, some accessor methods wont appear if its a singleValue
+ // role and vice-versa
+ if(isSingleValue)
+ {
+ switch(type) {
+ case CodeAccessorMethod::SET:
+ // SET method true ONLY IF changeability is NOT Frozen
+ if (changeType != Uml::chg_Frozen)
+ method->setWriteOutText(true);
+ else
+ method->setWriteOutText(false);
+ break;
+ case CodeAccessorMethod::GET:
+ method->setWriteOutText(true);
+ break;
+ case CodeAccessorMethod::ADD:
+ case CodeAccessorMethod::REMOVE:
+ case CodeAccessorMethod::LIST:
+ default: // list/add/remove always false
+ method->setWriteOutText(false);
+ break;
+ }
+ }
+ else
+ {
+ switch(type) {
+ // get/set always false
+ case CodeAccessorMethod::GET:
+ case CodeAccessorMethod::SET:
+ method->setWriteOutText(false);
+ break;
+ case CodeAccessorMethod::ADD:
+ // ADD method true ONLY IF changeability is NOT Frozen
+ if (changeType != Uml::chg_Frozen)
+ method->setWriteOutText(true);
+ else
+ method->setWriteOutText(false);
+ break;
+ case CodeAccessorMethod::REMOVE:
+ // Remove methods ONLY IF changeability is Changeable
+ if (changeType == Uml::chg_Changeable)
+ method->setWriteOutText(true);
+ else
+ method->setWriteOutText(false);
+ break;
+ case CodeAccessorMethod::LIST:
+ default:
+ method->setWriteOutText(true);
+ break;
+ }
+ }
+ }
+}
+
+// determine whether the parent object in this classfield indicates that it is
+// a single variable or a List (Vector). One day this will be done correctly with special
+// multiplicity object that we don't have to figure out what it means via regex.
+bool CodeClassField::fieldIsSingleValue ( )
+{
+ // For the time being, all attributes ARE single values (yes,
+ // I know this isnt always true, but we have to start somewhere.)
+ if(parentIsAttribute())
+ return true;
+
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ if(!role)
+ return true; // its really an attribute
+
+ QString multi = role->getMultiplicity();
+
+ if(multi.isEmpty() || multi.contains(QRegExp("^(0|1)$"))
+ || multi.contains(QRegExp("^0\\.\\.1$")))
+ return true;
+
+ return false;
+}
+
+void CodeClassField::initFields(bool inConstructor) {
+
+ m_writeOutMethods = false;
+ m_listClassName = QString ("");
+ m_declCodeBlock = NULL;
+
+ m_methodVector.setAutoDelete(false);
+ // m_methodMap = new QMap<CodeAccessorMethod::AccessorType, CodeAccessorMethod *>;
+
+ if (!inConstructor)
+ finishInitialization();
+}
+
+void CodeClassField::finishInitialization() {
+ m_declCodeBlock = CodeGenFactory::newDeclarationCodeBlock(getParentDocument(), this);
+ initAccessorMethods();
+ updateContent();
+
+ connect(getParentObject(),SIGNAL(modified()),this,SIGNAL(modified())); // child objects will trigger off this signal
+
+}
+
+#include "codeclassfield.moc"
diff --git a/umbrello/umbrello/codeclassfield.h b/umbrello/umbrello/codeclassfield.h
new file mode 100644
index 00000000..bd651b6e
--- /dev/null
+++ b/umbrello/umbrello/codeclassfield.h
@@ -0,0 +1,237 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+
+
+#ifndef CODECLASSFIELD_H
+#define CODECLASSFIELD_H
+
+#include "codeaccessormethodlist.h"
+#include "codeclassfielddeclarationblock.h"
+#include "codeparameter.h"
+#include "codeaccessormethod.h"
+
+// #include "codeclassfielddialog.h"
+
+
+class ClassifierCodeDocument;
+class UMLAttribute;
+class UMLObject;
+class UMLRole;
+
+/**
+ * class CodeClassField
+ * a special type of parameter.. occurs on class declarations.
+ */
+
+class CodeClassField : public CodeParameter
+{
+ Q_OBJECT
+public:
+
+ enum ClassFieldType { Attribute, PlainAssociation, Self, Aggregation, Composition, Unknown_Assoc };
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ CodeClassField ( ClassifierCodeDocument * parentDoc , UMLAttribute * attrib );
+ CodeClassField ( ClassifierCodeDocument * parentDoc , UMLRole * role);
+
+ /**
+ * Finish off initializations of the object.
+ * This is necessary as a separate method because we cannot call
+ * virtual methods that are reimplemented in a language specific class
+ * during our own construction (the own object is not finished being
+ * constructed and therefore the C++ dispatch mechanism does not yet
+ * work as expected.)
+ */
+ void finishInitialization();
+
+ // CodeClassField ( ClassifierCodeDocument * doc , UMLRole role);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeClassField ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Get the value of m_dialog
+ * @return the value of m_dialog
+ */
+ // CodeClassFieldDialog getDialog ( );
+
+ // Determine if this cf is attribute or some type of association
+ QString getTypeName ( );
+
+ /**
+ * @return CodeClassFieldDeclarationBlock representing the declaration statement of this class field
+ */
+ CodeClassFieldDeclarationBlock * getDeclarationCodeBlock( );
+
+ /**
+ * Get the list of Method objects held by m_methodVector
+ * @return CodeAccessorMethodList list of Method objects held by
+ * m_methodVector
+ */
+ CodeAccessorMethodList getMethodList();
+
+ /** Utility method to allow finding particular accessor method of this
+ * code class field by its type identifier.
+ */
+ CodeAccessorMethod * findMethodByType(CodeAccessorMethod::AccessorType type, int role_id = -1);
+
+ /** Determine whether the parent object in this classfield indicates that it is
+ * a single variable or a List (Vector). One day this will be done correctly with special
+ * multiplicity object.
+ */
+ bool fieldIsSingleValue ( );
+
+ /**
+ * Get the type of classfield this is.
+ */
+ ClassFieldType getClassFieldType();
+
+ // quick utility call to figure out if parent is an attribute or not
+ bool parentIsAttribute ( );
+
+ // get the type of object that will be added/removed from lists
+ // of objects (as per specification of associations)
+ QString getListObjectType();
+
+ /** determine if we will *allow* methods to be viewable.
+ * this flag is often used to toggle autogeneration of accessor
+ * methods in the code class field.
+ */
+ bool getWriteOutMethods ();
+
+ /** determine if we will *allow* methods to be viewable.
+ * this flag is often used to toggle autogeneration of accessor
+ * methods in the code class field.
+ */
+ void setWriteOutMethods( bool val);
+
+ /** Find the minimum number of things that can occur in an association
+ * If mistakenly called on attribute CF's the default value of is "0"
+ * is returned. Similarly, if the association (role) CF doesn't have a multiplicty
+ * 0 is returned.
+ */
+ int minimumListOccurances( );
+
+ /** Find the maximum number of things that can occur in an association
+ * If mistakenly called on attribute CF's the default value of is "1"
+ * is returned. If the association (role) CF doesn't have a multiplicty
+ * or has a "*" specified then '-1' (unbounded) is returned.
+ */
+ int maximumListOccurances( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** Force the syncronization of the content (methods and declarations)
+ * of this class field.
+ */
+ virtual void synchronize ();
+
+protected:
+
+ /** Set the parent UMLobject appropriately.
+ */
+ void setParentUMLObject (UMLObject * obj);
+
+ // CodeClassFieldDialog * m_dialog;
+
+ /** a little utility method to make life easier for code document programmers
+ */
+ QString cleanName(const QString &name);
+
+ /** another utility method to make life easier for code document programmers
+ * this one fixes the initial declared value of string attributes so that if
+ * its empty or lacking quotations, it comes out as ""
+ */
+ QString fixInitialStringDeclValue(const QString& val, const QString &type);
+
+ // set the list class name
+ void setListClassName ( const QString &className );
+
+ /**
+ * Add a Method object to the m_methodVector List
+ */
+ bool addMethod ( CodeAccessorMethod * add );
+
+ QString getUMLObjectName(UMLObject *obj);
+
+ /**
+ * Remove a Method object from m_methodVector List
+ */
+ bool removeMethod ( CodeAccessorMethod * remove);
+
+ // Updates the status of the accessor methods
+ // as to whether or not they should be written out.
+ void updateContent();
+
+private:
+
+ QString m_listClassName;
+ ClassFieldType m_classFieldType;
+ CodeClassFieldDeclarationBlock * m_declCodeBlock;
+ CodeAccessorMethodList m_methodVector; // the list of methods related to this codeclassfield
+ bool m_parentIsAttribute;
+
+ /** This flag tells if we want the methods to have the possibility
+ * of being written out. IF the value is false, then all methods
+ * are never written out.
+ */
+ bool m_writeOutMethods;
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** init class fields */
+ void initFields(bool inConstructor = false);
+
+ // initialize the accessor methods for this field
+ void initAccessorMethods();
+
+signals:
+
+ void modified ();
+
+};
+
+#endif // CODECLASSFIELD_H
diff --git a/umbrello/umbrello/codeclassfielddeclarationblock.cpp b/umbrello/umbrello/codeclassfielddeclarationblock.cpp
new file mode 100644
index 00000000..d02a83fa
--- /dev/null
+++ b/umbrello/umbrello/codeclassfielddeclarationblock.cpp
@@ -0,0 +1,174 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jul 25 2003
+ */
+
+/** basicially a class to allow for syncronization of the contents based on the
+ * values of the parentClassField's parentObject
+ */
+#include "codeclassfielddeclarationblock.h"
+
+#include "codeclassfield.h"
+#include "umlrole.h"
+
+// Constructors/Destructors
+//
+
+CodeClassFieldDeclarationBlock::CodeClassFieldDeclarationBlock ( CodeClassField * parentCF )
+ : CodeBlockWithComments ( (CodeDocument*) parentCF->getParentDocument() ),
+ OwnedCodeBlock ((UMLObject*) parentCF->getParentObject())
+{
+ init(parentCF);
+}
+
+CodeClassFieldDeclarationBlock::~CodeClassFieldDeclarationBlock ( ) {
+ // Q: is this needed??
+ // m_parentclassfield->getParentObject()->disconnect(this);
+}
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+/**
+ * Get the value of m_parentclassfield
+ * @return the value of m_parentclassfield
+ */
+CodeClassField * CodeClassFieldDeclarationBlock::getParentClassField ( ) {
+ return m_parentclassfield;
+}
+
+/** Get the parent object of the parentCodeClassfield
+ */
+UMLObject * CodeClassFieldDeclarationBlock::getParentObject ( ) {
+ return m_parentclassfield->getParentObject();
+}
+
+CodeDocument * CodeClassFieldDeclarationBlock::getParentDocument ( ) {
+ return TextBlock::getParentDocument();
+}
+
+// Other methods
+//
+
+// this type of textblock is special
+// we DONT release it when resetTextBlocks is
+// called because we re-use it over and over
+// until the codeclassfield is released.
+void CodeClassFieldDeclarationBlock::release () {
+ // do nothing
+}
+
+void CodeClassFieldDeclarationBlock::forceRelease () {
+ if(m_parentclassfield)
+ {
+ // m_parentclassfield->getParentObject()->disconnect(this);
+ m_parentclassfield->disconnect(this);
+ }
+ m_parentclassfield = 0;
+ OwnedCodeBlock::release();
+ TextBlock::release();
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeClassFieldDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & elem)
+{
+ QDomElement docElement = doc.createElement( "ccfdeclarationcodeblock" );
+
+ setAttributesOnNode(doc, docElement);
+
+ elem.appendChild( docElement );
+}
+
+void CodeClassFieldDeclarationBlock::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+void CodeClassFieldDeclarationBlock::setAttributesOnNode (QDomDocument & doc, QDomElement & elem ) {
+
+ // set super-class attributes
+ CodeBlockWithComments::setAttributesOnNode(doc, elem);
+ OwnedCodeBlock::setAttributesOnNode(doc, elem);
+
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeClassFieldDeclarationBlock::setAttributesFromNode( QDomElement & root ) {
+
+ // set attributes from the XMI
+ CodeBlockWithComments::setAttributesFromNode(root); // superclass load
+ OwnedCodeBlock::setAttributesFromNode(root); // superclass load
+
+ syncToParent();
+}
+
+/** set the class attributes from a passed object
+ */
+void CodeClassFieldDeclarationBlock::setAttributesFromObject (TextBlock * obj) {
+
+ CodeBlockWithComments::setAttributesFromObject(obj);
+
+ CodeClassFieldDeclarationBlock * ccb = dynamic_cast<CodeClassFieldDeclarationBlock*>(obj);
+ if(ccb)
+ {
+ m_parentclassfield->disconnect(this);
+ init(ccb->getParentClassField());
+
+ syncToParent();
+ }
+
+}
+
+void CodeClassFieldDeclarationBlock::syncToParent () {
+
+ // for role-based accessors, we DONT write ourselves out when
+ // the name of the role is not defined.
+ if(!(getParentClassField()->parentIsAttribute()))
+ {
+ UMLRole * parent = dynamic_cast<UMLRole*>(getParentObject());
+ if (parent == NULL)
+ return;
+ if(parent->getName().isEmpty())
+ {
+ getComment()->setWriteOutText(false);
+ setWriteOutText(false);
+ } else {
+ getComment()->setWriteOutText(true);
+ setWriteOutText(true);
+ }
+ }
+
+ // only update IF we are NOT AutoGenerated
+ if(getContentType() != AutoGenerated)
+ return;
+
+ updateContent();
+
+}
+
+void CodeClassFieldDeclarationBlock::init (CodeClassField * parentCF)
+{
+ m_parentclassfield = parentCF;
+ m_canDelete = false;
+ connect(m_parentclassfield,SIGNAL(modified()),this,SLOT(syncToParent()));
+}
+
+#include "codeclassfielddeclarationblock.moc"
diff --git a/umbrello/umbrello/codeclassfielddeclarationblock.h b/umbrello/umbrello/codeclassfielddeclarationblock.h
new file mode 100644
index 00000000..f52868e2
--- /dev/null
+++ b/umbrello/umbrello/codeclassfielddeclarationblock.h
@@ -0,0 +1,112 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jul 25 2003
+ */
+
+#ifndef CODECLASSFIELDDECLARATIONBLOCK_H
+#define CODECLASSFIELDDECLARATIONBLOCK_H
+
+
+class UMLObject;
+class CodeClassField;
+
+#include "codeblockwithcomments.h"
+#include "ownedcodeblock.h"
+
+/**
+ * class CodeClassFieldDeclarationBlock
+ * Used to declare classifier fields (e.g. either class attributes or classifier
+ * associations) in the code document for any given code classfield. This is a
+ * special CodeBlockWithComments which is "sync'd" to the parent CodeClassField.
+ */
+
+class CodeClassFieldDeclarationBlock : public CodeBlockWithComments, public OwnedCodeBlock
+{
+ friend class CodeClassField;
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CodeClassFieldDeclarationBlock (CodeClassField * parent);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeClassFieldDeclarationBlock ( );
+
+ /**
+ * Get the value of m_parentclassfield
+ * @return the value of m_parentclassfield
+ */
+ CodeClassField * getParentClassField ( );
+
+ /** A Utility method to get the parent object of the parentCodeClassfield
+ */
+ UMLObject * getParentObject ( );
+
+ // get the parent document
+ CodeDocument * getParentDocument ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+protected:
+
+ virtual void release ();
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** this is called by syncToParent
+ */
+ virtual void updateContent() = 0;
+
+ // so parent can actually release this block
+ void forceRelease ();
+
+private:
+
+ CodeClassField * m_parentclassfield;
+ void init(CodeClassField * parent);
+
+public slots:
+
+ virtual void syncToParent();
+
+};
+
+#endif // CODECLASSFIELDDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codeclassfieldlist.h b/umbrello/umbrello/codeclassfieldlist.h
new file mode 100644
index 00000000..c9ab4892
--- /dev/null
+++ b/umbrello/umbrello/codeclassfieldlist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef _CODECLASSFIELDLIST_H
+#define _CODECLASSFIELDLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class CodeClassField;
+
+typedef QPtrList<CodeClassField> CodeClassFieldList;
+typedef QPtrListIterator<CodeClassField> CodeClassFieldListIt;
+
+#endif
diff --git a/umbrello/umbrello/codecomment.cpp b/umbrello/umbrello/codecomment.cpp
new file mode 100644
index 00000000..b59e52b4
--- /dev/null
+++ b/umbrello/umbrello/codecomment.cpp
@@ -0,0 +1,62 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+#include "codecomment.h"
+#include "codedocument.h"
+#include <kdebug.h>
+
+// Constructors/Destructors
+//
+
+CodeComment::CodeComment (CodeDocument * doc, const QString & comment )
+ : TextBlock ( doc, comment )
+{
+
+}
+
+CodeComment::~CodeComment ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeComment::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ kDebug() << "CodeComment::saveToXMI is called!" << endl;
+ QDomElement blockElement = doc.createElement( "codecomment" );
+ setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may
+ // just use parent TextBlock method
+ root.appendChild( blockElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeComment::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+
+#include "codecomment.moc"
diff --git a/umbrello/umbrello/codecomment.h b/umbrello/umbrello/codecomment.h
new file mode 100644
index 00000000..18c2cba0
--- /dev/null
+++ b/umbrello/umbrello/codecomment.h
@@ -0,0 +1,68 @@
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+
+#ifndef CODECOMMENT_H
+#define CODECOMMENT_H
+
+#include <qstring.h>
+
+#include "textblock.h"
+
+/**
+ * class CodeComment
+ * Text which will be comments. These should be bracketed by what ever code type
+ * comment the language requires.
+ */
+
+class CodeComment : public TextBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Empty Constructor
+ */
+ explicit CodeComment ( CodeDocument * doc, const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeComment ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+protected:
+
+private:
+
+
+
+};
+
+#endif // CODECOMMENT_H
diff --git a/umbrello/umbrello/codedocument.cpp b/umbrello/umbrello/codedocument.cpp
new file mode 100644
index 00000000..e0bf0e73
--- /dev/null
+++ b/umbrello/umbrello/codedocument.cpp
@@ -0,0 +1,502 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+// own header
+#include "codedocument.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <kdebug.h>
+
+// local includes
+#include "codegenerator.h"
+#include "package.h"
+#include "umldoc.h"
+#include "uml.h"
+
+// Constructors/Destructors
+//
+
+CodeDocument::CodeDocument () : CodeGenObjectWithTextBlocks(this)
+{
+ initDoc();
+}
+
+
+CodeDocument::~CodeDocument ( ) {
+ // delete all the text blocks we have
+ TextBlock *tb;
+ for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
+ delete tb;
+ m_textblockVector.clear();
+ delete m_header;
+}
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+
+/**
+ * Set the value of m_filename
+ * @param new_var the new value of m_filename
+ */
+void CodeDocument::setFileName ( const QString &new_var ) {
+ m_filename = new_var;
+}
+
+/**
+ * Get the value of m_filename
+ * @return the value of m_filename
+ */
+QString CodeDocument::getFileName ( ) const {
+ return m_filename;
+}
+
+/**
+ * Set the value of m_filename
+ * @param new_var the new value of m_filename
+ */
+void CodeDocument::setFileExtension ( const QString &new_var ) {
+ m_fileExtension = new_var;
+ updateHeader(); // because we are using new heading file
+}
+
+/**
+ * Get the value of m_filename
+ * @return the value of m_filename
+ */
+QString CodeDocument::getFileExtension( ) const {
+ return m_fileExtension;
+}
+
+/**
+ * Set the value of the package.
+ * @param new_var the new value of m_package
+ */
+void CodeDocument::setPackage ( UMLPackage *new_var ) {
+ m_package = new_var;
+}
+
+/**
+ * Get the value of path for this code document.
+ * @return the value of the path
+ */
+QString CodeDocument::getPath ( ) {
+
+ QString path = getPackage();
+
+ // Replace all white spaces with blanks
+ path = path.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ path.replace(QRegExp(" "), "_");
+
+ // this allows multiple directory paths (ala Java, some other languages)
+ // in from the package specification
+ path.replace(QRegExp("\\."),"/"); // Simple hack!.. but this is more or less language
+ // dependant and should probably be commented out.
+ // Still, as a general default it may be useful -b.t.
+ return path;
+}
+
+/**
+ * Get the value of package name.
+ * @return the value of m_package->getName()
+ */
+QString CodeDocument::getPackage ( ) const {
+ if (m_package)
+ return m_package->getName();
+ return QString();
+}
+
+/**
+ * Set the value of m_ID
+ * @param new_var the new value of m_ID
+ */
+void CodeDocument::setID ( const QString &new_var ) {
+ m_ID = new_var;
+}
+
+/**
+ * Get the value of m_ID
+ * @return the value of m_ID
+ */
+QString CodeDocument::getID ( ) const {
+ return m_ID;
+}
+
+/**
+ * Set the value of m_writeOutCode
+ * Whether or not to write out this code document and any codeblocks, etc that it
+ * owns.
+ * @param new_var the new value of m_writeOutCode
+ */
+void CodeDocument::setWriteOutCode ( bool new_var ) {
+ m_writeOutCode = new_var;
+}
+
+/**
+ * Get the value of m_writeOutCode
+ * Whether or not to write out this code document and any codeblocks, etc that it
+ * owns.
+ * @return the value of m_writeOutCode
+ */
+bool CodeDocument::getWriteOutCode ( ) {
+ return m_writeOutCode;
+}
+
+/**
+ * Set the Header comment
+ */
+void CodeDocument::setHeader ( CodeComment * header ) {
+ m_header = header;
+}
+
+/**
+ * Get the Header comment
+ */
+CodeComment * CodeDocument::getHeader ( ) {
+ return m_header;
+}
+
+//
+// Other methods
+//
+
+QString CodeDocument::getUniqueTag ( const QString& prefix )
+{
+ QString tag = prefix ;
+ if(tag.isEmpty())
+ tag += "tblock";
+
+ tag = tag + "_0";
+ int number = lastTagIndex;
+ for ( ; findTextBlockByTag(tag, true); number++) {
+ tag = prefix + '_' + QString::number(number);
+ }
+ lastTagIndex = number;
+ return tag;
+}
+
+/**
+ * Insert a new text block before/after the existing text block. Returns
+ * false if it cannot insert the textblock.
+ */
+bool CodeDocument::insertTextBlock(TextBlock * newBlock, TextBlock * existingBlock, bool after)
+{
+
+ if(!newBlock || !existingBlock)
+ return false;
+
+ QString tag = existingBlock->getTag();
+ if(!findTextBlockByTag(tag, true))
+ return false;
+
+ int index = m_textblockVector.findRef(existingBlock);
+ if(index < 0)
+ {
+ // may be hiding in child hierarchical codeblock
+ for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next())
+ {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
+ if(hb && hb->insertTextBlock(newBlock, existingBlock, after))
+ return true; // found, and inserted, otherwise keep going
+ }
+ // ugh. where is the child block?
+ kWarning()<<" Warning: couldnt insert text block (tag:"<<newBlock->getTag()<<"). Reference text block (tag:"<<existingBlock->getTag()<<") not found."<<endl;
+ return false;
+ }
+
+ // if we get here.. it was in this object so insert
+
+ // check for tag FIRST
+ QString new_tag = newBlock->getTag();
+
+ // assign a tag if one doesn't already exist
+ if(new_tag.isEmpty())
+ {
+ new_tag = getUniqueTag();
+ newBlock->setTag(new_tag);
+ }
+
+ if(m_textBlockTagMap.contains(new_tag))
+ return false; // return false, we already have some object with this tag in the list
+ else
+ m_textBlockTagMap.insert(new_tag, newBlock);
+
+ if(after)
+ index++;
+
+ m_textblockVector.insert(index,newBlock);
+
+ return true;
+}
+
+/**
+ * Get the value of m_dialog
+ * @return the value of m_dialog
+ */
+/*
+CodeDocumentDialog * CodeDocument::getDialog ( ) {
+ return m_dialog;
+}
+*/
+
+// Other methods
+//
+
+QString CodeDocument::cleanName ( const QString &name ) {
+ return CodeGenerator::cleanName(name);
+}
+
+// update the text and status of the head comment
+void CodeDocument::updateHeader () {
+
+ //try to find a heading file (license, coments, etc) then extract its text
+ QString headingText = UMLApp::app()->getCommonPolicy()->getHeadingFile(getFileExtension());
+
+ headingText.replace(QRegExp("%filename%"),getFileName()+getFileExtension());
+ headingText.replace(QRegExp("%filepath%"),getPath());
+ headingText.replace( QRegExp("%time%"), QTime::currentTime().toString());
+ headingText.replace( QRegExp("%date%"), QDate::currentDate().toString());
+
+ getHeader()->setText(headingText);
+
+ // update the write out status of the header
+ if(UMLApp::app()->getCommonPolicy()->getIncludeHeadings())
+ getHeader()->setWriteOutText(true);
+ else
+ getHeader()->setWriteOutText(false);
+
+}
+
+/**
+ * create the string representation of this object.
+ * @return QString
+ */
+QString CodeDocument::toString ( ) {
+
+ // IF the whole document is turned "Off" then don't bother
+ // checking individual code blocks, just send back empty string
+ if(!getWriteOutCode())
+ return QString("");
+
+ QString content = getHeader()->toString();
+
+ // update the time/date
+
+ // comments, import, package codeblocks go next
+ TextBlockList * items = getTextBlockList();
+ for (TextBlock *c = items->first(); c; c = items->next())
+ {
+ if(c->getWriteOutText()) {
+ QString str = c->toString();
+ if(!str.isEmpty())
+ content.append(str);
+ }
+ }
+ return content;
+}
+
+void CodeDocument::synchronize() {
+ updateContent();
+}
+
+// need to overload method to beable to clear the childTextBlockMap
+void CodeDocument::resetTextBlocks() {
+ CodeGenObjectWithTextBlocks::resetTextBlocks();
+ m_childTextBlockTagMap.clear();
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeDocument::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void CodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement)
+{
+
+ // superclass call
+ CodeGenObjectWithTextBlocks::setAttributesOnNode(doc,docElement);
+
+ // now set local attributes/fields
+ docElement.setAttribute("fileName",getFileName());
+ docElement.setAttribute("fileExt",getFileExtension());
+ Uml::IDType pkgId = Uml::id_None;
+ if (m_package)
+ pkgId = m_package->getID();
+ docElement.setAttribute("package", ID2STR(pkgId));
+ docElement.setAttribute("writeOutCode",getWriteOutCode()?"true":"false");
+ docElement.setAttribute("id",getID());
+
+ // set the a header
+ // which we will store in its own separate child node block
+ QDomElement commElement = doc.createElement( "header" );
+ getHeader()->saveToXMI(doc, commElement); // comment
+ docElement.appendChild( commElement);
+
+ // doc codePolicy?
+ // FIX: store ONLY if different from the parent generator
+ // policy.. something which is not possible right now. -b.t.
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeDocument::setAttributesFromNode ( QDomElement & root) {
+
+ // now set local attributes
+ setFileName(root.attribute("fileName",""));
+ setFileExtension(root.attribute("fileExt",""));
+ QString pkgStr = root.attribute("package","");
+ if (!pkgStr.isEmpty() && pkgStr != "-1") {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (pkgStr.contains( QRegExp("\\D") )) {
+ // suspecting pre-1.5.3 file format where the package name was
+ // saved instead of the package ID.
+ UMLObject *o = umldoc->findUMLObject(pkgStr);
+ m_package = dynamic_cast<UMLPackage*>(o);
+ }
+ if (m_package == NULL) {
+ UMLObject *o = umldoc->findObjectById(STR2ID(pkgStr));
+ m_package = dynamic_cast<UMLPackage*>(o);
+ }
+ }
+ setWriteOutCode(root.attribute("writeOutCode","true") == "true" ? true : false);
+ setID(root.attribute("id",""));
+
+ // load comment now
+ // by looking for our particular child element
+ QDomNode node = root.firstChild();
+ QDomElement element = node.toElement();
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if( tag == "header" ) {
+ QDomNode cnode = element.firstChild();
+ QDomElement celem = cnode.toElement();
+ getHeader()->loadFromXMI(celem);
+ break;
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ // a rare case where the super-class load is AFTER local attributes
+ CodeGenObjectWithTextBlocks::setAttributesFromNode(root);
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void CodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement docElement = doc.createElement( "codedocument" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+// vanilla code documents don't have much
+// to do.. override this with a different
+// version for your own documents
+void CodeDocument::updateContent() {
+ updateHeader(); // doing this insures time/date stamp is at the time of this call
+}
+
+/**
+ * create a new CodeBlock object belonging to this CodeDocument.
+ * @return CodeBlock
+ */
+CodeBlock * CodeDocument::newCodeBlock ( ) {
+ return new CodeBlock(this);
+}
+
+/**
+ * create a new CodeBlockWithComments object belonging to this CodeDocument.
+ * @return CodeBlockWithComments
+ */
+CodeBlockWithComments * CodeDocument::newCodeBlockWithComments ( ) {
+ return new CodeBlockWithComments(this);
+}
+
+HierarchicalCodeBlock * CodeDocument::newHierarchicalCodeBlock ( ) {
+ HierarchicalCodeBlock *hb = new HierarchicalCodeBlock(this);
+ //hb->update();
+ return hb;
+}
+
+void CodeDocument::removeChildTagFromMap ( const QString &tag )
+{
+ m_childTextBlockTagMap.erase(tag);
+}
+
+void CodeDocument::addChildTagToMap ( const QString &tag, TextBlock * tb)
+{
+ m_childTextBlockTagMap.insert(tag, tb);
+}
+
+TextBlock * CodeDocument::findTextBlockByTag( const QString &tag , bool descendIntoChildren)
+{
+ //if we already know to which file this class was written/should be written, just return it.
+ if(m_textBlockTagMap.contains(tag))
+ return m_textBlockTagMap[tag];
+
+ if (descendIntoChildren)
+ if(m_childTextBlockTagMap.contains(tag))
+ return m_childTextBlockTagMap[tag];
+
+ return (TextBlock*) NULL;
+}
+
+void CodeDocument::initDoc () {
+
+ m_writeOutCode = true;
+ m_package = NULL;
+ m_fileExtension = QString("");
+ m_ID = QString(""); // leave with NO ID as a default
+
+ //m_textblockVector.setAutoDelete(false);
+
+ setHeader(new CodeComment(this));
+
+ lastTagIndex = 0;
+
+ // m_dialog = new CodeDocumentDialog( );
+
+}
+
+TextBlock * CodeDocument::findCodeClassFieldTextBlockByTag ( const QString &tag ) {
+ kWarning()<<"Called findCodeClassFieldMethodByTag("<<tag<<") for a regular CodeDocument"<<endl;
+ return (TextBlock *) NULL;
+}
+
+#include "codedocument.moc"
diff --git a/umbrello/umbrello/codedocument.h b/umbrello/umbrello/codedocument.h
new file mode 100644
index 00000000..609b70c6
--- /dev/null
+++ b/umbrello/umbrello/codedocument.h
@@ -0,0 +1,273 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+#ifndef CODEDOCUMENT_H
+#define CODEDOCUMENT_H
+
+#include <qobject.h>
+#include <qmap.h>
+#include <qstring.h>
+
+#include "codegenerationpolicy.h"
+#include "codegenobjectwithtextblocks.h"
+#include "hierarchicalcodeblock.h"
+
+class QWidget;
+class CodeAccessorMethod;
+class CodeBlockWithComments;
+class CodeComment;
+class CodeOperation;
+class TextBlock;
+class UMLPackage;
+
+//#include "codedocumentdialog.h"
+
+/**
+ * class CodeDocument
+ * A document containing the code for one file.
+ */
+
+// "friend" status is needed for HBlock so it may call addChildTagToMap which
+// is protected.
+class CodeDocument : public QObject, public CodeGenObjectWithTextBlocks
+{
+ friend class HierarchicalCodeBlock;
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Empty Constructor
+ */
+ /**
+ * Basic constructor for class.
+ */
+ CodeDocument ( );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeDocument ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_fileExtension
+ * @param new_var the new value of m_fileExtension
+ */
+ void setFileExtension ( const QString &new_var );
+
+ /**
+ * Get the value of m_fileExtension
+ * @return the value of m_fileExtension
+ */
+ QString getFileExtension ( ) const;
+
+ /**
+ * Set the complete value (name plus any extension) of m_filename
+ * @param new_var the new value of m_filename
+ */
+ void setFileName ( const QString &new_var );
+
+ /**
+ * Get the value of m_filename. This name is the "complete" filename,
+ * meaning that it contains both the file name plus any extension (e.g. "file.cpp")
+ * @return the value of m_filename
+ */
+ QString getFileName ( ) const;
+
+ /**
+ * Set the value of m_package
+ * @param new_var the new value of m_package
+ */
+ void setPackage ( UMLPackage *new_var );
+
+ /**
+ * Get the value of the package of this codedocument.
+ * @return the value of m_pathName
+ */
+ QString getPackage ( ) const;
+
+ /**
+ * Get the value of the path to this codedocument.
+ * @return the value of m_pathName
+ */
+ virtual QString getPath ( );
+
+ /**
+ * Set the value of m_ID
+ * @param new_id the new value of m_ID
+ */
+ void setID ( const QString &new_id);
+
+ /**
+ * Get the value of m_ID
+ * @return the value of m_ID
+ */
+ QString getID ( ) const;
+
+ /**
+ * Set the value of m_writeOutCode
+ * Whether or not to write out this code document and any codeblocks, etc that it
+ * owns.
+ * @param new_var the new value of m_writeOutCode
+ */
+ void setWriteOutCode ( bool new_var );
+
+ /**
+ * Get the value of m_writeOutCode
+ * Whether or not to write out this code document and any codeblocks, etc that it
+ * owns.
+ * @return the value of m_writeOutCode
+ */
+ bool getWriteOutCode ( );
+
+ /**
+ * Set a Header comment object
+ */
+ void setHeader ( CodeComment * comment );
+
+ /**
+ * Get the Header comment object
+ */
+ CodeComment * getHeader ( );
+
+ /**
+ * Insert a new text block after the existing text block. Returns
+ * false if it cannot insert the textblock.
+ */
+ bool insertTextBlock (TextBlock * newBlock, TextBlock * existingBlock, bool after = true);
+
+ /**
+ * Lookup a certain textblock by its tag value, returns NULL if it cant
+ * find the TextBlock with such a tag. If descendIntoChildren is true, then
+ * any child hierarchical textblocks will also be searched for a match.
+ */
+ TextBlock * findTextBlockByTag( const QString &tag , bool descendIntoChildren = false);
+
+ /**
+ * create the string representation of this object.
+ * @return QString
+ */
+ virtual QString toString ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /**
+ * create a new CodeBlock object belonging to this CodeDocument.
+ * @return CodeBlock
+ */
+ virtual CodeBlock * newCodeBlock ( );
+
+ /**
+ * create a new HierarchicalCodeBlock object belonging to this CodeDocument.
+ * @return HierarchicalCodeBlock
+ */
+ virtual HierarchicalCodeBlock * newHierarchicalCodeBlock ( );
+
+ /**
+ * create a new CodeBlockWithComments object belonging to this CodeDocument.
+ * @return CodeBlockWithComments
+ */
+ virtual CodeBlockWithComments * newCodeBlockWithComments ( );
+
+ // return a unique, and currently unallocated, text block tag for this document
+ virtual QString getUniqueTag( const QString& prefix = QString("") );
+
+ /** a little utility method to make life easier for the code document programmer
+ */
+ QString cleanName ( const QString &name );
+
+ // Cause this code document to synchronize to current generator policy
+ virtual void synchronize();
+
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ // these next 2 are needed by child hierarchical code blocks so
+ // that when they call getUniqueTag, we really get a unique tag
+ // Also, it allows 'findTextBlockByTag' To find any tagged text block
+ // anywhere in the document, whether directly owned by the document OR
+ // by some child hierarchical textblock
+ void addChildTagToMap ( const QString &tag, TextBlock * tb);
+ void removeChildTagFromMap ( const QString &tag );
+
+ // update the header text of this codedocument
+ void updateHeader ();
+
+ // reset/clear our inventory of textblocks in this document
+ void resetTextBlocks();
+
+ // update the content of this code document
+ // this is where you should lay out your code document structure of textblocks
+ // in the inheriting class, should it have any text in it.
+ virtual void updateContent();
+
+ // have to implement this for CodeObjectWithTextBlocks
+ // doenst actually do anythying fo ra vannilla code document
+ virtual TextBlock * findCodeClassFieldTextBlockByTag( const QString &tag );
+
+private:
+
+ int lastTagIndex;
+ QString m_filename;
+ QString m_fileExtension;
+ QString m_ID;
+ QString m_pathName;
+ UMLPackage *m_package;
+
+ bool m_writeOutCode; // Whether or not to write out this code document
+ // and any codeblocks, etc that it owns.
+
+ CodeComment * m_header;
+
+
+ void initDoc ( ) ;
+
+ // TextBlockList m_textblockVector;
+ // QMap<QString, TextBlock *> m_textBlockTagMap;
+
+ // for recording all of the textblocks held by child hierarchical codeblocks
+ QMap<QString, TextBlock *> m_childTextBlockTagMap;
+
+};
+
+#endif // CODEDOCUMENT_H
diff --git a/umbrello/umbrello/codedocumentlist.h b/umbrello/umbrello/codedocumentlist.h
new file mode 100644
index 00000000..7cb28a72
--- /dev/null
+++ b/umbrello/umbrello/codedocumentlist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef _CODEDOCUMENTLIST_H
+#define _CODEDOCUMENTLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class CodeDocument;
+
+typedef QPtrList<CodeDocument> CodeDocumentList;
+typedef QPtrListIterator<CodeDocument> CodeDocumentListIt;
+
+#endif
diff --git a/umbrello/umbrello/codegenerationpolicy.cpp b/umbrello/umbrello/codegenerationpolicy.cpp
new file mode 100644
index 00000000..df84e837
--- /dev/null
+++ b/umbrello/umbrello/codegenerationpolicy.cpp
@@ -0,0 +1,587 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+// own header
+#include "codegenerationpolicy.h"
+
+//system includes
+#include <cstdlib> //to get the user name
+
+// qt includes
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qdatetime.h>
+
+// kde includes
+#include <kconfig.h>
+#include <kdeversion.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "dialogs/codegenerationpolicypage.h"
+
+using namespace std;
+
+#define MAXLINES 256
+
+CodeGenerationPolicy::OverwritePolicy CodeGenerationPolicy::defaultOverwritePolicy() const {
+ return Ask;
+}
+
+bool CodeGenerationPolicy::defaultVerboseSectionComments() const {
+ return true;
+}
+
+bool CodeGenerationPolicy::defaultVerboseDocumentComments() const {
+ return true;
+}
+
+bool CodeGenerationPolicy::defaultIncludeHeadings() const {
+ return true;
+}
+
+CodeGenerationPolicy::NewLineType CodeGenerationPolicy::defaultLineEndingType() const {
+ return UNIX;
+}
+
+CodeGenerationPolicy::IndentationType CodeGenerationPolicy::defaultIndentType() const {
+ return SPACE;
+}
+
+int CodeGenerationPolicy::defaultIndentAmount() const {
+ return 2;
+}
+
+CodeGenerationPolicy::ModifyNamePolicy CodeGenerationPolicy::defaultModifyNamePolicy() const {
+ return No;
+}
+
+CodeGenerationPolicy::CommentStyle CodeGenerationPolicy::defaultCommentStyle() const {
+ return SingleLine;
+}
+
+CodeGenerationPolicy::ScopePolicy CodeGenerationPolicy::defaultAttribAccessorScope() const {
+ return FromParent;
+}
+
+CodeGenerationPolicy::ScopePolicy CodeGenerationPolicy::defaultAssocFieldScope() const {
+ return FromParent;
+}
+
+bool CodeGenerationPolicy::defaultAutoGenerateConstructors() const {
+ return false;
+}
+
+
+// Constructors/Destructors
+//
+
+CodeGenerationPolicy::CodeGenerationPolicy(CodeGenerationPolicy * clone)
+{
+
+ initFields();
+ setDefaults(clone,false);
+}
+
+CodeGenerationPolicy::CodeGenerationPolicy(KConfig * config)
+{
+ initFields();
+ setDefaults(config,false);
+}
+
+CodeGenerationPolicy::~CodeGenerationPolicy ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+/**
+ * Set the value of m_overwritePolicy
+ * Policy of how to deal with overwriting existing files. Allowed values are "ask",
+ * "yes" and "no".
+ * @param new_var the new value of m_overwritePolicy
+ */
+void CodeGenerationPolicy::setOverwritePolicy ( OverwritePolicy new_var ) {
+ m_overwritePolicy = new_var;
+}
+
+/**
+ * Get the value of m_overwritePolicy
+ * Policy of how to deal with overwriting existing files. Allowed values are "ask",
+ * "yes" and "no".
+ * @return the value of m_overwritePolicy
+ */
+CodeGenerationPolicy::OverwritePolicy CodeGenerationPolicy::getOverwritePolicy ( ) const {
+ return m_overwritePolicy;
+}
+
+/**
+ * Set the value of m_commentStyle
+ * @param new_var the new value of m_commentStyle
+ */
+void CodeGenerationPolicy::setCommentStyle ( CommentStyle new_var ) {
+ m_commentStyle = new_var;
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_commentStyle
+ * @return the value of m_commentStyle
+ */
+CodeGenerationPolicy::CommentStyle CodeGenerationPolicy::getCommentStyle ( ) {
+ return m_commentStyle;
+}
+
+/**
+ * Set the value of m_codeVerboseSectionComments
+ * Whether or not verbose code commenting for sections is desired. If true, comments
+ * for sections will be written even if the section is empty.
+ * @param new_var the new value of m_codeVerboseSectionComments
+ */
+void CodeGenerationPolicy::setCodeVerboseSectionComments ( bool new_var ) {
+ m_codeVerboseSectionComments = new_var;
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_codeVerboseSectionComments
+ * Whether or not verbose code commenting for sections is desired. If true, comments
+ * for sections will be written even if the section is empty.
+ * @return the value of m_codeVerboseSectionComments
+ */
+bool CodeGenerationPolicy::getCodeVerboseSectionComments ( ) const {
+ return m_codeVerboseSectionComments;
+}
+
+/**
+ * Set the value of m_codeVerboseDocumentComments
+ * Whether or not verbose code commenting for documentation is desired. If true,
+ * documentation for various code will be written even if no code would normally be
+ * created at that point in the file.
+ * @param new_var the new value of m_codeVerboseDocumentComments
+ */
+void CodeGenerationPolicy::setCodeVerboseDocumentComments ( bool new_var ) {
+ m_codeVerboseDocumentComments = new_var;
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_codeVerboseDocumentComments
+ * Whether or not verbose code commenting for documentation is desired. If true,
+ * documentation for various code will be written even if no code would normally be
+ * created at that point in the file.
+ * @return the value of m_codeVerboseDocumentComments
+ */
+bool CodeGenerationPolicy::getCodeVerboseDocumentComments ( ) const {
+ return m_codeVerboseDocumentComments;
+}
+
+/**
+ * Set the value of m_headingFileDir
+ * location of the header file template.
+ * @param new_var the new value of m_headingFileDir
+ */
+void CodeGenerationPolicy::setHeadingFileDir ( const QString & path) {
+ m_headingFiles.setPath(path);
+}
+
+/**
+ * Get the value of m_headingFileDir
+ * location of the header file template.
+ * @return the value of m_headingFileDir
+ */
+QString CodeGenerationPolicy::getHeadingFileDir ( ) const {
+ return m_headingFiles.absPath();
+}
+
+/**
+ * Set the value of m_includeHeadings
+ * @param new_var the new value of m_includeHeadings
+ */
+void CodeGenerationPolicy::setIncludeHeadings ( bool new_var ) {
+ m_includeHeadings = new_var;
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_includeHeadings
+ * @return the value of m_includeHeadings
+ */
+bool CodeGenerationPolicy::getIncludeHeadings ( ) const {
+ return m_includeHeadings;
+}
+
+/**
+ * Set the value of m_outputDirectory
+ * location of where output files will go.
+ * @param new_var the new value of m_outputDirectory
+ */
+void CodeGenerationPolicy::setOutputDirectory ( QDir new_var ) {
+ m_outputDirectory = new_var;
+}
+
+/**
+ * Get the value of m_outputDirectory
+ * location of where output files will go.
+ * @return the value of m_outputDirectory
+ */
+QDir CodeGenerationPolicy::getOutputDirectory ( ) {
+ return m_outputDirectory;
+}
+
+/**
+ * Set the value of m_lineEndingType
+ * What line ending characters to use.
+ * @param new_var the new value of m_lineEndingType
+ */
+void CodeGenerationPolicy::setLineEndingType ( NewLineType type) {
+ m_lineEndingType = type;
+ switch (m_lineEndingType) {
+ case MAC:
+ m_lineEndingChars = QString("\r\n");
+ break;
+ case DOS:
+ m_lineEndingChars = QString("\r");
+ break;
+ case UNIX:
+ default:
+ m_lineEndingChars = QString("\n");
+ break;
+ }
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_lineEndingType
+ * What line ending characters to use.
+ * @return the value of m_lineEndingType
+ */
+CodeGenerationPolicy::NewLineType CodeGenerationPolicy::getLineEndingType ( ) {
+ return m_lineEndingType;
+}
+
+/** Utility function to get the actual characters.
+ */
+QString CodeGenerationPolicy::getNewLineEndingChars ( ) const {
+ return m_lineEndingChars;
+}
+
+/**
+ * Set the value of m_indentationType
+ * The amount and type of whitespace to indent with.
+ * @param new_var the new value of m_indentationType
+ */
+void CodeGenerationPolicy::setIndentationType ( IndentationType new_var ) {
+ m_indentationType = new_var;
+ calculateIndentation();
+ emit modifiedCodeContent();
+}
+
+CodeGenerationPolicy::IndentationType CodeGenerationPolicy::getIndentationType ( ) {
+ return m_indentationType;
+}
+
+void CodeGenerationPolicy::setIndentationAmount ( int amount ) {
+ if(amount > -1)
+ {
+ m_indentationAmount = amount;
+ calculateIndentation();
+ emit modifiedCodeContent();
+ }
+}
+
+int CodeGenerationPolicy::getIndentationAmount ( ) {
+ return m_indentationAmount;
+}
+
+/**
+ * Utility method to get the amount (and type of whitespace) to indent with.
+ * @return the value of the indentation
+ */
+QString CodeGenerationPolicy::getIndentation ( ) const {
+ return m_indentation;
+}
+
+void CodeGenerationPolicy::calculateIndentation ( ) {
+ QString indent = "";
+ m_indentation = "";
+ switch (m_indentationType) {
+ case NONE:
+ break;
+ case TAB:
+ indent = QString("\t");
+ break;
+ default:
+ case SPACE:
+ indent = QString(" ");
+ break;
+ }
+
+ for (int i=0; i < m_indentationAmount; i++)
+ m_indentation += indent;
+}
+
+/**
+ * Set the value of m_modifyPolicy
+ * @param new_var the new value of m_modifyPolicy
+ */
+void CodeGenerationPolicy::setModifyPolicy ( ModifyNamePolicy new_var ) {
+ m_modifyPolicy = new_var;
+}
+
+/**
+ * Get the value of m_modifyPolicy
+ * @return the value of m_modifyPolicy
+ */
+CodeGenerationPolicy::ModifyNamePolicy CodeGenerationPolicy::getModifyPolicy ( ) const {
+ return m_modifyPolicy;
+}
+
+/**
+ * Set the value of m_autoGenerateConstructors
+ * @param new_var the new value
+ */
+void CodeGenerationPolicy::setAutoGenerateConstructors( bool var ) {
+ m_autoGenerateConstructors = var;
+ emit modifiedCodeContent();
+}
+
+/**
+ * Get the value of m_autoGenerateConstructors
+ * @return the value of m_autoGenerateConstructors
+ */
+bool CodeGenerationPolicy::getAutoGenerateConstructors( ){
+ return m_autoGenerateConstructors;
+}
+
+void CodeGenerationPolicy::setAttributeAccessorScope(ScopePolicy var) {
+ m_attributeAccessorScope = var;
+ emit modifiedCodeContent();
+}
+
+CodeGenerationPolicy::ScopePolicy CodeGenerationPolicy::getAttributeAccessorScope() {
+ return m_attributeAccessorScope;
+}
+
+void CodeGenerationPolicy::setAssociationFieldScope(ScopePolicy var) {
+ m_associationFieldScope = var;
+ emit modifiedCodeContent();
+}
+
+CodeGenerationPolicy::ScopePolicy CodeGenerationPolicy::getAssociationFieldScope() {
+ return m_associationFieldScope;
+}
+
+/**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+CodeGenerationPolicyPage * CodeGenerationPolicy::createPage ( QWidget *pWidget, const char *name ) {
+ return new CodeGenerationPolicyPage ( pWidget, name, 0 );
+}
+
+// Other methods
+//
+
+void CodeGenerationPolicy::emitModifiedCodeContentSig() {
+ if (!UMLApp::app()->getDocument()->loading())
+ emit modifiedCodeContent();
+}
+
+void CodeGenerationPolicy::setDefaults ( CodeGenerationPolicy * clone , bool emitUpdateSignal)
+{
+
+ if(!clone)
+ return;
+
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ setCodeVerboseSectionComments ( clone->getCodeVerboseSectionComments() );
+ setCodeVerboseDocumentComments ( clone->getCodeVerboseDocumentComments() );
+ setHeadingFileDir ( clone->getHeadingFileDir());
+ setIncludeHeadings ( clone->getIncludeHeadings());
+ setOutputDirectory ( clone->getOutputDirectory());
+ setLineEndingType ( clone->getLineEndingType());
+ setIndentationAmount ( clone->getIndentationAmount());
+ setIndentationType ( clone->getIndentationType());
+ setModifyPolicy ( clone->getModifyPolicy());
+ setOverwritePolicy ( clone->getOverwritePolicy() );
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ emit modifiedCodeContent();
+
+}
+
+void CodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal)
+{
+
+ if(!config)
+ return;
+
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ config -> setGroup("Code Generation");
+ setAttributeAccessorScope((ScopePolicy)config->readNumEntry("defaultAttributeAccessorScope",defaultAttribAccessorScope()));
+ setAssociationFieldScope((ScopePolicy)config->readNumEntry("defaultAssocFieldScope",defaultAssocFieldScope()));
+ setCommentStyle((CommentStyle)config->readNumEntry("commentStyle",defaultCommentStyle()));
+ setAutoGenerateConstructors(config->readBoolEntry("autoGenEmptyConstructors",defaultAutoGenerateConstructors()));
+ setCodeVerboseDocumentComments( config->readBoolEntry("forceDoc",defaultVerboseDocumentComments()) );
+ setCodeVerboseSectionComments( config->readBoolEntry("forceSections",defaultVerboseSectionComments()) );
+ setLineEndingType( (NewLineType) config->readNumEntry("lineEndingType",defaultLineEndingType()) );
+ setIndentationType( (IndentationType) config->readNumEntry("indentationType",defaultIndentType()) );
+ setIndentationAmount( config->readNumEntry("indentationAmount",defaultIndentAmount()));
+
+ QString path = config -> readPathEntry("outputDirectory");
+ if(path.isEmpty())
+ path = QDir::homeDirPath() + "/uml-generated-code/";
+ setOutputDirectory ( QDir (path) );
+
+ path = config -> readPathEntry("headingsDirectory");
+ if(path.isEmpty()) {
+ KStandardDirs stddirs;
+ path = stddirs.findDirs("data","umbrello/headings").first();
+ }
+ setHeadingFileDir ( path );
+
+ setIncludeHeadings( config->readBoolEntry("includeHeadings",defaultIncludeHeadings()) );
+ setOverwritePolicy( (OverwritePolicy)config->readNumEntry("overwritePolicy",defaultOverwritePolicy()));
+ setModifyPolicy( (ModifyNamePolicy)config->readNumEntry("modnamePolicy",defaultModifyNamePolicy()));
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ emit modifiedCodeContent();
+
+}
+
+void CodeGenerationPolicy::writeConfig (KConfig * config) {
+
+ config->setGroup("Code Generation");
+
+ config->writeEntry("defaultAttributeAccessorScope",getAttributeAccessorScope());
+ config->writeEntry("defaultAssocFieldScope",getAssociationFieldScope());
+ config->writeEntry("commentStyle",getCommentStyle());
+ config->writeEntry("autoGenEmptyConstructors",getAutoGenerateConstructors());
+ //config->writeEntry("newCodegen", getNewCodegen());
+ config->writeEntry("forceDoc",getCodeVerboseDocumentComments());
+ config->writeEntry("forceSections",getCodeVerboseSectionComments());
+
+ config->writeEntry("lineEndingType",getLineEndingType());
+ config->writeEntry("indentationType",getIndentationType());
+ config->writeEntry("indentationAmount",getIndentationAmount());
+
+ config->writePathEntry("outputDirectory",getOutputDirectory().absPath());
+ config->writePathEntry("headingsDirectory",getHeadingFileDir());
+ config->writeEntry("includeHeadings",getIncludeHeadings());
+ config->writeEntry("overwritePolicy",getOverwritePolicy());
+ config->writeEntry("modnamePolicy", getModifyPolicy());
+
+}
+
+// return the actual text
+QString CodeGenerationPolicy::getHeadingFile(const QString& str) {
+
+ if(!getIncludeHeadings() || str.isEmpty())
+ return QString("");
+ if(str.contains(" ") ||str.contains(";")) {
+ kWarning() << "File folder must not have spaces or semi colons!" << endl;
+ return QString("");
+ }
+ //if we only get the extension, then we look for the default
+ // heading.[extension]. If there is no such file, we try to
+ // get any file with the same extension
+ QString filename;
+ if(str.startsWith(".")) {
+ if(QFile::exists(m_headingFiles.absFilePath("heading"+str)))
+ filename = m_headingFiles.absFilePath("heading"+str);
+ else {
+ m_headingFiles.setNameFilter('*' + str);
+ //if there is more than one match we just take the first one
+ filename = m_headingFiles.absFilePath(m_headingFiles.entryList().first());
+ // kWarning() << "header file name set to " << filename << " because it was *" << endl;
+ }
+ } else { //we got a file name (not only extension)
+ filename = m_headingFiles.absFilePath(str);
+ }
+
+ QFile f(filename);
+ if(!f.open(IO_ReadOnly)) {
+ // kWarning() << "Error opening heading file: " << f.name() << endl;
+ // kWarning() << "Headings directory was " << m_headingFiles.absPath() << endl;
+ return QString("");
+ }
+
+ QTextStream ts(&f);
+ QString retstr = QString("");
+ QString endLine = getNewLineEndingChars();
+ for(int l = 0; l < MAXLINES && !ts.atEnd(); l++)
+ retstr += ts.readLine()+endLine;
+
+ //do variable substitution
+ retstr.replace( QRegExp("%author%"),QString(getenv("USER"))); //get the user name from some where else
+ retstr.replace( QRegExp("%headingpath%"),filename );
+ retstr.replace( QRegExp("%time%"), QTime::currentTime().toString());
+ retstr.replace( QRegExp("%date%"), QDate::currentDate().toString());
+ // the replace filepath, time parts are also in the code document updateHeader method
+ // (which is not a virtual function)...
+
+ return retstr;
+}
+
+void CodeGenerationPolicy::initFields ( ) {
+
+ blockSignals(true);
+
+ m_overwritePolicy = defaultOverwritePolicy();
+ m_codeVerboseSectionComments = defaultVerboseSectionComments();
+ m_codeVerboseDocumentComments = defaultVerboseDocumentComments();
+ m_includeHeadings = defaultIncludeHeadings();
+ setLineEndingType(defaultLineEndingType());
+ m_indentationType = defaultIndentType();
+ m_indentationAmount = defaultIndentAmount();
+ m_modifyPolicy = defaultModifyNamePolicy();
+ m_autoGenerateConstructors = defaultAutoGenerateConstructors();
+ m_attributeAccessorScope = defaultAttribAccessorScope();
+ m_associationFieldScope = defaultAssocFieldScope();
+ m_commentStyle = defaultCommentStyle();
+
+ m_outputDirectory.setPath(QDir::home().absPath() + "/uml-generated-code/");
+ m_headingFiles.setPath(QDir::home().absPath() + "/headings/");
+
+ calculateIndentation();
+
+ blockSignals(false);
+}
+
+#include "codegenerationpolicy.moc"
diff --git a/umbrello/umbrello/codegenerationpolicy.h b/umbrello/umbrello/codegenerationpolicy.h
new file mode 100644
index 00000000..3293ec6c
--- /dev/null
+++ b/umbrello/umbrello/codegenerationpolicy.h
@@ -0,0 +1,384 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+
+
+#ifndef CODEGENERATIONPOLICY_H
+#define CODEGENERATIONPOLICY_H
+
+#include <qobject.h>
+#include <qdir.h>
+#include <qdom.h>
+
+class QWidget;
+class KConfig;
+class CodeGenerationPolicyPage;
+
+/**
+ * class CodeGenerationPolicy
+ * This class describes the code generation policy for this project.
+ */
+
+class CodeGenerationPolicy : public QObject {
+ Q_OBJECT
+public:
+
+ /**
+ * OverwritePolicy can have the following values
+ * - Ok: if there is a file named the same as what you want to name your output file,
+ * you can overwrite the old file.
+ * - Ask:if there is a file named the same as what you want to name your output file,
+ * you should ask the User what to do, and give him the option to overwrite the file
+ * write the code to a different file, or to abort the generation of this class.
+ * - Never: you cannot overwrite any files. Generates a new file name like "fileName1.h", "fileName2.h"
+ * until you find an appropriate name.
+ * - Cancel: Do not output anything. This is only set if the user chooses Apply to All Remaining Files
+ * and clicks on Do not Output in the Ask dialog
+ */
+ enum OverwritePolicy {Ok=0, Ask, Never, Cancel};
+ enum ModifyNamePolicy {No=0, Underscore, Capitalise};
+ enum NewLineType {UNIX=0, DOS, MAC};
+ enum IndentationType {NONE=0, TAB, SPACE};
+ enum CommentStyle { SingleLine=0, MultiLine };
+ enum ScopePolicy { Public=200, Private, Protected, FromParent };
+
+ // set some reasonable defaults
+ OverwritePolicy defaultOverwritePolicy() const;
+ bool defaultVerboseSectionComments() const;
+ bool defaultVerboseDocumentComments() const;
+ bool defaultIncludeHeadings() const;
+ NewLineType defaultLineEndingType() const;
+ IndentationType defaultIndentType() const;
+ int defaultIndentAmount() const;
+ ModifyNamePolicy defaultModifyNamePolicy() const;
+ CommentStyle defaultCommentStyle() const;
+ ScopePolicy defaultAttribAccessorScope() const;
+ ScopePolicy defaultAssocFieldScope() const;
+ bool defaultAutoGenerateConstructors() const;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ // note that as the code gen policy may be the 'default' policy, it may
+ // not be coupled with a code generator.
+ CodeGenerationPolicy (CodeGenerationPolicy * clone = 0);
+ CodeGenerationPolicy (KConfig * config );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeGenerationPolicy ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_overwritePolicy
+ * Policy of how to deal with overwriting existing files.
+ * OverwritePolicy can have the following values
+ * - Ok: if there is a file named the same as what you want to name your output file,
+ * you can overwrite the old file.
+ * - Ask:if there is a file named the same as what you want to name your output file,
+ * you should ask the User what to do, and give him the option to overwrite the file
+ * write the code to a different file, or to abort the generation of this class.
+ * - Never: you cannot overwrite any files. Generates a new file name like "fileName1.h", "fileName2.h"
+ * until you find an appropriate name.
+ * - Cancel: Do not output anything. This is only set if the user chooses Apply to All Remaining Files
+ * and clicks on Do not Output in the Ask dialog
+ *
+ * @param new_var the new value of m_overwritePolicy
+ */
+ void setOverwritePolicy ( OverwritePolicy new_var );
+
+ /**
+ * Get the value of m_overwritePolicy
+ * Policy of how to deal with overwriting existing files. Allowed values are "Ok", "Ask",
+ * "Never" "Cancel".
+ * @return the value of m_overwritePolicy
+ */
+ OverwritePolicy getOverwritePolicy ( ) const;
+
+
+ /**
+ * Set the value of m_codeVerboseSectionComments
+ * Whether or not verbose code commenting for sections is desired. If true, comments
+ * for sections will be written even if the section is empty.
+ * @param new_var the new value of m_codeVerboseSectionComments
+ */
+ void setCodeVerboseSectionComments ( bool new_var );
+
+ /**
+ * Get the value of m_codeVerboseSectionComments
+ * Whether or not verbose code commenting for sections is desired. If true, comments
+ * for sections will be written even if the section is empty.
+ * @return the value of m_codeVerboseSectionComments
+ */
+ bool getCodeVerboseSectionComments ( ) const;
+
+
+ /**
+ * Set the value of m_codeVerboseDocumentComments
+ * Whether or not verbose code commenting for documentation is desired. If true,
+ * documentation for various code will be written even if no code would normally be
+ * created at that point in the file.
+ * @param new_var the new value of m_codeVerboseDocumentComments
+ */
+ void setCodeVerboseDocumentComments ( bool new_var );
+
+ /**
+ * Get the value of m_codeVerboseDocumentComments
+ * Whether or not verbose code commenting for documentation is desired. If true,
+ * documentation for various code will be written even if no code would normally be
+ * created at that point in the file.
+ * @return the value of m_codeVerboseDocumentComments
+ */
+ bool getCodeVerboseDocumentComments ( ) const;
+
+ /**
+ * Set the value of m_headingFileDir
+ * location of the header file template.
+ * @param path the new path of m_headingFileDir
+ */
+ void setHeadingFileDir ( const QString & path);
+
+ /**
+ * Get the value of m_headingFileDir
+ * location of the header file template.
+ * @return the value of m_headingFileDir
+ */
+ QString getHeadingFileDir ( ) const;
+
+
+ /**
+ * Set the value of m_includeHeadings
+ * @param new_var the new value of m_includeHeadings
+ */
+ void setIncludeHeadings ( bool new_var );
+
+ /**
+ * Get the value of m_includeHeadings
+ * @return the value of m_includeHeadings
+ */
+ bool getIncludeHeadings ( ) const;
+
+
+ /**
+ * Set the value of m_outputDirectory
+ * location of where output files will go.
+ * @param new_var the new value of m_outputDirectory
+ */
+ void setOutputDirectory ( QDir new_var );
+
+ /**
+ * Get the value of m_outputDirectory
+ * location of where output files will go.
+ * @return the value of m_outputDirectory
+ */
+ QDir getOutputDirectory ( );
+
+ /**
+ * Set the value of m_lineEndingType
+ * What line ending characters to use.
+ * @param new_var the new value of m_lineEndingType
+ */
+ void setLineEndingType ( NewLineType new_var );
+
+ /**
+ * Get the value of m_lineEndingType
+ * What line ending characters to use.
+ * @return the value of m_lineEndingType
+ */
+ NewLineType getLineEndingType ( );
+
+ /** Utility function to get the actual characters.
+ */
+ QString getNewLineEndingChars ( ) const;
+
+ /**
+ * Set the value of m_indentationType
+ * The amount and type of whitespace to indent with.
+ * @param type the new value of m_indentationType
+ */
+ void setIndentationType ( IndentationType type );
+
+ /**
+ * Get the value of m_indentationType
+ */
+ IndentationType getIndentationType ( );
+
+ /** How many units to indent for each indentation level.
+ */
+ void setIndentationAmount ( int amount );
+ int getIndentationAmount ( );
+
+ /**
+ * Get the string representation of each level of indentation.
+ * The amount and type of whitespace to indent with.
+ * @return the value of m_indentationType
+ */
+ QString getIndentation ( ) const;
+
+ /**
+ * Set the value of m_modifyPolicy
+ * @param new_var the new value of m_modifyPolicy
+ */
+ void setModifyPolicy ( ModifyNamePolicy new_var );
+
+ /**
+ * Get the value of m_modifyPolicy
+ * @return the value of m_modifyPolicy
+ */
+ ModifyNamePolicy getModifyPolicy ( ) const;
+
+ /**
+ * Set the value of m_autoGenerateConstructors
+ * @param var the new value
+ */
+ void setAutoGenerateConstructors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateConstructors
+ * @return value the boolean value of m_autoGenerateConstructors
+ */
+ bool getAutoGenerateConstructors ( );
+
+ /**
+ * Set the value of m_attributeAccessorScope
+ * @param var the new value
+ */
+ void setAttributeAccessorScope(ScopePolicy var);
+
+ /**
+ * Get the value of m_attributeAccessorScope
+ * @return the ScopePolicy value of m_attributeAccessorScope
+ */
+ ScopePolicy getAttributeAccessorScope();
+
+ /**
+ * Set the value of m_associationFieldScope
+ * @param var the new value
+ */
+ void setAssociationFieldScope(ScopePolicy var);
+
+ /**
+ * Get the value of m_associationFieldScope
+ * @return the ScopePolicy value of m_associationFieldScope
+ */
+ ScopePolicy getAssociationFieldScope();
+
+ /**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+ virtual CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0);
+
+ /**
+ * Gets the heading file (as a string) to be inserted at the
+ * beginning of the generated file. you give the file type as
+ * parameter and get the string. if fileName starts with a
+ * period (.) then fileName is the extension (.cpp, .h,
+ * .java) if fileName starts with another character you are
+ * requesting a specific file (mylicensefile.txt). The files
+ * can have parameters which are denoted by %parameter%.
+ *
+ * current parameters are
+ * %author%
+ * %date%
+ * %time%
+ * %filepath%
+ */
+ QString getHeadingFile(const QString& str);
+
+ /**
+ * set the defaults for this code generator from the passed generator.
+ */
+ virtual void setDefaults (CodeGenerationPolicy * defaults, bool emitUpdateSignal = true);
+
+ /**
+ * set the defaults from a config file for this code generator from the passed KConfig pointer.
+ */
+ virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true);
+
+ /**
+ * write Default params to passed KConfig pointer.
+ */
+ virtual void writeConfig (KConfig * config);
+
+ void emitModifiedCodeContentSig();
+
+ /**
+ * Set the value of m_commentStyle
+ * @param new_var the new value of m_commentStyle
+ */
+ void setCommentStyle ( CommentStyle new_var );
+
+ /**
+ * Get the value of m_commentStyle
+ * @return the value of m_commentStyle
+ */
+ CommentStyle getCommentStyle ( );
+
+signals:
+
+ // this signal is sent whenever a change is made to the policy
+ // which could modifiy code document content
+ void modifiedCodeContent();
+
+protected:
+
+ // Policy of how to deal with overwriting existing files. Allowed values are "ask", "yes" and "no".
+ OverwritePolicy m_overwritePolicy;
+
+ // Whether or not verbose code commenting for sections is desired.
+ // If true, comments for sections will be written even if the section is empty.
+ bool m_codeVerboseSectionComments;
+
+ // Whether or not verbose code commenting for documentation is desired.
+ // If true, documentation for various code will be written even if no
+ //code would normally be created at that point in the file.
+ bool m_codeVerboseDocumentComments;
+
+ QDir m_headingFiles; // location of the header file template.
+ bool m_includeHeadings;
+ QDir m_outputDirectory; // location of where output files will go.
+ NewLineType m_lineEndingType; // What type of line ending characters to use.
+ IndentationType m_indentationType; // The amount and type of whitespace to indent with.
+ int m_indentationAmount; // The amount of units to indent with.
+ ModifyNamePolicy m_modifyPolicy;
+ bool m_autoGenerateConstructors;
+ CommentStyle m_commentStyle;
+ ScopePolicy m_attributeAccessorScope;
+ ScopePolicy m_associationFieldScope;
+
+ // these 2 private fields 'cache' the string values of other fields we may frequently call for
+ QString m_lineEndingChars;
+ QString m_indentation;
+
+ void calculateIndentation ( );
+
+protected:
+
+ void initFields ( );
+
+};
+
+#endif // CODEGENERATIONPOLICY_H
diff --git a/umbrello/umbrello/codegenerator.cpp b/umbrello/umbrello/codegenerator.cpp
new file mode 100644
index 00000000..a8c2ae23
--- /dev/null
+++ b/umbrello/umbrello/codegenerator.cpp
@@ -0,0 +1,723 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+// own header
+#include "codegenerator.h"
+
+// system includes
+#include <cstdlib> //to get the user name
+
+// qt includes
+#include <qdatetime.h>
+#include <qregexp.h>
+#include <qdir.h>
+#include <qtextstream.h>
+
+// kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+#include <kapplication.h>
+
+// app includes
+#include "dialogs/overwritedialogue.h"
+#include "dialogs/codeviewerdialog.h"
+#include "codegenerators/simplecodegenerator.h"
+#include "attribute.h"
+#include "association.h"
+#include "classifier.h"
+#include "classifiercodedocument.h"
+#include "codedocument.h"
+#include "codegenerationpolicy.h"
+#include "operation.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlattributelist.h"
+#include "umloperationlist.h"
+#include "model_utils.h"
+
+// Constructors/Destructors
+//
+
+CodeGenerator::CodeGenerator ()
+ : QObject (UMLApp::app()->getDocument())
+{
+ initFields();
+}
+
+// FIX
+// hmm. this should be pure virtual so that implemented in sub-class
+CodeGenerator::CodeGenerator (QDomElement & element )
+ : QObject (UMLApp::app()->getDocument()) {
+ initFields();
+ loadFromXMI(element); // hmm. cant call this here.. its 'pure' virtual
+}
+
+CodeGenerator::~CodeGenerator ( ) {
+ // destroy all owned codedocuments
+ CodeDocument *doc;
+ for (CodeDocumentListIt it(m_codedocumentVector);
+ (doc = it.current()) != NULL; ++it)
+ delete doc;
+ m_codedocumentVector.clear();
+}
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+QString CodeGenerator::getUniqueID(CodeDocument * codeDoc)
+{
+
+ QString id = codeDoc->getID();
+
+ // does this document already exist? then just return its present id
+ if (!id.isEmpty() && findCodeDocumentByID(id))
+ return id;
+
+ // approach now differs by whether or not its a classifier code document
+ ClassifierCodeDocument * classDoc = dynamic_cast<ClassifierCodeDocument*>(codeDoc);
+ if(classDoc) {
+ UMLClassifier *c = classDoc->getParentClassifier();
+ id = ID2STR(c->getID()); // this is supposed to be unique already..
+ } else {
+
+ QString prefix = "doc";
+ QString id = prefix + "_0";
+ int number = lastIDIndex;
+ for ( ; findCodeDocumentByID(id); number++) {
+ id = prefix + '_' + QString::number(number);
+ }
+ lastIDIndex = number;
+ }
+
+ return id;
+}
+
+CodeDocument * CodeGenerator::findCodeDocumentByID( const QString &tag ) {
+ //if we already know to which file this class was written/should be written, just return it.
+ CodeDocument * doc = (CodeDocument*)NULL;
+ if((doc = m_codeDocumentDictionary.find(tag)))
+ return doc;
+
+ return doc;
+}
+
+bool CodeGenerator::addCodeDocument ( CodeDocument * doc )
+{
+ QString tag = doc->getID();
+
+ // assign a tag if one doesn't already exist
+ if(tag.isEmpty())
+ {
+ tag = getUniqueID(doc);
+ doc->setID(tag);
+ }
+
+ if(m_codeDocumentDictionary.find(tag))
+ return false; // return false, we already have some object with this tag in the list
+ else
+ m_codeDocumentDictionary.insert(tag, doc);
+
+ m_codedocumentVector.append(doc);
+ return true;
+}
+
+/**
+ * Remove a CodeDocument object from m_codedocumentVector List
+ */
+bool CodeGenerator::removeCodeDocument ( CodeDocument * remove_object ) {
+ QString tag = remove_object->getID();
+ if(!(tag.isEmpty()))
+ m_codeDocumentDictionary.remove(tag);
+ else
+ return false;
+
+ m_codedocumentVector.remove(remove_object);
+ return true;
+}
+
+/**
+ * Get the list of CodeDocument objects held by m_codedocumentVector
+ * @return QPtrList<CodeDocument *> list of CodeDocument objects held by
+ * m_codedocumentVector
+ */
+CodeDocumentList * CodeGenerator::getCodeDocumentList ( ) {
+ return &m_codedocumentVector;
+}
+
+// the vanilla version
+CodeViewerDialog * CodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc,
+ Settings::CodeViewerState state)
+{
+ return new CodeViewerDialog(parent, doc, state);
+}
+
+// Other methods
+//
+
+void CodeGenerator::loadFromXMI (QDomElement & qElement ) {
+
+ // don't do anything for simple (compatability) code generators
+ if(dynamic_cast<SimpleCodeGenerator*>(this))
+ return;
+
+ //now look for our particular child element
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ QString langType = Model_Utils::progLangToString( getLanguage() );
+
+ if (qElement.tagName() != "codegenerator"
+ || qElement.attribute("language", "UNKNOWN") != langType)
+ return;
+ // got our code generator element, now load
+ // codedocuments
+ QDomNode codeDocNode = qElement.firstChild();
+ QDomElement codeDocElement = codeDocNode.toElement();
+ while( !codeDocElement.isNull() ) {
+
+ QString docTag = codeDocElement.tagName();
+ if( docTag == "codedocument" ||
+ docTag == "classifiercodedocument"
+ ) {
+ QString id = codeDocElement.attribute( "id", "-1" );
+ CodeDocument * codeDoc = findCodeDocumentByID(id);
+ if(codeDoc)
+ codeDoc->loadFromXMI(codeDocElement);
+ else {
+ kWarning()<<" loadFromXMI: missing code document w/ id:"<<id<<", plowing ahead with pre-generated one."<<endl;
+ }
+ } else
+ kWarning()<<" loadFromXMI : got strange codegenerator child node:"<<docTag<<", ignoring."<<endl;
+
+ codeDocNode = codeDocElement.nextSibling();
+ codeDocElement = codeDocNode.toElement();
+ }
+}
+
+void CodeGenerator::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QString langType = Model_Utils::progLangToString( getLanguage() );
+ QDomElement docElement = doc.createElement( "codegenerator" );
+ docElement.setAttribute("language",langType);
+
+ CodeDocumentList * docList = getCodeDocumentList();
+ for (CodeDocument * codeDoc = docList->first(); codeDoc; codeDoc= docList->next())
+ codeDoc->saveToXMI(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+/**
+ * Initialize this code generator from its parent UMLDoc. When this is called, it will
+ * (re-)generate the list of code documents for this project (generator) by checking
+ * for new objects/attributes which have been added or changed in the documnet. One or more
+ * CodeDocuments will be created/overwritten/amended as is appropriate for the given language.
+ *
+ * In this 'generic' version a ClassifierCodeDocument will exist for each and
+ * every classifier that exists in our UMLDoc. IF when this is called, a code document
+ * doesn't exist for the given classifier, then we will created and add a new code
+ * document to our generator.
+ *
+ * IF you want to add non-classifier related code documents at this step,
+ * you will need to overload this method in the appropriate
+ * code generatator (see JavaCodeGenerator for an example of this).
+ */
+void CodeGenerator::initFromParentDocument( ) {
+
+ // Walk through the document converting classifiers into
+ // classifier code documents as needed (e.g only if doesn't exist)
+ UMLClassifierList concepts = UMLApp::app()->getDocument()->getClassesAndInterfaces();
+ for (UMLClassifier *c = concepts.first(); c; c = concepts.next())
+ {
+
+ // Doesn't exist? Then build one.
+ CodeDocument * codeDoc = findCodeDocumentByClassifier(c);
+ if (!codeDoc)
+ {
+ codeDoc = newClassifierCodeDocument(c);
+ addCodeDocument(codeDoc); // this will also add a unique tag to the code document
+ }
+ }
+
+}
+
+/**
+ * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument.
+ * "UserGenerated" code will be preserved, but Autogenerated contents will be updated/replaced
+ * or removed as is apppropriate.
+ */
+void CodeGenerator::syncCodeToDocument ( ) {
+ for (CodeDocument * doc = m_codedocumentVector.first(); doc; doc=m_codedocumentVector.next())
+ doc->synchronize();
+}
+
+// in this 'vanilla' version, we only worry about adding classifier
+// documents
+void CodeGenerator::checkAddUMLObject (UMLObject * obj) {
+ if (!obj)
+ return;
+
+ UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
+ if(c) {
+ CodeDocument * cDoc = newClassifierCodeDocument(c);
+ addCodeDocument(cDoc);
+ }
+}
+
+void CodeGenerator::checkRemoveUMLObject (UMLObject * obj)
+{
+
+ if (!obj)
+ return;
+
+ UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
+ if(c) {
+ ClassifierCodeDocument * cDoc = (ClassifierCodeDocument*) findCodeDocumentByClassifier(c);
+ if (cDoc)
+ removeCodeDocument(cDoc);
+ }
+
+}
+
+/**
+ * @return CodeDocument
+ * @param classifier
+ */
+CodeDocument * CodeGenerator::findCodeDocumentByClassifier ( UMLClassifier * classifier ) {
+ return findCodeDocumentByID(ID2STR(classifier->getID()));
+}
+
+
+/**
+ * Write out all code documents to file as appropriate.
+ */
+void CodeGenerator::writeCodeToFile ( )
+{
+ writeListedCodeDocsToFile(&m_codedocumentVector);
+}
+
+void CodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) {
+ CodeDocumentList docs;
+ docs.setAutoDelete(false);
+
+ for (UMLClassifier *concept= concepts.first(); concept; concept= concepts.next())
+ {
+ CodeDocument * doc = findCodeDocumentByClassifier(concept);
+ if(doc)
+ docs.append(doc);
+ }
+
+ writeListedCodeDocsToFile(&docs);
+}
+
+// Main method. Will write out passed code documents to file as appropriate.
+void CodeGenerator::writeListedCodeDocsToFile ( CodeDocumentList * docs ) {
+
+ // iterate thru all code documents
+ for (CodeDocument *doc = docs->first(); doc; doc = docs->next())
+ {
+
+ // we need this so we know when to emit a 'codeGenerated' signal
+ ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument *>(doc);
+ bool codeGenSuccess = false;
+
+ // we only write the document, if so requested
+ if(doc->getWriteOutCode())
+ {
+ QString filename = findFileName(doc);
+ // check that we may open that file for writing
+ QFile file;
+ if ( openFile(file,filename) ) {
+ QTextStream stream(&file);
+ stream<<doc->toString()<<endl;
+ file.close();
+ codeGenSuccess = true; // we wrote the code OK
+ } else {
+ kWarning() << "Cannot open file :"<<filename<<" for writing " << endl;
+ }
+ }
+
+ if(cdoc)
+ emit codeGenerated(cdoc->getParentClassifier(), codeGenSuccess);
+
+ }
+
+}
+
+/**
+ * Create a new Code document belonging to this package.
+ * @return CodeDocument
+ */
+CodeDocument * CodeGenerator::newCodeDocument ( ) {
+ CodeDocument * newCodeDoc = new CodeDocument ();
+ return newCodeDoc;
+}
+
+/**
+ * @return QString
+ * @param file
+ */
+
+QString CodeGenerator::getHeadingFile( const QString &file ) {
+ return UMLApp::app()->getCommonPolicy()->getHeadingFile(file);
+}
+
+/**
+ * @return QString
+ * @param codeDoc
+ * @param name
+ */
+QString CodeGenerator::overwritableName(const QString& name, const QString &extension ) {
+
+ CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
+ QDir outputDirectory = pol->getOutputDirectory();
+ QString filename = name + extension;
+
+ if (!outputDirectory.exists(filename)) {
+ return filename;
+ }
+
+ int suffix;
+ OverwriteDialogue overwriteDialog( name, outputDirectory.absPath(),
+ m_applyToAllRemaining, kapp -> mainWidget() );
+ switch (pol->getOverwritePolicy()) { //if it exists, check the OverwritePolicy we should use
+ case CodeGenerationPolicy::Ok: //ok to overwrite file
+ filename = name + extension;
+ break;
+ case CodeGenerationPolicy::Ask: //ask if we can overwrite
+ switch(overwriteDialog.exec()) {
+ case KDialogBase::Yes: //overwrite file
+ if ( overwriteDialog.applyToAllRemaining() ) {
+ pol->setOverwritePolicy(CodeGenerationPolicy::Ok);
+ filename = name + extension;
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ break;
+ case KDialogBase::No: //generate similar name
+ suffix = 1;
+ while (1) {
+ filename = name + "__" + QString::number(suffix) + extension;
+ if (!outputDirectory.exists(filename))
+ break;
+ suffix++;
+ }
+ if ( overwriteDialog.applyToAllRemaining() ) {
+ pol->setOverwritePolicy(CodeGenerationPolicy::Never);
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ break;
+ case KDialogBase::Cancel: //don't output anything
+ if ( overwriteDialog.applyToAllRemaining() ) {
+ pol->setOverwritePolicy(CodeGenerationPolicy::Cancel);
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ return QString();
+ break;
+ }
+
+ break;
+ case CodeGenerationPolicy::Never: //generate similar name
+ suffix = 1;
+ while (1) {
+ filename = name + "__" + QString::number(suffix) + extension;
+ if (!outputDirectory.exists(filename))
+ break;
+ suffix++;
+ }
+ break;
+ case CodeGenerationPolicy::Cancel: //don't output anything
+ return QString();
+ break;
+ }
+
+ return filename;
+}
+
+
+/**
+ * @return bool
+ * @param file
+ * @param name
+ */
+bool CodeGenerator::openFile (QFile & file, const QString &fileName ) {
+ //open files for writing.
+ if(fileName.isEmpty()) {
+ kWarning() << "cannot find a file name" << endl;
+ return false;
+ } else {
+ QDir outputDirectory = UMLApp::app()->getCommonPolicy()->getOutputDirectory();
+ file.setName(outputDirectory.absFilePath(fileName));
+ if(!file.open(IO_WriteOnly)) {
+ KMessageBox::sorry(0,i18n("Cannot open file %1 for writing. Please make sure the folder exists and you have permissions to write to it.").arg(file.name()),i18n("Cannot Open File"));
+ return false;
+ }
+ return true;
+ }
+
+}
+
+
+/**
+ * @return QString
+ * @param name
+ */
+QString CodeGenerator::cleanName ( const QString &name ) {
+ QString retval = name;
+ retval.replace(QRegExp("\\W"), "_");
+ return retval;
+}
+
+QString CodeGenerator::findFileName ( CodeDocument * codeDocument ) {
+
+ //else, determine the "natural" file name
+ QString name;
+
+ // Get the path name
+ QString path = codeDocument->getPath();
+
+ // if path is given add this as a directory to the file name
+ if (!path.isEmpty()) {
+ path.replace(QRegExp("::"), "/"); // Simple hack!
+ name = path + '/' + codeDocument->getFileName();
+ path = '/' + path;
+ } else {
+ name = codeDocument->getFileName();
+ }
+
+ // Convert all "::" to "/" : Platform-specific path separator
+ name.replace(QRegExp("::"), "/"); // Simple hack!
+
+ // if a path name exists check the existence of the path directory
+ if (!path.isEmpty()) {
+ QDir outputDirectory = UMLApp::app()->getCommonPolicy()->getOutputDirectory();
+ QDir pathDir(outputDirectory.absPath() + path);
+
+ // does our complete output directory exist yet? if not, try to create it
+ if (!pathDir.exists())
+ {
+ // ugh. dir separator here is UNIX specific..
+ QStringList dirs = QStringList::split("/",pathDir.absPath());
+ QString currentDir = "";
+
+ QStringList::iterator end(dirs.end());
+ for (QStringList::iterator dir(dirs.begin()); dir != end; ++dir)
+ {
+ currentDir += '/' + *dir;
+ if (! (pathDir.exists(currentDir)
+ || pathDir.mkdir(currentDir) ) )
+ {
+ KMessageBox::error(0, i18n("Cannot create the folder:\n") +
+ pathDir.absPath() + i18n("\nPlease check the access rights"),
+ i18n("Cannot Create Folder"));
+ return NULL;
+
+ }
+ }
+ }
+ }
+
+ name.simplifyWhiteSpace();
+ name.replace(QRegExp(" "),"_");
+
+ return overwritableName( name, codeDocument->getFileExtension() );
+}
+
+void CodeGenerator::findObjectsRelated(UMLClassifier *c, UMLPackageList &cList) {
+ UMLPackage *temp;
+ UMLAssociationList associations = c->getAssociations();
+
+ for (UMLAssociation *a = associations.first(); a; a = associations.next()) {
+ temp = 0;
+ switch (a->getAssocType()) {
+ case Uml::at_Generalization:
+ case Uml::at_Realization:
+ // only the "b" end is seen by the "a" end, not other way around
+ {
+ UMLObject *objB = a->getObject(Uml::B);
+ if (objB != c)
+ temp = (UMLPackage*)objB;
+ }
+ break;
+ case Uml::at_Dependency:
+ case Uml::at_UniAssociation:
+ {
+ UMLObject *objA = a->getObject(Uml::A);
+ UMLObject *objB = a->getObject(Uml::B);
+ if (objA == c)
+ temp = static_cast<UMLPackage*>(objB);
+ }
+ break;
+ case Uml::at_Aggregation:
+ case Uml::at_Composition:
+ case Uml::at_Association:
+ {
+ UMLObject *objA = a->getObject(Uml::A);
+ UMLObject *objB = a->getObject(Uml::B);
+ if (objA == c && objB->getBaseType() != Uml::ot_Datatype)
+ temp = static_cast<UMLPackage*>(objB);
+ }
+ break;
+ default: /* all others.. like for state diagrams..we currently don't use */
+ break;
+ }
+
+ // now add in list ONLY if its not already there
+ if(temp && !cList.containsRef(temp))
+ cList.append(temp);
+ }
+
+ //operations
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ temp =0;
+ //check return value
+ temp =(UMLClassifier*) op->getType();
+ if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.containsRef(temp))
+ cList.append(temp);
+ //check parameters
+ UMLAttributeList atl = op->getParmList();
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ temp = (UMLClassifier*)at->getType();
+ if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.containsRef(temp))
+ cList.append(temp);
+ }
+
+ }
+
+ //attributes
+ if (!c->isInterface()) {
+ UMLAttributeList atl = c->getAttributeList();
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ temp=0;
+ temp = (UMLClassifier*) at->getType();
+ if (temp && temp->getBaseType() != Uml::ot_Datatype && !cList.containsRef(temp))
+ cList.append(temp);
+ }
+ }
+
+
+}
+
+/**
+ * Format an output document.
+ * @return QString
+ * @param text
+ * @param lineprefix
+ * @param linewidth
+ */
+QString CodeGenerator::formatDoc(const QString &text, const QString &linePrefix, int lineWidth) {
+ QString output;
+
+ const QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ QStringList lines = QStringList::split(endLine, text);
+ for (QStringList::ConstIterator lit = lines.begin(); lit != lines.end(); ++lit) {
+ QString input = *lit;
+ input.remove( QRegExp("\\s+$") );
+ if (input.length() < (uint)lineWidth) {
+ output += linePrefix + input + endLine;
+ continue;
+ }
+ int index;
+ while ((index = input.findRev(" ", lineWidth)) >= 0) {
+ output += linePrefix + input.left(index) + endLine; // add line
+ input.remove(0, index + 1); //and remove processed string, including
+ // white space
+ }
+ if (!input.isEmpty())
+ output += linePrefix + input + endLine;
+ }
+ return output;
+}
+
+void CodeGenerator::initFields() {
+
+ m_document = UMLApp::app()->getDocument();
+ m_codeDocumentDictionary.setAutoDelete(false);
+ m_codedocumentVector.setAutoDelete(false);
+ m_applyToAllRemaining = true;
+ lastIDIndex = 0;
+
+ // initial population of our project generator
+ // CANT Be done here because we would call pure virtual method
+ // of newClassifierDocument (bad!).
+ // We should only call from the child
+ // initFromParentDocument();
+
+}
+
+void CodeGenerator::connect_newcodegen_slots() {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ connect(doc, SIGNAL(sigObjectCreated(UMLObject*)),
+ this, SLOT(checkAddUMLObject(UMLObject*)));
+ connect(doc, SIGNAL(sigObjectRemoved(UMLObject*)),
+ this, SLOT(checkRemoveUMLObject(UMLObject*)));
+ CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
+ connect(commonPolicy, SIGNAL(modifiedCodeContent()),
+ this, SLOT(syncCodeToDocument()));
+}
+
+// these are utility methods for accessing the default
+// code gen policy object and should go away when we
+// finally implement the CodeGenDialog class -b.t.
+void CodeGenerator::setForceDoc(bool f) {
+ UMLApp::app()->getCommonPolicy()->setCodeVerboseDocumentComments(f);
+}
+
+bool CodeGenerator::forceDoc() const {
+ return UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
+}
+
+void CodeGenerator::setForceSections(bool f) {
+ UMLApp::app()->getCommonPolicy()->setCodeVerboseSectionComments(f);
+}
+
+bool CodeGenerator::forceSections() const {
+ return UMLApp::app()->getCommonPolicy()->getCodeVerboseSectionComments();
+}
+
+QStringList CodeGenerator::defaultDatatypes() {
+ return QStringList();
+ //empty by default, override in your code generator
+}
+
+bool CodeGenerator::isReservedKeyword(const QString & keyword) {
+
+ const QStringList keywords = reservedKeywords();
+
+ return keywords.contains(keyword);
+}
+
+const QStringList CodeGenerator::reservedKeywords() const {
+ static QStringList emptyList;
+
+ return emptyList;
+}
+
+void CodeGenerator::createDefaultStereotypes() {
+ //empty by default, override in your code generator
+ //e.g. m_document->createDefaultStereotypes("constructor");
+}
+
+#include "codegenerator.moc"
diff --git a/umbrello/umbrello/codegenerator.h b/umbrello/umbrello/codegenerator.h
new file mode 100644
index 00000000..0928dbba
--- /dev/null
+++ b/umbrello/umbrello/codegenerator.h
@@ -0,0 +1,416 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+
+#ifndef CODEGENERATOR_H
+#define CODEGENERATOR_H
+
+#include <qdict.h>
+#include <qdir.h>
+
+#include "codegenerators/codegenpolicyext.h"
+#include "codegenerationpolicy.h"
+#include "umlpackagelist.h"
+#include "umlclassifierlist.h"
+#include "codedocumentlist.h"
+#include "codeviewerstate.h"
+#include "umlnamespace.h"
+
+class UMLAttribute;
+class UMLDoc;
+class UMLObject;
+class UMLRole;
+class UMLOperation;
+
+class ClassifierCodeDocument;
+class CodeAccessorMethod;
+class CodeBlock;
+class CodeBlockWithComments;
+class CodeClassField;
+class CodeClassFieldDeclarationBlock;
+class CodeComment;
+class CodeDocument;
+class CodeOperation;
+class CodeViewerDialog;
+
+class KConfig;
+
+/**
+ * class CodeGenerator
+ * This class collects together all of the code documents which form this project,
+ * and generates code for them in a given language.
+ */
+
+/**
+ * CodeGenerator is the base class for all CodeGenerators. It
+ * provides the interface through which all Generators are invoked and
+ * the all the basic functionality. The only thing it doesn't do is to
+ * generate code =)
+ *
+ * If you want to implement a CodeGenerator for some language follow
+ * these steps:
+ *
+ * Create a class which inherits CodeGenerator. This class can have
+ * any name, I use names like CppCodeGenerator for the Cpp Generator,
+ * JavaCodeGenerator for the Java Generator and so on, but you can use what
+ * you want.
+ *
+ * The code you generate should be output to "outputDirectory" and you
+ * should respect the OverwritePolicy specified. You should call
+ * findFileName(..) to get an appropriate file name, and then you can
+ * call openFile if you want, but if you want to do it yourself you
+ *
+ * Finally put your generator in a library which can be dlopened
+ * together with a factory class (see below) and you are ready to go.
+ */
+
+
+class CodeGenerator : public QObject {
+ Q_OBJECT
+
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+
+ /**
+ * Build a code generator.
+ * @return CodeGenerator
+ */
+ CodeGenerator ();
+
+ /**
+ * Build a code generator and then initialize it from an XMI element.
+ * @return CodeGenerator
+ * @param element an element from an XMI document
+ */
+ CodeGenerator (QDomElement & element );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeGenerator ( );
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Add a CodeDocument object to the m_codedocumentVector List
+ * @return boolean - will return false if it couldnt add a document.
+ */
+ bool addCodeDocument ( CodeDocument * add_object );
+
+ /**
+ * Replace (or possibly add a new) CodeDocument object to the m_codedocumentVector List.
+ * As names must be unique and each code document must have a name.
+ * @return boolean value which will be true if the passed document was able to replace some
+ * other document OR was added(no prior document existed..only when addIfPriorDocumentNotPresent is true).
+ * The document which was replaced will be deleted IF deleteReplacedDocument is true.
+ */
+ // bool replaceCodeDocument ( CodeDocument * replace_doc=0, bool addIfPriorDocumentNotPresent=true,
+ // bool deleteReplacedDocument=true );
+
+ /**
+ * Remove a CodeDocument object from m_codedocumentVector List
+ * @return boolean - will return false if it couldnt remove a document.
+ */
+ bool removeCodeDocument ( CodeDocument * remove_object );
+
+ /**
+ * Get the list of CodeDocument objects held by m_codedocumentVector
+ * @return CodeDocumentList list of CodeDocument objects held by
+ * m_codedocumentVector
+ */
+ CodeDocumentList * getCodeDocumentList ( );
+
+ // get a unique id for this codedocument
+ QString getUniqueID ( CodeDocument * codeDoc );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * Find a code document by the given id string.
+ * @return CodeDocument
+ */
+ CodeDocument * findCodeDocumentByID (const QString &id );
+
+ /**
+ * Write out all code documents to file as appropriate.
+ */
+ virtual void writeCodeToFile ( );
+
+ // this method is here to provide class wizard the
+ // ability to write out only those classes which
+ // are selected by the user.
+ virtual void writeCodeToFile(UMLClassifierList &list);
+
+ // these are utility methods for accessing the default
+ // code gen policy object and *perhaps* should go away when we
+ // finally implement the CodeGenDialog class -b.t.
+
+ void setModifyNamePolicy(CodeGenerationPolicy::ModifyNamePolicy p);
+ CodeGenerationPolicy::ModifyNamePolicy modifyNamePolicy()const;
+
+ void setIncludeHeadings(bool i);
+ bool includeHeadings() const;
+
+ void setHeadingFileDir(const QString &);
+ QString headingFileDir() const;
+
+ void setForceDoc(bool f);
+ bool forceDoc() const;
+
+ void setForceSections(bool f);
+ bool forceSections() const;
+
+
+ /**
+ * Gets the heading file (as a string) to be inserted at the
+ * beginning of the generated file. you give the file type as
+ * parameter and get the string. if fileName starts with a
+ * period (.) then fileName is the extension (.cpp, .h,
+ * .java) if fileName starts with another character you are
+ * requesting a specific file (mylicensefile.txt). The files
+ * can have parameters which are denoted by %parameter%.
+ *
+ * current parameters are
+ * %author%
+ * %date%
+ * %time%
+ * %filepath%
+ *
+ * @return QString
+ * @param file
+ */
+ virtual QString getHeadingFile (const QString &file );
+
+ /**
+ * Finds an appropriate file name for the given CodeDocument, taking into
+ * account the Overwrite Policy and asking the user what to do if need be
+ * (if policy == Ask).
+ *
+ * @param doc the CodeDocument for which an output file name is desired.
+ * @return the file name that should be used. (with extension) or
+ * NULL if none to be used
+ */
+ virtual QString findFileName(CodeDocument * doc);
+
+ /**
+ * Replaces spaces with underscores and capitalises as defined in m_modname
+ * @return QString
+ * @param name
+ */
+ static QString cleanName ( const QString &name );
+
+ /** Format documentation for output in source files
+ *
+ * @param text the documentation which has to be formatted
+ * @param linePrefix the prefix which has to be added in the beginnig of each line
+ * @param lineWidth the line width used for word-wrapping the documentation
+ *
+ * @return the formatted documentation text
+ */
+ QString formatDoc (const QString & text, const QString & linePrefix = " *", int lineWidth = 80 );
+
+ /**
+ * Finds all classes in the current document to which objects of class c
+ * are in some way related. Possible relations are Associations (generalization,
+ * composition, etc) as well as parameters to methods and return values
+ * this is useful in deciding which classes/files to import/include in code generation
+ * @param c the class for which relations are to be found
+ * @param cList a reference to the list into which return the result
+ */
+ static void findObjectsRelated(UMLClassifier *c, UMLPackageList &cList);
+
+ // a series of accessor method constructors that we need to define
+ // for any particular language.
+ virtual CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier ) = 0;
+
+ /**
+ * @param element
+ */
+ virtual void loadFromXMI (QDomElement & element );
+
+ /**
+ * Create a new Code document belonging to this package.
+ * @return CodeDocument pointer to new code document.
+ */
+ virtual CodeDocument * newCodeDocument ( );
+
+ /**
+ * Return the unique language enum that identifies this type of code generator
+ */
+ virtual Uml::Programming_Language getLanguage() = 0;
+
+ /**
+ * Find a code document by the given classifier.
+ * @return CodeDocument
+ * @param classifier
+ */
+ //FIX
+ // NOTE: this should be 'protected' or we could have problems with CPP code generator
+ CodeDocument * findCodeDocumentByClassifier (UMLClassifier * classifier );
+
+ /**
+ * Return the default datatypes for your language (bool, int etc)
+ * Default implementation returns empty list.
+ */
+ virtual QStringList defaultDatatypes();
+
+ /** Get the editing dialog for this code document
+ */
+ virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc,
+ Settings::CodeViewerState state);
+
+ /**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword is the string to check
+ *
+ */
+ virtual bool isReservedKeyword(const QString & rPossiblyReservedKeyword);
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+ /**
+ * Create the default stereotypes for your language (constructor, int etc)
+ */
+ virtual void createDefaultStereotypes ();
+
+ /**
+ * Initialize this code generator from its parent UMLDoc. When this is called,
+ * it will (re-)generate the list of code documents for this project (generator)
+ * by checking for new objects/attributes which have been added or changed in the
+ * document. One or more CodeDocuments will be created/overwritten/amended as is
+ * appropriate for the given language.
+ */
+ virtual void initFromParentDocument( );
+
+ /**
+ * Connect additional slots.
+ * Only required for Advanced Code Generators.
+ * To be called after constructing the code generator (see CodeGenFactory)
+ */
+ void connect_newcodegen_slots();
+
+protected:
+
+ /**
+ * Remove (and possibly delete) all AutoGenerated content type CodeDocuments but leave
+ * the UserGenerated (and any other type) documents in this generator alone.
+ */
+ // void removeAndDeleteAllAutoGeneratedCodeDocuments ( bool deleteRemovedDocs=true );
+
+ /**
+ * Returns a name that can be written to in the output directory,
+ * respecting the overwrite policy.
+ * If a file of the given name and extension does not exist,
+ * then just returns the name.
+ * If a file of the given name and extension does exist,
+ * then opens an overwrite dialog. In this case the name returned
+ * may be a modification of the input name.
+ * This method is invoked by findFileName().
+ *
+ * @param name the proposed output file name
+ * @param extension the extension to use
+ * @return the real file name that should be used (including extension) or
+ * QString::null if none to be used
+ */
+ QString overwritableName (const QString& name, const QString &extension );
+
+ /** Opens a file named "name" for writing in the outputDirectory.
+ * If something goes wrong, it informs the user
+ * if this function returns true, you know you can write to the file
+ * @return bool
+ * @param file
+ * @param name
+ */
+ bool openFile (QFile& file, const QString &name);
+
+ /** the actual internal routine which writes code documents
+ */
+ void writeListedCodeDocsToFile(CodeDocumentList * docs);
+
+ static const char * hierarchicalCodeBlockNodeName;
+
+ // map of what code documents we currently have in this generator.
+ QDict<CodeDocument> m_codeDocumentDictionary;
+
+ /**
+ * used by overwriteDialogue to know if the apply to all
+ * remaining files checkbox should be checked (is by default)
+ */
+ bool m_applyToAllRemaining;
+
+ /**
+ * The document object
+ */
+ UMLDoc* m_document;
+
+private:
+
+ /**
+ * Maps CodeDocuments to filenames. Used for finding out which file
+ * each class was written to.
+ */
+ // this seems silly and overkill now. -b.t.
+ // QMap<CodeDocument*,QString> *m_fileMap;
+
+ CodeDocumentList m_codedocumentVector;
+ int lastIDIndex;
+
+ void initFields() ;
+
+public slots:
+
+ /** These 2 functions check for adding or removing objects to the UMLDocument */
+ virtual void checkAddUMLObject (UMLObject * obj);
+ virtual void checkRemoveUMLObject (UMLObject * obj);
+
+ /**
+ * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument.
+ * "UserGenerated" code will be preserved, but Autogenerated contents will be updated/replaced
+ * or removed as is apppropriate.
+ */
+ virtual void syncCodeToDocument ( );
+
+signals:
+
+ /**
+ * This signal is emitted when code for a UMLClassifier has been
+ * generated. Its only really used by the codegenerationwizard to
+ * update its progress.
+ * @param concept The concept which was processed
+ * @param generated Flag, set to true if generation was successful
+ */
+ void codeGenerated(UMLClassifier* concept, bool generated);
+
+};
+
+#endif // CODEGENERATOR_H
+
diff --git a/umbrello/umbrello/codegenerators/Makefile.am b/umbrello/umbrello/codegenerators/Makefile.am
new file mode 100644
index 00000000..bc622fe0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/Makefile.am
@@ -0,0 +1,38 @@
+noinst_LTLIBRARIES = libcodegenerator.la
+
+INCLUDES = -I../dialogs -I$(top_srcdir)/umbrello/umbrello/dialogs $(all_includes)
+
+libcodegenerator_la_LDFLAGS = $(all_libraries)
+libcodegenerator_la_METASOURCES = AUTO
+libcodegenerator_la_SOURCES = codegenfactory.cpp classifierinfo.cpp \
+ javacodegenerator.cpp javaantcodedocument.cpp javacodeclassfield.cpp \
+ javaclassifiercodedocument.cpp javacodecomment.cpp javacodedocumentation.cpp \
+ javacodeoperation.cpp javacodeaccessormethod.cpp \
+ javaclassdeclarationblock.cpp javacodeclassfielddeclarationblock.cpp \
+ javacodegenerationpolicy.cpp javacodegenerationpolicypage.cpp \
+ javacodegenerationformbase.ui \
+ cppcodegenerator.cpp cppcodedocumentation.cpp cppcodeclassfield.cpp \
+ cppcodecomment.cpp cppmakecodedocument.cpp \
+ cppsourcecodedocument.cpp cppsourcecodeoperation.cpp cppsourcecodeaccessormethod.cpp \
+ cppsourcecodeclassfielddeclarationblock.cpp \
+ cppheadercodedocument.cpp cppheaderclassdeclarationblock.cpp \
+ cppheadercodeoperation.cpp cppheadercodeaccessormethod.cpp \
+ cppheadercodeclassfielddeclarationblock.cpp \
+ cppcodegenerationpolicy.cpp cppcodegenerationpolicypage.cpp \
+ cppcodegenerationformbase.ui cppcodegenerationform.cpp \
+ rubycodegenerator.cpp rubycodeclassfield.cpp \
+ rubyclassifiercodedocument.cpp rubycodecomment.cpp rubycodedocumentation.cpp \
+ rubycodeoperation.cpp rubycodeaccessormethod.cpp \
+ rubyclassdeclarationblock.cpp rubycodeclassfielddeclarationblock.cpp \
+ rubycodegenerationpolicy.cpp rubycodegenerationpolicypage.cpp \
+ rubycodegenerationformbase.ui \
+ simplecodegenerator.cpp \
+ adawriter.cpp aswriter.cpp cppwriter.cpp csharpwriter.cpp dwriter.cpp javawriter.cpp jswriter.cpp \
+ idlwriter.cpp pascalwriter.cpp perlwriter.cpp php5writer.cpp phpwriter.cpp \
+ pythonwriter.cpp rubywriter.cpp sqlwriter.cpp tclwriter.cpp xmlschemawriter.cpp \
+ xmlelementcodeblock.cpp xmlcodecomment.cpp \
+ codegen_utils.cpp
+libcodegenerator_la_COMPILE_FIRST = ../dialogs/codegenerationpolicybase.h
+
+KDE_OPTIONS = nofinal
+
diff --git a/umbrello/umbrello/codegenerators/adawriter.cpp b/umbrello/umbrello/codegenerators/adawriter.cpp
new file mode 100644
index 00000000..e1c79839
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/adawriter.cpp
@@ -0,0 +1,686 @@
+/***************************************************************************
+ * adawriter.cpp - description *
+ * ------------------- *
+ * Based on javawriter.cpp by Luis De la Parra Blum *
+ * copyright : (C) 2002 by Oliver Kellogg *
+ * (C) 2003-2007 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "adawriter.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../classifierlistitem.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../umltemplatelist.h"
+#include "../folder.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../umlnamespace.h"
+
+const QString AdaWriter::defaultPackageSuffix = "_Holder";
+
+AdaWriter::AdaWriter() {
+}
+
+AdaWriter::~AdaWriter() {}
+
+/**
+ * returns "Ada"
+ */
+Uml::Programming_Language AdaWriter::getLanguage() {
+ return Uml::pl_Ada;
+}
+
+
+bool AdaWriter::isOOClass(UMLClassifier *c) {
+ Uml::Object_Type ot = c->getBaseType();
+ if (ot == Uml::ot_Interface)
+ return true;
+ if (ot == Uml::ot_Enum)
+ return false;
+ if (ot != Uml::ot_Class) {
+ kDebug() << "AdaWriter::isOOClass: unknown object type " << ot << endl;
+ return false;
+ }
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant" || stype == "CORBATypedef" ||
+ stype == "CORBAStruct" || stype == "CORBAUnion")
+ return false;
+ // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are
+ // assumed to be OO classes.
+ return true;
+}
+
+QString AdaWriter::className(UMLClassifier *c, bool inOwnScope) {
+ // If the class has an enclosing package then it is assumed that
+ // the class name is the type name; if the class does not have an
+ // enclosing package then the class name acts as the Ada package
+ // name.
+ QString retval;
+ QString className = cleanName(c->getName());
+ UMLPackage *umlPkg = c->getUMLPackage();
+ if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical)) {
+ if (! inOwnScope)
+ retval = className + '.';
+ retval.append("Object");
+ } else {
+ if (! inOwnScope)
+ retval = umlPkg->getFullyQualifiedName(".") + '.';
+ retval.append(className);
+ }
+ return retval;
+}
+
+QString AdaWriter::packageName(UMLPackage *p) {
+ // If the class has an enclosing package then it is assumed that
+ // the class name is the type name; if the class does not have an
+ // enclosing package then the class name acts as the Ada package
+ // name.
+ UMLPackage *umlPkg = p->getUMLPackage();
+ QString className = cleanName(p->getName());
+ QString retval;
+
+ if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical))
+ umlPkg = NULL;
+
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(p);
+ if (umlPkg == NULL) {
+ retval = className;
+ if (c == NULL || !isOOClass(c))
+ retval.append(defaultPackageSuffix);
+ } else {
+ retval = umlPkg->getFullyQualifiedName(".");
+ }
+ return retval;
+}
+
+void AdaWriter::computeAssocTypeAndRole(UMLClassifier *c,
+ UMLAssociation *a,
+ QString& typeName, QString& roleName) {
+ UMLClassifier* assocEnd = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B));
+ if (assocEnd == NULL)
+ return;
+ const Uml::Association_Type assocType = a->getAssocType();
+ if (assocType != Uml::at_Aggregation && assocType != Uml::at_Composition)
+ return;
+ const QString multi = a->getMulti(Uml::B);
+ bool hasNonUnityMultiplicity = (!multi.isEmpty() && multi != "1");
+ hasNonUnityMultiplicity &= !multi.contains(QRegExp("^1 *\\.\\. *1$"));
+ roleName = cleanName(a->getRoleName(Uml::B));
+ if (roleName.isEmpty())
+ roleName = cleanName(a->getName());
+ if (roleName.isEmpty()) {
+ QString artificialName = cleanName(assocEnd->getName());
+ if (hasNonUnityMultiplicity) {
+ roleName = artificialName;
+ roleName.append("_Vector");
+ } else {
+ roleName = "M_";
+ roleName.append(artificialName);
+ }
+ }
+ typeName = className(assocEnd, (assocEnd == c));
+ if (hasNonUnityMultiplicity)
+ typeName.append("_Array_Ptr");
+ else if (assocType == Uml::at_Aggregation)
+ typeName.append("_Ptr");
+}
+
+void AdaWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ const bool isClass = !c->isInterface();
+ QString classname = cleanName(c->getName());
+ QString fileName = packageName(c).lower();
+ fileName.replace('.', '-');
+
+ //find an appropriate name for our file
+ fileName = overwritableName(c, fileName, ".ads");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile file;
+ if (!openFile(file, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // Start generating the code.
+
+ QTextStream ada(&file);
+ //try to find a heading file(license, comments, etc)
+ QString str;
+ str = getHeadingFile(".ads");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), file.name());
+ ada << str << endl;
+ }
+
+ // Import referenced classes.
+ UMLPackageList imports;
+ findObjectsRelated(c, imports);
+ if (imports.count()) {
+ for (UMLPackage *con = imports.first(); con; con = imports.next()) {
+ if (con->getBaseType() != Uml::ot_Datatype)
+ ada << "with " << packageName(con) << "; " << m_endl;
+ }
+ ada << m_endl;
+ }
+
+ // Generate generic formals.
+ UMLTemplateList template_params = c->getTemplateList();
+ if (template_params.count()) {
+ ada << getIndent() << "generic" << m_endl;
+ m_indentLevel++;
+ for (UMLTemplate *t = template_params.first(); t; t = template_params.next()) {
+ QString formalName = t->getName();
+ QString typeName = t->getTypeName();
+ if (typeName == "class") {
+ ada << getIndent() << "type " << formalName << " is tagged private;"
+ << m_endl;
+ } else {
+ // Check whether it's a data type.
+ UMLClassifier *typeObj = t->getType();
+ if (typeObj == NULL) {
+ kError() << "AdaWriter::writeClass(template_param "
+ << typeName << "): typeObj is NULL" << endl;
+ ada << getIndent() << "type " << formalName << " is new " << typeName
+ << " with private; -- CHECK: codegen error"
+ << m_endl;
+ } else if (typeObj->getBaseType() == Uml::ot_Datatype) {
+ ada << getIndent() << formalName << " : " << typeName << ";"
+ << m_endl;
+ } else {
+ ada << getIndent() << "type " << typeName << " is new "
+ << formalName << " with private;" << m_endl;
+ }
+ }
+ }
+ m_indentLevel--;
+ }
+
+ // Here comes the package proper.
+ QString pkg = packageName(c);
+ ada << getIndent() << "package " << pkg << " is" << m_endl << m_endl;
+ m_indentLevel++;
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLEnum *ue = static_cast<UMLEnum*>(c);
+ UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral);
+ uint i = 0;
+ ada << getIndent() << "type " << classname << " is (" << m_endl;
+ m_indentLevel++;
+ for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ ada << getIndent() << enumLiteral;
+ if (++i < litList.count())
+ ada << "," << m_endl;
+ }
+ m_indentLevel--;
+ ada << ");" << m_endl << m_endl;
+ m_indentLevel--;
+ ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl;
+ return;
+ }
+ if (! isOOClass(c)) {
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant") {
+ ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBAStruct") {
+ if (isClass) {
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ ada << getIndent() << "type " << classname << " is record" << m_endl;
+ m_indentLevel++;
+ for (at = atl.first(); at; at = atl.next()) {
+ QString name = cleanName(at->getName());
+ QString typeName = at->getTypeName();
+ ada << getIndent() << name << " : " << typeName;
+ QString initialVal = at->getInitialValue();
+ if (initialVal.latin1() && ! initialVal.isEmpty())
+ ada << " := " << initialVal;
+ ada << ";" << m_endl;
+ }
+ m_indentLevel--;
+ ada << getIndent() << "end record;" << m_endl << m_endl;
+ }
+ } else if(stype == "CORBAUnion") {
+ ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBATypedef") {
+ ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else {
+ ada << getIndent() << "-- " << stype << ": Unknown stereotype" << m_endl << m_endl;
+ }
+ m_indentLevel--;
+ ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl;
+ return;
+ }
+
+ // Write class Documentation if non-empty or if force option set.
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ ada << "--" << m_endl;
+ ada << "-- class " << classname << endl;
+ ada << formatDoc(c->getDoc(), "-- ");
+ ada << m_endl;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+
+ const QString name = className(c);
+ ada << getIndent() << "type " << name << " is ";
+ if (c->getAbstract())
+ ada << "abstract ";
+ if (superclasses.isEmpty()) {
+ ada << "tagged ";
+ } else {
+ // FIXME: Multiple inheritance is not yet supported
+ UMLClassifier* parent = superclasses.first();
+ ada << "new " << className(parent, false) << " with ";
+ }
+ ada << "private;" << m_endl << m_endl;
+ ada << getIndent() << "type " << name << "_Ptr is access all " << name << "'Class;" << m_endl << m_endl;
+ ada << getIndent() << "type " << name << "_Array is array (Positive range <>) of " << name << "_Ptr;" << m_endl << m_endl;
+ ada << getIndent() << "type " << name << "_Array_Ptr is access " << name << "_Array;" << m_endl << m_endl;
+
+ // Generate accessors for public attributes.
+ UMLAttributeList atl;
+ if (isClass) {
+ UMLAttributeList atpub;
+ atpub.setAutoDelete(false);
+
+ atl = c->getAttributeList();
+
+ UMLAttribute *at;
+ for (at = atl.first(); at; at = atl.next()) {
+ if (at->getVisibility() == Uml::Visibility::Public)
+ atpub.append(at);
+ }
+ if (forceSections() || atpub.count())
+ ada << getIndent() << "-- Accessors for public attributes:" << m_endl << m_endl;
+ for (at = atpub.first(); at; at = atpub.next()) {
+ QString member = cleanName(at->getName());
+ ada << getIndent() << "procedure Set_" << member << " (";
+ if (! at->getStatic())
+ ada << "Self : access " << name << "; ";
+ ada << "To : " << at->getTypeName() << ");" << m_endl;
+ ada << getIndent() << "function Get_" << member;
+ if (! at->getStatic())
+ ada << " (Self : access " << name << ")";
+ ada << " return " << at->getTypeName() << ";" << m_endl
+ << m_endl;
+ }
+ }
+
+ // Generate public operations.
+ UMLOperationList opl(c->getOpList());
+ UMLOperationList oppub;
+ oppub.setAutoDelete(false);
+ UMLOperation *op;
+ for (op = opl.first(); op; op = opl.next()) {
+ if (op->getVisibility() == Uml::Visibility::Public)
+ oppub.append(op);
+ }
+ if (forceSections() || oppub.count())
+ ada << getIndent() << "-- Public methods:" << m_endl << m_endl;
+ for (op = oppub.first(); op; op = oppub.next())
+ writeOperation(op, ada);
+
+ m_indentLevel--;
+ ada << getIndent() << "private" << m_endl << m_endl;
+ m_indentLevel++;
+
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ ada << getIndent() << "type " << name << " is ";
+ if (c->getAbstract())
+ ada << "abstract ";
+ if (superclasses.isEmpty()) {
+ ada << "tagged ";
+ } else {
+ // FIXME: Multiple inheritance is not yet supported
+ UMLClassifier* parent = superclasses.first();
+ ada << "new " << className(parent, false) << " with ";
+ }
+ ada << "record" << m_endl;
+ m_indentLevel++;
+
+ if (forceSections() || !aggregations.isEmpty()) {
+ ada << getIndent() << "-- Aggregations:" << m_endl;
+ for (UMLAssociation *a = aggregations.first(); a; a = aggregations.next()) {
+ if (c != a->getObject(Uml::A))
+ continue;
+ QString typeName, roleName;
+ computeAssocTypeAndRole(c, a, typeName, roleName);
+ ada << getIndent() << roleName << " : " << typeName << ";" << m_endl;
+ }
+ ada << endl;
+ }
+ if (forceSections() || !compositions.isEmpty()) {
+ ada << getIndent() << "-- Compositions:" << m_endl;
+ for (UMLAssociation *a = compositions.first(); a; a = compositions.next()) {
+ if (c != a->getObject(Uml::A))
+ continue;
+ QString typeName, roleName;
+ computeAssocTypeAndRole(c, a, typeName, roleName);
+ ada << getIndent() << roleName << " : " << typeName << ";" << m_endl;
+ }
+ ada << endl;
+ }
+
+ if (isClass && (forceSections() || atl.count())) {
+ ada << getIndent() << "-- Attributes:" << m_endl;
+ UMLAttribute *at;
+ for (at = atl.first(); at; at = atl.next()) {
+ if (at->getStatic())
+ continue;
+ ada << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ ada << " := " << at->getInitialValue();
+ ada << ";" << m_endl;
+ }
+ }
+ bool haveAttrs = (isClass && atl.count());
+ if (aggregations.isEmpty() && compositions.isEmpty() && !haveAttrs)
+ ada << getIndent() << "null;" << m_endl;
+ m_indentLevel--;
+ ada << getIndent() << "end record;" << m_endl << m_endl;
+ if (haveAttrs) {
+ bool seen_static_attr = false;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ if (! at->getStatic())
+ continue;
+ if (! seen_static_attr) {
+ ada << getIndent() << "-- Static attributes:" << m_endl;
+ seen_static_attr = true;
+ }
+ ada << getIndent();
+ if (at->getVisibility() == Uml::Visibility::Private)
+ ada << "-- Private: ";
+ ada << cleanName(at->getName()) << " : " << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ ada << " := " << at->getInitialValue();
+ ada << ";" << m_endl;
+ }
+ if (seen_static_attr)
+ ada << m_endl;
+ }
+ // Generate protected operations.
+ UMLOperationList opprot;
+ opprot.setAutoDelete(false);
+ for (op = opl.first(); op; op = opl.next()) {
+ if (op->getVisibility() == Uml::Visibility::Protected)
+ opprot.append(op);
+ }
+ if (forceSections() || opprot.count())
+ ada << getIndent() << "-- Protected methods:" << m_endl << m_endl;
+ for (op = opprot.first(); op; op = opprot.next())
+ writeOperation(op, ada);
+
+ // Generate private operations.
+ // These are currently only generated as comments in the private part
+ // of the spec.
+ // Once umbrello supports the merging of automatically generated and
+ // hand written code sections, private operations should be generated
+ // into the package body.
+ UMLOperationList oppriv;
+ oppriv.setAutoDelete(false);
+ for (op = opl.first(); op; op = opl.next()) {
+ const Uml::Visibility::Value vis = op->getVisibility();
+ if (vis == Uml::Visibility::Private ||
+ vis == Uml::Visibility::Implementation)
+ oppriv.append(op);
+ }
+ if (forceSections() || oppriv.count())
+ ada << getIndent() << "-- Private methods:" << m_endl << m_endl;
+ for (op = oppriv.first(); op; op = oppriv.next())
+ writeOperation(op, ada, true);
+
+ m_indentLevel--;
+ ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl;
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+
+void AdaWriter::writeOperation(UMLOperation *op, QTextStream &ada, bool is_comment) {
+ UMLAttributeList atl = op->getParmList();
+ QString rettype = op->getTypeName();
+ bool use_procedure = (rettype.isEmpty() || rettype == "void");
+
+ ada << getIndent();
+ if (is_comment)
+ ada << "-- ";
+ if (use_procedure)
+ ada << "procedure ";
+ else
+ ada << "function ";
+ ada << cleanName(op->getName()) << " ";
+ if (! (op->getStatic() && atl.count() == 0))
+ ada << "(";
+ UMLClassifier *parentClassifier = static_cast<UMLClassifier*>(op->getUMLPackage());
+ if (! op->getStatic()) {
+ ada << "Self : access " << className(parentClassifier);
+ if (atl.count())
+ ada << ";" << m_endl;
+ }
+ if (atl.count()) {
+ uint i = 0;
+ m_indentLevel++;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ ada << getIndent();
+ if (is_comment)
+ ada << "-- ";
+ ada << cleanName(at->getName()) << " : ";
+ Uml::Parameter_Direction pk = at->getParmKind();
+ if (pk == Uml::pd_Out)
+ ada << "out ";
+ else if (pk == Uml::pd_InOut)
+ ada << "in out ";
+ else
+ ada << "in ";
+ ada << at->getTypeName();
+ if (! at->getInitialValue().isEmpty())
+ ada << " := " << at->getInitialValue();
+ if (++i < atl.count()) //FIXME gcc warning
+ ada << ";" << m_endl;
+ }
+ m_indentLevel--;
+ }
+ if (! (op->getStatic() && atl.count() == 0))
+ ada << ")";
+ if (! use_procedure)
+ ada << " return " << rettype;
+ if (op->getAbstract())
+ ada << " is abstract";
+ ada << ";" << m_endl << m_endl;
+}
+
+QStringList AdaWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("Boolean");
+ l.append("Character");
+ l.append("Positive");
+ l.append("Natural");
+ l.append("Integer");
+ l.append("Short_Integer");
+ l.append("Long_Integer");
+ l.append("Float");
+ l.append("Long_Float");
+ l.append("Duration");
+ l.append("String");
+ return l;
+}
+
+/**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword The string to check.
+ */
+bool AdaWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) {
+
+ const QStringList keywords = reservedKeywords();
+
+ QStringList::ConstIterator it;
+ for (it = keywords.begin(); it != keywords.end(); ++it)
+ if ((*it).lower() == rPossiblyReservedKeyword.lower())
+ return true;
+
+ return false;
+}
+
+/**
+ * get list of reserved keywords
+ */
+const QStringList AdaWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if ( keywords.isEmpty() ) {
+ keywords.append( "abort" );
+ keywords.append( "abs" );
+ keywords.append( "abstract" );
+ keywords.append( "accept" );
+ keywords.append( "access" );
+ keywords.append( "aliased" );
+ keywords.append( "all" );
+ keywords.append( "and" );
+ keywords.append( "Argument_Error" );
+ keywords.append( "array" );
+ keywords.append( "Assert_Failure" );
+ keywords.append( "at" );
+ keywords.append( "begin" );
+ keywords.append( "body" );
+ keywords.append( "Boolean" );
+ keywords.append( "case" );
+ keywords.append( "Character" );
+ keywords.append( "constant" );
+ keywords.append( "Constraint_Error" );
+ keywords.append( "Conversion_Error" );
+ keywords.append( "Data_Error" );
+ keywords.append( "declare" );
+ keywords.append( "delay" );
+ keywords.append( "delta" );
+ keywords.append( "Dereference_Error" );
+ keywords.append( "Device_Error" );
+ keywords.append( "digits" );
+ keywords.append( "do" );
+ keywords.append( "Duration" );
+ keywords.append( "else" );
+ keywords.append( "elsif" );
+ keywords.append( "end" );
+ keywords.append( "End_Error" );
+ keywords.append( "entry" );
+ keywords.append( "exception" );
+ keywords.append( "exit" );
+ keywords.append( "false" );
+ keywords.append( "Float" );
+ keywords.append( "for" );
+ keywords.append( "function" );
+ keywords.append( "generic" );
+ keywords.append( "goto" );
+ keywords.append( "if" );
+ keywords.append( "in" );
+ keywords.append( "Index_Error" );
+ keywords.append( "Integer" );
+ keywords.append( "is" );
+ keywords.append( "Layout_Error" );
+ keywords.append( "Length_Error" );
+ keywords.append( "limited" );
+ keywords.append( "Long_Float" );
+ keywords.append( "Long_Integer" );
+ keywords.append( "Long_Long_Float" );
+ keywords.append( "Long_Long_Integer" );
+ keywords.append( "loop" );
+ keywords.append( "mod" );
+ keywords.append( "Mode_Error" );
+ keywords.append( "Name_Error" );
+ keywords.append( "Natural" );
+ keywords.append( "new" );
+ keywords.append( "not" );
+ keywords.append( "null" );
+ keywords.append( "of" );
+ keywords.append( "or" );
+ keywords.append( "others" );
+ keywords.append( "out" );
+ keywords.append( "package" );
+ keywords.append( "Pattern_Error" );
+ keywords.append( "Picture_Error" );
+ keywords.append( "Pointer_Error" );
+ keywords.append( "Positive" );
+ keywords.append( "pragma" );
+ keywords.append( "private" );
+ keywords.append( "procedure" );
+ keywords.append( "Program_Error" );
+ keywords.append( "protected" );
+ keywords.append( "raise" );
+ keywords.append( "range" );
+ keywords.append( "record" );
+ keywords.append( "rem" );
+ keywords.append( "renames" );
+ keywords.append( "requeue" );
+ keywords.append( "return" );
+ keywords.append( "reverse" );
+ keywords.append( "select" );
+ keywords.append( "separate" );
+ keywords.append( "Short_Float" );
+ keywords.append( "Short_Integer" );
+ keywords.append( "Short_Short_Float" );
+ keywords.append( "Short_Short_Integer" );
+ keywords.append( "Status_Error" );
+ keywords.append( "Storage_Error" );
+ keywords.append( "String" );
+ keywords.append( "subtype" );
+ keywords.append( "Tag_Error" );
+ keywords.append( "tagged" );
+ keywords.append( "task" );
+ keywords.append( "Tasking_Error" );
+ keywords.append( "terminate" );
+ keywords.append( "Terminator_Error" );
+ keywords.append( "then" );
+ keywords.append( "Time_Error" );
+ keywords.append( "Translation_Error" );
+ keywords.append( "true" );
+ keywords.append( "type" );
+ keywords.append( "until" );
+ keywords.append( "Update_Error" );
+ keywords.append( "use" );
+ keywords.append( "Use_Error" );
+ keywords.append( "when" );
+ keywords.append( "while" );
+ keywords.append( "Wide_Character" );
+ keywords.append( "Wide_String" );
+ keywords.append( "with" );
+ keywords.append( "xor" );
+ }
+
+ return keywords;
+}
+
+#include "adawriter.moc"
diff --git a/umbrello/umbrello/codegenerators/adawriter.h b/umbrello/umbrello/codegenerators/adawriter.h
new file mode 100644
index 00000000..ca5d9f67
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/adawriter.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+ adawriter.h - description
+ -------------------
+ Based on javawriter.h by Luis De la Parra Blum
+ begin : Sat Dec 14 2002
+ copyright : (C) 2002 by Oliver Kellogg
+ email : okellogg@users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef ADAWRITER_H
+#define ADAWRITER_H
+
+#include "simplecodegenerator.h"
+
+class UMLAssociation;
+class UMLOperation;
+
+/**
+ * class AdaWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate an Ada package spec for
+ * that concept
+ */
+class AdaWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ /**
+ * Basic Constructor
+ */
+ AdaWriter ();
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~AdaWriter ();
+
+ /**
+ * call this method to generate Ada code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass (UMLClassifier *c);
+
+ /**
+ * returns "Ada"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ QStringList defaultDatatypes();
+
+ /**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword The string to check.
+ * @return true if the keyword is reserved
+ */
+ virtual bool isReservedKeyword(const QString & rPossiblyReservedKeyword);
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * write one operation
+ * @param op the class for which we are generating code
+ * @param ada the stream associated with the output file
+ */
+ void writeOperation (UMLOperation *op, QTextStream &ada, bool is_comment = false);
+
+ /**
+ * Compute the type and role name from the given association.
+ *
+ * @param c The UMLClassifier for which code is being generated.
+ * @param a The UMLAssociation to analyze.
+ * @param typeName Return value: type name.
+ * @param roleName Return value: role name.
+ */
+ void computeAssocTypeAndRole (UMLClassifier *c,
+ UMLAssociation *a,
+ QString& typeName, QString& roleName);
+
+ bool isOOClass (UMLClassifier *c);
+
+ QString className(UMLClassifier *c, bool inOwnScope = true);
+
+ QString packageName(UMLPackage *p);
+
+ static const QString defaultPackageSuffix;
+
+};
+
+#endif // ADAWRITER_H
diff --git a/umbrello/umbrello/codegenerators/aswriter.cpp b/umbrello/umbrello/codegenerators/aswriter.cpp
new file mode 100644
index 00000000..ad55839d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/aswriter.cpp
@@ -0,0 +1,775 @@
+/***************************************************************************
+ begin : Sat Feb 08 2003
+ copyright : (C) 2003 by Alexander Blum
+ email : blum@kewbee.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "aswriter.h"
+#include "../association.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umldoc.h"
+#include "../attribute.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+ASWriter::ASWriter() {
+}
+
+ASWriter::~ASWriter() {}
+
+
+void ASWriter::writeClass(UMLClassifier *c)
+{
+ if(!c)
+ {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+ QString fileName = c->getName().lower();
+
+ //find an appropriate name for our file
+ fileName = findFileName(c,".as");
+ if (fileName.isEmpty())
+ {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile fileas;
+ if(!openFile(fileas,fileName))
+ {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream as(&fileas);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".as");
+ if(!str.isEmpty())
+ {
+ str.replace(QRegExp("%filename%"),fileName+".as");
+ str.replace(QRegExp("%filepath%"),fileas.name());
+ as << str << m_endl;
+ }
+
+
+ //write includes
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ for (UMLPackage *conc = includes.first(); conc; conc = includes.next())
+ {
+ QString headerName = findFileName(conc, ".as");
+ if ( !headerName.isEmpty() )
+ {
+ as << "#include \"" << findFileName(conc,".as") << "\"" << m_endl;
+ }
+ }
+ as << m_endl;
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty())
+ {
+ as << m_endl << "/**" << m_endl;
+ as << " * class " << classname << m_endl;
+ as << formatDoc(c->getDoc()," * ");
+ as << " */" << m_endl << m_endl;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ //check if class is abstract and / or has abstract methods
+ if(c->getAbstract() && !hasAbstractOps(c))
+ as << "/******************************* Abstract Class ****************************" << m_endl << " "
+ << classname << " does not have any pure virtual methods, but its author" << m_endl
+ << " defined it as an abstract class, so you should not use it directly." << m_endl
+ << " Inherit from it instead and create only objects from the derived classes" << m_endl
+ << "*****************************************************************************/" << m_endl << m_endl;
+
+ as << classname << " = function ()" << m_endl;
+ as << "{" << m_endl;
+ as << m_indentation << "this._init ();" << m_endl;
+ as << "}" << m_endl;
+ as << m_endl;
+
+ for(UMLClassifier *obj = superclasses.first();
+ obj; obj = superclasses.next()) {
+ as << classname << ".prototype = new " << cleanName(obj->getName()) << " ();" << m_endl;
+ }
+
+ as << m_endl;
+
+ const bool isClass = !c->isInterface();
+ if (isClass) {
+
+ UMLAttributeList atl = c->getAttributeList();
+
+ as << "/**" << m_endl;
+ QString temp = "_init sets all " + classname +
+ " attributes to their default values. " +
+ "Make sure to call this method within your class constructor";
+ as << formatDoc(temp, " * ");
+ as << " */" << m_endl;
+ as << classname << ".prototype._init = function ()" << m_endl;
+ as << "{" << m_endl;
+ for(UMLAttribute *at = atl.first(); at ; at = atl.next())
+ {
+ if (forceDoc() || !at->getDoc().isEmpty())
+ {
+ as << m_indentation << "/**" << m_endl
+ << formatDoc(at->getDoc(), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+ if(!at->getInitialValue().isEmpty())
+ {
+ as << m_indentation << "this.m_" << cleanName(at->getName()) << " = " << at->getInitialValue() << ";" << m_endl;
+ }
+ else
+ {
+ as << m_indentation << "this.m_" << cleanName(at->getName()) << " = \"\";" << m_endl;
+ }
+ }
+ }
+
+ //associations
+ if (forceSections() || !aggregations.isEmpty ())
+ {
+ as << m_endl << m_indentation << "/**Aggregations: */" << m_endl;
+ writeAssociation(classname, aggregations , as );
+
+ }
+
+ if( forceSections() || !compositions.isEmpty())
+ {
+ as << m_endl << m_indentation << "/**Compositions: */" << m_endl;
+ writeAssociation(classname, compositions , as );
+ }
+
+ as << m_endl;
+ as << m_indentation << "/**Protected: */" << m_endl;
+
+ if (isClass) {
+ UMLAttributeList atl = c->getAttributeList();
+ for (UMLAttribute *at = atl.first(); at ; at = atl.next())
+ {
+ if (at->getVisibility() == Uml::Visibility::Protected)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(at->getName()) << "\", 1);" << m_endl;
+ }
+ }
+ }
+
+ UMLOperationList opList(c->getOpList());
+ for (UMLOperation *op = opList.first(); op; op = opList.next())
+ {
+ if (op->getVisibility() == Uml::Visibility::Protected)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(op->getName()) << "\", 1);" << m_endl;
+ }
+ }
+ as << m_endl;
+ as << m_indentation << "/**Private: */" << m_endl;
+ if (isClass) {
+ UMLAttributeList atl = c->getAttributeList();
+ for (UMLAttribute *at = atl.first(); at; at = atl.next())
+ {
+ if (at->getVisibility() == Uml::Visibility::Private)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(at->getName()) << "\", 7);" << m_endl;
+ }
+ }
+ }
+
+ for (UMLOperation *op = opList.first(); op; op = opList.next())
+ {
+ if (op->getVisibility() == Uml::Visibility::Protected)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(op->getName()) << "\", 7);" << m_endl;
+ }
+ }
+ as << "}" << m_endl;
+
+ as << m_endl;
+
+ //operations
+ UMLOperationList ops(c->getOpList());
+ writeOperations(classname, &ops, as);
+
+ as << m_endl;
+
+ //finish file
+
+ //close files and notfiy we are done
+ fileas.close();
+ emit codeGenerated(c, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+
+void ASWriter::writeAssociation(QString& classname, UMLAssociationList& assocList , QTextStream &as )
+{
+ for(UMLAssociation *a = assocList.first(); a; a = assocList.next())
+ {
+ // association side
+ Uml::Role_Type role = a->getObject(Uml::A)->getName() == classname ? Uml::B:Uml::A;
+
+ QString roleName(cleanName(a->getRoleName(role)));
+
+ if (!roleName.isEmpty()) {
+
+ // association doc
+ if (forceDoc() || !a->getDoc().isEmpty()) {
+ as << m_indentation << "/**" << m_endl
+ << formatDoc(a->getDoc(), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+
+ // role doc
+ if (forceDoc() || !a->getRoleDoc(role).isEmpty()) {
+ as << m_indentation << "/**" << m_endl
+ << formatDoc(a->getRoleDoc(role), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+
+ bool okCvt;
+ int nMulti = a->getMulti(role).toInt(&okCvt,10);
+ bool isNotMulti = a->getMulti(role).isEmpty() || (okCvt && nMulti == 1);
+
+ QString typeName(cleanName(a->getObject(role)->getName()));
+
+ if (isNotMulti)
+ as << m_indentation << "this.m_" << roleName << " = new " << typeName << "();" << m_endl;
+ else
+ as << m_indentation << "this.m_" << roleName << " = new Array();" << m_endl;
+
+ // role visibility
+ if (a->getVisibility(role) == Uml::Visibility::Private)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"m_" << roleName << "\", 7);" << m_endl;
+ }
+ else if (a->getVisibility(role)== Uml::Visibility::Protected)
+ {
+ as << m_indentation << "ASSetPropFlags (this, \"m_" << roleName << "\", 1);" << m_endl;
+ }
+ }
+ }
+}
+
+void ASWriter::writeOperations(QString classname, UMLOperationList *opList, QTextStream &as)
+{
+ UMLOperation *op;
+ UMLAttributeList atl;
+ UMLAttribute *at;
+
+ for(op = opList->first(); op; op = opList->next())
+ {
+ atl = op -> getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at ; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ if( writeDoc ) //write method documentation
+ {
+ as << "/**" << m_endl << formatDoc(op->getDoc()," * ");
+
+ for (at = atl.first(); at; at = atl.next()) //write parameter documentation
+ {
+ if(forceDoc() || !at->getDoc().isEmpty())
+ {
+ as << " * @param " + cleanName(at->getName())<<m_endl;
+ as << formatDoc(at->getDoc()," * ");
+ }
+ }//end for : write parameter documentation
+ as << " */" << m_endl;
+ }//end if : write method documentation
+
+ as << classname << ".prototype." << cleanName(op->getName()) << " = function " << "(";
+
+ int i= atl.count();
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(),j++)
+ {
+ as << cleanName(at->getName())
+ << (!(at->getInitialValue().isEmpty()) ? (QString(" = ")+at->getInitialValue()) : QString(""))
+ << ((j < i-1)?", ":"");
+ }
+ as << ")" << m_endl << "{" << m_endl <<
+ m_indentation << m_endl << "}" << m_endl;
+ as << m_endl << m_endl;
+ }//end for
+}
+
+/**
+ * returns "ActionScript"
+ */
+Uml::Programming_Language ASWriter::getLanguage() {
+ return Uml::pl_ActionScript;
+}
+
+const QStringList ASWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if ( keywords.isEmpty() ) {
+ keywords << "abs"
+ << "acos"
+ << "add"
+ << "addListener"
+ << "addProperty"
+ << "align"
+ << "_alpha"
+ << "and"
+ << "appendChild"
+ << "apply"
+ << "Array"
+ << "asin"
+ << "atan"
+ << "atan2"
+ << "attachMovie"
+ << "attachSound"
+ << "attributes"
+ << "autoSize"
+ << "background"
+ << "backgroundColor"
+ << "BACKSPACE"
+ << "beginFill"
+ << "beginGradientFill"
+ << "blockIndent"
+ << "bold"
+ << "Boolean"
+ << "border"
+ << "borderColor"
+ << "bottomScroll"
+ << "break"
+ << "bullet"
+ << "call"
+ << "callee"
+ << "caller"
+ << "capabilities"
+ << "CAPSLOCK"
+ << "case"
+ << "ceil"
+ << "charAt"
+ << "charCodeAt"
+ << "childNodes"
+ << "chr"
+ << "clear"
+ << "clearInterval"
+ << "cloneNode"
+ << "close"
+ << "color"
+ << "Color"
+ << "comment"
+ << "concat"
+ << "connect"
+ << "contentType"
+ << "continue"
+ << "CONTROL"
+ << "cos"
+ << "createElement"
+ << "createEmptyMovieClip"
+ << "createTextField"
+ << "createTextNode"
+ << "_currentframe"
+ << "curveTo"
+ << "Date"
+ << "default"
+ << "delete"
+ << "DELETEKEY"
+ << "do"
+ << "docTypeDecl"
+ << "DOWN"
+ << "_droptarget"
+ << "duplicateMovieClip"
+ << "duration"
+ << "E"
+ << "else"
+ << "embedFonts"
+ << "enabled"
+ << "END"
+ << "endFill"
+ << "endinitclip"
+ << "ENTER"
+ << "eq"
+ << "escape"
+ << "ESCAPE"
+ << "eval"
+ << "evaluate"
+ << "exp"
+ << "false"
+ << "firstChild"
+ << "floor"
+ << "focusEnabled"
+ << "_focusrect"
+ << "font"
+ << "for"
+ << "_framesloaded"
+ << "fromCharCode"
+ << "fscommand"
+ << "function"
+ << "ge"
+ << "get"
+ << "getAscii"
+ << "getBeginIndex"
+ << "getBounds"
+ << "getBytesLoaded"
+ << "getBytesTotal"
+ << "getCaretIndex"
+ << "getCode"
+ << "getDate"
+ << "getDay"
+ << "getDepth"
+ << "getEndIndex"
+ << "getFocus"
+ << "getFontList"
+ << "getFullYear"
+ << "getHours"
+ << "getMilliseconds"
+ << "getMinutes"
+ << "getMonth"
+ << "getNewTextFormat"
+ << "getPan"
+ << "getProperty"
+ << "getRGB"
+ << "getSeconds"
+ << "getTextExtent"
+ << "getTextFormat"
+ << "getTime"
+ << "getTimer"
+ << "getTimezoneOffset"
+ << "getTransform"
+ << "getURL"
+ << "getUTCDate"
+ << "getUTCDay"
+ << "getUTCFullYear"
+ << "getUTCHours"
+ << "getUTCMilliseconds"
+ << "getUTCMinutes"
+ << "getUTCMonth"
+ << "getUTCSeconds"
+ << "getVersion"
+ << "getVolume"
+ << "getYear"
+ << "_global"
+ << "globalToLocal"
+ << "goto"
+ << "gotoAndPlay"
+ << "gotoAndStop"
+ << "gt"
+ << "hasAccessibility"
+ << "hasAudio"
+ << "hasAudioEncoder"
+ << "hasChildNodes"
+ << "hasMP3"
+ << "hasVideoEncoder"
+ << "height"
+ << "_height"
+ << "hide"
+ << "_highquality"
+ << "hitArea"
+ << "hitTest"
+ << "HOME"
+ << "hscroll"
+ << "html"
+ << "htmlText"
+ << "if"
+ << "ifFrameLoaded"
+ << "ignoreWhite"
+ << "in"
+ << "include"
+ << "indent"
+ << "indexOf"
+ << "initclip"
+ << "INSERT"
+ << "insertBefore"
+ << "install"
+ << "instanceof"
+ << "int"
+ << "isActive"
+ << "isDown"
+ << "isFinite"
+ << "isNaN"
+ << "isToggled"
+ << "italic"
+ << "join"
+ << "lastChild"
+ << "lastIndexOf"
+ << "le"
+ << "leading"
+ << "LEFT"
+ << "leftMargin"
+ << "length"
+ << "_level"
+ << "lineStyle"
+ << "lineTo"
+ << "list"
+ << "LN10"
+ << "LN2"
+ << "load"
+ << "loaded"
+ << "loadMovie"
+ << "loadMovieNum"
+ << "loadSound"
+ << "loadVariables"
+ << "loadVariablesNum"
+ << "LoadVars"
+ << "localToGlobal"
+ << "log"
+ << "LOG10E"
+ << "LOG2E"
+ << "max"
+ << "maxChars"
+ << "maxhscroll"
+ << "maxscroll"
+ << "MAX_VALUE"
+ << "mbchr"
+ << "mblength"
+ << "mbord"
+ << "mbsubstring"
+ << "method"
+ << "min"
+ << "MIN_VALUE"
+ << "moveTo"
+ << "multiline"
+ << "_name"
+ << "NaN"
+ << "ne"
+ << "NEGATIVE_INFINITY"
+ << "new"
+ << "newline"
+ << "nextFrame"
+ << "nextScene"
+ << "nextSibling"
+ << "nodeName"
+ << "nodeType"
+ << "nodeValue"
+ << "not"
+ << "null"
+ << "Number"
+ << "Object"
+ << "on"
+ << "onChanged"
+ << "onClipEvent"
+ << "onClose"
+ << "onConnect"
+ << "onData"
+ << "onDragOut"
+ << "onDragOver"
+ << "onEnterFrame"
+ << "onKeyDown"
+ << "onKeyUp"
+ << "onKillFocus"
+ << "onLoad"
+ << "onMouseDown"
+ << "onMouseMove"
+ << "onMouseUp"
+ << "onPress"
+ << "onRelease"
+ << "onReleaseOutside"
+ << "onResize"
+ << "onRollOut"
+ << "onRollOver"
+ << "onScroller"
+ << "onSetFocus"
+ << "onSoundComplete"
+ << "onUnload"
+ << "onUpdate"
+ << "onXML"
+ << "or"
+ << "ord"
+ << "_parent"
+ << "parentNode"
+ << "parseFloat"
+ << "parseInt"
+ << "parseXML"
+ << "password"
+ << "PGDN"
+ << "PGUP"
+ << "PI"
+ << "pixelAspectRatio"
+ << "play"
+ << "pop"
+ << "position"
+ << "POSITIVE_INFINITY"
+ << "pow"
+ << "prevFrame"
+ << "previousSibling"
+ << "prevScene"
+ << "print"
+ << "printAsBitmap"
+ << "printAsBitmapNum"
+ << "printNum"
+ << "__proto__"
+ << "prototype"
+ << "push"
+ << "_quality"
+ << "random"
+ << "registerClass"
+ << "removeListener"
+ << "removeMovieClip"
+ << "removeNode"
+ << "removeTextField"
+ << "replaceSel"
+ << "restrict"
+ << "return"
+ << "reverse"
+ << "RIGHT"
+ << "rightMargin"
+ << "_root"
+ << "_rotation"
+ << "round"
+ << "scaleMode"
+ << "screenColor"
+ << "screenDPI"
+ << "screenResolutionX"
+ << "screenResolutionY"
+ << "scroll"
+ << "selectable"
+ << "send"
+ << "sendAndLoad"
+ << "set"
+ << "setDate"
+ << "setFocus"
+ << "setFullYear"
+ << "setHours"
+ << "setInterval"
+ << "setMask"
+ << "setMilliseconds"
+ << "setMinutes"
+ << "setMonth"
+ << "setNewTextFormat"
+ << "setPan"
+ << "setProperty"
+ << "setRGB"
+ << "setSeconds"
+ << "setSelection"
+ << "setTextFormat"
+ << "setTime"
+ << "setTransform"
+ << "setUTCDate"
+ << "setUTCFullYear"
+ << "setUTCHours"
+ << "setUTCMilliseconds"
+ << "setUTCMinutes"
+ << "setUTCMonth"
+ << "setUTCSeconds"
+ << "setVolume"
+ << "setYear"
+ << "shift"
+ << "SHIFT"
+ << "show"
+ << "showMenu"
+ << "sin"
+ << "size"
+ << "slice"
+ << "sort"
+ << "sortOn"
+ << "Sound"
+ << "_soundbuftime"
+ << "SPACE"
+ << "splice"
+ << "split"
+ << "sqrt"
+ << "SQRT1_2"
+ << "SQRT2"
+ << "start"
+ << "startDrag"
+ << "status"
+ << "stop"
+ << "stopAllSounds"
+ << "stopDrag"
+ << "String"
+ << "substr"
+ << "substring"
+ << "super"
+ << "swapDepths"
+ << "switch"
+ << "TAB"
+ << "tabChildren"
+ << "tabEnabled"
+ << "tabIndex"
+ << "tabStops"
+ << "tan"
+ << "target"
+ << "_target"
+ << "targetPath"
+ << "tellTarget"
+ << "text"
+ << "textColor"
+ << "TextFormat"
+ << "textHeight"
+ << "textWidth"
+ << "this"
+ << "toggleHighQuality"
+ << "toLowerCase"
+ << "toString"
+ << "_totalframes"
+ << "toUpperCase"
+ << "trace"
+ << "trackAsMenu"
+ << "true"
+ << "type"
+ << "typeof"
+ << "undefined"
+ << "underline"
+ << "unescape"
+ << "uninstall"
+ << "unloadMovie"
+ << "unloadMovieNum"
+ << "unshift"
+ << "unwatch"
+ << "UP"
+ << "updateAfterEvent"
+ << "url"
+ << "_url"
+ << "useHandCursor"
+ << "UTC"
+ << "valueOf"
+ << "var"
+ << "variable"
+ << "_visible"
+ << "void"
+ << "watch"
+ << "while"
+ << "width"
+ << "_width"
+ << "with"
+ << "wordWrap"
+ << "_x"
+ << "XML"
+ << "xmlDecl"
+ << "XMLSocket"
+ << "_xmouse"
+ << "_xscale"
+ << "_y"
+ << "_ymouse";
+ }
+
+ return keywords;
+}
+
+#include "aswriter.moc"
diff --git a/umbrello/umbrello/codegenerators/aswriter.h b/umbrello/umbrello/codegenerators/aswriter.h
new file mode 100644
index 00000000..51a4a922
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/aswriter.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ aswriter.h - description
+ -------------------
+ begin : Sat Feb 08 2003
+ copyright : (C) 2003 by Alexander Blum
+ email : blum@kewbee.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef ASWRITER_H
+#define ASWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlassociationlist.h"
+
+/**
+ * class ASWriter is a ActionScript code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class ASWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ ASWriter();
+ virtual ~ASWriter();
+
+ /**
+ * call this method to generate Actionscript code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "ActionScript"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param as output stream for the AS file
+ */
+ void writeOperations(QString classname, UMLOperationList *opList, QTextStream &as);
+
+ /**
+ * write a list of associations
+ *
+ * @param classname the name of the class
+ * @param assocList the list of associations
+ * @param as output stream for the AS file
+ */
+ void writeAssociation(QString& classname, UMLAssociationList& assoclist , QTextStream &as);
+
+};
+
+#endif //ASWRITER
diff --git a/umbrello/umbrello/codegenerators/classifierinfo.cpp b/umbrello/umbrello/codegenerators/classifierinfo.cpp
new file mode 100644
index 00000000..690238cf
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/classifierinfo.cpp
@@ -0,0 +1,140 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov *
+ * (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#include "classifierinfo.h"
+
+#include "../classifier.h"
+#include "../operation.h"
+
+ClassifierInfo::ClassifierInfo( UMLClassifier *classifier)
+{
+ classifier_ = classifier;
+
+ // set default class, file names
+ className = classifier->getName();
+ fileName = classifier->getName().lower();
+
+ // determine up-front what we are dealing with
+ isInterface = classifier->isInterface();
+
+ // sort attributes by Scope
+ if(!isInterface) {
+ UMLAttributeList atl = classifier->getAttributeList();
+ for(UMLAttribute *at=atl.first(); at ; at=atl.next()) {
+ switch(at->getVisibility())
+ {
+ case Uml::Visibility::Public:
+ if(at->getStatic())
+ static_atpub.append(at);
+ else
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ if(at->getStatic())
+ static_atprot.append(at);
+ else
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ case Uml::Visibility::Implementation:
+ if(at->getStatic())
+ static_atpriv.append(at);
+ else
+ atpriv.append(at);
+ break;
+ }
+ }
+ }
+
+ // inheritance issues
+ superclasses = classifier->getSuperClasses(); // list of what we inherit from
+
+ subclasses = classifier->getSubClasses(); // list of what inherits from us
+
+ // another preparation, determine what we have
+ plainAssociations = classifier->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
+
+ uniAssociations = classifier->getUniAssociationToBeImplemented();
+
+ aggregations = classifier->getAggregations();
+
+ compositions = classifier->getCompositions();
+
+ // set some summary information about the classifier now
+ hasAssociations = plainAssociations.count() > 0 || aggregations.count() > 0 || compositions.count() > 0 || uniAssociations.count() > 0;
+ hasAttributes = atpub.count() > 0 || atprot.count() > 0 || atpriv.count() > 0
+ || static_atpub.count() > 0
+ || static_atprot.count() > 0
+ || static_atpriv.count() > 0;
+
+ hasStaticAttributes = static_atpub.count() > 0
+ || static_atprot.count() > 0
+ || static_atpriv.count() > 0;
+
+ hasAccessorMethods = hasAttributes || hasAssociations;
+
+ hasOperationMethods = classifier->getOpList().last() ? true : false;
+
+ hasMethods = hasOperationMethods || hasAccessorMethods;
+
+ // this is a bit too simplistic..some associations are for
+ // SINGLE objects, and WONT be declared as Vectors, so this
+ // is a bit overly inclusive (I guess that's better than the other way around)
+ hasVectorFields = hasAssociations ? true : false;
+}
+
+ClassifierInfo::~ClassifierInfo() { }
+
+UMLClassifierList ClassifierInfo::getPlainAssocChildClassifierList()
+{
+ return findAssocClassifierObjsInRoles(&plainAssociations);
+}
+
+UMLClassifierList ClassifierInfo::getAggregateChildClassifierList()
+{
+ return findAssocClassifierObjsInRoles(&aggregations);
+}
+
+UMLClassifierList ClassifierInfo::getCompositionChildClassifierList()
+{
+ return findAssocClassifierObjsInRoles(&compositions);
+}
+
+UMLClassifierList ClassifierInfo::findAssocClassifierObjsInRoles (UMLAssociationList * list)
+{
+ UMLClassifierList classifiers;
+
+ for (UMLAssociation *a = list->first(); a; a = list->next()) {
+ // DONT accept a classifier IF the association role is empty, by
+ // convention, that means to ignore the classifier on that end of
+ // the association.
+ // We also ignore classifiers which are the same as the current one
+ // (e.g. id matches), we only want the "other" classifiers
+ if (a->getObjectId(Uml::A) == classifier_->getID() && !a->getRoleName(Uml::B).isEmpty()) {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B));
+ if(c)
+ classifiers.append(c);
+ } else if (a->getObjectId(Uml::B) == classifier_->getID() && !a->getRoleName(Uml::A).isEmpty()) {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ if(c)
+ classifiers.append(c);
+ }
+ }
+
+ return classifiers;
+}
+
+UMLAttributeList ClassifierInfo::getAttList()
+{
+ return classifier_->getAttributeList();
+}
+
diff --git a/umbrello/umbrello/codegenerators/classifierinfo.h b/umbrello/umbrello/codegenerators/classifierinfo.h
new file mode 100644
index 00000000..53b7c02b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/classifierinfo.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003 Brian Thomas <brian.thomas@gsfc.nasa.gov> *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERINFO_H
+#define CLASSIFIERINFO_H
+
+#include "../umldoc.h"
+#include "../attribute.h"
+#include "../association.h"
+#include "../umlclassifierlist.h"
+#include "../umlassociationlist.h"
+#include "../umlattributelist.h"
+
+#include <qstring.h>
+
+
+class UMLClassifier;
+
+
+/**
+ * class ClassInfo is an object to hold summary information about a classifier
+ * in a convenient form for easy access by a code generator.
+ */
+class ClassifierInfo {
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ ClassifierInfo (UMLClassifier * classifier);
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~ClassifierInfo();
+
+ // Fields
+ //
+
+ /**
+ * Lists of attributes of this classifier (if a class)
+ * Sorted by scope.
+ */
+ UMLAttributeList atpub;
+ UMLAttributeList atprot;
+ UMLAttributeList atpriv;
+
+ /**
+ * Lists of static attributes of this classifier (if a class)
+ */
+ UMLAttributeList static_atpub;
+ UMLAttributeList static_atprot;
+ UMLAttributeList static_atpriv;
+
+ /**
+ * Lists of types of associations this classifier has
+ */
+ UMLAssociationList plainAssociations;
+ UMLAssociationList uniAssociations;
+ UMLAssociationList aggregations;
+ UMLAssociationList compositions;
+
+ /**
+ * what sub and super classifiers are related to this class
+ */
+ UMLClassifierList superclasses;
+ UMLClassifierList subclasses;
+
+ /**
+ * Various conditional information about our classifier.
+ */
+ bool isInterface; // Whether or not this classifier is an interface.
+ bool hasAssociations;
+ bool hasAttributes;
+ bool hasStaticAttributes;
+ bool hasMethods;
+ bool hasAccessorMethods;
+ bool hasOperationMethods;
+ bool hasVectorFields;
+
+ /**
+ * Class and File names
+ */
+ QString className;
+ QString fileName;
+
+ /**
+ * utility functions to allow easy determination of what classifiers
+ * are "owned" by the current one via named association type (e.g.
+ * plain, aggregate or compositions).
+ */
+ UMLClassifierList getPlainAssocChildClassifierList();
+ UMLClassifierList getAggregateChildClassifierList();
+ UMLClassifierList getCompositionChildClassifierList();
+
+ /**
+ * Utility method to obtain list of attributes, if they exist, for
+ * the current classfier.
+ */
+ UMLAttributeList getAttList();
+
+private:
+
+ UMLClassifier* classifier_;
+
+ /**
+ * Utility method called by "get*ChildClassfierList()" methods. It basically
+ * finds all the classifiers named in each association in the given association list
+ * which arent the current one. Usefull for finding which classifiers are "owned" by the
+ * current one via declared associations such as in aggregations/compositions.
+ */
+ UMLClassifierList findAssocClassifierObjsInRoles (UMLAssociationList * list);
+
+};
+
+#endif // CLASSIFIERINFO_H
+
diff --git a/umbrello/umbrello/codegenerators/codegen_utils.cpp b/umbrello/umbrello/codegenerators/codegen_utils.cpp
new file mode 100644
index 00000000..cb94cdde
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/codegen_utils.cpp
@@ -0,0 +1,413 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codegen_utils.h"
+// app includes
+#include "../uml.h"
+#include "../umldoc.h"
+
+namespace Codegen_Utils {
+
+QStringList cppDatatypes() {
+ QStringList l;
+ l.append("int");
+ l.append("char");
+ l.append("bool");
+ l.append("float");
+ l.append("double");
+ l.append("short");
+ l.append("long");
+ l.append("unsigned int");
+ l.append("unsigned short");
+ l.append("unsigned long");
+ l.append("string");
+ return l;
+}
+
+const QStringList reservedCppKeywords() {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords.append( "and" );
+ keywords.append( "and_eq" );
+ keywords.append( "__asm__" );
+ keywords.append( "asm" );
+ keywords.append( "__attribute__" );
+ keywords.append( "auto" );
+ keywords.append( "bitand" );
+ keywords.append( "bitor" );
+ keywords.append( "bool" );
+ keywords.append( "break" );
+ keywords.append( "BUFSIZ" );
+ keywords.append( "case" );
+ keywords.append( "catch" );
+ keywords.append( "char" );
+ keywords.append( "CHAR_BIT" );
+ keywords.append( "CHAR_MAX" );
+ keywords.append( "CHAR_MIN" );
+ keywords.append( "class" );
+ keywords.append( "CLOCKS_PER_SEC" );
+ keywords.append( "clock_t" );
+ keywords.append( "compl" );
+ keywords.append( "__complex__" );
+ keywords.append( "complex" );
+ keywords.append( "const" );
+ keywords.append( "const_cast" );
+ keywords.append( "continue" );
+ keywords.append( "__DATE__" );
+ keywords.append( "DBL_DIG" );
+ keywords.append( "DBL_EPSILON" );
+ keywords.append( "DBL_MANT_DIG" );
+ keywords.append( "DBL_MAX" );
+ keywords.append( "DBL_MAX_10_EXP" );
+ keywords.append( "DBL_MAX_EXP" );
+ keywords.append( "DBL_MIN" );
+ keywords.append( "DBL_MIN_10_EXP" );
+ keywords.append( "DBL_MIN_EXP" );
+ keywords.append( "default" );
+ keywords.append( "delete" );
+ keywords.append( "DIR" );
+ keywords.append( "div_t" );
+ keywords.append( "do" );
+ keywords.append( "double" );
+ keywords.append( "dynamic_cast" );
+ keywords.append( "E2BIG" );
+ keywords.append( "EACCES" );
+ keywords.append( "EAGAIN" );
+ keywords.append( "EBADF" );
+ keywords.append( "EBADMSG" );
+ keywords.append( "EBUSY" );
+ keywords.append( "ECANCELED" );
+ keywords.append( "ECHILD" );
+ keywords.append( "EDEADLK" );
+ keywords.append( "EDOM" );
+ keywords.append( "EEXIST" );
+ keywords.append( "EFAULT" );
+ keywords.append( "EFBIG" );
+ keywords.append( "EILSEQ" );
+ keywords.append( "EINPROGRESS" );
+ keywords.append( "EINTR" );
+ keywords.append( "EINVAL" );
+ keywords.append( "EIO" );
+ keywords.append( "EISDIR" );
+ keywords.append( "else" );
+ keywords.append( "EMFILE" );
+ keywords.append( "EMLINK" );
+ keywords.append( "EMSGSIZE" );
+ keywords.append( "ENAMETOOLONG" );
+ keywords.append( "ENFILE" );
+ keywords.append( "ENODEV" );
+ keywords.append( "ENOENT" );
+ keywords.append( "ENOEXEC" );
+ keywords.append( "ENOLCK" );
+ keywords.append( "ENOMEM" );
+ keywords.append( "ENOSPC" );
+ keywords.append( "ENOSYS" );
+ keywords.append( "ENOTDIR" );
+ keywords.append( "ENOTEMPTY" );
+ keywords.append( "ENOTSUP" );
+ keywords.append( "ENOTTY" );
+ keywords.append( "enum" );
+ keywords.append( "ENXIO" );
+ keywords.append( "EOF" );
+ keywords.append( "EPERM" );
+ keywords.append( "EPIPE" );
+ keywords.append( "ERANGE" );
+ keywords.append( "EROFS" );
+ keywords.append( "ESPIPE" );
+ keywords.append( "ESRCH" );
+ keywords.append( "ETIMEDOUT" );
+ keywords.append( "EXDEV" );
+ keywords.append( "EXIT_FAILURE" );
+ keywords.append( "EXIT_SUCCESS" );
+ keywords.append( "explicit" );
+ keywords.append( "export" );
+ keywords.append( "extern" );
+ keywords.append( "false" );
+ keywords.append( "__FILE__" );
+ keywords.append( "FILE" );
+ keywords.append( "FILENAME_MAX" );
+ keywords.append( "float" );
+ keywords.append( "FLT_DIG" );
+ keywords.append( "FLT_EPSILON" );
+ keywords.append( "FLT_MANT_DIG" );
+ keywords.append( "FLT_MAX" );
+ keywords.append( "FLT_MAX_10_EXP" );
+ keywords.append( "FLT_MAX_EXP" );
+ keywords.append( "FLT_MIN" );
+ keywords.append( "FLT_MIN_10_EXP" );
+ keywords.append( "FLT_MIN_EXP" );
+ keywords.append( "FLT_RADIX" );
+ keywords.append( "FLT_ROUNDS" );
+ keywords.append( "FOPEN_MAX" );
+ keywords.append( "for" );
+ keywords.append( "fpos_t" );
+ keywords.append( "friend" );
+ keywords.append( "__FUNCTION__" );
+ keywords.append( "__GNUC__" );
+ keywords.append( "goto" );
+ keywords.append( "HUGE_VAL" );
+ keywords.append( "if" );
+ keywords.append( "__imag__" );
+ keywords.append( "inline" );
+ keywords.append( "int" );
+ keywords.append( "INT16_MAX" );
+ keywords.append( "INT16_MIN" );
+ keywords.append( "int16_t" );
+ keywords.append( "INT32_MAX" );
+ keywords.append( "INT32_MIN" );
+ keywords.append( "int32_t" );
+ keywords.append( "INT64_MAX" );
+ keywords.append( "INT64_MIN" );
+ keywords.append( "int64_t" );
+ keywords.append( "INT8_MAX" );
+ keywords.append( "INT8_MIN" );
+ keywords.append( "int8_t" );
+ keywords.append( "INT_FAST16_MAX" );
+ keywords.append( "INT_FAST16_MIN" );
+ keywords.append( "int_fast16_t" );
+ keywords.append( "INT_FAST32_MAX" );
+ keywords.append( "INT_FAST32_MIN" );
+ keywords.append( "int_fast32_t" );
+ keywords.append( "INT_FAST64_MAX" );
+ keywords.append( "INT_FAST64_MIN" );
+ keywords.append( "int_fast64_t" );
+ keywords.append( "INT_FAST8_MAX" );
+ keywords.append( "INT_FAST8_MIN" );
+ keywords.append( "int_fast8_t" );
+ keywords.append( "INT_LEAST16_MAX" );
+ keywords.append( "INT_LEAST16_MIN" );
+ keywords.append( "int_least16_t" );
+ keywords.append( "INT_LEAST32_MAX" );
+ keywords.append( "INT_LEAST32_MIN" );
+ keywords.append( "int_least32_t" );
+ keywords.append( "INT_LEAST64_MAX" );
+ keywords.append( "INT_LEAST64_MIN" );
+ keywords.append( "int_least64_t" );
+ keywords.append( "INT_LEAST8_MAX" );
+ keywords.append( "INT_LEAST8_MIN" );
+ keywords.append( "int_least8_t" );
+ keywords.append( "INT_MAX" );
+ keywords.append( "INTMAX_MAX" );
+ keywords.append( "INTMAX_MIN" );
+ keywords.append( "intmax_t" );
+ keywords.append( "INT_MIN" );
+ keywords.append( "INTPTR_MAX" );
+ keywords.append( "INTPTR_MIN" );
+ keywords.append( "intptr_t" );
+ keywords.append( "_IOFBF" );
+ keywords.append( "_IOLBF" );
+ keywords.append( "_IONBF" );
+ keywords.append( "jmp_buf" );
+ keywords.append( "__label__" );
+ keywords.append( "LC_ALL" );
+ keywords.append( "LC_COLLATE" );
+ keywords.append( "LC_CTYPE" );
+ keywords.append( "LC_MONETARY" );
+ keywords.append( "LC_NUMERIC" );
+ keywords.append( "LC_TIME" );
+ keywords.append( "LDBL_DIG" );
+ keywords.append( "LDBL_EPSILON" );
+ keywords.append( "LDBL_MANT_DIG" );
+ keywords.append( "LDBL_MAX" );
+ keywords.append( "LDBL_MAX_10_EXP" );
+ keywords.append( "LDBL_MAX_EXP" );
+ keywords.append( "LDBL_MIN" );
+ keywords.append( "LDBL_MIN_10_EXP" );
+ keywords.append( "LDBL_MIN_EXP" );
+ keywords.append( "ldiv_t" );
+ keywords.append( "__LINE__" );
+ keywords.append( "LLONG_MAX" );
+ keywords.append( "long" );
+ keywords.append( "LONG_MAX" );
+ keywords.append( "LONG_MIN" );
+ keywords.append( "L_tmpnam" );
+ keywords.append( "M_1_PI" );
+ keywords.append( "M_2_PI" );
+ keywords.append( "M_2_SQRTPI" );
+ keywords.append( "MB_CUR_MAX" );
+ keywords.append( "MB_LEN_MAX" );
+ keywords.append( "mbstate_t" );
+ keywords.append( "M_E" );
+ keywords.append( "M_LN10" );
+ keywords.append( "M_LN2" );
+ keywords.append( "M_LOG10E" );
+ keywords.append( "M_LOG2E" );
+ keywords.append( "M_PI" );
+ keywords.append( "M_PI_2" );
+ keywords.append( "M_PI_4" );
+ keywords.append( "M_SQRT1_2" );
+ keywords.append( "M_SQRT2" );
+ keywords.append( "mutable" );
+ keywords.append( "namespace" );
+ keywords.append( "new" );
+ keywords.append( "not" );
+ keywords.append( "not_eq" );
+ keywords.append( "NPOS" );
+ keywords.append( "NULL" );
+ keywords.append( "operator" );
+ keywords.append( "or" );
+ keywords.append( "or_eq" );
+ keywords.append( "__PRETTY_FUNCTION__" );
+ keywords.append( "private" );
+ keywords.append( "protected" );
+ keywords.append( "PTRDIFF_MAX" );
+ keywords.append( "PTRDIFF_MIN" );
+ keywords.append( "ptrdiff_t" );
+ keywords.append( "public" );
+ keywords.append( "RAND_MAX" );
+ keywords.append( "__real__" );
+ keywords.append( "register" );
+ keywords.append( "reinterpret_cast" );
+ keywords.append( "restrict" );
+ keywords.append( "return" );
+ keywords.append( "SCHAR_MAX" );
+ keywords.append( "SCHAR_MIN" );
+ keywords.append( "SEEK_CUR" );
+ keywords.append( "SEEK_END" );
+ keywords.append( "SEEK_SET" );
+ keywords.append( "short" );
+ keywords.append( "SHRT_MAX" );
+ keywords.append( "SHRT_MIN" );
+ keywords.append( "SIGABRT" );
+ keywords.append( "SIGALRM" );
+ keywords.append( "SIG_ATOMIC_MAX" );
+ keywords.append( "SIG_ATOMIC_MIN" );
+ keywords.append( "sig_atomic_t" );
+ keywords.append( "SIGCHLD" );
+ keywords.append( "SIGCONT" );
+ keywords.append( "SIG_DFL" );
+ keywords.append( "SIG_ERR" );
+ keywords.append( "SIGFPE" );
+ keywords.append( "SIGHUP" );
+ keywords.append( "SIG_IGN" );
+ keywords.append( "SIGILL" );
+ keywords.append( "SIGINT" );
+ keywords.append( "SIGKILL" );
+ keywords.append( "signed" );
+ keywords.append( "SIGPIPE" );
+ keywords.append( "SIGQUIT" );
+ keywords.append( "SIGSEGV" );
+ keywords.append( "SIGSTOP" );
+ keywords.append( "SIGTERM" );
+ keywords.append( "SIGTRAP" );
+ keywords.append( "SIGTSTP" );
+ keywords.append( "SIGTTIN" );
+ keywords.append( "SIGTTOU" );
+ keywords.append( "SIGUSR1" );
+ keywords.append( "SIGUSR2" );
+ keywords.append( "SINT_MAX" );
+ keywords.append( "SINT_MIN" );
+ keywords.append( "SIZE_MAX" );
+ keywords.append( "sizeof" );
+ keywords.append( "size_t" );
+ keywords.append( "SLONG_MAX" );
+ keywords.append( "SLONG_MIN" );
+ keywords.append( "SSHRT_MAX" );
+ keywords.append( "SSHRT_MIN" );
+ keywords.append( "ssize_t" );
+ keywords.append( "static" );
+ keywords.append( "static_cast" );
+ keywords.append( "__STDC__" );
+ keywords.append( "__STDC_VERSION__" );
+ keywords.append( "stderr" );
+ keywords.append( "stdin" );
+ keywords.append( "stdout" );
+ keywords.append( "struct" );
+ keywords.append( "switch" );
+ keywords.append( "template" );
+ keywords.append( "this" );
+ keywords.append( "throw" );
+ keywords.append( "__TIME__" );
+ keywords.append( "time_t" );
+ keywords.append( "TMP_MAX" );
+ keywords.append( "true" );
+ keywords.append( "try" );
+ keywords.append( "typedef" );
+ keywords.append( "typeid" );
+ keywords.append( "typename" );
+ keywords.append( "typeof" );
+ keywords.append( "UCHAR_MAX" );
+ keywords.append( "UINT16_MAX" );
+ keywords.append( "uint16_t" );
+ keywords.append( "UINT32_MAX" );
+ keywords.append( "uint32_t" );
+ keywords.append( "UINT64_MAX" );
+ keywords.append( "uint64_t" );
+ keywords.append( "UINT8_MAX" );
+ keywords.append( "uint8_t" );
+ keywords.append( "UINT_FAST16_MAX" );
+ keywords.append( "uint_fast16_t" );
+ keywords.append( "UINT_FAST32_MAX" );
+ keywords.append( "uint_fast32_t" );
+ keywords.append( "UINT_FAST64_MAX" );
+ keywords.append( "uint_fast64_t" );
+ keywords.append( "UINT_FAST8_MAX" );
+ keywords.append( "uint_fast8_t" );
+ keywords.append( "UINT_LEAST16_MAX" );
+ keywords.append( "uint_least16_t" );
+ keywords.append( "UINT_LEAST32_MAX" );
+ keywords.append( "uint_least32_t" );
+ keywords.append( "UINT_LEAST64_MAX" );
+ keywords.append( "uint_least64_t" );
+ keywords.append( "UINT_LEAST8_MAX" );
+ keywords.append( "uint_least8_t" );
+ keywords.append( "UINT_MAX" );
+ keywords.append( "UINTMAX_MAX" );
+ keywords.append( "uintmax_t" );
+ keywords.append( "UINTPTR_MAX" );
+ keywords.append( "uintptr_t" );
+ keywords.append( "ULLONG_MAX" );
+ keywords.append( "ULONG_MAX" );
+ keywords.append( "union" );
+ keywords.append( "unsigned" );
+ keywords.append( "USHRT_MAX" );
+ keywords.append( "using" );
+ keywords.append( "va_list" );
+ keywords.append( "virtual" );
+ keywords.append( "void" );
+ keywords.append( "__volatile__" );
+ keywords.append( "volatile" );
+ keywords.append( "WCHAR_MAX" );
+ keywords.append( "WCHAR_MIN" );
+ keywords.append( "wchar_t" );
+ keywords.append( "wctrans_t" );
+ keywords.append( "wctype_t" );
+ keywords.append( "WEOF" );
+ keywords.append( "while" );
+ keywords.append( "WINT_MAX" );
+ keywords.append( "WINT_MIN" );
+ keywords.append( "wint_t" );
+ keywords.append( "xor" );
+ keywords.append( "xor_eq" );
+ }
+
+ return keywords;
+}
+
+void createCppStereotypes() {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->findOrCreateStereotype("constructor");
+ // declares an operation as friend
+ umldoc->findOrCreateStereotype("friend");
+ // to use in methods that aren't abstract
+ umldoc->findOrCreateStereotype("virtual");
+}
+
+QString capitalizeFirstLetter(const QString &string) {
+ QChar firstChar = string.at(0);
+ return firstChar.upper() + string.mid(1);
+}
+
+} // end namespace Codegen_Utils
+
diff --git a/umbrello/umbrello/codegenerators/codegen_utils.h b/umbrello/umbrello/codegenerators/codegen_utils.h
new file mode 100644
index 00000000..aaa7d117
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/codegen_utils.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGEN_UTILS_H
+#define CODEGEN_UTILS_H
+
+#include <qstringlist.h>
+
+namespace Codegen_Utils {
+
+/**
+ * Return list of C++ datatypes
+ */
+QStringList cppDatatypes();
+
+/**
+ * Get list of C++ reserved keywords
+ */
+const QStringList reservedCppKeywords();
+
+/**
+ * Add C++ stereotypes
+ */
+void createCppStereotypes();
+
+/**
+ * Return the input string with the first letter capitalized.
+ */
+QString capitalizeFirstLetter(const QString &string);
+
+}
+
+#endif // CODEGEN_UTILS_H
+
diff --git a/umbrello/umbrello/codegenerators/codegenfactory.cpp b/umbrello/umbrello/codegenerators/codegenfactory.cpp
new file mode 100644
index 00000000..00401653
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/codegenfactory.cpp
@@ -0,0 +1,360 @@
+/***************************************************************************
+ begin : Mon Jun 17 2002
+ copyright : (C) 2002 Luis De la Parra Blum <luis@delaparra.org>
+ and Brian Thomas
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codegenfactory.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// app includes
+#include "../codegenerator.h"
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../optionstate.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../umlrole.h"
+
+#include "adawriter.h"
+#include "cppwriter.h"
+#include "csharpwriter.h"
+#include "dwriter.h"
+#include "idlwriter.h"
+#include "javawriter.h"
+#include "pascalwriter.h"
+#include "perlwriter.h"
+#include "phpwriter.h"
+#include "php5writer.h"
+#include "pythonwriter.h"
+#include "rubywriter.h"
+#include "sqlwriter.h"
+#include "aswriter.h"
+#include "jswriter.h"
+#include "tclwriter.h"
+#include "xmlschemawriter.h"
+
+// the new
+#include "cppcodegenerator.h"
+#include "javacodegenerator.h"
+#include "rubycodegenerator.h"
+
+#include "cppheadercodedocument.h"
+#include "cppsourcecodedocument.h"
+#include "javaclassifiercodedocument.h"
+#include "rubyclassifiercodedocument.h"
+#include "javaantcodedocument.h"
+
+#include "cppheadercodeoperation.h"
+#include "cppsourcecodeoperation.h"
+#include "javacodeoperation.h"
+#include "rubycodeoperation.h"
+
+#include "cppcodeclassfield.h"
+#include "javacodeclassfield.h"
+#include "rubycodeclassfield.h"
+
+#include "cppheadercodeaccessormethod.h"
+#include "cppsourcecodeaccessormethod.h"
+#include "javacodeaccessormethod.h"
+#include "rubycodeaccessormethod.h"
+
+#include "cppheadercodeclassfielddeclarationblock.h"
+#include "cppsourcecodeclassfielddeclarationblock.h"
+#include "javacodeclassfielddeclarationblock.h"
+#include "rubycodeclassfielddeclarationblock.h"
+
+#include "cppcodedocumentation.h"
+#include "javacodecomment.h"
+#include "rubycodecomment.h"
+#include "xmlcodecomment.h"
+
+#include "cppcodegenerationpolicy.h"
+#include "javacodegenerationpolicy.h"
+#include "rubycodegenerationpolicy.h"
+
+namespace CodeGenFactory {
+
+CodeGenerator* createObject(Uml::Programming_Language pl) {
+ CodeGenerator* obj = 0;
+ Settings::OptionState optionState = Settings::getOptionState();
+ UMLApp::app()->setPolicyExt(NULL);
+ switch (pl) {
+ case Uml::pl_Ada:
+ obj = new AdaWriter();
+ break;
+ case Uml::pl_ActionScript:
+ obj = new ASWriter();
+ break;
+ case Uml::pl_Cpp:
+ if (optionState.generalState.newcodegen) {
+ obj = new CPPCodeGenerator();
+ obj->connect_newcodegen_slots();
+ } else {
+ obj = new CppWriter();
+ }
+ {
+ CPPCodeGenerationPolicy *p =
+ new CPPCodeGenerationPolicy(UMLApp::app()->getConfig());
+ UMLApp::app()->setPolicyExt(p);
+ }
+ break;
+ case Uml::pl_CSharp:
+ obj = new CSharpWriter();
+ break;
+ case Uml::pl_D:
+ obj = new DWriter();
+ break;
+ case Uml::pl_IDL:
+ obj = new IDLWriter();
+ break;
+ case Uml::pl_Java:
+ if (optionState.generalState.newcodegen) {
+ obj = new JavaCodeGenerator();
+ obj->connect_newcodegen_slots();
+ JavaCodeGenerationPolicy *p =
+ new JavaCodeGenerationPolicy(UMLApp::app()->getConfig());
+ UMLApp::app()->setPolicyExt(p);
+ } else
+ obj = new JavaWriter();
+ break;
+ case Uml::pl_JavaScript:
+ obj = new JSWriter();
+ break;
+ case Uml::pl_PHP:
+ obj = new PhpWriter();
+ break;
+ case Uml::pl_PHP5:
+ obj = new Php5Writer();
+ break;
+ case Uml::pl_Pascal:
+ obj = new PascalWriter();
+ break;
+ case Uml::pl_Perl:
+ obj = new PerlWriter();
+ break;
+ case Uml::pl_Python:
+ obj = new PythonWriter();
+ break;
+ case Uml::pl_Ruby:
+ if (optionState.generalState.newcodegen) {
+ obj = new RubyCodeGenerator();
+ obj->connect_newcodegen_slots();
+ RubyCodeGenerationPolicy *p =
+ new RubyCodeGenerationPolicy(UMLApp::app()->getConfig());
+ UMLApp::app()->setPolicyExt(p);
+ } else
+ obj = new RubyWriter();
+ break;
+ case Uml::pl_SQL:
+ obj = new SQLWriter();
+ break;
+ case Uml::pl_Tcl:
+ obj = new TclWriter();
+ break;
+ case Uml::pl_XMLSchema:
+ obj = new XMLSchemaWriter();
+ break;
+ default:
+ kWarning() << "cannot create object of type " << pl
+ << ". Type unknown" << endl;
+ break;
+ }
+ if (obj)
+ obj->initFromParentDocument();
+ return obj;
+}
+
+CodeDocument * newClassifierCodeDocument (UMLClassifier * c)
+{
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (!optionState.generalState.newcodegen)
+ return NULL;
+ ClassifierCodeDocument *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ retval = new CPPSourceCodeDocument(c);
+ break;
+ case Uml::pl_Java:
+ retval = new JavaClassifierCodeDocument(c);
+ break;
+ case Uml::pl_Ruby:
+ retval = new RubyClassifierCodeDocument(c);
+ break;
+ default:
+ break;
+ }
+ retval->initCodeClassFields();
+ retval->synchronize();
+ return retval;
+}
+
+CodeOperation *newCodeOperation(ClassifierCodeDocument *ccd, UMLOperation * op) {
+ CodeOperation *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ {
+ CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(ccd);
+ if (hcd)
+ return new CPPHeaderCodeOperation(hcd, op);
+ CPPSourceCodeDocument *scd = dynamic_cast<CPPSourceCodeDocument*>(ccd);
+ if (scd)
+ return new CPPSourceCodeOperation(scd, op);
+ }
+ break;
+ case Uml::pl_Java:
+ retval = new JavaCodeOperation(dynamic_cast<JavaClassifierCodeDocument*>(ccd), op);
+ break;
+ case Uml::pl_Ruby:
+ retval = new RubyCodeOperation(dynamic_cast<RubyClassifierCodeDocument*>(ccd), op);
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+
+CodeClassField * newCodeClassField(ClassifierCodeDocument *ccd, UMLAttribute *at) {
+ CodeClassField *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ retval = new CPPCodeClassField(ccd, at);
+ break;
+ case Uml::pl_Java:
+ retval = new JavaCodeClassField(ccd, at);
+ break;
+ case Uml::pl_Ruby:
+ retval = new RubyCodeClassField(ccd, at);
+ break;
+ default:
+ break;
+ }
+ retval->finishInitialization();
+ return retval;
+}
+
+CodeClassField * newCodeClassField(ClassifierCodeDocument *ccd, UMLRole *role) {
+ CodeClassField *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ retval = new CPPCodeClassField(ccd, role);
+ break;
+ case Uml::pl_Java:
+ retval = new JavaCodeClassField(ccd, role);
+ break;
+ case Uml::pl_Ruby:
+ retval = new RubyCodeClassField(ccd, role);
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+CodeAccessorMethod * newCodeAccessorMethod(ClassifierCodeDocument *ccd,
+ CodeClassField *cf,
+ CodeAccessorMethod::AccessorType type) {
+ CodeAccessorMethod *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ {
+ CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(ccd);
+ if (hcd) {
+ CPPHeaderCodeAccessorMethod *chcam = new CPPHeaderCodeAccessorMethod(cf, type);
+ chcam->update();
+ retval = chcam;
+ } else {
+ CPPSourceCodeAccessorMethod *cscam = new CPPSourceCodeAccessorMethod(cf, type);
+ cscam->update();
+ retval = cscam;
+ }
+ }
+ break;
+ case Uml::pl_Java:
+ {
+ JavaCodeAccessorMethod *jcam = new JavaCodeAccessorMethod(cf, type);
+ jcam->update();
+ retval = jcam;
+ retval->setOverallIndentationLevel(1);
+ }
+ break;
+ case Uml::pl_Ruby:
+ {
+ RubyCodeAccessorMethod *rcam = new RubyCodeAccessorMethod(cf, type);
+ rcam->update();
+ retval = rcam;
+ retval->setOverallIndentationLevel(1);
+ }
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+CodeClassFieldDeclarationBlock * newDeclarationCodeBlock (ClassifierCodeDocument *cd,
+ CodeClassField * cf) {
+ CodeClassFieldDeclarationBlock *retval = NULL;
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ {
+ CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(cd);
+ if (hcd)
+ return new CPPHeaderCodeClassFieldDeclarationBlock(cf);
+ CPPSourceCodeDocument *scd = dynamic_cast<CPPSourceCodeDocument*>(cd);
+ if (scd)
+ return new CPPSourceCodeClassFieldDeclarationBlock(cf);
+ }
+ break;
+ case Uml::pl_Java:
+ retval = new JavaCodeClassFieldDeclarationBlock(cf);
+ break;
+ case Uml::pl_Ruby:
+ retval = new RubyCodeClassFieldDeclarationBlock(cf);
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+CodeComment * newCodeComment (CodeDocument *cd) {
+ switch (UMLApp::app()->getActiveLanguage()) {
+ case Uml::pl_Cpp:
+ if (dynamic_cast<CPPHeaderCodeDocument*>(cd) ||
+ dynamic_cast<CPPSourceCodeDocument*>(cd))
+ return new CPPCodeDocumentation(cd);
+ break;
+ case Uml::pl_Java:
+ if (dynamic_cast<JavaClassifierCodeDocument*>(cd))
+ return new JavaCodeComment(cd);
+ break;
+ case Uml::pl_Ruby:
+ if (dynamic_cast<RubyClassifierCodeDocument*>(cd))
+ return new RubyCodeComment(cd);
+ break;
+ default:
+ break;
+ }
+ if (dynamic_cast<JavaANTCodeDocument*>(cd))
+ return new XMLCodeComment(cd);
+ return new CodeComment(cd);
+}
+
+} // end namespace CodeGenFactory
+
diff --git a/umbrello/umbrello/codegenerators/codegenfactory.h b/umbrello/umbrello/codegenerators/codegenfactory.h
new file mode 100644
index 00000000..27a0f293
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/codegenfactory.h
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGENFACTORY_H
+#define CODEGENFACTORY_H
+
+#include "../umlnamespace.h"
+#include "../codeaccessormethod.h"
+
+// fwd decls
+class CodeGenerator;
+class ClassifierCodeDocument;
+class CodeOperation;
+class CodeClassField;
+class CodeClassFieldDeclarationBlock;
+class UMLClassifier;
+class UMLOperation;
+class UMLAttribute;
+class UMLRole;
+
+/**
+ * CodeGenFactory allows creating the available code generators as well
+ * as the auxiliary objects required for the advanced code generators.
+ *
+ * @author Jonathan Riddell
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace CodeGenFactory {
+
+ /**
+ * Create a code generator specific to the given language.
+ */
+ CodeGenerator* createObject(Uml::Programming_Language pl);
+
+
+ /**
+ * Create a CodeOperation belonging to the given ClassifierCodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent ClassifierCodeDocument.
+ * @param op the related UMLOperation
+ * @return CodeOperation which is specific to the current language
+ */
+ CodeOperation *newCodeOperation(ClassifierCodeDocument *cd, UMLOperation * op);
+
+ /**
+ * Create an attribute CodeClassField belonging to the given
+ * ClassifierCodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent ClassifierCodeDocument
+ * @param at attribute which is parent of this class field
+ * @return CodeClassField which is specific to the current language
+ */
+ CodeClassField * newCodeClassField (ClassifierCodeDocument *cd, UMLAttribute * at);
+
+ /**
+ * Create an association role CodeClassField belonging to the given
+ * ClassifierCodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent ClassifierCodeDocument
+ * @param role association role which is parent of this class field
+ * @return CodeClassField which is specific to the current language
+ */
+ CodeClassField * newCodeClassField(ClassifierCodeDocument *cd, UMLRole *role);
+
+ /**
+ * Create a CodeAccessorMethod object belonging to the given ClassifierCodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent ClassifierCodeDocument
+ * @param cf CodeClassField which is parent of this object
+ * @param type CodeAccessorMethod::AccessorType to create
+ *
+ * @return CodeAccessorMethod which is specific to the current language
+ */
+ CodeAccessorMethod * newCodeAccessorMethod(ClassifierCodeDocument *cd,
+ CodeClassField *cf,
+ CodeAccessorMethod::AccessorType type);
+
+ /**
+ * Create a CodeClassFieldDeclarationBlock object belonging to the given
+ * ClassifierCodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent ClassifierCodeDocument
+ * @param cf CodeClassField which is parent of this object
+ *
+ * @return CodeClassFieldDeclarationBlock which is specific to the current language
+ */
+ CodeClassFieldDeclarationBlock * newDeclarationCodeBlock (ClassifierCodeDocument *cd,
+ CodeClassField * cf);
+
+ /**
+ * Create a new CodeComment object belonging to the given CodeDocument.
+ * Only applies to the advanced generators.
+ *
+ * @param cd the parent CodeDocument
+ * @return CodeBlockWithComments
+ */
+ CodeComment * newCodeComment (CodeDocument *cd);
+
+ /**
+ * Currently unused (for possible future use)
+ */
+ CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+}
+
+#endif //CODEGENFACTORY_H
diff --git a/umbrello/umbrello/codegenerators/codegenpolicyext.h b/umbrello/umbrello/codegenerators/codegenpolicyext.h
new file mode 100644
index 00000000..97ace9f2
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/codegenpolicyext.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGENPOLICYEXT_H
+#define CODEGENPOLICYEXT_H
+
+#include <qobject.h>
+
+class QWidget;
+class KConfig;
+class CodeGenerationPolicyPage;
+
+/**
+ * Base class for programming language specific code generation policy extensions.
+ * Not to be confused with CodeGenerationPolicy which contains the programming
+ * language independent policies.
+ *
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class CodeGenPolicyExt : public QObject {
+public:
+ CodeGenPolicyExt() {}
+ virtual ~CodeGenPolicyExt() {}
+
+ /**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+ virtual CodeGenerationPolicyPage * createPage(QWidget *parent = 0, const char *name = 0) = 0;
+
+ /**
+ * set the defaults from a config file for this code generator from the passed KConfig pointer.
+ */
+ virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true) = 0;
+
+ /**
+ * write Default params to passed KConfig pointer.
+ */
+ virtual void writeConfig (KConfig * config) = 0;
+};
+
+#endif
diff --git a/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp b/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp
new file mode 100644
index 00000000..b6b2fb72
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+// own header
+#include "cppcodeclassfield.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "../codegenerator.h"
+#include "../classifiercodedocument.h"
+#include "../attribute.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+#include "cppcodegenerationpolicy.h"
+
+
+// Constructors/Destructors
+//
+
+CPPCodeClassField::CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role)
+ : CodeClassField(parentDoc, role)
+{
+
+}
+
+CPPCodeClassField::CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib)
+ : CodeClassField(parentDoc, attrib)
+{
+
+}
+
+CPPCodeClassField::~CPPCodeClassField ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+QString CPPCodeClassField::getFieldName() {
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = (UMLAttribute*) getParentObject();
+ return cleanName(at->getName());
+ }
+ else
+ {
+ UMLRole * role = (UMLRole*) getParentObject();
+ QString roleName = role->getName();
+ if(fieldIsSingleValue()) {
+ return roleName.replace(0, 1, roleName.left(1).lower());
+ } else {
+ return roleName.lower() + "Vector";
+ }
+ }
+}
+
+QString CPPCodeClassField::getListFieldClassName () {
+ CodeGenPolicyExt * p = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy *policy = dynamic_cast<CPPCodeGenerationPolicy*>(p);
+ return policy->getVectorClassName();
+}
+
+QString CPPCodeClassField::getInitialValue() {
+
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() );
+ if (at) {
+ return fixInitialStringDeclValue(at->getInitialValue(), getTypeName());
+ } else {
+ kError() << "CPPCodeClassField::getInitialValue: parent object is not a UMLAttribute"
+ << endl;
+ return "";
+ }
+ }
+ else
+ {
+ if(fieldIsSingleValue()) {
+ // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1,
+ // then we can just return 'empty' string (minor problem).
+ return "";
+ } else {
+ return " new "+getListFieldClassName()+"( )";
+ }
+ }
+
+}
+
+
+#include "cppcodeclassfield.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodeclassfield.h b/umbrello/umbrello/codegenerators/cppcodeclassfield.h
new file mode 100644
index 00000000..d9c20255
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodeclassfield.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+
+
+#ifndef CPPCODECLASSFIELD_H
+#define CPPCODECLASSFIELD_H
+
+#include <qstring.h>
+
+#include "../codeclassfield.h"
+
+class ClassifierCodeDocument;
+
+class CPPCodeClassField : public CodeClassField
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role);
+ CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPCodeClassField ( );
+
+ QString getFieldType();
+ QString getFieldName();
+ QString getInitialValue();
+ /** get the name of the class which holds lists, e.g. "QPtrlist" or
+ * "Vector" or "List" and so on.
+ */
+ QString getListFieldClassName();
+
+
+protected:
+
+private:
+
+};
+
+#endif // CPPCODECLASSFIELD_H
diff --git a/umbrello/umbrello/codegenerators/cppcodecomment.cpp b/umbrello/umbrello/codegenerators/cppcodecomment.cpp
new file mode 100644
index 00000000..8d480e93
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodecomment.cpp
@@ -0,0 +1,98 @@
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+// own header
+#include "cppcodecomment.h"
+
+// qt/kde includes
+#include <qregexp.h>
+
+// Constructors/Destructors
+//
+
+CPPCodeComment::CPPCodeComment ( CodeDocument * doc, const QString & text )
+ : CodeComment (doc, text)
+{
+
+}
+
+CPPCodeComment::~CPPCodeComment ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void CPPCodeComment::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "cppcodecomment" );
+ setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may
+ // just use parent TextBlock method
+ root.appendChild( blockElement );
+}
+
+/**
+ * @return QString
+ */
+QString CPPCodeComment::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ output.append(formatMultiLineText (getText()+endLine, indent +"// ", endLine));
+ }
+
+ return output;
+}
+
+QString CPPCodeComment::getNewEditorLine ( int amount ) {
+ QString line = getIndentationString(amount) + "// ";
+ return line;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString CPPCodeComment::unformatText ( const QString & text , const QString & indent)
+{
+
+ // remove leading or trailing comment stuff
+ QString mytext = TextBlock::unformatText(text, indent);
+
+ // now leading slashes
+ mytext.remove(QRegExp("^\\/\\/\\s*"));
+ return mytext;
+}
+
+#include "cppcodecomment.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodecomment.h b/umbrello/umbrello/codegenerators/cppcodecomment.h
new file mode 100644
index 00000000..085e1a7f
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodecomment.h
@@ -0,0 +1,83 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+
+
+#ifndef CPPCODECOMMENT_H
+#define CPPCODECOMMENT_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+/**
+ * class CPPCodeComment
+ * A CPP code comment. There is only a single styles of comments:
+ * these are simply started with double slash sequence and no terminating
+ * characters
+ */
+
+class CPPCodeComment : virtual public CodeComment
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit CPPCodeComment ( CodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPCodeComment ( );
+
+ // Public attributes
+ //
+
+
+ // other
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the "//" sequence as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+protected:
+
+private:
+
+};
+
+#endif // CPPCODECOMMENT_H
diff --git a/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp b/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp
new file mode 100644
index 00000000..833e648e
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+// own header
+#include "cppcodedocumentation.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "../codedocument.h"
+#include "../codegenerator.h"
+#include "../codegenerationpolicy.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPCodeDocumentation::CPPCodeDocumentation ( CodeDocument * doc, const QString & text )
+ : CodeComment (doc, text)
+{
+
+}
+
+CPPCodeDocumentation::~CPPCodeDocumentation ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void CPPCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "cppcodedocumentation" );
+ setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may
+ // just use parent TextBlock method
+ root.appendChild( blockElement );
+}
+
+/**
+ * @return QString
+ */
+QString CPPCodeDocumentation::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ bool useDoubleDashOutput = true;
+
+ // need to figure out output type from cpp policy
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ useDoubleDashOutput = false;
+
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ QString body = getText();
+ if(useDoubleDashOutput)
+ {
+ if(!body.isEmpty())
+ output.append(formatMultiLineText (body, indent +"// ", endLine));
+ } else {
+ output.append(indent+"/**"+endLine);
+ output.append(formatMultiLineText (body, indent +" * ", endLine));
+ output.append(indent+" */"+endLine);
+ }
+ }
+
+ return output;
+}
+
+QString CPPCodeDocumentation::getNewEditorLine ( int amount )
+{
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return getIndentationString(amount) + " * ";
+ else
+ return getIndentationString(amount) + "// ";
+}
+
+int CPPCodeDocumentation::firstEditableLine() {
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return 1;
+ return 0;
+}
+
+int CPPCodeDocumentation::lastEditableLine() {
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ return -1; // very last line is NOT editable
+ }
+ return 0;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString CPPCodeDocumentation::unformatText ( const QString & text , const QString & indent)
+{
+
+ QString mytext = TextBlock::unformatText(text, indent);
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ // remove leading or trailing comment stuff
+ mytext.remove(QRegExp('^'+indent));
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ mytext.remove(QRegExp("^\\/\\*\\*\\s*\n?"));
+ mytext.remove(QRegExp("\\s*\\*\\/\\s*\n?$"));
+ mytext.remove(QRegExp("^\\s*\\*\\s*"));
+ } else
+ mytext.remove(QRegExp("^\\/\\/\\s*"));
+
+ return mytext;
+}
+
+
diff --git a/umbrello/umbrello/codegenerators/cppcodedocumentation.h b/umbrello/umbrello/codegenerators/cppcodedocumentation.h
new file mode 100644
index 00000000..79bc4fe0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodedocumentation.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+
+
+#ifndef CPPCODEDOCUMENTATION_H
+#define CPPCODEDOCUMENTATION_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+class CodeDocument;
+
+/**
+ * class CPPCodeDocumentation
+ * A CPP code comment. There is only a single styles of comments:
+ * these are simply started with double slash sequence and no terminating
+ * characters
+ */
+
+class CPPCodeDocumentation : virtual public CodeComment
+{
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit CPPCodeDocumentation ( CodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPCodeDocumentation ( );
+
+ // Public attributes
+ //
+
+ // Other
+ //
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the " * " sequence as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+ /** Ush. These are terrifically bad and must one day go away.
+ * Both methods indicate the range of lines in this textblock
+ * which may be edited by the codeeditor (assuming that any are
+ * actually editable). The default case is no lines are editable.
+ * The line numbering starts with '0' and a '-1' means no line
+ * qualifies.
+ */
+ virtual int firstEditableLine();
+ virtual int lastEditableLine();
+
+protected:
+
+private:
+
+};
+
+#endif // CPPCODEDOCUMENTATION_H
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp
new file mode 100644
index 00000000..a4acf713
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp
@@ -0,0 +1,305 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Nov 20 2003
+ */
+
+// own header
+#include "cppcodegenerationform.h"
+
+// qt/kde includes
+#include <qlabel.h>
+#include <qregexp.h>
+#include <qlistview.h>
+#include <kfiledialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+
+
+CPPCodeGenerationForm::CPPCodeGenerationForm( QWidget *parent, const char *name )
+ : CPPCodeGenerationFormBase (parent,name)
+{
+ init();
+
+ GeneralOptionsListView->addColumn(tr2i18n("General Options"));
+ pOptionPackageIsANamespace = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Package is a namespace"),
+ QCheckListItem::CheckBox );
+ pOptionVirtualDestructors = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Virtual destructors"),
+ QCheckListItem::CheckBox );
+ pOptionGenerateEmptyConstructors = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Generate empty constructors"),
+ QCheckListItem::CheckBox );
+ pOptionGenerateAccessorMethods = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Generate accessor methods"),
+ QCheckListItem::CheckBox );
+ pOptionOperationsAreInline = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Operations are inline"),
+ QCheckListItem::CheckBox );
+ pOptionAccessorsAreInline = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Accessors are inline"),
+ QCheckListItem::CheckBox );
+
+ pOptionAccessorsArePublic = new QCheckListItem( GeneralOptionsListView,
+ tr2i18n("Accessors are public"),
+ QCheckListItem::CheckBox );
+
+ connect(GeneralOptionsListView,
+ SIGNAL(clicked(QListViewItem *)), this,
+ SLOT(generalOptionsListViewClicked(QListViewItem *))
+ );
+
+}
+
+CPPCodeGenerationForm::~CPPCodeGenerationForm()
+{
+}
+
+void CPPCodeGenerationForm::browseClicked()
+{
+ QString button = sender()->name();
+ QString file = KFileDialog::getOpenFileName( QString::null, "*.h", this, "Get Header File");
+
+ if(file.isEmpty())
+ return;
+
+ if(button=="m_browseStringButton") {
+ // search for match in history list, if absent, then add it
+ m_stringIncludeFileHistoryCombo->setCurrentItem(file, true);
+ }
+ else if(button=="m_browseListButton") {
+ // search for match in history list, if absent, then add it
+ m_listIncludeFileHistoryCombo->setCurrentItem(file, true);
+ }
+}
+
+void CPPCodeGenerationForm::generalOptionsListViewClicked(QListViewItem *pSender) {
+
+ // operations are inline and accessors are operations :)
+ if (pOptionOperationsAreInline->isOn() && pOptionGenerateAccessorMethods->isOn())
+ pOptionAccessorsAreInline->setOn(true);
+
+ if (pSender == pOptionPackageIsANamespace) {
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionPackageIsANamespace");
+#endif
+ return;
+ }
+ if (pSender == pOptionVirtualDestructors) {
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionVirtualDestructors");
+#endif
+ return;
+ }
+ if (pSender == pOptionGenerateEmptyConstructors) {
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionVirtualDestructors");
+#endif
+ return;
+ }
+ if (pSender == pOptionGenerateAccessorMethods) {
+ pOptionAccessorsAreInline->setEnabled(pOptionGenerateAccessorMethods->isOn());
+ pOptionAccessorsArePublic->setEnabled(pOptionGenerateAccessorMethods->isOn());
+ // reset the value if needed
+ if (!pOptionGenerateAccessorMethods->isOn())
+ {
+ pOptionAccessorsAreInline->setOn(false);
+ pOptionAccessorsArePublic->setOn(false);
+ }
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionGenerateAccessorMethods");
+#endif
+ return;
+ }
+ if (pSender == pOptionOperationsAreInline) {
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionOperationsAreInline");
+#endif
+ return;
+ }
+ if (pSender == pOptionAccessorsAreInline) {
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "sender=pOptionAccessorsAreInline");
+#endif
+ return;
+ }
+
+#if 0
+ KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): "
+ "unknown sender");
+#endif
+ return;
+}
+
+void CPPCodeGenerationForm::init() {
+ pOptionPackageIsANamespace = NULL;
+ pOptionVirtualDestructors = NULL;
+ pOptionGenerateEmptyConstructors = NULL;
+ pOptionGenerateAccessorMethods = NULL;
+ pOptionOperationsAreInline = NULL;
+ pOptionAccessorsAreInline = NULL;
+}
+
+/**
+ *
+ * set the display state of option "Package Is Namespace"
+ *
+ */
+void CPPCodeGenerationForm::setPackageIsANamespace(bool bFlag) {
+ pOptionPackageIsANamespace->setOn(bFlag);
+}
+
+/**
+ *
+ * set the display state of option "Virtual Destructors"
+ *
+ */
+void CPPCodeGenerationForm::setVirtualDestructors(bool bFlag) {
+ pOptionVirtualDestructors->setOn(bFlag);
+}
+
+/**
+ *
+ * set the display state of option "Generate Empty Constructors"
+ *
+ */
+void CPPCodeGenerationForm::setGenerateEmptyConstructors(bool bFlag) {
+ pOptionGenerateEmptyConstructors->setOn(bFlag);
+}
+
+/**
+ *
+ * set the display state of option "Generate Accessor Methods"
+ *
+ */
+void CPPCodeGenerationForm::setGenerateAccessorMethods(bool bFlag) {
+ pOptionGenerateAccessorMethods->setOn(bFlag);
+ // initial settings
+ pOptionAccessorsAreInline->setEnabled(pOptionGenerateAccessorMethods->isOn());
+ pOptionAccessorsArePublic->setEnabled(pOptionGenerateAccessorMethods->isOn());
+ // reset the value if needed
+ if (!pOptionGenerateAccessorMethods->isOn())
+ {
+ pOptionAccessorsAreInline->setOn(false);
+ pOptionAccessorsArePublic->setOn(false);
+ }
+}
+
+/**
+ *
+ * set the display state of option "Operations Are Inline"
+ *
+ */
+void CPPCodeGenerationForm::setOperationsAreInline(bool bFlag) {
+ pOptionOperationsAreInline->setOn(bFlag);
+}
+
+/**
+ *
+ * set the display state of option "Accessors Are Inline"
+ *
+ */
+void CPPCodeGenerationForm::setAccessorsAreInline(bool bFlag) {
+ pOptionAccessorsAreInline->setOn(bFlag);
+}
+
+/**
+ *
+ * set the display state of option "Accessors Are Public"
+ *
+ */
+void CPPCodeGenerationForm::setAccessorsArePublic(bool bFlag) {
+ pOptionAccessorsArePublic->setOn(bFlag);
+}
+
+/**
+ *
+ * get the display state of option "Package Is Namespace"
+ *
+ */
+bool CPPCodeGenerationForm::getPackageIsANamespace()
+{
+ return pOptionPackageIsANamespace->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Virtual Destructors"
+ *
+ */
+bool CPPCodeGenerationForm::getVirtualDestructors()
+{
+ return pOptionVirtualDestructors->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Generate Empty Constructors"
+ *
+ */
+bool CPPCodeGenerationForm::getGenerateEmptyConstructors()
+{
+ return pOptionGenerateEmptyConstructors->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Generate Accessor Methods"
+ *
+ */
+bool CPPCodeGenerationForm::getGenerateAccessorMethods()
+{
+ return pOptionGenerateAccessorMethods->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Operations Are Inline"
+ *
+ */
+bool CPPCodeGenerationForm::getOperationsAreInline()
+{
+ return pOptionOperationsAreInline->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Accessors Are Inline"
+ *
+ */
+bool CPPCodeGenerationForm::getAccessorsAreInline()
+{
+ return pOptionAccessorsAreInline->isOn();
+}
+
+/**
+ *
+ * get the display state of option "Accessors Are Public"
+ *
+ */
+bool CPPCodeGenerationForm::getAccessorsArePublic()
+{
+ return pOptionAccessorsArePublic->isOn();
+}
+
+
+#include "cppcodegenerationform.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationform.h b/umbrello/umbrello/codegenerators/cppcodegenerationform.h
new file mode 100644
index 00000000..73441a82
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationform.h
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 30 2003
+ */
+
+#ifndef CPPCODEGENERATIONFORM_H
+#define CPPCODEGENERATIONFORM_H
+
+#include "cppcodegenerationformbase.h"
+
+class QCheckListItem;
+
+/**
+ * @author Brian Thomas
+ */
+
+class CPPCodeGenerationForm : public CPPCodeGenerationFormBase {
+ Q_OBJECT
+public:
+
+ /**
+ * std ctor
+ */
+ explicit CPPCodeGenerationForm (QWidget *parent=0, const char *name=0);
+
+ /**
+ * std dtor
+ */
+ virtual ~CPPCodeGenerationForm();
+
+ /**
+ * set the display state of option "Package Is A Namespace"
+ */
+ void setPackageIsANamespace(bool bFlag = true);
+
+ /**
+ * set the display state of option "Virtual Destructors"
+ */
+ void setVirtualDestructors(bool bFlag = true);
+
+ /**
+ * set the display state of option "Generate Empty Constructors"
+ */
+ void setGenerateEmptyConstructors(bool bFlag = true);
+
+ /**
+ * set the display state of option "Generate Accessor Methods"
+ */
+ void setGenerateAccessorMethods(bool bFlag = true);
+
+ /**
+ * set the display state of option "Operations Are Inline"
+ */
+ void setOperationsAreInline(bool bFlag = true);
+
+ /**
+ * set the display state of option "Accessors Are Inline"
+ */
+ void setAccessorsAreInline(bool bFlag = true);
+
+ /**
+ * set the display state of option "Accessors Are Public"
+ */
+ void setAccessorsArePublic(bool bFlag = true);
+
+ /**
+ * set the display state of option "Generate Makefile Document"
+ */
+ void setGenerateMakefileDocument(bool bFlag = true);
+
+ /**
+ * get the display state of option "Package Is A Namespace"
+ */
+ bool getPackageIsANamespace();
+
+ /**
+ * get the display state of option "Virtual Destructors"
+ */
+ bool getVirtualDestructors();
+
+ /**
+ * get the display state of option "Generate Empty Constructors"
+ */
+ bool getGenerateEmptyConstructors();
+
+ /**
+ * get the display state of option "Generate Accessors Methods"
+ */
+ bool getGenerateAccessorMethods();
+
+ /**
+ * get the display state of option "Operations Are Inline"
+ */
+ bool getOperationsAreInline();
+
+ /**
+ * get the display state of option "Accessors Are Inline"
+ */
+ bool getAccessorsAreInline();
+
+ /**
+ * get the display state of option "Accessors Are Public"
+ */
+ bool getAccessorsArePublic();
+
+ /**
+ * get the display state of option "Generate Makefile Document"
+ */
+ bool getGenerateMakefileDocument();
+
+protected:
+
+public slots:
+
+ virtual void browseClicked();
+
+private slots:
+ virtual void generalOptionsListViewClicked(QListViewItem *);
+
+private:
+
+ /*
+ * check boxes for the available options
+ */
+ QCheckListItem *pOptionPackageIsANamespace;
+ QCheckListItem *pOptionVirtualDestructors;
+ QCheckListItem *pOptionGenerateEmptyConstructors;
+ QCheckListItem *pOptionGenerateAccessorMethods;
+ QCheckListItem *pOptionOperationsAreInline;
+ QCheckListItem *pOptionAccessorsAreInline;
+ QCheckListItem *pOptionAccessorsArePublic;
+
+ /**
+ * initialize all attributes
+ */
+ void init();
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui b/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui
new file mode 100644
index 00000000..2599ae35
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui
@@ -0,0 +1,481 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CPPCodeGenerationFormBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CPPCodeGenerationFormBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>648</width>
+ <height>549</height>
+ </rect>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>44</y>
+ <width>436</width>
+ <height>72</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Documentation</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Slash-Slash (//)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Slash-Star (/** */)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_SelectCommentStyle</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Style:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>11</y>
+ <width>436</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;C++ Code Generation&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>120</y>
+ <width>436</width>
+ <height>305</height>
+ </rect>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView">
+ <property name="name">
+ <cstring>GeneralOptionsListView</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Method Body Generation</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>410</width>
+ <height>113</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Use following for classes in generated code:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KHistoryCombo" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_listClassHCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="historyItems">
+ <stringlist>
+ <string>QPtrList</string>
+ <string>vector</string>
+ </stringlist>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1_3_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Variable&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="4" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_browseStringButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="7">
+ <property name="name">
+ <cstring>m_globalStringCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KHistoryCombo" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_stringClassHCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="historyItems">
+ <stringlist>
+ <string>QString</string>
+ <string>string</string>
+ </stringlist>
+ </property>
+ </widget>
+ <spacer row="2" column="6">
+ <property name="name">
+ <cstring>spacer2_2_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="6">
+ <property name="name">
+ <cstring>spacer1_2_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>stringClassTextLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;String&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>listClassTextLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;List&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="KHistoryCombo" row="1" column="3">
+ <property name="name">
+ <cstring>m_listIncludeFileHistoryCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="insertionPolicy">
+ <enum>AtTop</enum>
+ </property>
+ <property name="historyItems">
+ <stringlist>
+ <string>qptrlist.h</string>
+ <string>vector</string>
+ </stringlist>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="5" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel4_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;i&gt;global?&lt;/i&gt;</string>
+ </property>
+ </widget>
+ <widget class="KHistoryCombo" row="2" column="3">
+ <property name="name">
+ <cstring>m_stringIncludeFileHistoryCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="insertionPolicy">
+ <enum>AtTop</enum>
+ </property>
+ <property name="historyItems">
+ <stringlist>
+ <string>qstring.h</string>
+ <string>string</string>
+ </stringlist>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="7">
+ <property name="name">
+ <cstring>m_globalListCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel3_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Class name</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="4" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_browseListButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="3" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel5_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;i&gt;&lt;p align="center"&gt;Include file&lt;/p&gt;&lt;/i&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_browseListButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CPPCodeGenerationFormBase</receiver>
+ <slot>browseClicked()</slot>
+ </connection>
+ <connection>
+ <sender>m_browseStringButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CPPCodeGenerationFormBase</receiver>
+ <slot>browseClicked()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>browseClicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp
new file mode 100644
index 00000000..d0359603
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp
@@ -0,0 +1,390 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+// own header
+#include "cppcodegenerationpolicy.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+#include <kconfig.h>
+// app includes
+#include "cppcodegenerationpolicypage.h"
+#include "../uml.h"
+
+const bool CPPCodeGenerationPolicy::DEFAULT_AUTO_GEN_ACCESSORS = true;
+const bool CPPCodeGenerationPolicy::DEFAULT_INLINE_ACCESSORS = false;
+const bool CPPCodeGenerationPolicy::DEFAULT_INLINE_OPERATIONS = false;
+const bool CPPCodeGenerationPolicy::DEFAULT_VIRTUAL_DESTRUCTORS = true;
+const bool CPPCodeGenerationPolicy::DEFAULT_PACKAGE_IS_NAMESPACE = true;
+const char * CPPCodeGenerationPolicy::DEFAULT_STRING_CLASS_NAME = "string";
+const char * CPPCodeGenerationPolicy::DEFAULT_STRING_CLASS_INCLUDE = "string";
+const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_CLASS_NAME = "vector";
+const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_CLASS_INCLUDE = "vector";
+const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_APPEND = "%VARNAME%.push_back(value);";
+const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_REMOVE = "int size = %VARNAME%.size();\nfor ( int i = 0; i < size; ++i) {\n\t%ITEMCLASS% item = %VARNAME%.at(i);\n\tif(item == value) {\n\t\tvector<%ITEMCLASS%>::iterator it = %VARNAME%.begin() + i;\n\t\t%VARNAME%.erase(it);\n\t\treturn;\n\t}\n }";
+const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_INIT = ""; // nothing to do in std::vector
+const char * CPPCodeGenerationPolicy::DEFAULT_OBJECT_METHOD_INIT = "%VARNAME% = new %ITEMCLASS%( );";
+const bool CPPCodeGenerationPolicy::DEFAULT_STRING_INCLUDE_GLOBAL = true;
+const bool CPPCodeGenerationPolicy::DEFAULT_VECTOR_INCLUDE_GLOBAL = true;
+const bool CPPCodeGenerationPolicy::DEFAULT_PUBLIC_ACCESSORS = false;
+
+
+// Constructors/Destructors
+//
+
+CPPCodeGenerationPolicy::CPPCodeGenerationPolicy(KConfig *config)
+{
+ init();
+ setDefaults(config,false);
+}
+
+CPPCodeGenerationPolicy::~CPPCodeGenerationPolicy ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+/**
+ * Set the value of m_publicAccessors
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setAccessorsArePublic ( bool var )
+{
+ m_publicAccessors = var;
+ // @todo we should probably use an own signal for this
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_publicAccessors
+ * @return value the boolean value of m_publicAccessors
+ */
+bool CPPCodeGenerationPolicy::getAccessorsArePublic( )
+{
+ return m_publicAccessors;
+}
+
+/**
+ * Set the value of m_inlineAccessors
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setAccessorsAreInline ( bool var )
+{
+ m_inlineAccessors = var;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_inlineAccessors
+ * @return value the boolean value of m_inlineAccessors
+ */
+bool CPPCodeGenerationPolicy::getAccessorsAreInline( )
+{
+ return m_inlineAccessors;
+}
+
+/**
+ * Set the value of m_inlineOperations
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setOperationsAreInline ( bool var )
+{
+ m_inlineOperations = var;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_inlineOperations
+ * @return value the boolean value of m_inlineOperations
+ */
+bool CPPCodeGenerationPolicy::getOperationsAreInline( )
+{
+ return m_inlineOperations;
+}
+
+/**
+ * Set the value of m_virtualDestructors
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setDestructorsAreVirtual ( bool var )
+{
+ m_virtualDestructors = var;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_virtualDestructors
+ * @return value the boolean value of m_virtualDestructors
+ */
+bool CPPCodeGenerationPolicy::getDestructorsAreVirtual( )
+{
+ return m_virtualDestructors;
+}
+
+/**
+ * Set the value of m_packageIsNamespace
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setPackageIsNamespace ( bool var ) {
+ m_packageIsNamespace = var;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_packageIsNamespace
+ * @return value the boolean value of m_packageIsNamespace
+ */
+bool CPPCodeGenerationPolicy::getPackageIsNamespace( ) {
+ return m_packageIsNamespace;
+}
+
+/**
+ * Set the value of m_autoGenerateAccessors
+ * @param new_var the new value
+ */
+void CPPCodeGenerationPolicy::setAutoGenerateAccessors( bool var ) {
+ m_autoGenerateAccessors = var;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+bool CPPCodeGenerationPolicy::getAutoGenerateAccessors( ){
+ return m_autoGenerateAccessors;
+}
+
+QString CPPCodeGenerationPolicy::getStringClassName() {
+ return m_stringClassName;
+}
+
+QString CPPCodeGenerationPolicy::getStringClassNameInclude() {
+ return m_stringClassNameInclude;
+}
+
+QString CPPCodeGenerationPolicy::getVectorClassName() {
+ return m_vectorClassName;
+}
+
+QString CPPCodeGenerationPolicy::getVectorClassNameInclude() {
+ return m_vectorClassNameInclude;
+}
+
+void CPPCodeGenerationPolicy::setStringClassName(const QString &value) {
+ m_stringClassName = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+void CPPCodeGenerationPolicy::setStringClassNameInclude(const QString &value) {
+ m_stringClassNameInclude = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+void CPPCodeGenerationPolicy::setVectorClassName(const QString &value) {
+ m_vectorClassName = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+void CPPCodeGenerationPolicy::setVectorClassNameInclude(const QString &value) {
+ m_vectorClassNameInclude = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+/** determine if the string include is global one */
+bool CPPCodeGenerationPolicy::stringIncludeIsGlobal () {
+ return m_stringIncludeIsGlobal;
+}
+
+bool CPPCodeGenerationPolicy::vectorIncludeIsGlobal () {
+ return m_vectorIncludeIsGlobal;
+}
+
+void CPPCodeGenerationPolicy::setStringIncludeIsGlobal(bool value) {
+ m_stringIncludeIsGlobal = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+void CPPCodeGenerationPolicy::setVectorIncludeIsGlobal(bool value) {
+ m_vectorIncludeIsGlobal = value;
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+QString CPPCodeGenerationPolicy::getVectorMethodAppend(const QString & variableName, const QString & itemClassName) {
+ QString value = m_vectorMethodAppendBase;
+ if(!variableName.isEmpty())
+ value.replace(QRegExp("%VARNAME%"),variableName);
+ value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName);
+ if(!itemClassName.isEmpty())
+ value.replace(QRegExp("%ITEMCLASS%"),itemClassName);
+ return value;
+}
+
+QString CPPCodeGenerationPolicy::getVectorMethodRemove(const QString & variableName, const QString & itemClassName) {
+ QString value = m_vectorMethodRemoveBase;
+ if(!variableName.isEmpty())
+ value.replace(QRegExp("%VARNAME%"),variableName);
+ value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName);
+ if(!itemClassName.isEmpty())
+ value.replace(QRegExp("%ITEMCLASS%"),itemClassName);
+ return value;
+}
+
+QString CPPCodeGenerationPolicy::getVectorMethodInit(const QString & variableName, const QString & itemClassName) {
+ QString value = m_vectorMethodInitBase;
+ if(!variableName.isEmpty())
+ value.replace(QRegExp("%VARNAME%"),variableName);
+ value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName);
+ if(!itemClassName.isEmpty())
+ value.replace(QRegExp("%ITEMCLASS%"),itemClassName);
+ return value;
+}
+
+QString CPPCodeGenerationPolicy::getObjectMethodInit(const QString & variableName, const QString & itemClassName) {
+ QString value = m_objectMethodInitBase;
+ if(!variableName.isEmpty())
+ value.replace(QRegExp("%VARNAME%"),variableName);
+ value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName);
+ if(!itemClassName.isEmpty())
+ value.replace(QRegExp("%ITEMCLASS%"),itemClassName);
+ return value;
+}
+
+// Other methods
+//
+
+void CPPCodeGenerationPolicy::writeConfig ( KConfig * config )
+{
+
+ // write ONLY the CPP specific stuff
+ config->setGroup("CPP Code Generation");
+
+ config->writeEntry("autoGenAccessors",getAutoGenerateAccessors());
+
+ config->writeEntry("inlineAccessors",getAccessorsAreInline());
+ config->writeEntry("publicAccessors",getAccessorsArePublic());
+ config->writeEntry("inlineOps",getOperationsAreInline());
+ config->writeEntry("virtualDestructors",getDestructorsAreVirtual());
+ config->writeEntry("packageIsNamespace",getPackageIsNamespace());
+
+ config->writeEntry("stringClassName",getStringClassName());
+ config->writeEntry("stringClassNameInclude",getStringClassNameInclude());
+ config->writeEntry("stringIncludeIsGlobal",stringIncludeIsGlobal());
+
+ config->writeEntry("vectorClassName",getVectorClassName());
+ config->writeEntry("vectorClassNameInclude",getVectorClassNameInclude());
+ config->writeEntry("vectorIncludeIsGlobal",vectorIncludeIsGlobal());
+
+}
+
+void CPPCodeGenerationPolicy::setDefaults ( CPPCodeGenerationPolicy * cppclone, bool emitUpdateSignal )
+{
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ {
+ setAutoGenerateAccessors(cppclone->getAutoGenerateAccessors());
+
+ setAccessorsAreInline(cppclone->getAccessorsAreInline());
+ setOperationsAreInline(cppclone->getOperationsAreInline());
+ setDestructorsAreVirtual(cppclone->getDestructorsAreVirtual());
+ setPackageIsNamespace(cppclone->getPackageIsNamespace());
+
+ setStringClassName(cppclone->getStringClassName() );
+ setStringClassNameInclude(cppclone->getStringClassNameInclude());
+ setStringIncludeIsGlobal(cppclone->stringIncludeIsGlobal());
+
+ setVectorClassName(cppclone->getVectorClassName());
+ setVectorClassNameInclude(cppclone->getVectorClassNameInclude());
+ setVectorIncludeIsGlobal(cppclone->vectorIncludeIsGlobal());
+
+ }
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+
+}
+
+void CPPCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal )
+{
+
+ if(!config)
+ return;
+
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ // now do cpp specific stuff
+ config -> setGroup("CPP Code Generation");
+
+ setAutoGenerateAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ACCESSORS));
+
+ setAccessorsAreInline(config->readBoolEntry("inlineAccessors",DEFAULT_INLINE_ACCESSORS));
+ setAccessorsArePublic(config->readBoolEntry("publicAccessors",DEFAULT_PUBLIC_ACCESSORS));
+ setOperationsAreInline(config->readBoolEntry("inlineOps",DEFAULT_INLINE_OPERATIONS));
+ setDestructorsAreVirtual(config->readBoolEntry("virtualDestructors",DEFAULT_VIRTUAL_DESTRUCTORS));
+ setPackageIsNamespace(config->readBoolEntry("packageIsNamespace",DEFAULT_PACKAGE_IS_NAMESPACE));
+
+ setStringClassName(config->readEntry("stringClassName",DEFAULT_STRING_CLASS_NAME) );
+ setStringClassNameInclude(config->readEntry("stringClassNameInclude",DEFAULT_STRING_CLASS_INCLUDE ) );
+ setStringIncludeIsGlobal(config->readBoolEntry("stringIncludeIsGlobal",DEFAULT_STRING_INCLUDE_GLOBAL) );
+
+ setVectorClassName(config->readEntry("vectorClassName",DEFAULT_VECTOR_CLASS_NAME) );
+ setVectorClassNameInclude(config->readEntry("vectorClassNameInclude",DEFAULT_VECTOR_CLASS_INCLUDE) );
+ setVectorIncludeIsGlobal(config->readBoolEntry("vectorIncludeIsGlobal",DEFAULT_VECTOR_INCLUDE_GLOBAL) );
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig();
+}
+
+
+/**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+CodeGenerationPolicyPage * CPPCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) {
+ return new CPPCodeGenerationPolicyPage ( parent, name, this );
+}
+
+void CPPCodeGenerationPolicy::init() {
+
+ m_inlineAccessors = DEFAULT_INLINE_ACCESSORS;
+ m_publicAccessors = DEFAULT_PUBLIC_ACCESSORS;
+ m_inlineOperations = DEFAULT_INLINE_OPERATIONS;
+ m_virtualDestructors = DEFAULT_VIRTUAL_DESTRUCTORS;
+ m_packageIsNamespace = DEFAULT_PACKAGE_IS_NAMESPACE;
+
+ m_stringClassName = DEFAULT_STRING_CLASS_NAME;
+ m_stringClassNameInclude = DEFAULT_STRING_CLASS_INCLUDE;
+ m_stringIncludeIsGlobal = DEFAULT_STRING_INCLUDE_GLOBAL;
+
+ m_vectorClassName = DEFAULT_VECTOR_CLASS_NAME;
+ m_vectorClassNameInclude = DEFAULT_VECTOR_CLASS_INCLUDE;
+ m_vectorIncludeIsGlobal = DEFAULT_VECTOR_INCLUDE_GLOBAL;
+
+ m_vectorMethodAppendBase = DEFAULT_VECTOR_METHOD_APPEND;
+ m_vectorMethodRemoveBase = DEFAULT_VECTOR_METHOD_REMOVE;
+ m_vectorMethodInitBase = DEFAULT_VECTOR_METHOD_INIT;
+ m_objectMethodInitBase = DEFAULT_OBJECT_METHOD_INIT;
+
+}
+
+
+#include "cppcodegenerationpolicy.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h
new file mode 100644
index 00000000..cda5d1f8
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h
@@ -0,0 +1,227 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+#ifndef CPPCODEGENERATIONPOLICY_H
+#define CPPCODEGENERATIONPOLICY_H
+
+#include <qstring.h>
+#include "codegenpolicyext.h"
+#include "../codegenerationpolicy.h"
+
+class KConfig;
+class CodeGenerationPolicyPage;
+
+class CPPCodeGenerationPolicy : public CodeGenPolicyExt
+{
+ Q_OBJECT
+public:
+
+ static const bool DEFAULT_AUTO_GEN_EMPTY_CONSTRUCTORS;
+ static const bool DEFAULT_AUTO_GEN_ACCESSORS;
+ static const bool DEFAULT_INLINE_ACCESSORS;
+ static const bool DEFAULT_INLINE_OPERATIONS;
+ static const bool DEFAULT_VIRTUAL_DESTRUCTORS;
+ static const bool DEFAULT_PACKAGE_IS_NAMESPACE;
+ static const bool DEFAULT_PUBLIC_ACCESSORS;
+
+ static const bool DEFAULT_STRING_INCLUDE_GLOBAL;
+ static const bool DEFAULT_VECTOR_INCLUDE_GLOBAL;
+
+ static const char * DEFAULT_STRING_CLASS_NAME;
+ static const char * DEFAULT_STRING_CLASS_INCLUDE;
+ static const char * DEFAULT_VECTOR_CLASS_NAME;
+ static const char * DEFAULT_VECTOR_CLASS_INCLUDE;
+ static const char * DEFAULT_VECTOR_METHOD_APPEND;
+ static const char * DEFAULT_VECTOR_METHOD_REMOVE;
+ static const char * DEFAULT_VECTOR_METHOD_INIT;
+ static const char * DEFAULT_OBJECT_METHOD_INIT;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ CPPCodeGenerationPolicy ( KConfig * config = 0 );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPCodeGenerationPolicy ( );
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_inlineAccessors
+ * @param var the new value
+ */
+ void setAccessorsAreInline ( bool var );
+
+ /**
+ * Get the value of m_inlineAccessors
+ * @return value the boolean value of m_inlineAccessors
+ */
+ bool getAccessorsAreInline( );
+
+ /**
+ * Set the value of m_inlineOperations
+ * @param var the new value
+ */
+ void setOperationsAreInline ( bool var );
+
+ /**
+ * Get the value of m_inlineOperations
+ * @return value the boolean value of m_inlineOperations
+ */
+ bool getOperationsAreInline( );
+
+ /**
+ * Set the value of m_virtualDestructors
+ * @param var the new value
+ */
+ void setDestructorsAreVirtual ( bool var );
+
+ /**
+ * Get the value of m_virtualDestructors
+ * @return value the boolean value of m_virtualDestructors
+ */
+ bool getDestructorsAreVirtual( );
+
+ /**
+ * Set the value of m_packageIsNamespace
+ * @param var the new value
+ */
+ void setPackageIsNamespace ( bool var );
+
+ /**
+ * Get the value of m_packageIsNamespace
+ * @return value the boolean value of m_packageIsNamespace
+ */
+ bool getPackageIsNamespace( );
+
+
+ /**
+ * Set the value of m_autoGenerateAccessors
+ * @param var the new value
+ */
+ void setAutoGenerateAccessors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateAccessors
+ * @return value the boolean value of m_autoGenerateAccessors
+ */
+ bool getAutoGenerateAccessors( );
+
+ /**
+ * Set the value of m_publicAccessors
+ * @param var the new value
+ */
+ void setAccessorsArePublic ( bool var );
+
+ /**
+ * Get the value of m_publicAccessors
+ * @return value the boolean value of m_inlineAccessors
+ */
+ bool getAccessorsArePublic( );
+
+ /** We want to be flexible about which classes are allowed for generation
+ * of the CPP code. In the next 4 methods, we give accessors that allow getting
+ * the names of the classes, and their include files for string and vectors.
+ */
+ QString getStringClassName();
+ QString getStringClassNameInclude();
+ QString getVectorClassName();
+ QString getVectorClassNameInclude();
+
+ /** determine if the string include is global one */
+ bool stringIncludeIsGlobal ();
+ bool vectorIncludeIsGlobal ();
+
+ /** also allow setting these parameters! */
+ void setStringClassName(const QString &value);
+ void setStringClassNameInclude(const QString &value);
+ void setVectorClassName(const QString &value);
+ void setVectorClassNameInclude(const QString &value);
+
+ /** allow setting of these params */
+ void setStringIncludeIsGlobal (bool value);
+ void setVectorIncludeIsGlobal (bool value);
+
+ /** More flexible generation. We want to allow the user to specify how the
+ * bodies of the vector methods should be auto-generated.
+ */
+ QString getVectorMethodAppend(const QString & variableName ="", const QString & itemClassName = "");
+ QString getVectorMethodRemove(const QString & variableName ="", const QString & itemClassName = "");
+ QString getVectorMethodInit(const QString & variableName ="", const QString & itemClassName = "");
+
+ /** Be somewhat flexible about how new object classes are initialized.
+ * Not sure if this should be user configureable. For now, it isnt.
+ */
+ QString getObjectMethodInit(const QString & variableName ="", const QString & itemClassName = "");
+
+ /**
+ * set the defaults for this code generator from the passed generator.
+ */
+ virtual void setDefaults (CPPCodeGenerationPolicy * defaults, bool emitUpdateSignal = true);
+
+ /**
+ * set the defaults from a config file for this code generator from the passed KConfig pointer.
+ */
+ virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true);
+
+ /**
+ * write Default params to passed KConfig pointer.
+ */
+ virtual void writeConfig (KConfig * config);
+
+ /**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+ CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0);
+
+protected:
+
+ /**
+ */
+ void init ( );
+
+private:
+
+ bool m_autoGenerateAccessors;
+
+ bool m_inlineAccessors;
+ bool m_inlineOperations;
+ bool m_virtualDestructors;
+ bool m_packageIsNamespace;
+ bool m_publicAccessors;
+
+ bool m_stringIncludeIsGlobal;
+ bool m_vectorIncludeIsGlobal;
+
+ QString m_stringClassName;
+ QString m_stringClassNameInclude;
+ QString m_vectorClassName;
+ QString m_vectorClassNameInclude;
+ QString m_vectorMethodAppendBase;
+ QString m_vectorMethodRemoveBase;
+ QString m_vectorMethodInitBase;
+ QString m_objectMethodInitBase;
+
+};
+
+#endif // CPPCODEGENERATIONPOLICY_H
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp
new file mode 100644
index 00000000..f05833dc
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 30 2003
+ */
+
+// own header
+#include "cppcodegenerationpolicypage.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <qlabel.h>
+#include <kcombobox.h>
+#include <qcheckbox.h>
+// app includes
+#include "cppcodegenerationformbase.h"
+#include "../uml.h"
+
+CPPCodeGenerationPolicyPage::CPPCodeGenerationPolicyPage( QWidget *parent, const char *name, CPPCodeGenerationPolicy * policy )
+ : CodeGenerationPolicyPage(parent, name, policy)
+{
+ CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy();
+ form = new CPPCodeGenerationForm(this);
+ form->m_SelectCommentStyle->setCurrentItem((int)(common->getCommentStyle()));
+ form->setPackageIsANamespace(policy->getPackageIsNamespace());
+ form->setVirtualDestructors(policy->getDestructorsAreVirtual());
+ form->setGenerateAccessorMethods(policy->getAutoGenerateAccessors());
+ form->setGenerateEmptyConstructors(common->getAutoGenerateConstructors());
+ form->setOperationsAreInline(policy->getOperationsAreInline());
+ form->setAccessorsAreInline(policy->getAccessorsAreInline());
+ form->setAccessorsArePublic(policy->getAccessorsArePublic());
+
+ form->m_stringClassHCombo->setCurrentItem(policy->getStringClassName(),true);
+ form->m_listClassHCombo->setCurrentItem(policy->getVectorClassName(),true);
+
+ form->m_stringIncludeFileHistoryCombo->setCurrentItem(policy->getStringClassNameInclude(),true);
+ form->m_listIncludeFileHistoryCombo->setCurrentItem(policy->getVectorClassNameInclude(),true);
+
+ form->m_globalStringCheckBox->setChecked(policy->stringIncludeIsGlobal());
+ form->m_globalListCheckBox->setChecked(policy->vectorIncludeIsGlobal());
+}
+
+CPPCodeGenerationPolicyPage::~CPPCodeGenerationPolicyPage()
+{
+}
+
+void CPPCodeGenerationPolicyPage::apply()
+{
+ CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy();
+
+ // now do our cpp-specific configs
+ CPPCodeGenerationPolicy * parent = (CPPCodeGenerationPolicy*) m_parentPolicy;
+
+ // block signals so that we don't generate too many sync signals for child code
+ // documents
+ parent->blockSignals(true);
+
+ common->setCommentStyle((CodeGenerationPolicy::CommentStyle ) form->m_SelectCommentStyle->currentItem());
+ common->setAutoGenerateConstructors(form->getGenerateEmptyConstructors());
+ parent->setAutoGenerateAccessors(form->getGenerateAccessorMethods());
+
+ parent->setDestructorsAreVirtual(form->getVirtualDestructors());
+ parent->setPackageIsNamespace(form->getPackageIsANamespace());
+ parent->setAccessorsAreInline(form->getAccessorsAreInline());
+ parent->setOperationsAreInline(form->getOperationsAreInline());
+ parent->setAccessorsArePublic(form->getAccessorsArePublic());
+
+ parent->setStringClassName(form->m_stringClassHCombo->currentText());
+ parent->setStringClassNameInclude(form->m_stringIncludeFileHistoryCombo->currentText());
+ parent->setStringIncludeIsGlobal(form->m_globalStringCheckBox->isChecked());
+
+ parent->setVectorClassName(form->m_listClassHCombo->currentText());
+ parent->setVectorClassNameInclude(form->m_listIncludeFileHistoryCombo->currentText());
+ parent->setVectorIncludeIsGlobal(form->m_globalListCheckBox->isChecked());
+
+ parent->blockSignals(false);
+
+ // now send out modified code content signal
+ common->emitModifiedCodeContentSig();
+
+}
+
+
+#include "cppcodegenerationpolicypage.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h
new file mode 100644
index 00000000..a1d6633b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 30 2003
+ */
+
+#ifndef CPPCODEGENERATIONPOLICYPAGE_H
+#define CPPCODEGENERATIONPOLICYPAGE_H
+
+#include "../dialogs/codegenerationpolicypage.h"
+
+#include "cppcodegenerationform.h"
+#include "cppcodegenerationpolicy.h"
+
+/**
+ * @author Brian Thomas
+ */
+
+class CPPCodeGenerationPolicyPage : public CodeGenerationPolicyPage {
+ Q_OBJECT
+public:
+
+ explicit CPPCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, CPPCodeGenerationPolicy * policy = 0);
+
+ virtual ~CPPCodeGenerationPolicyPage();
+
+protected:
+
+ CPPCodeGenerationForm * form;
+
+public slots:
+
+ void apply();
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerator.cpp b/umbrello/umbrello/codegenerators/cppcodegenerator.cpp
new file mode 100644
index 00000000..1130107b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerator.cpp
@@ -0,0 +1,366 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+// own header
+#include "cppcodegenerator.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+#include <kconfig.h>
+
+// app includes
+#include "cppcodedocumentation.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppsourcecodedocument.h"
+#include "cppheadercodedocument.h"
+#include "codegen_utils.h"
+#include "codeviewerdialog.h"
+#include "../codedocumentlist.h"
+#include "../uml.h"
+
+const bool CPPCodeGenerator::DEFAULT_BUILD_MAKEFILE = false;
+
+// Constructors/Destructors
+//
+
+CPPCodeGenerator::CPPCodeGenerator () {
+ initAttributes();
+}
+
+CPPCodeGenerator::~CPPCodeGenerator ( ) {
+ // destroy all separately owned codedocuments (e.g. header docs)
+ CodeDocument *doc;
+ for (CodeDocumentListIt it(m_headercodedocumentVector);
+ (doc = it.current()) != NULL; ++it)
+ delete doc;
+ m_headercodedocumentVector.clear();
+}
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+/**
+ * returns "C++"
+ */
+Uml::Programming_Language CPPCodeGenerator::getLanguage() {
+ return Uml::pl_Cpp;
+}
+
+/**
+ * Set the value of m_createMakefile
+ * @param new_var the new value of m_createMakefile
+ */
+void CPPCodeGenerator::setCreateProjectMakefile ( bool buildIt) {
+ m_createMakefile = buildIt;
+ CodeDocument * antDoc = findCodeDocumentByID(CPPMakefileCodeDocument::DOCUMENT_ID_VALUE);
+ if (antDoc)
+ antDoc->setWriteOutCode(buildIt);
+}
+
+/**
+ * Get the value of m_createMakefile
+ * @return the value of m_createMakefile
+ */
+bool CPPCodeGenerator::getCreateProjectMakefile ( ) {
+ return m_createMakefile;
+}
+
+bool CPPCodeGenerator::addHeaderCodeDocument ( CPPHeaderCodeDocument * doc )
+{
+
+ QString tag = doc->getID();
+
+ // assign a tag if one doesn't already exist
+ if(tag.isEmpty())
+ {
+ tag = "cppheader"+ID2STR(doc->getParentClassifier()->getID());
+ doc->setID(tag);
+ }
+
+ if(m_codeDocumentDictionary.find(tag))
+ return false; // return false, we already have some object with this tag in the list
+ else
+ m_codeDocumentDictionary.insert(tag, doc);
+
+ m_headercodedocumentVector.append(doc);
+ return true;
+}
+
+/**
+ * Remove a header CodeDocument object from m_headercodedocumentVector List
+ */
+bool CPPCodeGenerator::removeHeaderCodeDocument ( CPPHeaderCodeDocument * remove_object ) {
+ QString tag = remove_object->getID();
+ if(!(tag.isEmpty()))
+ m_codeDocumentDictionary.remove(tag);
+ else
+ return false;
+
+ m_headercodedocumentVector.remove(remove_object);
+ return true;
+}
+
+// In the C++ version, we need to make both source and header files as well
+// as the makefile available.
+CodeViewerDialog * CPPCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc,
+ Settings::CodeViewerState state)
+{
+
+ ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument*>(doc);
+ if(!cdoc)
+ // bah..not a classcode document?? then just use vanilla version
+ return CodeGenerator::getCodeViewerDialog(parent,doc,state);
+ else {
+ // build with passed (source) code document
+ CodeViewerDialog *dialog;
+
+ // use classifier to find appropriate header document
+ UMLClassifier * c = cdoc->getParentClassifier();
+ CPPHeaderCodeDocument * hdoc = findHeaderCodeDocumentByClassifier(c);
+ if(hdoc)
+ {
+ // if we have a header document..build with that
+ dialog = new CodeViewerDialog(parent, hdoc, state);
+ dialog->addCodeDocument(doc);
+ } else
+ // shouldn't happen, but lets try to gracefully deliver something.
+ dialog = new CodeViewerDialog(parent, doc, state);
+
+ // add in makefile if available and desired
+ if(getCreateProjectMakefile())
+ dialog->addCodeDocument(findCodeDocumentByID(CPPMakefileCodeDocument::DOCUMENT_ID_VALUE));
+
+ return dialog;
+ }
+}
+
+// Other methods
+//
+
+// Change the following dataTypes to the ones the user really
+// wants in their code. Not yet complete.
+QString CPPCodeGenerator::fixTypeName(const QString &string)
+{
+ return cleanName(string);
+}
+
+// special method needed so that we write out the header code documents
+void CPPCodeGenerator::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement docElement = doc.createElement( "codegenerator" );
+ docElement.setAttribute("language", "C++");
+
+ CodeDocumentList * docList = getCodeDocumentList();
+ for (CodeDocument * codeDoc = docList->first(); codeDoc; codeDoc= docList->next())
+ codeDoc->saveToXMI(doc, docElement);
+
+ for (CodeDocument * hcodeDoc = m_headercodedocumentVector.first(); hcodeDoc; hcodeDoc=m_headercodedocumentVector.next())
+ hcodeDoc->saveToXMI(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+/**
+ * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument.
+ * Need to override parent method because we have header documents to consider too.
+ */
+void CPPCodeGenerator::syncCodeToDocument ( ) {
+
+ CodeDocumentList * docList = getCodeDocumentList();
+
+ for (CodeDocument * doc = docList->first(); doc; doc=docList->next())
+ doc->synchronize();
+
+ for (CodeDocument * hcodeDoc = m_headercodedocumentVector.first(); hcodeDoc; hcodeDoc=m_headercodedocumentVector.next())
+ hcodeDoc->synchronize();
+
+}
+
+/**
+ * Write out all code documents to file as appropriate.
+ */
+void CPPCodeGenerator::writeCodeToFile ( )
+{
+ // write all source documents (incl. Makefile)
+ writeListedCodeDocsToFile(getCodeDocumentList());
+
+ // write all header documents
+ writeListedCodeDocsToFile(&m_headercodedocumentVector);
+
+}
+
+// overridden because we need to be able to generate code for
+// both the header and source documents
+void CPPCodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) {
+ CodeDocumentList docs;
+ docs.setAutoDelete(false);
+
+ for (UMLClassifier *concept= concepts.first(); concept; concept= concepts.next())
+ {
+ CodeDocument * doc = findCodeDocumentByClassifier(concept);
+ if(doc)
+ docs.append(doc);
+ CodeDocument * hdoc = findHeaderCodeDocumentByClassifier(concept);
+ if(hdoc)
+ docs.append(hdoc);
+ }
+
+ writeListedCodeDocsToFile(&docs);
+}
+
+
+/**
+ * Find a cppheadercodedocument by the given classifier.
+ * @return CPPHeaderCodeDocument
+* @param classifier
+*/
+CPPHeaderCodeDocument * CPPCodeGenerator::findHeaderCodeDocumentByClassifier (UMLClassifier * classifier )
+{
+ CodeDocument * doc = findCodeDocumentByID("cppheader"+ID2STR(classifier->getID()));
+ return dynamic_cast<CPPHeaderCodeDocument*>(doc);
+}
+
+/**
+ * @return ClassifierCodeDocument
+ * @param classifier The classifier for which the CodeDocument is to be created
+ */
+// source document version.
+CodeDocument * CPPCodeGenerator::newClassifierCodeDocument (UMLClassifier * classifier)
+{
+ ClassifierCodeDocument *doc = new CPPSourceCodeDocument(classifier);
+ doc->initCodeClassFields();
+ return doc;
+}
+
+CPPHeaderCodeDocument * CPPCodeGenerator::newHeaderClassifierCodeDocument (UMLClassifier * classifier)
+{
+ CPPHeaderCodeDocument *doc = new CPPHeaderCodeDocument(classifier);
+ doc->initCodeClassFields();
+ return doc;
+}
+
+/**
+ * @return CPPMakefileCodeDocument
+ * @param this
+ */
+CPPMakefileCodeDocument * CPPCodeGenerator::newMakefileCodeDocument ( ) {
+ return new CPPMakefileCodeDocument();
+}
+
+
+/**
+ * Overloaded so that we may have both source and header documents for each
+ * classifier.
+ */
+void CPPCodeGenerator::initFromParentDocument( ) {
+
+ // Walk through the document converting classifiers into
+ // classifier code documents as needed (e.g only if doesn't exist)
+ UMLClassifierList concepts = UMLApp::app()->getDocument()->getClassesAndInterfaces();
+ for (UMLClassifier *c = concepts.first(); c; c = concepts.next())
+ {
+
+ // Doesn't exist? Then build one.
+ CodeDocument * codeDoc = findCodeDocumentByClassifier(c);
+ if (!codeDoc)
+ {
+ codeDoc = newClassifierCodeDocument(c);
+ codeDoc->synchronize();
+ addCodeDocument(codeDoc); // this will also add a unique tag to the code document
+ }
+
+ CPPHeaderCodeDocument * hcodeDoc = findHeaderCodeDocumentByClassifier(c);
+ if (!hcodeDoc)
+ {
+ hcodeDoc = newHeaderClassifierCodeDocument(c);
+ hcodeDoc->synchronize();
+ addHeaderCodeDocument(hcodeDoc); // this will also add a unique tag to the code document
+ }
+ }
+
+}
+
+// need to worry about adding both source, and header documents for each
+// classifier
+void CPPCodeGenerator::checkAddUMLObject (UMLObject * obj) {
+ if (!obj)
+ return;
+
+ // if the obj being created is a native data type
+ // there's no reason to create a .h/.cpp file
+ if (isReservedKeyword(obj->getName()))
+ return;
+
+ UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
+ if(c) {
+ CodeDocument * cDoc = newClassifierCodeDocument(c);
+ CPPHeaderCodeDocument * hcodeDoc = newHeaderClassifierCodeDocument(c);
+ addCodeDocument(cDoc);
+ addHeaderCodeDocument(hcodeDoc); // this will also add a unique tag to the code document
+ }
+}
+
+// need to worry about removing both source, and header documents for each
+// classifier
+void CPPCodeGenerator::checkRemoveUMLObject (UMLObject * obj)
+{
+
+ if (!obj)
+ return;
+
+ UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj);
+ if(c) {
+
+ // source
+ ClassifierCodeDocument * cDoc = (ClassifierCodeDocument*) findCodeDocumentByClassifier(c);
+ if (cDoc)
+ removeCodeDocument(cDoc);
+
+ // header
+ CPPHeaderCodeDocument * hcodeDoc = findHeaderCodeDocumentByClassifier(c);
+ if (hcodeDoc)
+ removeHeaderCodeDocument(hcodeDoc);
+ }
+
+}
+
+void CPPCodeGenerator::initAttributes ( )
+{
+ m_createMakefile = false;
+
+ UMLApp::app()->setPolicyExt ( new CPPCodeGenerationPolicy(UMLApp::app()->getConfig()) );
+
+ // load Classifier documents from parent document
+ //initFromParentDocument();
+}
+
+QStringList CPPCodeGenerator::defaultDatatypes() {
+ return Codegen_Utils::cppDatatypes();
+}
+
+const QStringList CPPCodeGenerator::reservedKeywords() const {
+ return Codegen_Utils::reservedCppKeywords();
+}
+
+void CPPCodeGenerator::createDefaultStereotypes (){
+ Codegen_Utils::createCppStereotypes();
+}
+
+#include "cppcodegenerator.moc"
diff --git a/umbrello/umbrello/codegenerators/cppcodegenerator.h b/umbrello/umbrello/codegenerators/cppcodegenerator.h
new file mode 100644
index 00000000..7104d403
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppcodegenerator.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+
+#ifndef CPPCODEGENERATOR_H
+#define CPPCODEGENERATOR_H
+
+#include <qstring.h>
+#include "../codedocumentlist.h"
+#include "../codeviewerstate.h"
+#include "../codegenerator.h"
+#include "../umldoc.h"
+#include "cppmakecodedocument.h"
+
+class CodeViewerDialog;
+class CPPHeaderCodeDocument;
+class CodeBlockWithComments;
+class KConfig;
+
+class CPPCodeGenerator : public CodeGenerator
+{
+ Q_OBJECT
+public:
+
+ static const bool DEFAULT_BUILD_MAKEFILE;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Basic Constructor
+ */
+ CPPCodeGenerator ();
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPCodeGenerator ( );
+
+ /**
+ * Set the value of m_createMakefile
+ * @param new_var the new value of m_createMakefile
+ */
+ void setCreateProjectMakefile ( bool new_var );
+
+ /**
+ * Get the value of m_createMakefile
+ * @return the value of m_createMakefile
+ */
+ bool getCreateProjectMakefile ( );
+
+ // Public attribute accessor methods
+ //
+
+ QString fixTypeName(const QString &string);
+
+ /**
+ * Add a header CodeDocument object from m_headercodedocumentVector List
+ */
+ bool addHeaderCodeDocument ( CPPHeaderCodeDocument * doc );
+
+ /**
+ * Remove a header CodeDocument object from m_headercodedocumentVector List
+ */
+ bool removeHeaderCodeDocument ( CPPHeaderCodeDocument * remove_object );
+
+ /**
+ * returns "Cpp"
+ */
+ Uml::Programming_Language getLanguage();
+
+ // generate 2 different types of classifier code documents.
+ CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+ CPPHeaderCodeDocument * newHeaderClassifierCodeDocument (UMLClassifier * classifier);
+
+ /** Get the editing dialog for this code document
+ */
+ virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc,
+ Settings::CodeViewerState state);
+
+ /**
+ * Write out all code documents to file as appropriate.
+ */
+ virtual void writeCodeToFile ( );
+
+ // this method is here to provide class wizard the
+ // ability to write out only those classes which
+ // are selected by the user.
+ virtual void writeCodeToFile(UMLClassifierList &list);
+
+ /**
+ * Add C++ primitives as datatypes
+ */
+ QStringList defaultDatatypes();
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+ /**
+ * Add the default stereotypes for c++ (constructor, int etc)
+ */
+ virtual void createDefaultStereotypes ();
+
+ void initFromParentDocument( );
+
+protected:
+
+ /**
+ * @return CPPMakeCodeDocument
+ */
+ CPPMakefileCodeDocument * newMakefileCodeDocument ( );
+
+ /**
+ * Find a cppheadercodedocument by the given classifier.
+ * @return CPPHeaderCodeDocument
+ * @param classifier
+ */
+ CPPHeaderCodeDocument * findHeaderCodeDocumentByClassifier (UMLClassifier * classifier );
+
+private:
+
+ bool m_createMakefile;
+
+ // a separate list for recording the header documents
+ CodeDocumentList m_headercodedocumentVector;
+
+ void initAttributes ( ) ;
+
+public slots:
+
+ /** These 2 functions check for adding or removing objects to the UMLDocument
+ * they are need to be overridden here because unlike in the Java (or most other lang)
+ * we add 2 types of classifiercodedocument per classifier,
+ * e.g. a "source" and a "header" document.
+ */
+ virtual void checkAddUMLObject (UMLObject * obj);
+ virtual void checkRemoveUMLObject (UMLObject * obj);
+
+ /**
+ * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument.
+ * "UserGenerated" code will be preserved, but Autogenerated contents will be updated/replaced
+ * or removed as is apppropriate.
+ */
+ virtual void syncCodeToDocument ( );
+};
+
+#endif // CPPCODEGENERATOR_H
diff --git a/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp
new file mode 100644
index 00000000..ea5612c9
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp
@@ -0,0 +1,160 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#include "cppheaderclassdeclarationblock.h"
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppcodedocumentation.h"
+#include "../model_utils.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPHeaderClassDeclarationBlock::CPPHeaderClassDeclarationBlock
+ ( CPPHeaderCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment)
+ : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment)
+{
+ init(parentDoc, comment);
+}
+
+CPPHeaderClassDeclarationBlock::~CPPHeaderClassDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CPPHeaderClassDeclarationBlock::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+/** set the class attributes from a passed object
+ */
+void CPPHeaderClassDeclarationBlock::setAttributesFromObject (TextBlock * obj)
+{
+ HierarchicalCodeBlock::setAttributesFromObject(obj);
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void CPPHeaderClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "cppheaderclassdeclarationblock" );
+
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * update the start and end text for this hierarchicalcodeblock.
+ */
+void CPPHeaderClassDeclarationBlock::updateContent ( )
+{
+
+ CPPHeaderCodeDocument *parentDoc = dynamic_cast<CPPHeaderCodeDocument*>(getParentDocument());
+ UMLClassifier *c = parentDoc->getParentClassifier();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ bool isInterface = parentDoc->parentIsInterface(); // a little shortcut
+ QString CPPHeaderClassName = CodeGenerator::cleanName(c->getName());
+ bool forceDoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
+
+ // COMMENT
+
+ //check if class is abstract.. it should have abstract methods
+ if(!isInterface && c->getAbstract() && !c->hasAbstractOps())
+ {
+ getComment()->setText("******************************* Abstract Class ****************************"+endLine
+ +CPPHeaderClassName+" does not have any pure virtual methods, but its author"+endLine
+ +" defined it as an abstract class, so you should not use it directly."+endLine
+ +" Inherit from it instead and create only objects from the derived classes"+endLine
+ +"*****************************************************************************");
+ } else {
+ if(isInterface)
+ getComment()->setText("Interface "+CPPHeaderClassName+endLine+c->getDoc());
+ else
+ getComment()->setText("Class "+CPPHeaderClassName+endLine+c->getDoc());
+ }
+
+ if(forceDoc || !c->getDoc().isEmpty())
+ getComment()->setWriteOutText(true);
+ else
+ getComment()->setWriteOutText(false);
+
+
+ // Now set START/ENDING Text
+ QString startText = "";
+
+ /*
+ */
+
+ /*
+ if(parentDoc->parentIsInterface())
+ startText.append("interface ");
+ else
+ */
+ startText.append("class ");
+
+ startText.append(CPPHeaderClassName);
+
+ // write inheritances out
+ UMLClassifierList superclasses = c->findSuperClassConcepts();
+ int nrof_superclasses = superclasses.count();
+
+ // write out inheritance
+ int i = 0;
+ if(nrof_superclasses >0)
+ startText.append(" : ");
+ for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next())
+ {
+ startText.append(concept->getVisibility().toString() + ' ' +
+ CodeGenerator::cleanName(concept->getName()));
+ if(i != (nrof_superclasses-1))
+ startText.append(", ");
+ i++;
+ }
+
+ // Set the header and end text for the hier.codeblock
+ setStartText(startText+" {");
+
+ // setEndText("}"); // not needed
+
+}
+
+void CPPHeaderClassDeclarationBlock::init (CPPHeaderCodeDocument *parentDoc, const QString &comment)
+{
+
+ setComment(new CPPCodeDocumentation(parentDoc));
+ getComment()->setText(comment);
+
+ setEndText("};");
+
+ updateContent();
+
+}
+
+
+#include "cppheaderclassdeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h
new file mode 100644
index 00000000..683f0475
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h
@@ -0,0 +1,67 @@
+
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#ifndef CPPHEADERCLASSDECLARATIONBLOCK_H
+#define CPPHEADERCLASSDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "cppheadercodedocument.h"
+#include "../ownedhierarchicalcodeblock.h"
+
+class CPPHeaderClassDeclarationBlock : public OwnedHierarchicalCodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ explicit CPPHeaderClassDeclarationBlock ( CPPHeaderCodeDocument * parentDoc, const QString &start = "", const QString &endText = "}", const QString &comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPHeaderClassDeclarationBlock ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ virtual void loadFromXMI ( QDomElement & root );
+
+protected:
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+ /**
+ * Update the start/end text of this codeblock.
+ */
+ void updateContent ( );
+
+private:
+
+ void init (CPPHeaderCodeDocument * parent, const QString &comment);
+
+};
+
+#endif // CPPHEADERCLASSDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp
new file mode 100644
index 00000000..0ab67b85
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp
@@ -0,0 +1,170 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Aug 31 2003
+ */
+
+// own header
+#include "cppheadercodeaccessormethod.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "../attribute.h"
+#include "../classifiercodedocument.h"
+#include "cppcodegenerator.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+
+#include "cppsourcecodedocument.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppcodeclassfield.h"
+#include "cppcodedocumentation.h"
+
+// Constructors/Destructors
+//
+
+CPPHeaderCodeAccessorMethod::CPPHeaderCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type)
+ : CodeAccessorMethod ( field )
+{
+ setType(type);
+}
+
+void CPPHeaderCodeAccessorMethod::update()
+{
+ updateMethodDeclaration();
+ updateContent();
+}
+
+CPPHeaderCodeAccessorMethod::~CPPHeaderCodeAccessorMethod ( ) { }
+
+// Other
+//
+
+// we basically want to update the body of this method
+void CPPHeaderCodeAccessorMethod::updateContent( )
+{
+ CodeClassField * parentField = getParentClassField();
+ CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField);
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ bool isInlineMethod = policy->getAccessorsAreInline( );
+ Uml::Visibility scope = parentField->getVisibility();
+ QString variableName = cppfield->getFieldName();
+ QString itemClassName = cppfield->getTypeName();
+ QString text;
+
+ if(isInlineMethod) {
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ text = policy->getVectorMethodAppend(variableName, itemClassName);
+ break;
+ case CodeAccessorMethod::REMOVE:
+ text = policy->getVectorMethodRemove(variableName, itemClassName);
+ break;
+ case CodeAccessorMethod::SET:
+ text = variableName+" = value;";
+ break;
+ case CodeAccessorMethod::LIST:
+ case CodeAccessorMethod::GET:
+ default:
+ text = "return " + variableName + ';';
+ break;
+ }
+ }
+
+ setText(text);
+}
+
+// we basically want to update the start text of this method
+void CPPHeaderCodeAccessorMethod::updateMethodDeclaration()
+{
+
+ CodeClassField * parentField = getParentClassField();
+ ClassifierCodeDocument * doc = parentField->getParentDocument();
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField);
+
+ bool isInlineMethod = policy->getAccessorsAreInline( );
+
+ QString vectorClassName = policy->getVectorClassName();
+ QString fieldName = cppfield->getFieldName();
+ QString fieldType = cppfield->getTypeName();
+ QString objectType = cppfield->getListObjectType();
+ if(objectType.isEmpty())
+ objectType = fieldName;
+
+ QString methodReturnType = "void";
+ QString methodName;
+ QString methodParams;
+ QString headerText;
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ methodName = "add_"+fieldType;
+ methodReturnType = "void";
+ methodParams = objectType+" value ";
+ headerText = "Add a "+fieldName+" object to the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void";
+ break;
+ case CodeAccessorMethod::REMOVE:
+ methodName = "remove_"+fieldType;
+ methodParams = objectType+" value ";
+ methodReturnType = "void";
+ headerText = "Remove a "+fieldName+" object from the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void";
+ break;
+ case CodeAccessorMethod::LIST:
+ methodName = "get_"+fieldType+"_list";
+ methodReturnType = vectorClassName;
+ headerText = "Get the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return "+vectorClassName+"with list of objects";
+ break;
+ case CodeAccessorMethod::SET:
+ methodName = "set_"+fieldName;
+ methodParams = fieldType+" value ";
+ methodReturnType = "void";
+ headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@param value the value of "+fieldName;
+ break;
+ case CodeAccessorMethod::GET:
+ default:
+ methodName = "get_"+fieldName;
+ methodReturnType = fieldType;
+ headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName;
+ break;
+ }
+
+ // set header
+ CPPCodeDocumentation * header = new CPPCodeDocumentation(doc);
+ if(!getParentObject()->getDoc().isEmpty())
+ header->setText(headerText);
+ setComment(header);
+
+ // set start/end method text
+ QString startText = methodReturnType + ' ' + methodName + " (" + methodParams +')';
+ if (isInlineMethod)
+ startText += " {";
+ else
+ startText += ';';
+ QString endText = (isInlineMethod ? "}" : "");
+
+ setStartMethodText(startText);
+ setEndMethodText(endText);
+
+ setOverallIndentationLevel(1);
+}
+
+
+
+#include "cppheadercodeaccessormethod.moc"
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h
new file mode 100644
index 00000000..7b39fc6d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h
@@ -0,0 +1,57 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Aug 31 2003
+ */
+
+#ifndef CPPHEADERACCESSORMETHOD_H
+#define CPPHEADERACCESSORMETHOD_H
+
+#include "../codeaccessormethod.h"
+
+#include <qstring.h>
+
+class CodeClassField;
+
+class CPPHeaderCodeAccessorMethod : public CodeAccessorMethod
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ CPPHeaderCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPHeaderCodeAccessorMethod ( );
+
+ /**
+ * Must be called before this object is usable
+ */
+ void update();
+
+protected:
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent();
+
+private:
+
+};
+
+#endif // CPPHEADERACCESSORMETHOD_H
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp
new file mode 100644
index 00000000..0fdfeb0a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp
@@ -0,0 +1,78 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#include "cppheadercodeclassfielddeclarationblock.h"
+
+#include "cppcodeclassfield.h"
+#include "cppheadercodedocument.h"
+
+// Constructors/Destructors
+//
+
+CPPHeaderCodeClassFieldDeclarationBlock::CPPHeaderCodeClassFieldDeclarationBlock ( CodeClassField * parent )
+ : CodeClassFieldDeclarationBlock ( parent )
+{
+ setOverallIndentationLevel(1);
+ updateContent();
+}
+
+CPPHeaderCodeClassFieldDeclarationBlock::~CPPHeaderCodeClassFieldDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+/**
+ */
+void CPPHeaderCodeClassFieldDeclarationBlock::updateContent( )
+{
+ UMLObject *umlparent = CodeClassFieldDeclarationBlock::getParentObject();
+ if (umlparent == NULL) {
+ return;
+ }
+
+ CodeClassField * cf = getParentClassField();
+ CPPCodeClassField * hcppcf = dynamic_cast<CPPCodeClassField*>(cf);
+
+ // Set the comment
+ QString notes = umlparent->getDoc();
+ getComment()->setText(notes);
+ if(notes.isEmpty())
+ getComment()->setWriteOutText(false);
+ else
+ getComment()->setWriteOutText(true);
+
+
+ // Set the body
+ QString staticValue = umlparent->getStatic() ? "static " : "";
+ QString typeName = hcppcf->getTypeName();
+ QString fieldName = hcppcf->getFieldName();
+
+ // Ugh. Sloppy exception.
+ if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue())
+ typeName = hcppcf->getListFieldClassName();
+
+ QString body = staticValue + ' ' + typeName + ' ' + fieldName + ';';
+
+ setText(body);
+
+}
+
+
+
+#include "cppheadercodeclassfielddeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h
new file mode 100644
index 00000000..755507c6
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h
@@ -0,0 +1,51 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#ifndef CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H
+#define CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "../codeclassfielddeclarationblock.h"
+
+class CPPHeaderCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPHeaderCodeClassFieldDeclarationBlock ( CodeClassField * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPHeaderCodeClassFieldDeclarationBlock ( );
+
+protected:
+
+ // this will be called by syncToParent whenever the parent object is "modified"
+ void updateContent ( );
+
+private:
+
+
+};
+
+#endif // CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp b/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp
new file mode 100644
index 00000000..fe909c5d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp
@@ -0,0 +1,813 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Aug 28 2003
+ */
+
+/**
+ We carve the CPP document up into 2 documents, "source" and "header".
+ This one represents the header portion.
+ The sections of each are as follows:
+
+ * header
+ * includes
+ * import statements
+ * class declaration
+ * guts of the class (e.g. field decl, accessor methods, operations, dependant classes)
+*/
+
+// own header
+#include "cppheadercodedocument.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppcodedocumentation.h"
+#include "cppheadercodeaccessormethod.h"
+#include "cppheadercodeoperation.h"
+#include "cppheaderclassdeclarationblock.h"
+#include "cppheadercodeclassfielddeclarationblock.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../classifierlistitem.h"
+#include "../enum.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPHeaderCodeDocument::CPPHeaderCodeDocument ( UMLClassifier * concept )
+ : ClassifierCodeDocument (concept)
+{
+ setFileExtension(".h");
+
+ //initCodeClassFields(); // this is dubious because it calls down to
+ // CodeGenFactory::newCodeClassField(this)
+ // but "this" is still in construction at that time.
+
+ // needed? I doubt it, but it feels good to do it.
+ classDeclCodeBlock = 0;
+ publicBlock = 0;
+ protectedBlock = 0;
+ privateBlock = 0;
+ namespaceBlock = 0;
+ pubConstructorBlock = 0;
+ protConstructorBlock = 0;
+ privConstructorBlock = 0;
+ pubOperationsBlock = 0;
+ privOperationsBlock = 0;
+ protOperationsBlock = 0;
+
+ // this will call updateContent() as well as other things that sync our document.
+ //synchronize();
+
+}
+
+CPPHeaderCodeDocument::~CPPHeaderCodeDocument ( ) {
+ resetTextBlocks();
+}
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+CPPHeaderClassDeclarationBlock * CPPHeaderCodeDocument::getClassDecl()
+{
+
+ if(!classDeclCodeBlock) {
+ classDeclCodeBlock = new CPPHeaderClassDeclarationBlock (this); // was deleted before our load
+ classDeclCodeBlock->setTag("classDeclarationBlock");
+ }
+ return classDeclCodeBlock;
+}
+
+// Other methods
+//
+
+// Sigh. NOT optimal. The only reason that we need to have this
+// is so we can create the CPPHeaderClassDeclarationBlock.
+// would be better if we could create a handler interface that each
+// codeblock used so all we have to do here is add the handler
+void CPPHeaderCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root)
+{
+
+ QDomNode tnode = root.firstChild();
+ QDomElement telement = tnode.toElement();
+ bool loadCheckForChildrenOK = false;
+ while( !telement.isNull() ) {
+ QString nodeName = telement.tagName();
+
+ if( nodeName == "textblocks" ) {
+
+ QDomNode node = telement.firstChild();
+ QDomElement element = node.toElement();
+
+ // if there is nothing to begin with, then we don't worry about it
+ loadCheckForChildrenOK = element.isNull() ? true : false;
+
+ while( !element.isNull() ) {
+ QString name = element.tagName();
+
+ if( name == "codecomment" ) {
+ CodeComment * block = new CPPCodeDocumentation(this);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeComment to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeaccessormethod" ||
+ name == "ccfdeclarationcodeblock"
+ ) {
+ QString acctag = element.attribute("tag","");
+ // search for our method in the
+ TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
+ if(!tb || !addTextBlock(tb))
+ {
+ kError()<<"Unable to add codeclassfield child method to:"<<this<<endl;
+ // DON'T delete
+ } else
+ loadCheckForChildrenOK= true;
+
+ } else
+ if( name == "codeblock" ) {
+ CodeBlock * block = newCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeBlock to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeblockwithcomments" ) {
+ CodeBlockWithComments * block = newCodeBlockWithComments();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeBlockwithcomments to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "header" ) {
+ // do nothing.. this is treated elsewhere
+ } else
+ if( name == "hierarchicalcodeblock" ) {
+ HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeoperation" ) {
+ // find the code operation by id
+ QString id = element.attribute("parent_id","-1");
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+ if(op) {
+ CodeOperation * block = new CPPHeaderCodeOperation(this, op);
+ block->loadFromXMI(element);
+ if(addTextBlock(block))
+ loadCheckForChildrenOK= true;
+ else
+ {
+ kError()<<"Unable to add codeoperation to:"<<this<<endl;
+ block->deleteLater();
+ }
+ } else
+ kError()<<"Unable to find operation create codeoperation for:"<<this<<endl;
+ }
+ else
+ if( name == "cppheaderclassdeclarationblock" )
+ {
+ CPPHeaderClassDeclarationBlock * block = getClassDecl();
+ block->loadFromXMI(element);
+ // normally this would be populated by the following syncToparent
+ // call, but we cant wait for it, so lets just do it now.
+ namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0);
+
+ if(!namespaceBlock || !namespaceBlock->addTextBlock(block))
+ {
+ kError()<<"Error:cant add class declaration codeblock"<<endl;
+ // DON'T delete/release block
+ // block->release();
+ } else
+ loadCheckForChildrenOK= true;
+
+ }
+ // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
+ //else
+ //kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl;
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+ break;
+ }
+
+ tnode = telement.nextSibling();
+ telement = tnode.toElement();
+ }
+
+ if(!loadCheckForChildrenOK)
+ {
+ CodeDocument * test = dynamic_cast<CodeDocument*>(this);
+ if(test)
+ {
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
+ } else {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
+ if(hb)
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
+ else
+ kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
+ }
+ }
+
+}
+
+void CPPHeaderCodeDocument::resetTextBlocks()
+{
+
+ // all special pointers need to be zero'd out.
+ classDeclCodeBlock = 0;
+ publicBlock = 0;
+ protectedBlock = 0;
+ privateBlock = 0;
+ namespaceBlock = 0;
+ pubConstructorBlock = 0;
+ protConstructorBlock = 0;
+ privConstructorBlock = 0;
+ pubOperationsBlock = 0;
+ privOperationsBlock = 0;
+ protOperationsBlock = 0;
+
+ // now do the traditional release of child text blocks
+ ClassifierCodeDocument::resetTextBlocks();
+
+}
+
+/**
+ * @param op
+ */
+// in the vannilla version, we just tack all operations on the end
+// of the document
+bool CPPHeaderCodeDocument::addCodeOperation (CodeOperation * op )
+{
+ Uml::Visibility scope = op->getParentOperation()->getVisibility();
+ if(!op->getParentOperation()->isLifeOperation())
+ {
+ switch (scope) {
+ default:
+ case Uml::Visibility::Public:
+ return pubOperationsBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Protected:
+ return protOperationsBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Private:
+ return privOperationsBlock->addTextBlock(op);
+ break;
+ }
+ } else {
+ switch (scope) {
+ default:
+ case Uml::Visibility::Public:
+ return pubConstructorBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Protected:
+ return protConstructorBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Private:
+ return privConstructorBlock->addTextBlock(op);
+ break;
+ }
+ }
+}
+
+
+/**
+ * Save the XMI representation of this object
+ * @return bool status of save
+ */
+/*
+void CPPHeaderCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root )
+{
+ QDomElement docElement = doc.createElement( "" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+*/
+
+// This method will cause the class to rebuild its text representation.
+// based on the parent classifier object.
+// For any situation in which this is called, we are either building the code
+// document up, or replacing/regenerating the existing auto-generated parts. As
+// such, we will want to insert everything we resonablely will want
+// during creation. We can set various parts of the document (esp. the
+// comments) to appear or not, as needed.
+void CPPHeaderCodeDocument::updateContent( )
+{
+ // Gather info on the various fields and parent objects of this class...
+ UMLClassifier * c = getParentClassifier();
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+
+ // first, set the global flag on whether or not to show classfield info
+ CodeClassFieldList * cfList = getCodeClassFieldList();
+ for(CodeClassField * field = cfList->first(); field; field = cfList->next())
+ field->setWriteOutMethods(policy->getAutoGenerateAccessors());
+
+ // attribute-based ClassFields
+ // we do it this way to have the static fields sorted out from regular ones
+ CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public );
+ CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public );
+ CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected );
+ CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected );
+ CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private );
+ CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private);
+
+ // association-based ClassFields
+ // don't care if they are static or not..all are lumped together
+ CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Public);
+ CodeClassFieldList publicAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Public);
+ CodeClassFieldList publicCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Public );
+
+ CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Protected);
+ CodeClassFieldList protAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Protected);
+ CodeClassFieldList protCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Protected);
+
+ CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Private);
+ CodeClassFieldList privAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Private);
+ CodeClassFieldList privCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Private);
+
+ bool hasOperationMethods = c->getOpList().last() ? true : false;
+ bool hasNamespace = false;
+ bool isEnumeration = false;
+ bool isInterface = parentIsInterface();
+ bool hasclassFields = hasClassFields();
+ bool forcedoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ UMLClassifierList superclasses = c->findSuperClassConcepts();
+
+
+ // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
+ //
+
+ // Write the hash define stuff to prevent multiple parsing/inclusion of header
+ QString cppClassName = CodeGenerator::cleanName(c->getName());
+ QString hashDefine = CodeGenerator::cleanName(c->getName().upper().simplifyWhiteSpace());
+ QString defText = "#ifndef "+hashDefine + "_H"+ endLine + "#define "+ hashDefine + "_H";
+ addOrUpdateTaggedCodeBlockWithComments("hashDefBlock", defText, "", 0, false);
+
+ // INCLUDE CODEBLOCK
+ //
+ // Q: Why all utils? Isnt just List and Vector the only classes we are using?
+ // A: doesn't matter at all; its more readable to just include '*' and cpp compilers
+ // don't slow down or anything. (TZ)
+ QString includeStatement = "";
+ bool stringGlobal = policy->stringIncludeIsGlobal();
+ QString sStartBrak = stringGlobal ? "<" : "\"";
+ QString sEndBrak = stringGlobal ? ">" : "\"";
+ includeStatement.append("#include "+sStartBrak+policy->getStringClassNameInclude()+sEndBrak+endLine);
+ if ( hasObjectVectorClassFields() )
+ {
+ bool vecGlobal = policy->vectorIncludeIsGlobal();
+ QString vStartBrak = vecGlobal ? "<" : "\"";
+ QString vEndBrak = vecGlobal ? ">" : "\"";
+ QString value ="#include "+vStartBrak+policy->getVectorClassNameInclude()+vEndBrak;
+ includeStatement.append(value+endLine);
+ }
+
+ //only include classes in a different package from this class
+ UMLPackageList includes;
+ QMap<UMLPackage *,QString> packageMap; // so we don't repeat packages
+
+ CodeGenerator::findObjectsRelated(c,includes);
+ for(UMLPackage *con = includes.first(); con ; con = includes.next())
+ if (con->getBaseType() != Uml::ot_Datatype && !packageMap.contains(con))
+ {
+ packageMap.insert(con,con->getPackage());
+ if(con != getParentClassifier())
+ includeStatement.append("#include \""+CodeGenerator::cleanName(con->getName().lower())+".h\""+endLine);
+ }
+ // now, add/update the includes codeblock
+ CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString::null, 0, false);
+ if(includeStatement.isEmpty() && inclBlock->getContentType() == CodeBlock::AutoGenerated)
+ inclBlock->setWriteOutText(false);
+ else
+ inclBlock->setWriteOutText(true);
+
+ // Using
+ QString usingStatement;
+ for(UMLClassifier *classifier = superclasses.first(); classifier ; classifier = superclasses.next()) {
+ if(classifier->getPackage()!=c->getPackage() && !classifier->getPackage().isEmpty()) {
+ usingStatement.append("using "+CodeGenerator::cleanName(c->getPackage())+"::"+cleanName(c->getName())+';'+endLine);
+ }
+ }
+ CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments("using", usingStatement, "", 0, false);
+ if(usingStatement.isEmpty() && usingBlock->getContentType() == CodeBlock::AutoGenerated)
+ usingBlock->setWriteOutText(false);
+ else
+ usingBlock->setWriteOutText(true);
+
+ // namespace
+ // This needs special treatment. We cant use "nowriteouttext" for this, as
+ // that will prevent the class declaration from being written. Instead, we
+ // check if "hasNamspace" is true or not, and then indent the remaining code
+ // appropriately as well as set the start/end text of this namespace block.
+ if (c->getUMLPackage() && policy->getPackageIsNamespace())
+ hasNamespace = true;
+ else
+ hasNamespace = false;
+
+ // set start/end text of namespace block
+ namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0);
+ if(hasNamespace) {
+ UMLPackageList pkgList = c->getPackages();
+ QString pkgs;
+ UMLPackage *pkg;
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ pkgs += "namespace " + CodeGenerator::cleanName(pkg->getName()) + " { ";
+ }
+ namespaceBlock->setStartText(pkgs);
+ QString closingBraces;
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ closingBraces += "} ";
+ }
+ namespaceBlock->setEndText(closingBraces);
+ namespaceBlock->getComment()->setWriteOutText(true);
+ } else {
+ namespaceBlock->setStartText("");
+ namespaceBlock->setEndText("");
+ namespaceBlock->getComment()->setWriteOutText(false);
+ }
+
+ // Enum types for include
+ if (!isInterface) {
+ QString enumStatement;
+ QString indent = UMLApp::app()->getCommonPolicy()->getIndentation();
+ UMLEnum* e = dynamic_cast<UMLEnum*>(c);
+ if (e) {
+ enumStatement.append(indent + "enum " + cppClassName + " {" + endLine);
+
+ // populate
+ UMLClassifierListItemList ell = e->getFilteredList(Uml::ot_EnumLiteral);
+ for (UMLClassifierListItem *el=ell.first(); el ; ) {
+ enumStatement.append(indent+indent);
+ enumStatement.append(CodeGenerator::cleanName(el->getName()));
+ if ((el=ell.next()) != 0)
+ enumStatement.append(", "+endLine);
+ else
+ break;
+ enumStatement.append(endLine);
+ }
+ enumStatement.append(indent+"};");
+ isEnumeration = true;
+ }
+ namespaceBlock->addOrUpdateTaggedCodeBlockWithComments("enums", enumStatement, "", 0, false);
+ }
+
+ // CLASS DECLARATION BLOCK
+ //
+
+ // add the class declaration block to the namespace block.
+ CPPHeaderClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
+ namespaceBlock->addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
+
+ // Is this really true?? hmm..
+ if(isEnumeration)
+ myClassDeclCodeBlock->setWriteOutText(false); // not written out IF its an enumeration class
+ else
+ myClassDeclCodeBlock->setWriteOutText(true);
+
+ //
+ // Main Sub-Blocks
+ //
+
+ // declare public, protected and private methods, attributes (fields).
+ // set the start text ONLY if this is the first time we created the objects.
+ bool createdPublicBlock = publicBlock == 0 ? true : false;
+ publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("publicBlock","Public stuff",0);
+ if (createdPublicBlock)
+ publicBlock->setStartText("public:");
+
+ bool createdProtBlock = protectedBlock == 0 ? true : false;
+ protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("protectedBlock","Protected stuff",0);
+ if(createdProtBlock)
+ protectedBlock->setStartText("protected:");
+
+ bool createdPrivBlock = privateBlock == 0 ? true : false;
+ privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("privateBlock","Private stuff",0);
+ if(createdPrivBlock)
+ privateBlock->setStartText("private:");
+
+ //
+ // * CLASS FIELD declaration section
+ //
+
+ // setup/get/create the field declaration code block
+ //
+
+ // public fields: Update the comment: we only set comment to appear under the following conditions
+ HierarchicalCodeBlock * publicFieldDeclBlock = publicBlock->getHierarchicalCodeBlock("publicFieldsDecl", "Fields", 1);
+ CodeComment * pubFcomment = publicFieldDeclBlock->getComment();
+ if (!forcedoc && !hasclassFields )
+ pubFcomment->setWriteOutText(false);
+ else
+ pubFcomment->setWriteOutText(true);
+
+ // protected fields: Update the comment: we only set comment to appear under the following conditions
+ HierarchicalCodeBlock * protectedFieldDeclBlock = protectedBlock->getHierarchicalCodeBlock("protectedFieldsDecl", "Fields", 1);
+ CodeComment * protFcomment = protectedFieldDeclBlock->getComment();
+ if (!forcedoc && !hasclassFields )
+ protFcomment->setWriteOutText(false);
+ else
+ protFcomment->setWriteOutText(true);
+
+ // private fields: Update the comment: we only set comment to appear under the following conditions
+ HierarchicalCodeBlock * privateFieldDeclBlock = privateBlock->getHierarchicalCodeBlock("privateFieldsDecl", "Fields", 1);
+ CodeComment * privFcomment = privateFieldDeclBlock->getComment();
+ if (!forcedoc && !hasclassFields )
+ privFcomment->setWriteOutText(false);
+ else
+ privFcomment->setWriteOutText(true);
+
+
+ // now actually declare the fields within the appropriate HCodeBlock
+ //
+
+ // public
+ declareClassFields(staticPublicAttribClassFields, publicFieldDeclBlock);
+ declareClassFields(publicAttribClassFields, publicFieldDeclBlock);
+ declareClassFields(publicPlainAssocClassFields, publicFieldDeclBlock);
+ declareClassFields(publicAggregationClassFields, publicFieldDeclBlock);
+ declareClassFields(publicCompositionClassFields, publicFieldDeclBlock);
+
+ // protected
+ declareClassFields(staticProtectedAttribClassFields, protectedFieldDeclBlock);
+ declareClassFields(protectedAttribClassFields, protectedFieldDeclBlock);
+ declareClassFields(protPlainAssocClassFields, protectedFieldDeclBlock);
+ declareClassFields(protAggregationClassFields, protectedFieldDeclBlock);
+ declareClassFields(protCompositionClassFields, protectedFieldDeclBlock);
+
+ // private
+ declareClassFields(staticPrivateAttribClassFields, privateFieldDeclBlock);
+ declareClassFields(privateAttribClassFields, privateFieldDeclBlock);
+ declareClassFields(privPlainAssocClassFields, privateFieldDeclBlock);
+ declareClassFields(privAggregationClassFields, privateFieldDeclBlock);
+ declareClassFields(privCompositionClassFields, privateFieldDeclBlock);
+
+ //
+ // METHODS section
+ //
+
+ // get/create the method codeblock
+
+ // public methods
+ HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock("pubMethodsBlock", "", 1);
+ CodeComment * pubMethodsComment = pubMethodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forcedoc && !hasclassFields && !hasOperationMethods)
+ pubMethodsComment->setWriteOutText(false);
+ else
+ pubMethodsComment->setWriteOutText(true);
+
+ // protected methods
+ HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock("protMethodsBlock", "", 1);
+ CodeComment * protMethodsComment = protMethodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forcedoc && !hasclassFields && !hasOperationMethods)
+ protMethodsComment->setWriteOutText(false);
+ else
+ protMethodsComment->setWriteOutText(true);
+
+ // private methods
+ HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock("privMethodsBlock", "", 1);
+ CodeComment * privMethodsComment = privMethodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forcedoc && !hasclassFields && !hasOperationMethods)
+ privMethodsComment->setWriteOutText(false);
+ else
+ privMethodsComment->setWriteOutText(true);
+
+
+ // METHODS sub-section : constructor methods
+ //
+ CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
+
+ // setup/get/create the constructor codeblocks
+
+ // public
+ pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * pubConstComment = pubConstructorBlock->getComment();
+ if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ pubConstComment->setWriteOutText(false);
+ else
+ pubConstComment->setWriteOutText(true);
+
+ // protected
+ protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * protConstComment = protConstructorBlock->getComment();
+ if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ protConstComment->setWriteOutText(false);
+ else
+ protConstComment->setWriteOutText(true);
+
+ // private
+ privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * privConstComment = privConstructorBlock->getComment();
+ if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ privConstComment->setWriteOutText(false);
+ else
+ privConstComment->setWriteOutText(true);
+
+ // add/get the empty constructor. I guess since there is no
+ // meta-data to state what the scope of this method is, we will make it
+ // "public" as a default. This might present problems if the user wants
+ // to move the block into the "private" or "protected" blocks.
+ QString emptyConstStatement = cppClassName + " ( ) { }";
+
+ // search for this first in the entire document. IF not present, put
+ // it in the public constructor method block
+ TextBlock * emptyConstTb = findTextBlockByTag("emptyconstructor", true);
+ CodeBlockWithComments * emptyConstBlock = dynamic_cast<CodeBlockWithComments*>(emptyConstTb);
+ if(!emptyConstBlock)
+ emptyConstBlock = pubConstructorBlock->addOrUpdateTaggedCodeBlockWithComments("emptyconstructor", emptyConstStatement, "Empty Constructor", 1, false);
+
+ // Now, as an additional condition we only show the empty constructor block
+ // IF it was desired to be shown
+ if(!isInterface && pol->getAutoGenerateConstructors())
+ emptyConstBlock->setWriteOutText(true);
+ else
+ emptyConstBlock->setWriteOutText(false);
+
+
+ // METHODS subsection : ACCESSOR METHODS
+ //
+
+ // get/create the accessor codeblock
+
+ // public
+ HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * pubAccessComment = pubAccessorBlock->getComment();
+ if (!forcedoc && !hasclassFields)
+ pubAccessComment->setWriteOutText(false);
+ else
+ pubAccessComment->setWriteOutText(true);
+
+ // protected
+ HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * protAccessComment = protAccessorBlock->getComment();
+ if (!forcedoc && !hasclassFields)
+ protAccessComment->setWriteOutText(false);
+ else
+ protAccessComment->setWriteOutText(true);
+
+ // private
+ HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * privAccessComment = privAccessorBlock->getComment();
+ // We've to copy the private accessorMethods to the public block
+ if (!forcedoc && !hasclassFields)
+ privAccessComment->setWriteOutText(false);
+ else
+ privAccessComment->setWriteOutText(true);
+
+ // now, 2 sub-sub sections in accessor block
+ // add/update accessor methods for attributes
+ HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubRegularAccessorMethods", "", 1);
+ pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+
+ HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock("protStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock("protRegularAccessorMethods", "", 1);
+ protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+
+ HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock("privStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock("privRegularAccessorMethods", "", 1);
+ privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+
+ // now add in accessors as appropriate
+
+ // public stuff
+ pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields);
+
+ // generate accessors as public
+ if (policy && policy->getAccessorsArePublic())
+ {
+ pubRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
+ }
+
+ pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields);
+
+ // protected stuff
+ protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields);
+
+ // accessors are public so we don't have to create it here
+ if (policy && !policy->getAccessorsArePublic())
+ protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
+
+ protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields);
+
+ // private stuff
+ privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields);
+
+ // accessors are public so we don't have to create it here
+ if (policy && !policy->getAccessorsArePublic())
+ privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
+
+ privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields);
+
+
+ // METHODS subsection : Operation methods (e.g. methods derive from operations but which arent constructors)
+ //
+
+ // setup/get/create the operations codeblock
+
+ // public
+ pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * pubOcomment = pubOperationsBlock->getComment();
+ if (!forcedoc && !hasOperationMethods )
+ pubOcomment->setWriteOutText(false);
+ else
+ pubOcomment->setWriteOutText(true);
+
+ //protected
+ protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * protOcomment = protOperationsBlock->getComment();
+ if (!forcedoc && !hasOperationMethods )
+ protOcomment->setWriteOutText(false);
+ else
+ protOcomment->setWriteOutText(true);
+
+ //private
+ privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * privOcomment = privOperationsBlock->getComment();
+ if (!forcedoc && !hasOperationMethods )
+ privOcomment->setWriteOutText(false);
+ else
+ privOcomment->setWriteOutText(true);
+
+ // Operations
+ //
+ // nothing to do here.. "updateOperations" in parent class puts things
+ // in the right place using the "addCodeOperation" method we defined in this class
+
+ // FINISH up with hash def block close
+ QString defTextEnd = "#endif //"+hashDefine + "_H";
+ addOrUpdateTaggedCodeBlockWithComments("hashDefBlockEnd", defTextEnd, "", 0, false);
+
+}
+
+
+#include "cppheadercodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/cppheadercodedocument.h b/umbrello/umbrello/codegenerators/cppheadercodedocument.h
new file mode 100644
index 00000000..ca75627f
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodedocument.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Aug 28 2003
+ */
+
+#ifndef CPPHEADERCODEDOCUMENT_H
+#define CPPHEADERCODEDOCUMENT_H
+
+#include <qstring.h>
+
+#include "../codeclassfieldlist.h"
+#include "../classifiercodedocument.h"
+#include "../hierarchicalcodeblock.h"
+#include "classifierinfo.h"
+
+class CPPHeaderClassDeclarationBlock;
+
+/**
+ * class CPPHeaderCodeDocument
+ * A CPP UMLClassifier Header Code Document.
+ */
+
+class CPPHeaderCodeDocument : public ClassifierCodeDocument
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPHeaderCodeDocument (UMLClassifier * classifier);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPHeaderCodeDocument ( );
+
+ /** add a code operation to this cpp classifier code document.
+ * @return bool which is true IF the code operation was added successfully
+ */
+ bool addCodeOperation (CodeOperation * op );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ //virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+protected:
+
+ // reset/clear our inventory of textblocks in this document
+ void resetTextBlocks();
+
+ /**
+ * need to overwrite this for cpp header since we need to pick up the
+ * header class declaration block.
+ */
+ virtual void loadChildTextBlocksFromNode ( QDomElement & root);
+
+ void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, CPPHeaderClassDeclarationBlock * codeBlock);
+
+ /**
+ * create a new code comment. IN this case it is a CPPCodeDocumentation object.
+ */
+ CodeComment * newCodeComment ( );
+
+ void updateContent();
+
+private:
+
+ CPPHeaderClassDeclarationBlock * classDeclCodeBlock;
+
+ HierarchicalCodeBlock * publicBlock;
+ HierarchicalCodeBlock * privateBlock;
+ HierarchicalCodeBlock * protectedBlock;
+
+ HierarchicalCodeBlock * namespaceBlock;
+
+ HierarchicalCodeBlock * pubConstructorBlock;
+ HierarchicalCodeBlock * protConstructorBlock;
+ HierarchicalCodeBlock * privConstructorBlock;
+
+ HierarchicalCodeBlock * pubOperationsBlock;
+ HierarchicalCodeBlock * privOperationsBlock;
+ HierarchicalCodeBlock * protOperationsBlock;
+
+ /**
+ *
+ */
+ CPPHeaderClassDeclarationBlock * getClassDecl();
+
+};
+
+#endif // CPPHEADERCODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp b/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp
new file mode 100644
index 00000000..ca8ad727
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#include "cppheadercodeoperation.h"
+
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppheadercodedocument.h"
+#include "cppcodedocumentation.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPHeaderCodeOperation::CPPHeaderCodeOperation
+ ( CPPHeaderCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment )
+ : CodeOperation (doc, parent, body, comment)
+{
+ // lets not go with the default comment and instead use
+ // full-blown cpp documentation object instead
+ setComment(new CPPCodeDocumentation(doc));
+
+ // these things never change..
+ setOverallIndentationLevel(1);
+
+ setText("");
+ setStartMethodText("");
+ setEndMethodText("");
+
+ updateMethodDeclaration();
+ updateContent();
+
+}
+
+CPPHeaderCodeOperation::~CPPHeaderCodeOperation ( ) { }
+
+// Other methods
+//
+
+// we basically just want to know whether or not to print out
+// the body of the operation.
+// In C++ if the operations are inline, then we DO print out
+// the body text.
+void CPPHeaderCodeOperation::updateContent( )
+{
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ bool isInlineMethod = policy->getOperationsAreInline( );
+
+ if(isInlineMethod)
+ setText(""); // change whatever it is to "";
+}
+
+// we basically want to update the doc and start text of this method
+void CPPHeaderCodeOperation::updateMethodDeclaration()
+{
+ ClassifierCodeDocument *ccd = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ bool isInterface = ccd->parentIsInterface();
+ UMLOperation * o = getParentOperation();
+
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ bool isInlineMethod = policy->getOperationsAreInline( );
+
+ QString endLine = getNewLineEndingChars();
+
+ // first, the comment on the operation, IF its autogenerated/empty
+ QString comment = o->getDoc();
+ if(comment.isEmpty() && getContentType() == CodeBlock::AutoGenerated)
+ {
+ UMLAttributeList parameters = o->getParmList();
+ for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
+ comment += endLine + "@param " + iterator.current()->getName() + ' ';
+ comment += iterator.current()->getDoc();
+ }
+ getComment()->setText(comment);
+ }
+
+ // no return type for constructors
+ QString methodReturnType = o->getTypeName();
+ QString methodName = o->getName();
+ QString paramStr = QString("");
+
+ // assemble parameters
+ UMLAttributeList list = getParentOperation()->getParmList();
+ int nrofParam = list.count();
+ int paramNum = 0;
+ for(UMLAttribute* parm = list.first(); parm; parm=list.next())
+ {
+ QString rType = parm->getTypeName();
+ QString paramName = parm->getName();
+ QString initialValue = parm->getInitialValue();
+ paramStr += rType + ' ' + paramName;
+ if(!initialValue.isEmpty())
+ paramStr += '=' + initialValue;
+
+ paramNum++;
+
+ if (paramNum != nrofParam )
+ paramStr += ", ";
+ }
+
+ // if an operation isn't a constructor or a destructor and it has no return type
+ if (o->isLifeOperation()) // constructor/destructor has no type
+ methodReturnType = "";
+ else if (methodReturnType.isEmpty()) // this operation should be 'void'
+ methodReturnType = QString("void");
+
+ // set start/end method text
+ QString prototype = methodReturnType+' '+methodName+" ("+paramStr+')';
+
+ QString startText;
+ QString endText;
+
+ applyStereotypes (prototype, o, isInlineMethod, isInterface, startText, endText);
+
+ setStartMethodText(prototype+startText);
+ setEndMethodText(endText);
+}
+
+int CPPHeaderCodeOperation::lastEditableLine() {
+ ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ UMLOperation * o = getParentOperation();
+ if(doc->parentIsInterface() || o->getAbstract())
+ return -1; // very last line is NOT editable as its a one-line declaration w/ no body in
+ // an interface.
+ return 0;
+}
+
+void CPPHeaderCodeOperation::applyStereotypes (QString& prototype, UMLOperation * pOp,
+ bool inlinePolicy, bool interface,
+ QString& start, QString& end)
+{
+ // if the class is an interface, all methods will be declared as pure
+ // virtual functions
+ start = (inlinePolicy ? " {" : ";");
+ end = (inlinePolicy ? "}" : "");
+ if (pOp->getConst())
+ prototype += " const";
+ if (interface || pOp->getAbstract()) {
+ // constructor can't be virtual or abstract
+ if (!pOp->isLifeOperation()) {
+ prototype = "virtual " + prototype + " = 0";
+ if (inlinePolicy) {
+ start = ";";
+ end = "";
+ }
+ }
+ } // constructors could not be declared as static
+ else if (pOp->getStatic() && !pOp->isLifeOperation()) {
+ prototype = "static " + prototype;
+ }
+ // apply the stereotypes
+ if (!pOp->getStereotype().isEmpty()) {
+ if ((pOp->getStereotype() == "friend") || (pOp->getStereotype(false) == "virtual")) {
+ if (!pOp->isLifeOperation() && !(interface || pOp->getAbstract()) && !pOp->getStatic())
+ prototype = pOp->getStereotype() + ' ' + prototype;
+ }
+ }
+}
+
+#include "cppheadercodeoperation.moc"
diff --git a/umbrello/umbrello/codegenerators/cppheadercodeoperation.h b/umbrello/umbrello/codegenerators/cppheadercodeoperation.h
new file mode 100644
index 00000000..1d4fbca7
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppheadercodeoperation.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+
+#ifndef CPPHEADERCODEOPERATION_H
+#define CPPHEADERCODEOPERATION_H
+
+#include <qstring.h>
+#include "../codeoperation.h"
+
+class CPPHeaderCodeDocument;
+
+class CPPHeaderCodeOperation : virtual public CodeOperation
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPHeaderCodeOperation ( CPPHeaderCodeDocument * doc, UMLOperation * op,
+ const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPHeaderCodeOperation ( );
+
+ virtual int lastEditableLine();
+
+protected:
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent( );
+
+ /**
+ * Check to see if we have a valid stereotype to apply in the operation
+ */
+ virtual void applyStereotypes (QString&, UMLOperation *, bool, bool, QString&, QString&);
+
+};
+
+#endif // CPPHEADERCODEOPERATION_H
diff --git a/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp b/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp
new file mode 100644
index 00000000..d13152b4
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp
@@ -0,0 +1,78 @@
+
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jun 24 2003
+ */
+
+#include "cppcodegenerator.h"
+
+#include <qregexp.h>
+
+const char * CPPMakefileCodeDocument::DOCUMENT_ID_VALUE = "Makefile_DOC";
+
+// Constructors/Destructors
+//
+
+CPPMakefileCodeDocument::CPPMakefileCodeDocument ( )
+{
+ setFileName("Makefile"); // default name
+ setFileExtension("");
+ setID(DOCUMENT_ID_VALUE); // default id tag for this type of document
+}
+
+CPPMakefileCodeDocument::~CPPMakefileCodeDocument ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+// we add in our code blocks that describe how to generate
+// the project here...
+void CPPMakefileCodeDocument::updateContent( ) {
+ // FIX : fill in content
+}
+
+/**
+ * @return QString
+ */
+QString CPPMakefileCodeDocument::toString ( ) {
+ return "# cpp make build document";
+}
+
+// We overwritten by CPP language implementation to get lowercase path
+QString CPPMakefileCodeDocument::getPath ( )
+{
+
+ QString path = getPackage();
+
+ // Replace all white spaces with blanks
+ path.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ path.replace(QRegExp(" "), "_");
+
+ path.replace(QRegExp("\\."),"/");
+ path.replace(QRegExp("::"),"/");
+
+ path.lower();
+
+ return path;
+
+}
+
+
+#include "cppmakecodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/cppmakecodedocument.h b/umbrello/umbrello/codegenerators/cppmakecodedocument.h
new file mode 100644
index 00000000..98efe272
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppmakecodedocument.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jun 24 2003
+ */
+
+
+
+#ifndef CPPMAKECODEDOCUMENT_H
+#define CPPMAKECODEDOCUMENT_H
+
+#include "../codedocument.h"
+#include <qstring.h>
+
+/**
+ * class CPPMakefileCodeDocument
+ * Represents
+ */
+
+class CPPMakefileCodeDocument : public CodeDocument
+{
+ Q_OBJECT
+public:
+
+ static const char * DOCUMENT_ID_VALUE;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPMakefileCodeDocument ( );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPMakefileCodeDocument ( );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+ QString getPath ( );
+
+ void updateContent();
+
+protected:
+
+private:
+
+
+
+};
+
+#endif // CPPMAKECODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp
new file mode 100644
index 00000000..da2a86cb
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Aug 31 2003
+ */
+
+// own header
+#include "cppsourcecodeaccessormethod.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "../attribute.h"
+#include "../classifiercodedocument.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppcodeclassfield.h"
+#include "cppcodedocumentation.h"
+
+// Constructors/Destructors
+//
+
+CPPSourceCodeAccessorMethod::CPPSourceCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type)
+ : CodeAccessorMethod ( field )
+{
+ setType(type);
+ setEndMethodText("}");
+}
+
+void CPPSourceCodeAccessorMethod::update()
+{
+ updateMethodDeclaration();
+ updateContent();
+}
+
+CPPSourceCodeAccessorMethod::~CPPSourceCodeAccessorMethod ( ) { }
+
+// Other
+//
+
+// we basically want to update the body of this method
+void CPPSourceCodeAccessorMethod::updateContent( )
+{
+ CodeClassField * parentField = getParentClassField();
+ CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField);
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ bool isInlineMethod = policy->getAccessorsAreInline( );
+
+ QString variableName = cppfield->getFieldName();
+ QString itemClassName = cppfield->getTypeName();
+ QString text;
+
+ if(isInlineMethod) {
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ text = policy->getVectorMethodAppend(variableName, itemClassName);
+ break;
+ case CodeAccessorMethod::REMOVE:
+ text = policy->getVectorMethodRemove(variableName, itemClassName);
+ break;
+ case CodeAccessorMethod::SET:
+ text = variableName+" = value;";
+ break;
+ case CodeAccessorMethod::LIST:
+ case CodeAccessorMethod::GET:
+ default:
+ text = "return "+variableName+';';
+ break;
+ }
+ }
+
+ setText(text);
+}
+
+// we basically want to update the start text of this method
+void CPPSourceCodeAccessorMethod::updateMethodDeclaration()
+{
+
+ CodeClassField * parentField = getParentClassField();
+ ClassifierCodeDocument * doc = parentField->getParentDocument();
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField);
+ UMLClassifier * c = doc->getParentClassifier();
+
+ bool isInlineMethod = policy->getAccessorsAreInline( );
+
+ QString vectorClassName = policy->getVectorClassName();
+ QString fieldName = cppfield->getFieldName();
+ QString fieldType = cppfield->getTypeName();
+ QString objectType = cppfield->getListObjectType();
+ if(objectType.isEmpty())
+ objectType = fieldName;
+
+ QString methodReturnType = "void";
+ QString methodName;
+ QString methodParams;
+ QString headerText;
+ QString className = CodeGenerator::cleanName(c->getName());
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ methodName = "add_"+fieldType;
+ methodReturnType = "void";
+ methodParams = objectType+" value ";
+ headerText = "Add a "+fieldName+" object to the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void";
+ break;
+ case CodeAccessorMethod::REMOVE:
+ methodName = "remove_"+fieldType;
+ methodParams = objectType+" value ";
+ methodReturnType = "void";
+ headerText = "Remove a "+fieldName+" object from the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void";
+ break;
+ case CodeAccessorMethod::LIST:
+ methodName = "get_"+fieldType+"_list";
+ methodReturnType = vectorClassName;
+ headerText = "Get the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return "+vectorClassName+"with list of objects";
+ break;
+ case CodeAccessorMethod::SET:
+ methodName = "set_"+fieldName;
+ methodParams = fieldType+" value ";
+ methodReturnType = "void";
+ headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@param value the value of "+fieldName;
+ break;
+ case CodeAccessorMethod::GET:
+ default:
+ methodName = "get_"+fieldName;
+ methodReturnType = fieldType;
+ headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName;
+ break;
+ }
+
+ // set header
+ CPPCodeDocumentation * header = new CPPCodeDocumentation(doc);
+ if(!getParentObject()->getDoc().isEmpty())
+ header->setText(headerText);
+ setComment(header);
+
+ // set start method text (EndText never changes)
+ setStartMethodText(methodReturnType+' '+className+"::"+methodName+" ("+methodParams+')' + " {");
+
+ setOverallIndentationLevel(0);
+
+ // these ONLY appear if they arent inline
+ if(isInlineMethod)
+ setWriteOutText(false);
+
+}
+
+
+
+#include "cppsourcecodeaccessormethod.moc"
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h
new file mode 100644
index 00000000..60d9c369
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h
@@ -0,0 +1,57 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+#ifndef CPPSOURCECODEACCESSORMETHOD_H
+#define CPPSOURCECODEACCESSORMETHOD_H
+
+#include <qstring.h>
+
+#include "../codeaccessormethod.h"
+
+class CodeClassField;
+
+class CPPSourceCodeAccessorMethod : public CodeAccessorMethod
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ CPPSourceCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPSourceCodeAccessorMethod ( );
+
+ /**
+ * Must be called before this object is usable
+ */
+ void update();
+
+protected:
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent();
+
+private:
+
+};
+
+#endif // CPPSOURCECODEACCESSORMETHOD_H
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp
new file mode 100644
index 00000000..7d60b1c3
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#include "cppsourcecodeclassfielddeclarationblock.h"
+
+#include "cppcodeclassfield.h"
+#include "../model_utils.h"
+
+// Constructors/Destructors
+//
+
+CPPSourceCodeClassFieldDeclarationBlock::CPPSourceCodeClassFieldDeclarationBlock ( CodeClassField * parent )
+ : CodeClassFieldDeclarationBlock ( parent )
+{
+ setOverallIndentationLevel(1);
+ updateContent();
+}
+
+CPPSourceCodeClassFieldDeclarationBlock::~CPPSourceCodeClassFieldDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+/**
+ */
+void CPPSourceCodeClassFieldDeclarationBlock::updateContent( )
+{
+
+ /*
+ CodeClassField * cf = getParentClassField();
+ ClassifierCodeDocument * doc = cf->getParentDocument();
+ CPPCodeClassField * jcf = dynamic_cast<CPPCodeClassField*>(cf);
+ CPPClassifierCodeDocument* jdoc = dynamic_cast<CPPClassifierCodeDocument*>(doc);
+
+ // Set the comment
+ QString notes = getParentObject()->getDoc();
+ getComment()->setText(notes);
+
+ // Set the body
+ QString staticValue = getParentObject()->getStatic() ? "static " : "";
+ QString scopeStr = getParentObject()->getVisibility().toString();
+
+ QString typeName = jcf->getTypeName();
+ QString fieldName = jcf->getFieldName();
+ QString initialV = jcf->getInitialValue();
+
+ QString body = staticValue+scopeStr+" "+typeName+" "+fieldName;
+ if (!initialV.isEmpty())
+ body.append(" = " + initialV);
+ setText(body+";");
+ */
+ setText("FIX ME;");
+
+
+}
+
+
+
+#include "cppsourcecodeclassfielddeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h
new file mode 100644
index 00000000..e5b908a0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h
@@ -0,0 +1,51 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#ifndef CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H
+#define CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "../codeclassfielddeclarationblock.h"
+
+class CPPSourceCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPSourceCodeClassFieldDeclarationBlock ( CodeClassField * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPSourceCodeClassFieldDeclarationBlock ( );
+
+protected:
+
+ // this will be called by syncToParent whenever the parent object is "modified"
+ void updateContent ( );
+
+private:
+
+
+};
+
+#endif // CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp b/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp
new file mode 100644
index 00000000..be054937
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Aug 28 2003
+ */
+
+/**
+ We carve the CPP document up into 2 documents, "source" and "header".
+ The sections of each are as follows:
+
+ * header
+ * includes
+ * constructor methods
+ * all other methods
+
+*/
+
+// own header
+#include "cppsourcecodedocument.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <qregexp.h>
+// app includes
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppcodedocumentation.h"
+#include "cppcodeclassfield.h"
+#include "cppsourcecodeclassfielddeclarationblock.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPSourceCodeDocument::CPPSourceCodeDocument ( UMLClassifier * concept )
+ : ClassifierCodeDocument (concept) {
+ init ( );
+}
+
+CPPSourceCodeDocument::~CPPSourceCodeDocument ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+QString CPPSourceCodeDocument::getCPPClassName (const QString &name) {
+ return CodeGenerator::cleanName(name);
+}
+
+// Initialize this cpp classifier code document
+void CPPSourceCodeDocument::init ( ) {
+
+ setFileExtension(".cpp");
+
+ methodsBlock = 0;
+ constructorBlock = 0;
+
+ //initCodeClassFields(); // this is dubious because it calls down to
+ // CodeGenFactory::newCodeClassField(this)
+ // but "this" is still in construction at that time.
+
+ // this will call updateContent() as well as other things that sync our document.
+ //synchronize();
+}
+
+/**
+ * @param op
+ */
+// in the vannilla version, we just tack all operations on the end
+// of the document
+bool CPPSourceCodeDocument::addCodeOperation (CodeOperation * op ) {
+
+ if(!op->getParentOperation()->isLifeOperation())
+ {
+ return methodsBlock->addTextBlock(op);
+ } else
+ return constructorBlock->addTextBlock(op);
+}
+
+
+void CPPSourceCodeDocument::resetTextBlocks()
+{
+
+ // all special pointers need to be zero'd out.
+ methodsBlock = 0;
+ constructorBlock = 0;
+
+ // now do the traditional release of child text blocks
+ ClassifierCodeDocument::resetTextBlocks();
+
+}
+
+// This method will cause the class to rebuild its text representation.
+// based on the parent classifier object.
+// For any situation in which this is called, we are either building the code
+// document up, or replacing/regenerating the existing auto-generated parts. As
+// such, we will want to insert everything we reasonably will want
+// during creation. We can set various parts of the document (esp. the
+// comments) to appear or not, as needed.
+void CPPSourceCodeDocument::updateContent( )
+{
+
+ // Gather info on the various fields and parent objects of this class...
+ //UMLClassifier * c = getParentClassifier();
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ // first, set the global flag on whether or not to show classfield info
+ CodeClassFieldList * cfList = getCodeClassFieldList();
+ for(CodeClassField * field = cfList->first(); field; field = cfList->next())
+ field->setWriteOutMethods(policy->getAutoGenerateAccessors());
+
+ // attribute-based ClassFields
+ // we do it this way to have the static fields sorted out from regular ones
+ CodeClassFieldList staticAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true);
+ CodeClassFieldList attribClassFields = getSpecificClassFields (CodeClassField::Attribute, false);
+ // association-based ClassFields
+ // don't care if they are static or not..all are lumped together
+ CodeClassFieldList plainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation );
+ CodeClassFieldList aggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation );
+ CodeClassFieldList compositionClassFields = getSpecificClassFields ( CodeClassField::Composition );
+
+ // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
+ //
+
+ // INCLUDE CODEBLOCK
+ QString includeStatement = "";
+ // Include own header file
+ QString myOwnName( getParentClassifier()->getName() );
+ includeStatement.append("#include \""+CodeGenerator::cleanName(myOwnName.lower())+".h\""+endLine);
+ CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString::null, 0, false);
+ iblock->setWriteOutText(true);
+
+ // After the includes we have just 2 big blocks basically, the "constructor" block and the
+ // block for the rest of our methods (operations + accessors)
+
+ constructorBlock = getHierarchicalCodeBlock("constructionMethodsBlock", "Constructors/Destructors", 0);
+ methodsBlock = getHierarchicalCodeBlock("otherMethodsBlock", "Methods", 0);
+
+ // add accessors to the methods block
+ methodsBlock->addCodeClassFieldMethods(staticAttribClassFields);
+ methodsBlock->addCodeClassFieldMethods(attribClassFields);
+ methodsBlock->addCodeClassFieldMethods(plainAssocClassFields);
+ methodsBlock->addCodeClassFieldMethods(aggregationClassFields);
+ methodsBlock->addCodeClassFieldMethods(compositionClassFields);
+
+ // constructors and other operations are handled by the "addCodeOperation" method above.
+
+}
+
+
+#include "cppsourcecodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodedocument.h b/umbrello/umbrello/codegenerators/cppsourcecodedocument.h
new file mode 100644
index 00000000..8ca59c95
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodedocument.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Aug 28 2003
+ */
+
+#ifndef CPPSOURCECODEDOCUMENT_H
+#define CPPSOURCECODEDOCUMENT_H
+
+#include <qstring.h>
+
+#include "../classifiercodedocument.h"
+#include "../hierarchicalcodeblock.h"
+#include "classifierinfo.h"
+
+/**
+ * class CPPSourceCodeDocument
+ * A CPP UMLClassifier Source Code Document.
+ */
+
+class CPPSourceCodeDocument : public ClassifierCodeDocument
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CPPSourceCodeDocument (UMLClassifier * classifier);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPSourceCodeDocument ( );
+
+ /** add a code operation to this cpp classifier code document.
+ * @return bool which is true IF the code operation was added successfully
+ */
+ bool addCodeOperation (CodeOperation * op );
+
+protected:
+
+ // reset/clear our inventory of textblocks in this document
+ void resetTextBlocks();
+
+ // a little utility method to save us some work
+ QString getCPPClassName (const QString &name);
+
+ void updateContent();
+
+private:
+
+ HierarchicalCodeBlock * constructorBlock;
+ HierarchicalCodeBlock * methodsBlock;
+
+ void init ( );
+
+};
+
+#endif // CPPSOURCECODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp
new file mode 100644
index 00000000..0d8115b6
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+#include "cppsourcecodeoperation.h"
+
+#include "cppcodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "cppsourcecodedocument.h"
+#include "cppcodedocumentation.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+CPPSourceCodeOperation::CPPSourceCodeOperation ( CPPSourceCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment )
+ : CodeOperation (doc, parent, body, comment)
+{
+ // lets not go with the default comment and instead use
+ // full-blown cpp documentation object instead
+ setComment(new CPPCodeDocumentation(doc));
+
+ // these things never change..
+ setOverallIndentationLevel(0);
+ setEndMethodText("}");
+
+ //updateMethodDeclaration();
+ CodeGenPolicyExt * pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ UMLClassifier * c = doc->getParentClassifier();
+ UMLOperation * o = getParentOperation();
+ bool isInterface = doc->parentIsInterface();
+ bool isInlineMethod = policy->getOperationsAreInline( );
+
+ // first, the comment on the operation
+ QString cmnt = o->getDoc();
+ getComment()->setText(cmnt);
+
+ QString returnType = o->getTypeName();
+ QString methodName = o->getName();
+ QString paramStr = QString("");
+ QString className = CodeGenerator::cleanName(c->getName());
+
+ // assemble parameters
+ UMLAttributeList list = getParentOperation()->getParmList();
+ int nrofParam = list.count();
+ int paramNum = 0;
+ for(UMLAttribute* parm = list.first(); parm; parm=list.next())
+ {
+ QString rType = parm->getTypeName();
+ QString paramName = parm->getName();
+ paramStr += rType + ' ' + paramName;
+ paramNum++;
+
+ if (paramNum != nrofParam )
+ paramStr += ", ";
+ }
+
+ // no return type for constructors/destructors
+ if (o->isLifeOperation())
+ returnType = "";
+ // if an operation isn't a constructor/destructor and it has no return type
+ // this operation should be void
+ else if (returnType.isEmpty())
+ returnType = QString("void");
+
+ QString startText = returnType + ' ';
+
+ // if a property has a friend stereotype, the operation should
+ // not be a class name
+ if (o->getStereotype() != "friend")
+ startText += className + "::";
+ startText += methodName + " (" + paramStr + ')';
+ if (o->getConst())
+ startText += " const";
+ startText += " {";
+
+ setStartMethodText(startText);
+
+ // Only write this out if its a child of an interface OR is abstract.
+ // and its not inline
+ if(isInterface || o->getAbstract() || isInlineMethod)
+ {
+ setWriteOutText(false);
+ } else {
+ setWriteOutText(true);
+ }
+
+
+ updateContent();
+}
+
+CPPSourceCodeOperation::~CPPSourceCodeOperation ( ) { }
+
+// Other methods
+//
+
+// we basically just want to know whether or not to print out
+// the body of the operation.
+// In C++ if the operations are inline, then we DONT print out
+// the body text.
+void CPPSourceCodeOperation::updateContent( )
+{
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ bool isInlineMethod = policy->getOperationsAreInline();
+
+ if(!isInlineMethod)
+ setText(""); // change whatever it is to "";
+
+}
+
+// we basically want to update the doc and start text of this method
+void CPPSourceCodeOperation::updateMethodDeclaration()
+{
+
+ CPPSourceCodeDocument * doc = dynamic_cast<CPPSourceCodeDocument*>(getParentDocument());
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
+ UMLClassifier * c = doc->getParentClassifier();
+ UMLOperation * o = getParentOperation();
+ bool isInterface = doc->parentIsInterface();
+ bool isInlineMethod = policy->getOperationsAreInline( );
+
+ // first, the comment on the operation
+ QString comment = o->getDoc();
+ getComment()->setText(comment);
+
+ QString returnType = o->getTypeName();
+ QString methodName = o->getName();
+ QString paramStr = QString("");
+ QString className = CodeGenerator::cleanName(c->getName());
+
+ // assemble parameters
+ UMLAttributeList list = getParentOperation()->getParmList();
+ int nrofParam = list.count();
+ int paramNum = 0;
+ for(UMLAttribute* parm = list.first(); parm; parm=list.next())
+ {
+ QString rType = parm->getTypeName();
+ QString paramName = parm->getName();
+ paramStr += rType + ' ' + paramName;
+ paramNum++;
+
+ if (paramNum != nrofParam )
+ paramStr += ", ";
+ }
+
+ // no return type for constructors/destructors
+ if (o->isLifeOperation())
+ returnType = "";
+ // if an operation isn't a constructor/destructor and it has no return type
+ // this operation should be void
+ else if (returnType.isEmpty())
+ returnType = QString("void");
+
+ QString startText = returnType + ' ';
+
+ // if a property has a friend stereotype, the operation should
+ // not be a class name
+ if (o->getStereotype() != "friend")
+ startText += className + "::";
+ startText += methodName + " (" + paramStr + ')';
+ if (o->getConst())
+ startText += " const";
+ startText += " {";
+
+ setStartMethodText(startText);
+
+ // Only write this out if its a child of an interface OR is abstract.
+ // and its not inline
+ if(isInterface || o->getAbstract() || isInlineMethod)
+ {
+ setWriteOutText(false);
+ } else {
+ setWriteOutText(true);
+ }
+
+}
+
+#include "cppsourcecodeoperation.moc"
diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h
new file mode 100644
index 00000000..e2112178
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 1 2003
+ */
+
+
+#ifndef CPPSOURCECODEOPERATION_H
+#define CPPSOURCECODEOPERATION_H
+
+#include <qstring.h>
+#include "../codeoperation.h"
+
+class CPPSourceCodeDocument;
+
+class CPPSourceCodeOperation : virtual public CodeOperation
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ CPPSourceCodeOperation ( CPPSourceCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CPPSourceCodeOperation ( );
+
+protected:
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent( );
+
+};
+
+#endif // CPPSOURCECODEOPERATION_H
diff --git a/umbrello/umbrello/codegenerators/cppwriter.cpp b/umbrello/umbrello/codegenerators/cppwriter.cpp
new file mode 100644
index 00000000..b24c12b0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppwriter.cpp
@@ -0,0 +1,1283 @@
+/***************************************************************************
+ * cppwriter.cpp - description *
+ * This is the "old" code generator that does not support code editing *
+ * in the Modeller but uses significantly less file space because the *
+ * source code is not replicated in the XMI file. *
+ * *
+ * copyright : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov *
+ * (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ * *
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// own header
+#include "cppwriter.h"
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "classifierinfo.h"
+#include "codegen_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../umltemplatelist.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../classifierlistitem.h"
+#include "../model_utils.h"
+#include "../codegenerationpolicy.h"
+
+// 3-14-2003: this code developed from the javawriter with parts of the
+// original cppwriter by Luis De la Parra Blum
+
+CppWriter::CppWriter()
+{
+ // Probably we could resolve this better through the use of templates,
+ // but its a quick n dirty fix for the timebeing.. until codegeneration
+ // template system is in place.
+ // You can insert code here. 3 general variables exist: "%VARNAME%"
+ // allows you to specify where the vector variable should be in your code,
+ // and "%ITEMCLASS%", if needed, where the class of the item is declared.
+ VECTOR_METHOD_APPEND = "%VARNAME%.push_back(add_object);"; // for std::vector
+ VECTOR_METHOD_REMOVE = "int i, size = %VARNAME%.size();\nfor ( i = 0; i < size; i++) {\n\t%ITEMCLASS% item = %VARNAME%.at(i);\n\tif(item == remove_object) {\n\t\tvector<%ITEMCLASS%>::iterator it = %VARNAME%.begin() + i;\n\t\t%VARNAME%.erase(it);\n\t\treturn;\n\t}\n }"; // for std::vector
+ VECTOR_METHOD_INIT = QString(); // nothing to be done
+ /*
+ VECTOR_METHOD_APPEND = "%VARNAME%.append(&add_object);"; // Qt lib implementation
+ VECTOR_METHOD_REMOVE = "%VARNAME%.removeRef(&remove_object);"; // Qt lib implementation
+ VECTOR_METHOD_INIT = "%VARNAME%.setAutoDelete(false);"; // Qt library
+ */
+
+ OBJECT_METHOD_INIT = "%VARNAME% = new %ITEMCLASS%( );"; // Qt library
+
+ // boolean config params
+ INLINE_ASSOCIATION_METHODS = false;
+
+}
+
+CppWriter::~CppWriter() { }
+
+Uml::Programming_Language CppWriter::getLanguage() {
+ return Uml::pl_Cpp;
+}
+
+CPPCodeGenerationPolicy *CppWriter::policyExt() {
+ return static_cast<CPPCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt());
+}
+
+void CppWriter::writeClass(UMLClassifier *c)
+{
+
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!\n";
+ return;
+ }
+
+ QFile fileh, filecpp;
+
+ // find an appropriate name for our file
+ QString fileName = findFileName(c, ".h");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // preparations
+ m_classifierInfo = new ClassifierInfo(c);
+ m_classifierInfo->fileName = fileName;
+ m_classifierInfo->className = cleanName(c->getName());
+
+ if (c->getVisibility() != Uml::Visibility::Implementation) {
+ if( !openFile(fileh, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ // write Header file
+ writeHeaderFile(c, fileh);
+ fileh.close();
+ }
+
+ // Determine whether the implementation file is required.
+ // (It is not required if the class is an enumeration.)
+ bool need_impl = true;
+ if (c->getBaseType() == Uml::ot_Enum) {
+ need_impl = false;
+ }
+ if (need_impl) {
+ fileName.replace( QRegExp(".h$"), ".cpp");
+ if( !openFile(filecpp, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ // write Source file
+ writeSourceFile(c, filecpp);
+ filecpp.close();
+ }
+
+ // Wrap up: free m_classifierInfo, emit done code
+ m_classifierInfo = 0;
+
+ emit codeGenerated(c, true);
+
+}
+
+void CppWriter::writeHeaderFile (UMLClassifier *c, QFile &fileh) {
+
+ // open stream for writing
+ QTextStream h (&fileh);
+
+ // up the indent level to one
+ m_indentLevel = 1;
+
+ // write header blurb
+ QString str = getHeadingFile(".h");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),m_classifierInfo->fileName + ".h");
+ str.replace(QRegExp("%filepath%"),fileh.name());
+ h << str<< m_endl;
+ }
+
+ // Write the hash define stuff to prevent multiple parsing/inclusion of header
+ QString hashDefine = m_classifierInfo->className.upper().simplifyWhiteSpace().replace(QRegExp(" "), "_");
+ writeBlankLine(h);
+ h << "#ifndef "<< hashDefine + "_H" << m_endl;
+ h << "#define "<< hashDefine + "_H" << m_endl;
+
+ writeClassDecl(c, h);
+
+ // last thing..close our hashdefine
+ h << m_endl << "#endif // " << hashDefine + "_H" << m_endl;
+
+}
+
+void CppWriter::writeHeaderAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream)
+{
+
+ // attributes
+ writeHeaderAttributeAccessorMethods(permitScope, true, stream); // write static attributes first
+ writeHeaderAttributeAccessorMethods(permitScope, false, stream);
+
+ // associations
+ writeAssociationMethods(m_classifierInfo->plainAssociations, permitScope,
+ true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream);
+ writeAssociationMethods(m_classifierInfo->uniAssociations, permitScope,
+ true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream);
+ writeAssociationMethods(m_classifierInfo->aggregations, permitScope,
+ true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream);
+ writeAssociationMethods(m_classifierInfo->compositions, permitScope,
+ true, INLINE_ASSOCIATION_METHODS, false, c->getID(), stream);
+
+ writeBlankLine(stream);
+
+}
+
+void CppWriter::writeHeaderFieldDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream)
+{
+ // attributes
+ writeAttributeDecls(permitScope, true, stream); // write static attributes first
+ writeAttributeDecls(permitScope, false, stream);
+
+ // associations
+ writeAssociationDecls(m_classifierInfo->plainAssociations, permitScope, c->getID(), stream);
+ writeAssociationDecls(m_classifierInfo->uniAssociations, permitScope, c->getID(), stream);
+ writeAssociationDecls(m_classifierInfo->aggregations, permitScope, c->getID(), stream);
+ writeAssociationDecls(m_classifierInfo->compositions, permitScope, c->getID(), stream);
+
+}
+
+void CppWriter::writeSourceFile (UMLClassifier *c, QFile &filecpp ) {
+
+ // open stream for writing
+ QTextStream cpp (&filecpp);
+
+ // set the starting indentation at zero
+ m_indentLevel = 0;
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".cpp");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),m_classifierInfo->fileName + ".cpp");
+ str.replace(QRegExp("%filepath%"),filecpp.name());
+ cpp << str << m_endl;
+ }
+
+ // IMPORT statements
+ // Q: Why all utils? Isnt just List and Vector the only classes we are using?
+ // Our import *should* also look at operations, and check that objects being
+ // used arent in another package (and thus need to be explicitly imported here).
+ cpp << "#include \"" << m_classifierInfo->className << ".h\"" << m_endl;
+ writeBlankLine(cpp);
+
+ if (c->getVisibility() == Uml::Visibility::Implementation) {
+ writeClassDecl(c, cpp);
+ }
+
+ // Start body of class
+
+ // Constructors: anything we more we need to do here ?
+ //
+ if(!m_classifierInfo->isInterface)
+ writeConstructorMethods(cpp);
+
+ // METHODS
+ //
+
+ // write comment for section IF needed
+ QString indent = getIndent();
+ if (forceDoc() || m_classifierInfo->hasAccessorMethods || m_classifierInfo->hasOperationMethods)
+ {
+
+ writeComment(" ", indent, cpp);
+ writeComment("Methods", indent, cpp);
+ writeComment(" ", indent, cpp);
+ writeBlankLine(cpp);
+ writeBlankLine(cpp);
+ }
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || m_classifierInfo->hasAccessorMethods )
+ {
+ writeComment("Accessor methods", indent, cpp);
+ writeComment(" ", indent, cpp);
+ writeBlankLine(cpp);
+ }
+
+ // Accessor methods for attributes
+ const bool bInlineAccessors = policyExt()->getAccessorsAreInline();
+ if (!bInlineAccessors && m_classifierInfo->hasAttributes)
+ {
+ writeAttributeMethods(&(m_classifierInfo->static_atpub), Uml::Visibility::Public, false, true, !bInlineAccessors, cpp);
+ writeAttributeMethods(&(m_classifierInfo->atpub), Uml::Visibility::Public, false, false, !bInlineAccessors, cpp);
+ writeAttributeMethods(&(m_classifierInfo->static_atprot), Uml::Visibility::Protected, false, true, !bInlineAccessors, cpp);
+ writeAttributeMethods(&(m_classifierInfo->atprot), Uml::Visibility::Protected, false, false, !bInlineAccessors, cpp);
+ writeAttributeMethods(&(m_classifierInfo->static_atpriv), Uml::Visibility::Private, false, true, !bInlineAccessors, cpp);
+ writeAttributeMethods(&(m_classifierInfo->atpriv), Uml::Visibility::Private, false, false, !bInlineAccessors, cpp);
+ }
+
+ // accessor methods for associations
+
+ // public
+ writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Public, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Public, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Public, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Public, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+
+ // protected
+ writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Protected, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Protected, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Protected, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Protected, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+
+
+ // private
+ writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Private, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Private, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Private, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Private, false,
+ !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp);
+ writeBlankLine(cpp);
+
+ // Other operation methods -- all other operations are now written
+ //
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || m_classifierInfo->hasOperationMethods)
+ {
+ writeComment("Other methods", indent, cpp);
+ writeComment(" ", indent, cpp);
+ writeBlankLine(cpp);
+ }
+
+ if(!policyExt()->getOperationsAreInline())
+ {
+ writeOperations(c,false,Uml::Visibility::Public,cpp);
+ writeOperations(c,false,Uml::Visibility::Protected,cpp);
+ writeOperations(c,false,Uml::Visibility::Private,cpp);
+ }
+
+ // Yep, bringing up the back of the bus, our initialization method for attributes
+ writeInitAttibuteMethod (cpp);
+
+ writeBlankLine(cpp);
+
+}
+
+void CppWriter::writeClassDecl(UMLClassifier *c, QTextStream &cpp)
+{
+ UMLClassifierList superclasses = m_classifierInfo->superclasses;
+ for(UMLClassifier *classifier = superclasses.first(); classifier ;classifier = superclasses.next()) {
+ QString headerName = findFileName(classifier, ".h");
+ if (!headerName.isEmpty()) {
+ cpp << "#include \"" << headerName << "\"" << m_endl;
+ }
+ }
+
+ writeBlankLine(cpp);
+ cpp << "#include " << policyExt()->getStringClassNameInclude() << m_endl;
+ if(m_classifierInfo->hasVectorFields)
+ {
+ cpp << "#include " << policyExt()->getVectorClassNameInclude() << m_endl;
+ writeBlankLine(cpp);
+ }
+
+ if(m_classifierInfo->hasAssociations)
+ {
+ // write all includes we need to include other classes, that arent us.
+ printAssociationIncludeDecl (m_classifierInfo->plainAssociations, c->getID(), cpp);
+ printAssociationIncludeDecl (m_classifierInfo->uniAssociations, c->getID(), cpp);
+ printAssociationIncludeDecl (m_classifierInfo->aggregations, c->getID(), cpp);
+ printAssociationIncludeDecl (m_classifierInfo->compositions, c->getID(), cpp);
+
+ writeBlankLine(cpp);
+ }
+
+
+ for(UMLClassifier *classifier = superclasses.first(); classifier ; classifier = superclasses.next()) {
+ if(classifier->getPackage()!=c->getPackage() && !classifier->getPackage().isEmpty()) {
+ cpp << "using " << cleanName(classifier->getPackage()) << "::" << cleanName(classifier->getName()) << ";" << m_endl;
+ }
+ }
+
+ if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace())
+ cpp << m_endl << "namespace " << cleanName(c->getPackage()) << " {" << m_endl << m_endl;
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ cpp << m_endl << "/**" << m_endl;
+ cpp << " * class " << m_classifierInfo->className << m_endl;
+ cpp << formatDoc(c->getDoc()," * ");
+ cpp << " */";
+ writeBlankLine(cpp);
+ writeBlankLine(cpp);
+ }
+
+ //check if class is abstract and / or has abstract methods
+ if((c->getAbstract() || m_classifierInfo->isInterface )
+ && !hasAbstractOps(c))
+ cpp << "/******************************* Abstract Class ****************************" << m_endl
+ <<m_classifierInfo->className << " does not have any pure virtual methods, but its author" << m_endl
+ <<" defined it as an abstract class, so you should not use it directly." << m_endl
+ <<" Inherit from it instead and create only objects from the derived classes" << m_endl
+ <<"*****************************************************************************/" << m_endl << m_endl;
+
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLClassifierListItemList litList = c->getFilteredList(Uml::ot_EnumLiteral);
+ uint i = 0;
+ cpp << "enum " << m_classifierInfo->className << " {" << m_endl;
+ for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ cpp << getIndent() << enumLiteral;
+ if (++i < litList.count())
+ cpp << ",";
+ cpp << m_endl;
+ }
+ cpp << m_endl << "};" << m_endl; // end of class header
+ if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace())
+ cpp << "} // end of package namespace" << m_endl;
+ return;
+ }
+
+ // Generate template parameters.
+ UMLTemplateList template_params = c->getTemplateList();
+ if (template_params.count()) {
+ cpp << "template<";
+ for (UMLTemplate *t = template_params.first(); t; ) {
+ QString formalName = t->getName();
+ QString typeName = t->getTypeName();
+ cpp << typeName << " " << formalName;
+ if ((t = template_params.next()) != NULL)
+ cpp << ", ";
+ }
+ cpp << ">" << m_endl;
+ }
+
+ cpp << "class " << m_classifierInfo->className;
+ if (m_classifierInfo->superclasses.count() > 0)
+ cpp << " : ";
+ uint numOfSuperClasses = m_classifierInfo->superclasses.count();
+ uint i = 0;
+ for (UMLClassifier *superClass = m_classifierInfo->superclasses.first();
+ superClass ; superClass = m_classifierInfo->superclasses.next())
+ {
+ i++;
+ if (superClass->getAbstract() || superClass->isInterface())
+ cpp << "virtual ";
+ cpp << "public " << cleanName(superClass->getName());
+ if (i < numOfSuperClasses)
+ cpp << ", ";
+ }
+
+ cpp << m_endl << "{" << m_endl; // begin the body of the class
+
+
+ //declarations of operations
+ //
+
+ //
+ // write out field and operations decl grouped by visibility
+ //
+
+ // PUBLIC attribs/methods
+ cpp << "public:" << m_endl << m_endl; // print visibility decl.
+ // for public: constructors are first ops we print out
+ if(!m_classifierInfo->isInterface)
+ writeConstructorDecls(cpp);
+ writeHeaderFieldDecl(c,Uml::Visibility::Public, cpp);
+ writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, cpp);
+ writeOperations(c,true,Uml::Visibility::Public,cpp);
+
+ // PROTECTED attribs/methods
+ //
+ cpp << "protected" << ":" << m_endl << m_endl; // print visibility decl.
+ writeHeaderFieldDecl(c,Uml::Visibility::Protected, cpp);
+ writeHeaderAccessorMethodDecl(c, Uml::Visibility::Protected, cpp);
+ writeOperations(c,true,Uml::Visibility::Protected,cpp);
+
+ // PRIVATE attribs/methods
+ //
+ cpp << "private" << ":" << m_endl << m_endl; // print visibility decl.
+ writeHeaderFieldDecl(c,Uml::Visibility::Private, cpp);
+ writeHeaderAccessorMethodDecl(c, Uml::Visibility::Private, cpp);
+ writeOperations(c,true,Uml::Visibility::Private,cpp);
+ writeInitAttibuteDecl(cpp); // this is always private, used by constructors to initialize class
+
+ // end of class header
+ cpp << m_endl << "};" << m_endl;
+
+ // end of class namespace, if any
+ if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace())
+ cpp << "}; // end of package namespace" << m_endl;
+
+}
+
+void CppWriter::writeAttributeDecls (Uml::Visibility visibility, bool writeStatic, QTextStream &stream )
+{
+
+ if(m_classifierInfo->isInterface)
+ return;
+
+ UMLAttributeList * list;
+ switch (visibility)
+ {
+ case Uml::Visibility::Private:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atpriv);
+ else
+ list = &(m_classifierInfo->atpriv);
+ break;
+
+ case Uml::Visibility::Protected:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atprot);
+ else
+ list = &(m_classifierInfo->atprot);
+ break;
+
+ case Uml::Visibility::Public:
+ default:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atpub);
+ else
+ list = &(m_classifierInfo->atpub);
+ break;
+ }
+
+ //write documentation
+ if(forceDoc() || list->count() > 0)
+ {
+ QString strVis = Codegen_Utils::capitalizeFirstLetter(visibility.toString());
+ QString strStatic = writeStatic ? "Static ":"";
+ writeComment(strStatic + strVis + " attributes",getIndent(), stream);
+ writeComment(" ",getIndent(), stream);
+ writeBlankLine(stream);
+ }
+
+ if (list->count() > 0) {
+
+ // write attrib declarations now
+ bool isFirstAttrib = true;
+ QString documentation;
+ for(UMLAttribute *at=list->first(); at; at=list->next())
+ {
+
+ // bool noPriorDocExists = documentation.isEmpty();
+ documentation = at->getDoc();
+
+ // add a line for code clarity IF PRIOR attrib has comment on it
+ // OR this line has documentation
+ // if(!isFirstAttrib && (!documentation.isEmpty()||!noPriorDocExists))
+ // writeBlankLine(stream);
+
+ isFirstAttrib = false;
+
+ QString varName = getAttributeVariableName(at);
+
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString typeName = fixTypeName(at->getTypeName());
+ if(!documentation.isEmpty())
+ writeComment(documentation, getIndent(), stream);
+ stream << getIndent() << staticValue << typeName << " " << varName << ";" << m_endl;
+
+ }
+
+ /*
+ if(list->count() > 0)
+ writeBlankLine(stream);
+ */
+
+ }
+
+}
+
+void CppWriter::writeHeaderAttributeAccessorMethods (Uml::Visibility visibility, bool writeStatic, QTextStream &stream )
+{
+ // check the current policy about generate accessors as public
+ UMLAttributeList * list;
+ switch (visibility)
+ {
+ case Uml::Visibility::Private:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atpriv);
+ else
+ list = &(m_classifierInfo->atpriv);
+ break;
+
+ case Uml::Visibility::Protected:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atprot);
+ else
+ list = &(m_classifierInfo->atprot);
+ break;
+
+ case Uml::Visibility::Public:
+ default:
+ if(writeStatic)
+ list = &(m_classifierInfo->static_atpub);
+ else
+ list = &(m_classifierInfo->atpub);
+ break;
+ }
+
+ // switch to public
+ if (visibility != Uml::Visibility::Public)
+ stream << "public:" << m_endl << m_endl;
+
+ // write accessor methods for attribs we found
+ writeAttributeMethods(list, visibility, true, false, policyExt()->getAccessorsAreInline(), stream);
+
+ // switch back to previous vis.
+ if (visibility != Uml::Visibility::Public)
+ stream << visibility.toString() << ":" << m_endl << m_endl;
+}
+
+// this is for writing *source* or *header* file attribute methods
+//
+void CppWriter::writeAttributeMethods(UMLAttributeList *attribs,
+ Uml::Visibility visibility, bool isHeaderMethod,
+ bool isStatic,
+ bool writeMethodBody, QTextStream &stream)
+{
+
+ if (!policyExt()->getAutoGenerateAccessors())
+ return;
+
+ if (forceDoc() || attribs->count() > 0)
+ {
+ QString strVis = Codegen_Utils::capitalizeFirstLetter(visibility.toString());
+ QString strStatic = (isStatic ? " static" : "");
+ writeBlankLine(stream);
+ writeComment(strVis + strStatic + " attribute accessor methods",getIndent(),stream);
+ writeComment(" ",getIndent(), stream);
+ writeBlankLine(stream);
+ }
+
+ // return now if NO attributes to work on
+ if (attribs->count() == 0)
+ return;
+
+ UMLAttribute *at;
+ for(at=attribs->first(); at; at=attribs->next())
+ {
+
+ QString varName = getAttributeVariableName(at);
+ QString methodBaseName = cleanName(at->getName());
+
+ // force capitalizing the field name, this is silly,
+ // from what I can tell, this IS the default behavior for
+ // cleanName. I dunno why its not working -b.t.
+ methodBaseName = methodBaseName.stripWhiteSpace();
+ methodBaseName.replace(0,1,methodBaseName.at(0).upper());
+
+ writeSingleAttributeAccessorMethods(at->getTypeName(), varName,
+ methodBaseName, at->getDoc(), Uml::chg_Changeable, isHeaderMethod,
+ at->getStatic(), writeMethodBody, stream);
+ }
+
+}
+
+void CppWriter::writeComment(const QString &comment, const QString &myIndent, QTextStream &cpp)
+{
+ // in the case we have several line comment..
+ // NOTE: this part of the method has the problem of adopting UNIX newline,
+ // need to resolve for using with MAC/WinDoze eventually I assume
+ if (comment.contains(QRegExp("\n"))) {
+
+ QStringList lines = QStringList::split( "\n", comment);
+ for(uint i= 0; i < lines.count(); i++)
+ {
+ cpp << myIndent << "// " << lines[i] << m_endl;
+ }
+ } else {
+ // this should be more fancy in the future, breaking it up into 80 char
+ // lines so that it doesn't look too bad
+ cpp << myIndent << "// "<< comment << m_endl;
+ }
+}
+
+void CppWriter::writeDocumentation(QString header, QString body, QString end, QTextStream &cpp)
+{
+ writeBlankLine(cpp);
+ QString indent = getIndent();
+
+ cpp << indent << "/**" << m_endl;
+ if (!header.isEmpty())
+ cpp << formatDoc(header, indent + " * ");
+ if (!body.isEmpty())
+ cpp << formatDoc(body, indent + " * ");
+ if (!end.isEmpty())
+ {
+ QStringList lines = QStringList::split( "\n", end);
+ for(uint i= 0; i < lines.count(); i++)
+ cpp << formatDoc(lines[i], indent + " * ");
+ }
+ cpp << indent << " */" << m_endl;
+}
+
+void CppWriter::writeAssociationDecls(UMLAssociationList associations, Uml::Visibility permitScope, Uml::IDType id, QTextStream &h)
+{
+
+ if( forceSections() || !associations.isEmpty() )
+ {
+ bool printRoleA = false, printRoleB = false;
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == id && !a->getRoleName(Uml::B).isEmpty())
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty())
+ printRoleA = true;
+
+ // First: we insert documentaion for association IF it has either role AND some documentation (!)
+ if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
+ writeComment(a->getDoc(), getIndent(), h);
+
+ // print RoleB decl
+ if (printRoleB && a->getVisibility(Uml::B) == permitScope)
+ {
+
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::B)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), a->getMulti(Uml::B), a->getRoleDoc(Uml::B), h);
+ }
+
+ // print RoleA decl
+ if (printRoleA && a->getVisibility(Uml::A) == permitScope)
+ {
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::A)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), a->getMulti(Uml::A), a->getRoleDoc(Uml::A), h);
+ }
+
+ // reset for next association in our loop
+ printRoleA = false;
+ printRoleB = false;
+ }
+ }
+}
+
+void CppWriter::writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi,
+ QString doc, QTextStream &stream)
+{
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty())
+ return;
+
+ QString indent = getIndent();
+
+ // always put space between this and prior decl, if any
+ writeBlankLine(stream);
+
+ if (!doc.isEmpty())
+ writeComment(doc, indent, stream);
+
+ // declare the association based on whether it is this a single variable
+ // or a List (Vector). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.lower();
+
+ // record this for later consideration of initialization IF the
+ // multi value requires 1 of these objects
+ if(ObjectFieldVariables.findIndex(fieldVarName) == -1 &&
+ multi.contains(QRegExp("^1$"))
+ )
+ {
+ // ugh. UGLY. Storing variable name and its class in pairs.
+ ObjectFieldVariables.append(fieldVarName);
+ ObjectFieldVariables.append(fieldClassName);
+ }
+
+ stream << indent << fieldClassName << " * " << fieldVarName << ";" << m_endl;
+ }
+ else
+ {
+ QString fieldVarName = "m_" + roleName.lower() + "Vector";
+
+ // record unique occurrences for later when we want to check
+ // for initialization of this vector
+ if(VectorFieldVariables.findIndex(fieldVarName) == -1)
+ VectorFieldVariables.append(fieldVarName);
+
+ stream << indent << policyExt()->getVectorClassName() <<"<" << fieldClassName << "*";
+ stream << "> " << fieldVarName << ";" << m_endl;
+ }
+}
+
+// for either source or header files
+void CppWriter::writeAssociationMethods (UMLAssociationList associations,
+ Uml::Visibility permitVisib,
+ bool isHeaderMethod,
+ bool writeMethodBody,
+ bool writePointerVar,
+ Uml::IDType myID, QTextStream &stream)
+{
+ if( forceSections() || !associations.isEmpty() )
+ {
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+
+ // insert the methods to access the role of the other
+ // class in the code of this one
+ if (a->getObjectId(Uml::A) == myID && a->getVisibility(Uml::B) == permitVisib)
+ {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::B).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::B)) + (writePointerVar ? " *":"");
+ writeAssociationRoleMethod(fieldClassName,
+ isHeaderMethod,
+ writeMethodBody,
+ a->getRoleName(Uml::B),
+ a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
+ a->getChangeability(Uml::B), stream);
+ }
+ }
+
+ if (a->getObjectId(Uml::B) == myID && a->getVisibility(Uml::A) == permitVisib)
+ {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::A).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::A)) + (writePointerVar ? " *":"");
+ writeAssociationRoleMethod(fieldClassName,
+ isHeaderMethod,
+ writeMethodBody,
+ a->getRoleName(Uml::A),
+ a->getMulti(Uml::A),
+ a->getRoleDoc(Uml::A),
+ a->getChangeability(Uml::A),
+ stream);
+ }
+ }
+
+ }
+ }
+}
+
+void CppWriter::writeAssociationRoleMethod (const QString &fieldClassName,
+ bool isHeaderMethod,
+ bool writeMethodBody,
+ const QString &roleName, const QString &multi,
+ const QString &description, Uml::Changeability_Type change,
+ QTextStream &stream)
+{
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.lower();
+ writeSingleAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, change, isHeaderMethod, false, writeMethodBody, stream);
+ }
+ else
+ {
+ QString fieldVarName = "m_" + roleName.lower() + "Vector";
+ writeVectorAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, change, isHeaderMethod, writeMethodBody, stream);
+ }
+}
+
+void CppWriter::writeVectorAttributeAccessorMethods (
+ const QString &fieldClassName, const QString &fieldVarName,
+ const QString &fieldName, const QString &description,
+ Uml::Changeability_Type changeType,
+ bool isHeaderMethod,
+ bool writeMethodBody,
+ QTextStream &stream)
+{
+
+ QString className = fixTypeName(fieldClassName);
+ QString fldName = Codegen_Utils::capitalizeFirstLetter(fieldName);
+ QString indent = getIndent();
+
+ // ONLY IF changeability is NOT Frozen
+ if (changeType != Uml::chg_Frozen)
+ {
+ writeDocumentation("Add a " + fldName + " object to the " + fieldVarName + " List",description,"",stream);
+ stream << indent << "void ";
+ if(!isHeaderMethod)
+ stream << m_classifierInfo->className << "::";
+ stream << "add" << fldName << " ( " << className << " add_object )";
+ if (writeMethodBody) {
+ QString method = VECTOR_METHOD_APPEND;
+ method.replace(QRegExp("%VARNAME%"),fieldVarName);
+ method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName());
+ method.replace(QRegExp("%ITEMCLASS%"),className);
+ stream << indent << " {" << m_endl;
+ m_indentLevel++;
+ printTextAsSeparateLinesWithIndent(method,getIndent(),stream);
+ m_indentLevel--;
+ stream << indent << "}" << m_endl;
+ } else
+ stream << ";" << m_endl;
+ }
+
+ // ONLY IF changeability is Changeable
+ if (changeType == Uml::chg_Changeable)
+ {
+ writeDocumentation("Remove a " + fldName + " object from " + fieldVarName + " List",
+ description, "", stream);
+ stream << indent << "void ";
+ if(!isHeaderMethod)
+ stream << m_classifierInfo->className << "::";
+ stream << "remove" << fldName << " ( " << className << " remove_object )";
+ if (writeMethodBody) {
+ QString method = VECTOR_METHOD_REMOVE;
+ method.replace(QRegExp("%VARNAME%"),fieldVarName);
+ method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName());
+ method.replace(QRegExp("%ITEMCLASS%"),className);
+ stream << indent << " {" << m_endl;
+ m_indentLevel++;
+ printTextAsSeparateLinesWithIndent(method,getIndent(),stream);
+ m_indentLevel--;
+ stream << indent << "}" << m_endl;
+ } else
+ stream << ";" << m_endl;
+ }
+
+ // always allow getting the list of stuff
+ QString returnVarName = policyExt()->getVectorClassName() + '<' + className + '>';
+ writeDocumentation("Get the list of " + fldName + " objects held by " + fieldVarName,
+ description,
+ "@return " + returnVarName + " list of " + fldName + " objects held by " + fieldVarName,
+ stream);
+ stream << indent << returnVarName << " ";
+ if(!isHeaderMethod)
+ stream << m_classifierInfo->className << "::";
+ stream << "get" << fldName << "List ( )";
+ if(writeMethodBody) {
+ stream << indent << " {" << m_endl;
+ m_indentLevel++;
+ stream << getIndent() << "return " << fieldVarName << ";" << m_endl;
+ m_indentLevel--;
+ stream << indent << "}" << m_endl;
+ } else
+ stream << ";" << m_endl;
+
+}
+
+
+void CppWriter::writeSingleAttributeAccessorMethods(
+ const QString& fieldClassName, const QString& fieldVarName,
+ const QString& fieldName, const QString &description,
+ Uml::Changeability_Type change,
+ bool isHeaderMethod,
+ bool isStatic,
+ bool writeMethodBody,
+ QTextStream &stream)
+{
+
+ // DON'T write this IF its a source method AND writeMethodBody is "false"
+ if(!isHeaderMethod && !writeMethodBody)
+ return;
+
+ QString className = fixTypeName(fieldClassName);
+ QString fldName = Codegen_Utils::capitalizeFirstLetter(fieldName);
+ QString indent = getIndent();
+
+ // set method
+ if (change == Uml::chg_Changeable && !isStatic) {
+ writeDocumentation("Set the value of " + fieldVarName,description,"@param new_var the new value of " + fieldVarName,stream);
+ stream << indent << "void ";
+ if(!isHeaderMethod)
+ stream << m_classifierInfo->className << "::";
+ stream << "set" << fldName << " ( " << className << " new_var )";
+
+ if(writeMethodBody) {
+ stream << indent << " {" << m_endl;
+ m_indentLevel++;
+ stream << getIndent() << indent;
+ m_indentLevel--;
+ if(isStatic)
+ stream << m_classifierInfo->className << "::";
+ stream << fieldVarName << " = new_var;" << m_endl;
+ stream << indent << "}" << m_endl;
+ } else
+ stream << ";" << m_endl;
+ }
+
+ // get method
+ writeDocumentation("Get the value of " + fieldVarName,description,"@return the value of " + fieldVarName,stream);
+ stream << indent << className << " ";
+ if(!isHeaderMethod)
+ stream << m_classifierInfo->className << "::";
+ stream << "get" << fldName << " ( )";
+
+ if(writeMethodBody) {
+ stream << indent << " {" << m_endl;
+ m_indentLevel++;
+ stream << getIndent() << "return ";
+ m_indentLevel--;
+ if(isStatic)
+ stream << m_classifierInfo->className << "::";
+ stream << fieldVarName << ";" << m_endl;
+ stream << indent << "}";
+ } else
+ stream << ";" << m_endl;
+
+ writeBlankLine(stream);
+}
+
+// one day, this should print out non-empty constructor operations too.
+void CppWriter::writeConstructorDecls(QTextStream &stream)
+{
+ const bool generateEmptyConstructors =
+ UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors();
+ if (forceDoc() || generateEmptyConstructors)
+ {
+ writeComment("Constructors/Destructors", getIndent(), stream);
+ writeComment(" ", getIndent(), stream);
+ writeBlankLine(stream);
+ }
+ if (!generateEmptyConstructors)
+ return;
+
+ writeDocumentation("", "Empty Constructor", "", stream);
+ stream << getIndent() << m_classifierInfo->className << " ( );" << m_endl;
+ writeDocumentation("", "Empty Destructor", "", stream);
+ stream << getIndent();
+ stream << "virtual ~" << m_classifierInfo->className << " ( );" << m_endl;
+ writeBlankLine(stream);
+}
+
+void CppWriter::writeInitAttibuteDecl (QTextStream &stream)
+{
+ if (UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors() &&
+ m_classifierInfo->hasAttributes)
+ stream << getIndent() << "void initAttributes ( ) ;" << m_endl;
+}
+
+void CppWriter::writeInitAttibuteMethod (QTextStream &stream)
+{
+ // only need to do this under certain conditions
+ if (!UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors() ||
+ !m_classifierInfo->hasAttributes)
+ return;
+
+ QString className = m_classifierInfo->className;
+ QString indent = getIndent();
+
+ stream << indent << "void " << className << "::" << "initAttributes ( ) {" << m_endl;
+
+ m_indentLevel++;
+ // first, initiation of fields derived from attributes
+ UMLAttributeList atl = m_classifierInfo->getAttList();
+ for(UMLAttribute *at = atl.first(); at ; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty()) {
+ QString varName = getAttributeVariableName(at);
+ stream << getIndent() << varName << " = " << at->getInitialValue() << ";" << m_endl;
+ }
+ }
+ // Now initialize the association related fields (e.g. vectors)
+ if (!VECTOR_METHOD_INIT.isEmpty()) {
+ QStringList::Iterator it;
+ for( it = VectorFieldVariables.begin(); it != VectorFieldVariables.end(); ++it ) {
+ QString fieldVarName = *it;
+ QString method = VECTOR_METHOD_INIT;
+ method.replace(QRegExp("%VARNAME%"),fieldVarName);
+ method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName());
+ stream << getIndent() << method << m_endl;
+ }
+ }
+
+ if (!OBJECT_METHOD_INIT.isEmpty()) {
+ QStringList::Iterator it;
+ for( it = ObjectFieldVariables.begin(); it != ObjectFieldVariables.end(); ++it ) {
+ QString fieldVarName = *it;
+ it++;
+ QString fieldClassName = *it;
+ QString method = OBJECT_METHOD_INIT;
+ method.replace(QRegExp("%VARNAME%"),fieldVarName);
+ method.replace(QRegExp("%ITEMCLASS%"),fieldClassName);
+ stream << getIndent() << method << m_endl;
+ }
+ }
+
+ // clean up
+ ObjectFieldVariables.clear(); // shouldn't be needed?
+ VectorFieldVariables.clear(); // shouldn't be needed?
+
+ m_indentLevel--;
+
+ stream << indent << "}" << m_endl;
+}
+
+// one day, this should print out non-empty constructor operations too.
+void CppWriter::writeConstructorMethods(QTextStream &stream)
+{
+ const bool generateEmptyConstructors =
+ UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors();
+
+ if (forceDoc() || generateEmptyConstructors) {
+ writeComment("Constructors/Destructors", getIndent(), stream);
+ writeComment(" ", getIndent(), stream);
+ writeBlankLine(stream);
+ }
+ if (!generateEmptyConstructors)
+ return;
+
+ QString className = m_classifierInfo->className;
+ // empty constructor
+ QString indent = getIndent();
+ stream << indent << className << "::" << className << " ( ) {" << m_endl;
+ if(m_classifierInfo->hasAttributes)
+ stream << indent << indent << "initAttributes();" << m_endl;
+ stream << indent << "}" << m_endl;
+ writeBlankLine(stream);
+
+ // empty destructor
+ stream << getIndent() << className << "::~" << className << " ( ) { }" << m_endl;
+ writeBlankLine(stream);
+}
+
+// IF the type is "string" we need to declare it as
+// the Java Object "String" (there is no string primative in Java).
+QString CppWriter::fixTypeName(const QString &string)
+{
+ if (string.isEmpty())
+ return "void";
+ if (string == "string")
+ return policyExt()->getStringClassName();
+ return string;
+}
+
+void CppWriter::writeOperations(UMLClassifier *c, bool isHeaderMethod,
+ Uml::Visibility permitScope, QTextStream &cpp) {
+
+ UMLOperationList oplist;
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList inputlist = c->getOpList();
+ for (UMLOperation *op = inputlist.first(); op; op = inputlist.next()) {
+ if (op->getVisibility() == permitScope) {
+ oplist.append(op);
+ }
+ }
+
+ // do people REALLY want these comments? Hmm.
+ /*
+ if(forceSections() || oppub.count())
+ {
+ writeComment("public operations",getIndent(),cpp);
+ writeBlankLine(cpp);
+ }
+ */
+ writeOperations(oplist,isHeaderMethod, cpp);
+
+}
+
+// write operation in either header or
+// a source file
+void CppWriter::writeOperations(UMLOperationList &oplist, bool isHeaderMethod, QTextStream &cpp) {
+ QString className = m_classifierInfo->className;
+ const bool generateEmptyConstructors =
+ UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors();
+
+ // generate method decl for each operation given
+ for (UMLOperation *op = oplist.first(); op; op = oplist.next()) {
+
+ QString returnStr; // buffer for documentation
+ QString methodReturnType;
+ UMLAttributeList atl = op->getParmList(); // method parameters
+
+ if (op->isConstructorOperation()) {
+ if (generateEmptyConstructors && atl.count() == 0)
+ continue; // it's already been written, see writeConstructor{Decls,Methods}
+ } else if (op->isDestructorOperation()) {
+ if (generateEmptyConstructors)
+ continue; // it's already been written, see writeConstructor{Decls,Methods}
+ } else {
+ methodReturnType = fixTypeName(op->getTypeName());
+ if(methodReturnType != "void")
+ returnStr += "@return " + methodReturnType + '\n';
+ }
+
+ QString str;
+ if (op->getAbstract() || m_classifierInfo->isInterface) {
+ if (isHeaderMethod) {
+ // declare abstract method as 'virtual'
+ str += "virtual ";
+ }
+ }
+
+ // static declaration for header file
+ if (isHeaderMethod && op->getStatic())
+ str += "static ";
+
+ // returntype of method
+ str += methodReturnType + ' ';
+
+ if (!isHeaderMethod)
+ str += className + "::";
+
+ str += cleanName(op->getName()) + " (";
+
+ // generate parameters
+ uint j = 0;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next(), j++) {
+ QString typeName = fixTypeName(at->getTypeName());
+ QString atName = cleanName(at->getName());
+ str += typeName + ' ' + atName;
+ const QString initVal = at->getInitialValue();
+ if (! initVal.isEmpty())
+ str += " = " + initVal;
+ if (j < atl.count() - 1)
+ str += ", ";
+ returnStr += "@param " + atName + ' ' + at->getDoc() + '\n';
+ }
+ str += " )";
+
+ if (op->getConst())
+ str += " const";
+
+ // method body : only gets IF its not in a header
+ if (isHeaderMethod && !policyExt()->getOperationsAreInline())
+ str += ';'; // terminate now
+ else
+ str +=getIndent() + " {\n\n" + getIndent() + '}'; // empty method body
+
+ // write it out
+ writeDocumentation("", op->getDoc(), returnStr, cpp);
+ cpp << getIndent() << str << m_endl;
+ writeBlankLine(cpp);
+ }
+}
+
+// To prevent circular including when both classifiers on either end
+// of an association have roles we need to have forward declaration of
+// the other class...but only IF its not THIS class (as could happen
+// in self-association relationship).
+void CppWriter::printAssociationIncludeDecl (UMLAssociationList list, Uml::IDType myId, QTextStream &stream)
+{
+
+ for (UMLAssociation *a = list.first(); a; a = list.next()) {
+ UMLClassifier *current = NULL;
+ bool isFirstClass = true;
+
+ // only use OTHER classes (e.g. we don't need to write includes for ourselves!!
+ // AND only IF the roleName is defined, otherwise, its not meant to be noticed.
+ if (a->getObjectId(Uml::A) == myId && !a->getRoleName(Uml::B).isEmpty()) {
+ current = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B));
+ } else if (a->getObjectId(Uml::B) == myId && !a->getRoleName(Uml::A).isEmpty()) {
+ current = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ isFirstClass = false;
+ }
+
+ // as header doc for this method indicates, we need to be a bit sophisticated on
+ // how to declare some associations.
+ if( current )
+ if( !isFirstClass && !a->getRoleName(Uml::A).isEmpty() && !a->getRoleName(Uml::B).isEmpty())
+ stream << "class " << current->getName() << ";" << m_endl; // special case: use forward declaration
+ else
+ stream << "#include \"" << current->getName() << ".h\"" << m_endl; // just the include statement
+ }
+}
+
+QString CppWriter::fixInitialStringDeclValue(const QString &value, const QString &type)
+{
+ QString val = value;
+ // check for strings only
+ if (!val.isEmpty() && type == policyExt()->getStringClassName()) {
+ if (!val.startsWith("\""))
+ val.prepend("\"");
+ if (!val.endsWith("\""))
+ val.append("\"");
+ }
+ return val;
+}
+
+// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
+QString CppWriter::getUMLObjectName(UMLObject *obj)
+{
+ return(obj!=0)?obj->getName():QString("NULL");
+}
+
+void CppWriter::writeBlankLine(QTextStream &stream)
+{
+ stream << m_endl;
+}
+
+void CppWriter::printTextAsSeparateLinesWithIndent (const QString &text, const QString &indent, QTextStream &stream)
+{
+ if(text.isEmpty())
+ return;
+
+ QStringList lines = QStringList::split( "\n", text);
+ for(uint i= 0; i < lines.count(); i++)
+ stream << indent << lines[i] << m_endl;
+}
+
+QString CppWriter::getAttributeVariableName (UMLAttribute *at)
+{
+ QString fieldName = "m_" + cleanName(at->getName());
+ return fieldName;
+}
+
+QStringList CppWriter::defaultDatatypes() {
+ return Codegen_Utils::cppDatatypes();
+}
+
+const QStringList CppWriter::reservedKeywords() const {
+ return Codegen_Utils::reservedCppKeywords();
+}
+
diff --git a/umbrello/umbrello/codegenerators/cppwriter.h b/umbrello/umbrello/codegenerators/cppwriter.h
new file mode 100644
index 00000000..8ae58226
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/cppwriter.h
@@ -0,0 +1,293 @@
+/***************************************************************************
+ cppwriter.h - description
+ This is the "old" code generator that does not support code editing
+ in the Modeller but uses significantly less file space because the
+ source code is not replicated in the XMI file.
+ -------------------
+ copyright : (C) 2003 Brian Thomas
+ (C) 2004 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef CPPWRITER_H
+#define CPPWRITER_H
+
+#include "simplecodegenerator.h"
+#include "cppcodegenerationpolicy.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+#include "../umlassociationlist.h"
+
+class QFile;
+class ClassifierInfo;
+
+/**
+ * class CppWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate both a header (.h) and
+ * source (.cpp) file for that classifier.
+ */
+class CppWriter : public SimpleCodeGenerator {
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ CppWriter();
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~CppWriter();
+
+ /**
+ * call this method to generate cpp code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "C++"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * Add C++ primitives as datatypes
+ */
+ QStringList defaultDatatypes();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * Writes class's documentation to the class header
+ * public abstract class Foo extents {
+ */
+ void writeClassDecl(UMLClassifier *c, QTextStream &cpp);
+
+ /**
+ * Writes the comment and class constructor declaration or methods
+ */
+ void writeConstructorDecls(QTextStream &h);
+ void writeConstructorMethods(QTextStream &cpp);
+
+ /**
+ * write all field declarations, for both attributes and associations for the
+ * given permitted scope.
+ */
+ void writeFieldDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream);
+
+ /**
+ * write all method declarations, for attributes and associations
+ * for the given permitted scope.
+ */
+ void writeAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream);
+
+ /**
+ * write all operations for a given class
+ * @param c the class for which we are generating code
+ * @param isHeaderMethod true when writing to a header file, false for body file
+ * @param permitScope what type of method to write (by Scope)
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLClassifier *c, bool isHeaderMethod, Uml::Visibility permitScope, QTextStream &j);
+
+ /**
+ * write a list of operations for a given class
+ * @param list the list of operations you want to write
+ * @param isHeaderMethod true when writing to a header file, false for body file
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLOperationList &list, bool isHeaderMethod, QTextStream &j);
+
+ /**
+ * write all attributes for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * writes the Attribute declarations
+ * @param visibility the visibility of the attribs to print out
+ * @param writeStatic whether to write static or non-static attributes out
+ * @param stream text stream
+ */
+ void writeAttributeDecls (Uml::Visibility visibility, bool writeStatic, QTextStream &stream );
+
+ /**
+ * Write out fields and operations for this class selected on a particular
+ * visibility.
+ */
+ void writeHeaderFieldDecl(UMLClassifier *c, Uml::Visibility permitVisibility, QTextStream &stream);
+
+ void writeHeaderAttributeAccessorMethods (Uml::Visibility visibility, bool writeStatic, QTextStream &stream );
+
+ void writeHeaderAttributeAccessorMethodDecls(UMLClassifier *c, Uml::Visibility permitVisibility, QTextStream &stream);
+ void writeHeaderAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream);
+
+
+ /**
+ * Searches a list of associations for appropriate ones to write out as attributes
+ */
+ void writeAssociationDecls(UMLAssociationList associations, Uml::Visibility permit, Uml::IDType id, QTextStream &stream);
+
+ /**
+ * Writes out an association as an attribute using Vector
+ */
+ void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi,
+ QString doc, QTextStream &stream);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in attribs list.
+ */
+ void writeAttributeMethods(UMLAttributeList *attribs, Uml::Visibility visib, bool isHeaderMethod,
+ bool isStatic,
+ bool writeMethodBody, QTextStream &stream);
+
+ /**
+ * calls @ref writeAssociationRoleMethod() on each of the associations in the given list
+ */
+ void writeAssociationMethods(UMLAssociationList associations, Uml::Visibility permitVisib,
+ bool isHeaderMethod,
+ bool writeMethodBody, bool writePointerVar, Uml::IDType id, QTextStream &stream);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() or @ref
+ * writeVectorAttributeAccessorMethods() on the association
+ * role
+ */
+ void writeAssociationRoleMethod(const QString &fieldClassName, bool isHeaderMethod, bool writeMethodBody,
+ const QString &roleName, const QString &multi,
+ const QString &description, Uml::Changeability_Type change,
+ QTextStream &stream);
+
+ /**
+ * Writes getFoo() and setFoo() accessor methods for the attribute
+ */
+ void writeSingleAttributeAccessorMethods(
+ const QString &fieldClassName, const QString &Name,
+ const QString &fieldName, const QString &description,
+ Uml::Changeability_Type change,
+ bool isHeaderMethod,
+ bool isStatic, bool writeMethodBody, QTextStream &cpp);
+
+ /**
+ * Writes addFoo() and removeFoo() accessor methods for the Vector attribute
+ */
+ void writeVectorAttributeAccessorMethods(
+ const QString &fieldClassName, const QString &fieldVarName,
+ const QString &fieldName, const QString &description,
+ Uml::Changeability_Type change,
+ bool isHeaderMethod,
+ bool writeMethodBody,
+ QTextStream &cpp);
+
+ /**
+ * Writes a // style comment
+ */
+ void writeComment(const QString &text, const QString &indent, QTextStream &cpp);
+
+ /**
+ * Writes a documentation comment
+ */
+ void writeDocumentation(QString header, QString body, QString end, QTextStream &cpp);
+
+
+ /**
+ * write the header file for this classifier.
+ */
+ void writeHeaderFile (UMLClassifier *c, QFile &file);
+
+ /**
+ * write the source code body file for this classifier.
+ */
+ void writeSourceFile (UMLClassifier *c, QFile &file);
+
+ /**
+ * utility method to break up a block of text, which has embedded newline chars,
+ * and print them to a stream as separate lines of text, indented as directed.
+ */
+ void printTextAsSeparateLinesWithIndent (const QString &text, const QString &indent,
+ QTextStream &stream);
+
+ /**
+ * Intellegently print out header include/forward decl. for associated classes.
+ */
+ void printAssociationIncludeDecl (UMLAssociationList list, Uml::IDType this_id, QTextStream &stream);
+
+ /**
+ * If needed, write out the method to initialize attributes of our class.
+ */
+ void writeInitAttibuteMethod (QTextStream &stream);
+
+ /**
+ * If needed, write out the declaration for the method to initialize attributes of our class.
+ */
+ void writeInitAttibuteDecl (QTextStream &stream);
+
+ /**
+ * Returns the name of the given object (if it exists)
+ */
+ QString getUMLObjectName(UMLObject *obj);
+
+ /**
+ * Replaces `string' with STRING_TYPENAME.
+ */
+ QString fixTypeName(const QString &string);
+
+ /**
+ * check that initial values of strings have quotes around them
+ */
+ QString fixInitialStringDeclValue(const QString &value, const QString &type);
+
+ /**
+ * Determine what the variable name of this attribute should be.
+ */
+ QString getAttributeVariableName (UMLAttribute *at);
+
+ /**
+ * Write a blank line
+ */
+ void writeBlankLine(QTextStream &stream);
+
+ /**
+ * Return the policy object
+ */
+ CPPCodeGenerationPolicy *policyExt();
+
+ /**
+ * Summary information about current classifier.
+ */
+ ClassifierInfo * m_classifierInfo;
+
+ QString VECTOR_METHOD_APPEND;
+ QString VECTOR_METHOD_REMOVE;
+ QString VECTOR_METHOD_INIT;
+ QString OBJECT_METHOD_INIT;
+
+ /**
+ * Create association methods for class attributes/associations/operations as inline decl in header.
+ */
+ bool INLINE_ASSOCIATION_METHODS;
+
+ QStringList ObjectFieldVariables;
+ QStringList VectorFieldVariables;
+
+};
+
+
+
+#endif // CPPWRITER_H
diff --git a/umbrello/umbrello/codegenerators/csharpwriter.cpp b/umbrello/umbrello/codegenerators/csharpwriter.cpp
new file mode 100644
index 00000000..73975b48
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/csharpwriter.cpp
@@ -0,0 +1,725 @@
+/***************************************************************************
+ * *
+ * 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) 2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+//
+// C++ Implementation: csharpwriter
+//
+#include "csharpwriter.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../folder.h"
+#include "../classifier.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+static const char *reserved_words[] = {
+ "abstract",
+ "as",
+ "base",
+ "bool",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "checked",
+ "class",
+ "const",
+ "continue",
+ "decimal",
+ "default",
+ "delegate",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "event",
+ "explicit",
+ "extern",
+ "false",
+ "finally",
+ "for",
+ "foreach",
+ "goto",
+ "if",
+ "implicit",
+ "in",
+ "int",
+ "interface",
+ "internal",
+ "is",
+ "lock",
+ "long",
+ "namespace",
+ "new",
+ "null",
+ "object",
+ "operator",
+ "out",
+ "override",
+ "params",
+ "private",
+ "protected",
+ "public",
+ "readonly",
+ "ref",
+ "return",
+ "sbyte",
+ "sealed",
+ "short",
+ "sizeof",
+ "stackalloc",
+ "static",
+ "string",
+ "struct",
+ "switch",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typeof",
+ "uint",
+ "ulong",
+ "unchecked",
+ "unsafe",
+ "ushort",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "while",
+ 0
+};
+
+CSharpWriter::CSharpWriter()
+ : SimpleCodeGenerator()
+{
+}
+
+
+CSharpWriter::~CSharpWriter()
+{
+}
+
+QStringList CSharpWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("bool");
+ l.append("byte");
+ l.append("char");
+ l.append("decimal");
+ l.append("double");
+ l.append("fixed");
+ l.append("float");
+ l.append("fixed");
+ l.append("float");
+ l.append("int");
+ l.append("long");
+ l.append("object");
+ l.append("sbyte");
+ l.append("short");
+ l.append("string");
+ l.append("uint");
+ l.append("ulong");
+ l.append("ushort");
+ return l;
+}
+
+void CSharpWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".cs");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile filecs;
+ if (!openFile(filecs, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream cs(&filecs);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".cs");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),filecs.name());
+ cs<<str<<m_endl;
+ }
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
+
+ // write generic includes
+ cs << "using System;" << m_endl;
+ cs << "using System.Text;" << m_endl;
+ cs << "using System.Collections;" << m_endl;
+ cs << "using System.Collections.Generic;" << m_endl << m_endl;
+
+ //write includes and namespace
+
+ UMLPackage *container = c->getUMLPackage();
+ if (container == logicalView)
+ container = NULL;
+
+ UMLPackageList includes;
+ findObjectsRelated(c, includes);
+ m_seenIncludes.clear();
+ //m_seenIncludes.append(logicalView);
+ if (includes.count()) {
+ UMLPackage *p;
+ for (UMLPackageListIt it(includes); (p = it.current()) != NULL; ++it) {
+ UMLClassifier *cl = dynamic_cast<UMLClassifier*>(p);
+ if (cl)
+ p = cl->getUMLPackage();
+ if (p != logicalView && m_seenIncludes.findRef(p) == -1 && p != container) {
+ cs << "using " << p->getFullyQualifiedName(".") << ";" << m_endl;
+ m_seenIncludes.append(p);
+ }
+ }
+ cs << m_endl;
+ }
+
+ m_container_indent = "";
+
+ if (container) {
+ cs << "namespace " << container->getFullyQualifiedName(".") << m_endl;
+ cs << "{" << m_endl << m_endl;
+ m_container_indent = m_indentation;
+ m_seenIncludes.append(container);
+ }
+
+ //Write class Documentation if there is somthing or if force option
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ cs << m_container_indent << "/// <summary>" << m_endl;
+ cs << formatDoc(c->getDoc(), m_container_indent + "/// " );
+ cs << m_container_indent << "/// </summary>" << m_endl ;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+ UMLAssociationList realizations = c->getRealizations();
+ bool isInterface = c->isInterface();
+ m_unnamedRoles = 1;
+
+ cs << m_container_indent << "public ";
+
+ //check if it is an interface or regular class
+ if (isInterface) {
+ cs << "interface " << classname;
+ } else {
+ //check if class is abstract and / or has abstract methods
+ if (c->getAbstract() || c->hasAbstractOps())
+ cs << "abstract ";
+
+ cs << "class " << classname << (superclasses.count() > 0 ? " : ":"");
+
+ // write baseclass, ignore interfaces, write error on multiple inheritance
+ if (superclasses.count() > 0) {
+ UMLClassifier *obj;
+ int supers = 0;
+ for (obj = superclasses.first(); obj; obj = superclasses.next()) {
+ if (!obj->isInterface()) {
+ if (supers > 0) {
+ cs << " // AND ";
+ }
+ cs << cleanName(obj->getName());
+ supers++;
+ }
+ }
+ if (supers > 1) {
+ cs << m_endl << "//WARNING: C# does not support multiple inheritance but there is more than 1 superclass defined in your UML model!" << m_endl;
+ }
+ }
+ //check for realizations
+ UMLAssociationList realizations = c->getRealizations();
+ UMLAssociation *a;
+
+ if (!realizations.isEmpty()) {
+ for (a = realizations.first(); a; a = realizations.next()) {
+ UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
+ if(real != c) {
+ // write list of realizations
+ cs << ", " << real->getName();
+ }
+
+ }
+ }
+ }
+ cs << m_endl << m_container_indent << '{' << m_endl;
+
+ //associations
+ if (forceSections() || !aggregations.isEmpty()) {
+ cs << m_endl << m_container_indent << m_indentation << "#region Aggregations" << m_endl << m_endl;
+ writeAssociatedAttributes(aggregations, c, cs);
+ cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl;
+ }
+
+ //compositions
+ if (forceSections() || !compositions.isEmpty()) {
+ cs << m_endl << m_container_indent << m_indentation << "#region Compositions" << m_endl << m_endl;
+ writeAssociatedAttributes(compositions, c, cs);
+ cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl;
+ }
+
+ //attributes
+ // FIXME: C# allows Properties in interface!
+ if (!isInterface)
+ writeAttributes(c, cs);
+
+ //operations
+ writeOperations(c, cs);
+
+ //finish file
+ cs << m_endl << m_container_indent << "}" << m_endl << m_endl; // close class
+
+ if (container) {
+ cs << "} // end of namespace "
+ << container->getFullyQualifiedName(".") << m_endl << m_endl;
+ }
+
+ //close files and notfiy we are done
+ filecs.close();
+ emit codeGenerated(c, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void CSharpWriter::writeOperations(UMLClassifier *c, QTextStream &cs) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ bool isInterface = c->isInterface();
+ bool generateErrorStub = true;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList opl(c->getOpList());
+ for (UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch (op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // write realizations (recursive)
+ UMLAssociationList realizations = c->getRealizations();
+
+ if (!isInterface && !realizations.isEmpty()) {
+ writeRealizationsRecursive(c, &realizations, cs);
+ }
+
+ // write public operations
+ if (forceSections() || !oppub.isEmpty()) {
+ cs << m_endl << m_container_indent << m_indentation << "#region Public methods" << m_endl << m_endl;
+ writeOperations(oppub,cs,isInterface,false,generateErrorStub);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+ }
+
+ // write protected operations
+ if (forceSections() || !opprot.isEmpty()) {
+ cs << m_endl << m_container_indent << m_indentation << "#region Protected methods" << m_endl << m_endl;
+ writeOperations(opprot,cs,isInterface,false,generateErrorStub);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+ }
+
+ // write private operations
+ if (forceSections() || !oppriv.isEmpty()) {
+ cs << m_endl << m_container_indent << m_indentation << "#region Private methods" << m_endl << m_endl;
+ writeOperations(oppriv,cs,isInterface,false,generateErrorStub);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+ }
+
+ // write superclasses abstract methods
+ UMLClassifierList superclasses = c->getSuperClasses();
+
+ if (!isInterface && !c->getAbstract() && !c->hasAbstractOps()
+ && superclasses.count() > 0) {
+ writeOverridesRecursive(&superclasses, cs);
+ }
+
+}
+
+void CSharpWriter::writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs) {
+ // oplist for implemented abstract operations
+ UMLOperationList opabstract;
+ opabstract.setAutoDelete(false);
+ UMLClassifier *obj;
+
+ for (obj = superclasses->first(); obj; obj = superclasses->next()) {
+ if (!obj->isInterface() && obj->hasAbstractOps()) {
+ // collect abstract ops
+ UMLOperationList opl(obj->getOpList());
+ for (UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ if (op->getAbstract()) {
+ opabstract.append(op);
+ }
+ }
+
+ // write abstract implementations
+ cs << m_endl << m_container_indent << m_indentation << "#region " << obj->getName() << " members" << m_endl << m_endl;
+ writeOperations(opabstract,cs,false,true,true);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+
+ opabstract.clear();
+ }
+ // Recurse to parent superclasses
+ UMLClassifierList superRecursive = obj->getSuperClasses();
+ UMLClassifierList *superRecursivePtr =& superRecursive;
+ if (superRecursivePtr->count() > 0) {
+ writeOverridesRecursive(superRecursivePtr, cs);
+ }
+ }
+}
+void CSharpWriter::writeRealizationsRecursive(UMLClassifier *currentClass, UMLAssociationList *realizations, QTextStream &cs) {
+
+ UMLAssociation *a;
+ for (a = realizations->first(); a; a = realizations->next()) {
+
+ // we know its a classifier if its in the list
+ UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
+
+ //FIXME: Interfaces realize themselves without this condition!?
+ if (real == currentClass)
+ continue;
+
+ // collect operations of one realization
+ UMLOperationList opreal = real->getOpList();
+
+ // write realizations
+ cs << m_endl << m_container_indent << m_indentation << "#region " << real->getName() << " members" << m_endl << m_endl;
+ writeOperations(opreal,cs,false,false,true);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+
+ // Recurse to parent realizations
+ UMLAssociationList parentReal = real->getRealizations();
+ if (!parentReal.isEmpty()) {
+ writeRealizationsRecursive(real, &parentReal, cs);
+ }
+ }
+}
+
+void CSharpWriter::writeOperations(UMLOperationList opList,
+ QTextStream &cs, bool isInterface /* = false */,
+ bool isOverride /* = false */,
+ bool generateErrorStub /* = false */) {
+
+ for (UMLOperation *op=opList.first(); op ; op=opList.next()) {
+ UMLAttributeList atl = op->getParmList();
+ UMLAttribute *at;
+
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+
+ for (at = atl.first(); at; at = atl.next()) {
+ writeDoc |= !at->getDoc().isEmpty();
+ }
+
+ //write method documentation
+ if (writeDoc && !isOverride)
+ {
+ cs << m_container_indent << m_indentation << "/// <summary>" << m_endl;
+ cs << formatDoc(op->getDoc(), m_container_indent + m_indentation + "/// ");
+ cs << m_container_indent << m_indentation << "/// </summary>" << m_endl;
+
+ //write parameter documentation
+ for (at = atl.first(); at; at = atl.next())
+ {
+ if (forceDoc() || !at->getDoc().isEmpty()) {
+ cs << m_container_indent << m_indentation << "/// <param name=\"" << cleanName(at->getName()) << "\">";
+ //removing newlines from parameter doc
+ cs << formatDoc(at->getDoc(), "").replace("\n", " ").remove('\r').replace(QRegExp(" $"), "");
+ cs << "</param>" << m_endl;
+ }
+ }
+
+ // FIXME: "returns" should contain documentation, not type.
+ cs << m_container_indent << m_indentation << "/// <returns>";
+ if (! op->getTypeName().isEmpty()) {
+ cs << makeLocalTypeName(op);
+ }
+ cs << "</returns>" << m_endl;
+
+ }
+
+ // method visibility
+ cs << m_container_indent << m_indentation;
+ if (!isInterface) {
+ if (!isOverride) {
+ if (op->getAbstract()) cs << "abstract ";
+ cs << op->getVisibility().toString() << " ";
+ if (op->getStatic()) cs << "static ";
+ }
+ else {
+ // method overriding an abstract parent
+ cs << op->getVisibility().toString() << " override ";
+ if (op->getStatic()) cs << "static ";
+ }
+ }
+
+ // return type (unless constructor, destructor)
+ if (!op->isLifeOperation()) {
+ if (op->getTypeName().isEmpty()) {
+ cs << "void ";
+ }
+ else {
+ cs << makeLocalTypeName(op) << " ";
+ }
+ }
+
+ // method name
+ cs << cleanName(op->getName()) << "(";
+
+ // method parameters
+ int i= atl.count();
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+
+ cs << makeLocalTypeName(at) << " " << cleanName(at->getName());
+
+ // no initial values in C#
+ //<< (!(at->getInitialValue().isEmpty()) ?
+ // (QString(" = ")+at->getInitialValue()) :
+ // QString(""))
+ cs << ((j < i-1)?", ":"");
+ }
+ cs << ")";
+
+ //FIXME: how to control generation of error stub?
+ if (!isInterface && (!op->getAbstract() || isOverride)) {
+ cs << m_endl << m_container_indent << m_indentation << "{" << m_endl;
+ if (generateErrorStub) {
+ cs << m_container_indent << m_indentation << m_indentation;
+ cs << "throw new Exception(\"The method or operation is not implemented.\");" << m_endl;
+ }
+ cs << m_container_indent << m_indentation << "}" << m_endl;
+ }
+ else {
+ cs << ';' << m_endl;
+ }
+ cs << m_endl;
+ }
+}
+
+void CSharpWriter::writeAttributes(UMLClassifier *c, QTextStream &cs) {
+
+ UMLAttributeList atpub, atprot, atpriv, atdefval;
+ atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ atdefval.setAutoDelete(false);
+
+ //sort attributes by scope and see if they have a default value
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+
+ for (at = atl.first(); at ; at = atl.next()) {
+ if (!at->getInitialValue().isEmpty())
+ atdefval.append(at);
+ switch (at->getVisibility()) {
+ case Uml::Visibility::Public:
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ atpriv.append(at);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (forceSections() || atl.count())
+ cs << m_endl << m_container_indent << m_indentation << "#region Attributes" << m_endl << m_endl;
+
+ // write public attributes
+ if (forceSections() || atpub.count()) {
+ writeAttributes(atpub,cs);
+ }
+
+ // write protected attributes
+ if (forceSections() || atprot.count()) {
+ writeAttributes(atprot,cs);
+ }
+
+ // write private attributes
+ if (forceSections() || atpriv.count()) {
+ writeAttributes(atpriv,cs);
+ }
+
+ if (forceSections() || atl.count())
+ cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+
+}
+
+
+void CSharpWriter::writeAttributes(UMLAttributeList &atList, QTextStream &cs) {
+
+ for (UMLAttribute *at = atList.first(); at ; at = atList.next()) {
+
+ bool asProperty = true;
+ if (at->getVisibility() == Uml::Visibility::Private) {
+ asProperty = false;
+ }
+ writeAttribute(at->getDoc(), at->getVisibility(), at->getStatic(),
+ makeLocalTypeName(at), at->getName(), at->getInitialValue(), asProperty, cs);
+
+ cs << m_endl;
+ } // end for
+ return;
+}
+
+void CSharpWriter::writeAssociatedAttributes(UMLAssociationList &associated, UMLClassifier *c, QTextStream &cs) {
+
+ UMLAssociation *a;
+ for (a = associated.first(); a ; a = associated.next()) {
+ if (c != a->getObject(Uml::A)) // we need to be at the A side
+ continue;
+
+ UMLObject *o = a->getObject(Uml::B);
+ if (o == NULL) {
+ kError() << "composition role B object is NULL" << endl;
+ continue;
+ }
+ // Take name and documentaton from Role, take type name from the referenced object
+ QString roleName = cleanName(a->getRoleName(Uml::B));
+ QString typeName = cleanName(o->getName());
+ if (roleName.isEmpty()) {
+ roleName = QString("UnnamedRoleB_%1").arg(m_unnamedRoles++);
+ }
+ QString roleDoc = a->getRoleDoc(Uml::B);
+
+ //FIXME:is this simple condition enough?
+ if (a->getMulti(Uml::B).isEmpty() || a->getMulti(Uml::B) == "1") {
+ // normal attribute
+ writeAttribute(roleDoc, a->getVisibility(Uml::B), false, typeName, roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs);
+ } else {
+ // array
+ roleDoc += "\n(Array of " + typeName + ')';
+ writeAttribute(roleDoc, a->getVisibility(Uml::B), false, "ArrayList", roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs);
+ }
+ }
+}
+
+void CSharpWriter::writeAttribute(QString doc, Uml::Visibility visibility, bool isStatic, QString typeName, QString name, QString initialValue, bool asProperty, QTextStream &cs) {
+
+ if (forceDoc() || !doc.isEmpty()) {
+
+ cs << m_container_indent << m_indentation << "/// <summary>" << m_endl;
+ cs << formatDoc(doc, m_container_indent + m_indentation + "/// ");
+ cs << m_container_indent << m_indentation << "/// </summary>" << m_endl;
+
+ }
+ cs << m_container_indent << m_indentation;
+ cs << visibility.toString() << " ";
+ if (isStatic) cs << "static ";
+
+ //Variable type with/without namespace path
+ cs << typeName << " ";
+
+ cs << cleanName(name);
+
+ // FIXME: may need a GUI switch to not generate as Property?
+
+ // Generate as Property if not private
+ if (asProperty)
+ {
+ cs << m_endl;
+ cs << m_container_indent << m_indentation << "{" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << "get" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << "{" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << m_indentation << "return m_" << cleanName(name) << ";" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << "}" << m_endl;
+
+ cs << m_container_indent << m_indentation << m_indentation << "set" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << "{" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << m_indentation << "m_" << cleanName(name) << " = value;" << m_endl;
+ cs << m_container_indent << m_indentation << m_indentation << "}" << m_endl;
+ cs << m_container_indent << m_indentation << "}" << m_endl;
+ cs << m_container_indent << m_indentation << "private ";
+ if (isStatic) cs << "static ";
+ cs << typeName << " m_" << cleanName(name);
+ }
+
+ if (!initialValue.isEmpty())
+ cs << " = " << initialValue;
+
+ cs << ";" << m_endl << m_endl;
+}
+
+QString CSharpWriter::makeLocalTypeName(UMLClassifierListItem *cl) {
+ UMLPackage *p = cl->getType()->getUMLPackage();
+ if (m_seenIncludes.findRef(p) != -1) {
+ return cl->getType()->getName();
+ }
+ else {
+ return cl->getTypeName();
+ }
+
+}
+
+/**
+ * returns "C#"
+ */
+Uml::Programming_Language CSharpWriter::getLanguage() {
+ return Uml::pl_CSharp;
+}
+
+const QStringList CSharpWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ for (int i = 0; reserved_words[i]; i++)
+ keywords.append(reserved_words[i]);
+ }
+
+ return keywords;
+}
+
+#include "csharpwriter.moc"
+
diff --git a/umbrello/umbrello/codegenerators/csharpwriter.h b/umbrello/umbrello/codegenerators/csharpwriter.h
new file mode 100644
index 00000000..a6d20f2d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/csharpwriter.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * *
+ * 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) 2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+//
+// C++ Interface: csharpwriter
+//
+// @author Ferenc Veres
+//
+#ifndef CSHARPWRITER_H
+#define CSHARPWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+#include "../umloperationlist.h"
+#include "../classifierlistitem.h"
+#include "../umlassociationlist.h"
+
+
+/**
+ * class CSharpWriter is a C# code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class CSharpWriter : public SimpleCodeGenerator
+{
+ Q_OBJECT
+public:
+ CSharpWriter();
+
+ virtual ~CSharpWriter();
+ /**
+ * call this method to generate Php code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "C#"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+ /**
+ * get list of predefined data types
+ */
+ QStringList defaultDatatypes();
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * Adds extra indenting if the class is in a container (namespace)
+ */
+ QString m_container_indent;
+
+ /**
+ * Collection of included namespaces, to skip them from variable types.
+ */
+ UMLPackageList m_seenIncludes;
+
+ /**
+ * Counts associations without a role name for giving a default name.
+ */
+ int m_unnamedRoles;
+
+ /**
+ * write realizations of a class and recurse to parent classes
+
+ * @param currentClass class to start with
+ * @param realizations realizations of this class
+ * @param cs output stream
+ */
+ void writeRealizationsRecursive(UMLClassifier *currentClass,
+ UMLAssociationList *realizations,
+ QTextStream &cs);
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param cs output stream
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &cs);
+
+ /**
+ * write a list of class operations
+ *
+ * @param opList the list of operations
+ * @param cs output stream
+ * @param interface indicates if the operation is an interface member
+ * @param isOverride implementation of an inherited abstract function
+ */
+ void writeOperations(UMLOperationList opList,
+ QTextStream &cs,
+ bool interface = false,
+ bool isOverride = false,
+ bool generateErrorStub = false);
+
+ /**
+ * write superclasses' abstract methods
+ *
+ * @param superclasses List of superclasses to start recursing on
+ * @param cs output stream
+ */
+ void writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs);
+
+ /** write all the attributes of a class
+ * @param c the class we are generating code for
+ * @param cs output stream
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &cs);
+
+ /** write a list of class attributes
+ * @param atList the list of attributes
+ * @param cs output stream
+ */
+ void writeAttributes(UMLAttributeList &atList, QTextStream &cs);
+
+ /**
+ * write attributes from associated objects (compositions, aggregations)
+ * @param associated list of associated objects
+ * @param c currently written class, to see association direction
+ * @param cs output stream
+ */
+ void writeAssociatedAttributes(UMLAssociationList &associated, UMLClassifier *c, QTextStream &cs);
+
+ /**
+ * write a single attribute to the output stream
+ * @param doc attribute documentation
+ * @param visibility attribute visibility
+ * @param isStatic static attribute
+ * @param typeName class/type of the attribute
+ * @param name name of the attribute
+ * @param initialValue initial value given to the attribute at declaration
+ * @param asProperty true writes as property (get/set), false writes single line variable
+ * @param cs output stream
+ */
+ void writeAttribute(QString doc, Uml::Visibility visibility, bool isStatic, QString typeName, QString name, QString initialValue, bool asProperty, QTextStream &cs);
+
+ /** find the type in used namespaces, if namespace found return short name, complete otherwise.
+ *
+ * @param at Operation or Attribute to check type
+ */
+ QString makeLocalTypeName(UMLClassifierListItem *cl);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/codegenerators/dwriter.cpp b/umbrello/umbrello/codegenerators/dwriter.cpp
new file mode 100644
index 00000000..3e16b136
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/dwriter.cpp
@@ -0,0 +1,970 @@
+
+/***************************************************************************
+ * *
+ * 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) 2007 Jari-Matti Mäkelä <jmjm@iki.fi> *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/***************************************************************************
+ This is the "old" code generator that does not support code editing
+ in the Modeller but uses significantly less file space because the
+ source code is not replicated in the XMI file.
+ ***************************************************************************/
+
+// own header
+#include "dwriter.h"
+// qt includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+// kde includes
+#include <kdebug.h>
+// app includes
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../association.h"
+#include "../template.h"
+#include "../umltemplatelist.h"
+#include "codegen_utils.h"
+
+DWriter::DWriter() {
+ startline = m_endl + m_indentation;
+}
+
+DWriter::~DWriter() {}
+
+Uml::Programming_Language DWriter::getLanguage() {
+ return Uml::pl_D;
+}
+
+// FIXME: doesn't work yet
+void DWriter::writeModuleDecl(UMLClassifier *c, QTextStream &d) {
+ if(!c->getPackage().isEmpty())
+ d << "module " << c->getPackage() << ";" << m_endl;
+
+ writeBlankLine(d);
+}
+
+void DWriter::writeModuleImports(UMLClassifier *c, QTextStream &d) {
+ // another preparation, determine what we have
+ UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
+ UMLAssociationList uniAssociations = c->getUniAssociationToBeImplemented();
+
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ bool hasAssociations = aggregations.count() + associations.count() +
+ compositions.count() + uniAssociations.count() > 0;
+
+ if (hasAssociations) {
+ // import tango, if that mode is set
+ writeBlankLine(d);
+ }
+
+ //only import classes in a different package as this class
+ UMLPackageList imports;
+ findObjectsRelated(c, imports);
+ for (UMLPackage *con = imports.first(); con; con = imports.next()) {
+ if (con->getBaseType() == Uml::ot_Datatype)
+ continue;
+ QString pkg = con->getPackage();
+ if (!pkg.isEmpty() && pkg != c->getPackage())
+ d << "import " << pkg << "." << cleanName(con->getName()) << ";"
+ << m_endl;
+ }
+
+ writeBlankLine(d);
+}
+
+void DWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug()<<"Cannot write class of NULL concept!\n";
+ return;
+ }
+
+ isInterface = c->isInterface();
+
+ QString fileName = cleanName(c->getName().lower());
+
+ //find an appropriate name for our file
+ fileName = findFileName(c, ".d");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // check that we may open that file for writing
+ QFile file;
+ if ( !openFile(file, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // open text stream to file
+ QTextStream d(&file);
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".d");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),file.name());
+ d<<str<<m_endl;
+ }
+
+ // source file begins with the module declaration
+ writeModuleDecl(c, d);
+
+ // imports
+ writeModuleImports(c, d);
+
+ // write the opening declaration for the class incl any documentation,
+ // interfaces and/or inheritence issues we have
+ writeClassDecl(c, d);
+
+ // start body of class
+ d << " {" << m_endl;
+
+
+ // Preparations
+ //
+
+ // sort attributes by Scope
+ UMLAttributeList atl;
+ UMLAttributeList atpub, atprot, atpriv, atpkg, atexport;
+ UMLAttributeList final_atpub, final_atprot, final_atpriv, final_atpkg, final_atexport;
+
+ atpub.setAutoDelete(false);
+ final_atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ final_atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ final_atpriv.setAutoDelete(false);
+ atpkg.setAutoDelete(false);
+ final_atpkg.setAutoDelete(false);
+ atexport.setAutoDelete(false);
+ final_atexport.setAutoDelete(false);
+
+ if (!isInterface) {
+ UMLAttributeList atl = c->getAttributeList();
+ for (UMLAttribute *at = atl.first(); at ; at = atl.next()) {
+ switch(at->getVisibility())
+ {
+ case Uml::Visibility::Public:
+ if(at->getStatic())
+ final_atpub.append(at);
+ else
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ if(at->getStatic())
+ final_atprot.append(at);
+ else
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ if(at->getStatic())
+ final_atpriv.append(at);
+ else
+ atpriv.append(at);
+ break;/* TODO: requires support from the gui & other structures
+ case Uml::Visibility::Package:
+ if(at->getStatic())
+ final_atpkg.append(at);
+ else
+ atpkg.append(at);
+ break;
+ case Uml::Visibility::Export:
+ if(at->getStatic())
+ final_atexport.append(at);
+ else
+ atexport.append(at);
+ break;*/
+ default:
+ break;
+ }
+ }
+ }
+
+ // another preparation, determine what we have
+ UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
+ UMLAssociationList uniAssociations = c->getUniAssociationToBeImplemented();
+
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ bool hasAssociations = aggregations.count() + associations.count() + compositions.count() + uniAssociations.count() > 0;
+ bool hasAttributes = atl.count() > 0;
+ bool hasAccessorMethods = hasAttributes || hasAssociations;
+ bool hasOperationMethods = c->getOpList().count() > 0;
+
+ // ATTRIBUTES
+ //
+
+ // write comment for section IF needed
+ if (forceDoc() || hasAccessorMethods)
+ {
+ writeComment("", m_indentation, d);
+ writeComment("Fields", m_indentation, d);
+ writeComment("", m_indentation, d);
+ writeBlankLine(d);
+ }
+
+ writeAttributeDecls(final_atpub, final_atprot, final_atpriv, d);
+ writeAttributeDecls(atpub, atprot, atpriv, d);
+
+ writeAssociationDecls(associations, c->getID(), d);
+ writeAssociationDecls(uniAssociations, c->getID(), d);
+ writeAssociationDecls(aggregations, c->getID(), d);
+ writeAssociationDecls(compositions, c->getID(), d);
+
+ //FIXME: find constructors and write them here
+
+ // write constructors
+ if(!isInterface) writeConstructor(c, d);
+
+
+ // METHODS
+ //
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || hasAccessorMethods ) {
+ writeComment("", m_indentation, d);
+ writeComment("Accessors", m_indentation, d);
+ writeComment("", m_indentation, d);
+ writeBlankLine(d);
+ }
+
+
+ // Accessors for attributes
+ writeAttributeMethods(final_atpub, Uml::Visibility::Public, d);
+ writeAttributeMethods(final_atprot, Uml::Visibility::Protected, d);
+ writeAttributeMethods(final_atpriv, Uml::Visibility::Private, d);
+ writeAttributeMethods(atpub, Uml::Visibility::Public, d);
+ writeAttributeMethods(atprot, Uml::Visibility::Protected, d);
+ writeAttributeMethods(atpriv, Uml::Visibility::Private, d);
+
+ // accessor methods for associations
+
+ // first: determine the name of the other class
+ writeAssociationMethods(associations, c, d);
+ writeAssociationMethods(uniAssociations, c, d);
+ writeAssociationMethods(aggregations, c, d);
+ writeAssociationMethods(compositions, c, d);
+
+ // Other operation methods
+ // all other operations are now written
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || hasOperationMethods) {
+ writeComment("", m_indentation, d);
+ writeComment("Other methods", m_indentation, d);
+ writeComment("", m_indentation, d);
+ writeBlankLine(d);
+ }
+
+ writeOperations(c, d);
+
+ d << "}" << m_endl; // end class
+
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+void DWriter::writeClassDecl(UMLClassifier *c, QTextStream &d) {
+
+ // class documentation
+ if (!c->getDoc().isEmpty()) {
+ writeDocumentation("", c->getDoc(), "", "", d);
+ }
+
+ /*
+ * Class declaration
+ *
+ * (private) class foo(T, ..., Z) : class1, ..., classN, interface1, ..., interfaceN
+ * a b c d e f g
+ */
+
+ // (a) visibility modifier
+ switch(c->getVisibility()) {
+ case Uml::Visibility::Private: d << "private "; break;
+ default: break;
+ }
+
+ // (b) keyword
+ // TODO what about structs?
+ if (isInterface) {
+ d << "interface ";
+ } else {
+ if (c->getAbstract()) {
+ d << "abstract ";
+ }
+
+ d << "class ";
+ }
+
+ // (c) class name
+ QString classname = cleanName(c->getName()); // our class name
+ d << classname;
+
+ // (d) template parameters
+ UMLTemplateList template_params = c->getTemplateList();
+ if (template_params.count()) {
+ d << "(";
+
+ for (UMLTemplate *t = template_params.first(); t; ) {
+ // TODO: hm, leaving the type blank results in "class"
+ // so we omit it (also because "class" in this context is illegal)
+ if (t->getTypeName() != "class") {
+ d << t->getTypeName();
+ d << " ";
+ }
+
+ d << t->getName();
+
+ if ((t = template_params.next()) != NULL)
+ d << ", ";
+ }
+
+ d << ")";
+ }
+
+ // (e) inheritances
+ UMLClassifierList superclasses =
+ c->findSuperClassConcepts(UMLClassifier::CLASS);
+ UMLClassifierList superinterfaces =
+ c->findSuperClassConcepts(UMLClassifier::INTERFACE);
+
+ int count = superclasses.count() + superinterfaces.count();
+
+ if (count > 0) {
+ d << " : ";
+
+ // (f) base classes
+ for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) {
+ d << cleanName(concept->getName());
+
+ count--;
+
+ if (count>0) d << ", ";
+ }
+
+ // (g) interfaces
+ for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next()) {
+ d << cleanName(concept->getName());
+
+ count--;
+
+ if (count>0) d << ", ";
+ }
+ }
+}
+
+void DWriter::writeProtectionMod(Uml::Visibility visibility, QTextStream &d) {
+ d << m_indentation << scopeToDDecl(visibility) << ":" << m_endl << m_endl;
+}
+
+void DWriter::writeAttributeDecl(Uml::Visibility visibility, UMLAttributeList &atlist, QTextStream &d) {
+ if (atlist.count()==0) return;
+
+ writeProtectionMod(visibility, d);
+
+ for(UMLAttribute *at=atlist.first(); at; at=atlist.next()) {
+ // documentation
+ if (!at->getDoc().isEmpty()) {
+ writeComment(at->getDoc(), m_indentation, d, true);
+ }
+
+ d << m_indentation;
+
+ // static attribute?
+ if (at->getStatic()) d << "static ";
+
+ // method return type
+ d << fixTypeName(at->getTypeName()) << " ";
+
+ // TODO: find out whether this class has accessors or not
+ bool hasAccessorMethods = true;
+
+ // attribute name
+ if (hasAccessorMethods) {
+ d << "m_";
+ }
+ d << cleanName(at->getName());
+
+ // initial value
+ QString initVal = fixInitialStringDeclValue(at->getInitialValue(), at->getTypeName());
+ if (!initVal.isEmpty()) d << " = " << initVal;
+ d << ";" << m_endl << m_endl;
+ }
+}
+
+void DWriter::writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
+ UMLAttributeList &atpriv, QTextStream &d ) {
+
+ writeAttributeDecl(Uml::Visibility::Public, atpub, d);
+ writeAttributeDecl(Uml::Visibility::Protected, atprot, d);
+ writeAttributeDecl(Uml::Visibility::Private, atpriv, d);
+ //TODO: export and package
+}
+
+void DWriter::writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &d) {
+ if (atpub.count()==0) return;
+
+ writeProtectionMod(visibility, d);
+
+ for(UMLAttribute *at=atpub.first(); at; at=atpub.next()) {
+ QString fieldName = cleanName(at->getName());
+ writeSingleAttributeAccessorMethods(
+ at->getTypeName(), "m_" + fieldName, fieldName, at->getDoc(),
+ visibility, Uml::chg_Changeable, at->getStatic(), d);
+ }
+}
+
+void DWriter::writeComment(const QString &comment, const QString &myIndent,
+ QTextStream &d, bool dDocStyle) {
+ if(dDocStyle) {
+ d << myIndent << "/**" << m_endl;
+ }
+
+ QStringList lines = QStringList::split("\n", comment);
+
+ if (lines.count() == 0) lines << comment;
+
+ for (uint i = 0; i < lines.count(); ++i) {
+ QString tmp = lines[i];
+
+ while (tmp.length() > 77) {
+ uint l = tmp.left(77).findRev(' ');
+ if (l < 1) l = tmp.find(' ', 77);
+ if (l < 1 || l > tmp.length()) {
+ d << myIndent << (dDocStyle ? " * " : "// ") << tmp << m_endl;
+ break;
+ }
+ d << myIndent << (dDocStyle ? " * " : "// ") << tmp.left(l) << m_endl;
+ tmp = tmp.right(tmp.length() - l);
+ }
+
+ d << myIndent << (dDocStyle ? " * " : "// ") << tmp << m_endl;
+ }
+
+ if(dDocStyle) {
+ d << myIndent << " */" << m_endl;
+ }
+}
+
+void DWriter::writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &d) {
+ d << indent << "/**" << m_endl;
+ if (!header.isEmpty())
+ d << formatDoc(header, indent+" * ");
+ if (!body.isEmpty())
+ d << formatDoc(body, indent+" * ");
+ if (!end.isEmpty())
+ {
+ QStringList lines = QStringList::split( "\n", end);
+ for (uint i= 0; i < lines.count(); i++)
+ d << formatDoc(lines[i], indent + " * ");
+ }
+ d<<indent<< " */" << m_endl;
+}
+
+void DWriter::writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &d) {
+
+ if( forceSections() || !associations.isEmpty() )
+ {
+ bool printRoleA = false, printRoleB = false;
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == id)
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id)
+ printRoleA = true;
+
+ // First: we insert documentaion for association IF it has either role AND some documentation (!)
+ if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
+ writeComment(a->getDoc(), m_indentation, d);
+
+ // print RoleB decl
+ if (printRoleB)
+ {
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::B)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), a->getMulti(Uml::B), a->getRoleDoc(Uml::B), a->getVisibility(Uml::B), d);
+ }
+
+ // print RoleA decl
+ if (printRoleA)
+ {
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::A)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), a->getMulti(Uml::A), a->getRoleDoc(Uml::A), a->getVisibility(Uml::A), d);
+ }
+ }
+ }
+}
+
+void DWriter::writeAssociationRoleDecl(QString fieldClassName,
+ QString roleName, QString multi,
+ QString doc, Uml::Visibility /*visib*/, QTextStream &d) {
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty()) return;
+
+ if (!doc.isEmpty()) {
+ writeComment(doc, m_indentation, d);
+ }
+
+ bool hasAccessors = true;
+
+ // declare the association based on whether it is this a single variable
+ // or a List (Vector). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
+ d << m_indentation << fieldClassName << " ";
+
+ if (hasAccessors) d << "m_";
+
+ d << deCapitaliseFirstLetter(roleName) << ";";
+ } else {
+ d << m_indentation << fieldClassName << "[] ";
+ //TODO: templated containers
+
+ if (hasAccessors) d << "m_";
+
+ d << pluralize(deCapitaliseFirstLetter(roleName)) << ";";
+ // from here we could initialize default values, or put in an init() section
+ // of the constructors
+ }
+
+ // always put space between this and following decl, if any
+ writeBlankLine(d);
+}
+
+void DWriter::writeAssociationMethods (UMLAssociationList associations, UMLClassifier *thisClass, QTextStream &d) {
+ if( forceSections() || !associations.isEmpty() ) {
+ for(UMLAssociation *a = associations.first(); a; a = associations.next()) {
+ // insert the methods to access the role of the other
+ // class in the code of this one
+ if (a->getObjectId(Uml::A) == thisClass->getID()) {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::B).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::B));
+ writeAssociationRoleMethod(fieldClassName,
+ a->getRoleName(Uml::B),
+ a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
+ a->getVisibility(Uml::B),
+ a->getChangeability(Uml::B), d);
+ }
+ }
+
+ if (a->getObjectId(Uml::B) == thisClass->getID()) {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::A).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::A));
+ writeAssociationRoleMethod(fieldClassName, a->getRoleName(Uml::A),
+ a->getMulti(Uml::A),
+ a->getRoleDoc(Uml::A),
+ a->getVisibility(Uml::A),
+ a->getChangeability(Uml::A),
+ d);
+ }
+ }
+ }
+ }
+}
+
+void DWriter::writeAssociationRoleMethod (QString fieldClassName, QString roleName, QString multi,
+ QString description, Uml::Visibility visib, Uml::Changeability_Type change,
+ QTextStream &d) {
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
+ QString fieldVarName = "m_" + deCapitaliseFirstLetter(roleName);
+
+ writeSingleAttributeAccessorMethods(
+ fieldClassName, fieldVarName, roleName, description, visib, change, false, d);
+ } else {
+ QString fieldVarName = "m_" + pluralize(deCapitaliseFirstLetter(roleName));
+
+ writeVectorAttributeAccessorMethods(
+ fieldClassName, fieldVarName, pluralize(roleName), description, visib, change, d);
+ }
+}
+
+void DWriter::writeVectorAttributeAccessorMethods (QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility /*visibility*/, Uml::Changeability_Type changeType,
+ QTextStream &d) {
+
+ fieldClassName = fixTypeName(fieldClassName);
+ QString fieldNameUP = unPluralize(fieldName);
+ QString fieldNameUC = Codegen_Utils::capitalizeFirstLetter(fieldNameUP);
+
+ // ONLY IF changeability is NOT Frozen
+ if (changeType != Uml::chg_Frozen) {
+ writeDocumentation("Adds a " + fieldNameUP + " to the list of " +
+ fieldName + '.', description, "", m_indentation, d);
+
+ d << m_indentation << "void add" << fieldNameUC << "(";
+ d << fieldClassName << " new" << fieldNameUC << ") {";
+ d << startline << m_indentation << fieldVarName << " ~= new" << fieldNameUC << ";";
+ d << startline << "}" << m_endl << m_endl;
+ }
+
+ // ONLY IF changeability is Changeable
+ if (changeType == Uml::chg_Changeable) {
+ writeDocumentation("Removes a " + fieldNameUP + " from the list of " +
+ fieldName + '.', description, "", m_indentation, d);
+
+ d << m_indentation << "void remove" << fieldNameUC << "(";
+ d << fieldClassName << " " << fieldNameUP << ") {" << startline;
+ d << m_indentation << "int idx = " << fieldVarName << ".length;" << startline;
+ d << m_indentation << "foreach(i, o; " << fieldVarName << ")" << startline;
+ d << m_indentation << m_indentation << "if (o && o == " << fieldNameUP << ") {" << startline;
+ d << m_indentation << m_indentation << m_indentation << "idx = i;" << startline;
+ d << m_indentation << m_indentation << m_indentation << "break;" << startline;
+ d << m_indentation << m_indentation << "}" << m_endl << startline;
+ d << m_indentation << fieldVarName << " = " << fieldVarName;
+ d << "[0..idx] ~ " << fieldVarName << "[idx..$];" << startline;
+ d << "}" << m_endl << m_endl;
+ }
+
+ // always allow getting the list of stuff
+ writeDocumentation("Returns the list of " + fieldName + '.',
+ description, "@return List of " + fieldName + '.',
+ m_indentation, d);
+
+ d << m_indentation << fieldClassName << "[] get" << fieldName << "() {";
+ d << startline << m_indentation << "return " << fieldVarName << ";";
+ d << startline << "}" << m_endl << m_endl;
+}
+
+
+void DWriter::writeSingleAttributeAccessorMethods(QString fieldClassName,
+ QString fieldVarName, QString fieldName, QString description, Uml::Visibility /*visibility*/,
+ Uml::Changeability_Type change, bool isFinal, QTextStream &d) {
+
+ fieldClassName = fixTypeName(fieldClassName);
+ QString fieldNameUC = Codegen_Utils::capitalizeFirstLetter(fieldName);
+ if (fieldName.left(2) == "m_") fieldName = fieldName.right(fieldName.length()-2);
+
+ // set method
+ if (change == Uml::chg_Changeable && !isFinal) {
+ writeDocumentation("Sets the value of " + fieldName + '.', description,
+ "@param new" + fieldNameUC + " The new value of " + fieldName + '.',
+ m_indentation, d);
+
+ d << m_indentation << fieldClassName << " " << fieldName << "(";
+ d << fieldClassName << " new" << fieldNameUC << ") {";
+ d << startline << m_indentation << "return " << fieldVarName << " = new" << fieldNameUC << ";";
+ d << startline << "}" << m_endl << m_endl;
+ }
+
+ // get method
+ writeDocumentation("Returns the value of " + fieldName + '.', description,
+ "@return The value of " + fieldName + '.',
+ m_indentation, d);
+
+ d << m_indentation << fieldClassName << " " << fieldName << "() {";
+ d << startline << m_indentation << "return " << fieldVarName << ";";
+ d << startline << "}" << m_endl << m_endl;
+}
+
+void DWriter::writeConstructor(UMLClassifier *c, QTextStream &d) {
+
+ if (forceDoc())
+ {
+ d<<startline;
+ writeComment("", m_indentation, d);
+ writeComment("Constructors", m_indentation, d);
+ writeComment("", m_indentation, d);
+ writeBlankLine(d);
+ }
+
+ // write the first constructor
+ QString className = cleanName(c->getName());
+ d << m_indentation << "public this("<<") { }";
+
+}
+
+// IF the type is "string" we need to declare it as
+// the D Object "String" (there is no string primative in D).
+// Same thing again for "bool" to "boolean"
+QString DWriter::fixTypeName(const QString& string) {
+ if (string.isEmpty())
+ return "void";
+ if (string == "string")
+ return "char[]";
+ if (string == "unsigned short")
+ return "ushort";
+ if (string == "unsigned int")
+ return "uint";
+ if (string == "unsigned long")
+ return "ulong";
+ return string;
+}
+
+QStringList DWriter::defaultDatatypes() {
+ QStringList l;
+ l << "void"
+ << "bool"
+ << "byte"
+ << "ubyte"
+ << "short"
+ << "ushort"
+ << "int"
+ << "uint"
+ << "long"
+ << "ulong"
+ << "cent"
+ << "ucent"
+ << "float"
+ << "double"
+ << "real"
+ << "ifloat"
+ << "idouble"
+ << "ireal"
+ << "cfloat"
+ << "cdouble"
+ << "creal"
+ << "char"
+ << "wchar"
+ << "dchar";
+ return l;
+}
+
+
+bool DWriter::compareDMethod(UMLOperation *op1, UMLOperation *op2) {
+ if (op1 == NULL || op2 == NULL)
+ return false;
+ if (op1 == op2)
+ return true;
+ if (op1->getName() != op2->getName())
+ return false;
+ UMLAttributeList atl1 = op1->getParmList();
+ UMLAttributeList atl2 = op2->getParmList();
+ if (atl1.count() != atl2.count())
+ return false;
+ UMLAttribute *at1;
+ UMLAttribute *at2;
+ for (at1 = atl1.first(), at2 = atl2.first(); at1 && at2 ; at1 = atl1.next(),at2 = atl2.next())
+ {
+ if (at1->getTypeName() != at2->getTypeName())
+ return false;
+ }
+ return true;
+
+}
+
+bool DWriter::dMethodInList(UMLOperation *umlOp, UMLOperationList &opl) {
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ if (DWriter::compareDMethod(op, umlOp)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void DWriter::getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath) {
+ UMLClassifierList superClasses = c->findSuperClassConcepts();
+
+ for (UMLClassifier *concept= superClasses.first(); concept; concept = superClasses.next())
+ {
+ getSuperImplementedOperations(concept, yetImplementedOpList, toBeImplementedOpList, (concept->isInterface() && noClassInPath));
+ UMLOperationList opl = concept->getOpList();
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ if (concept->isInterface() && noClassInPath) {
+ if (!DWriter::dMethodInList(op,toBeImplementedOpList))
+ toBeImplementedOpList.append(op);
+ }
+ else
+ {
+ if (!DWriter::dMethodInList(op, yetImplementedOpList))
+ yetImplementedOpList.append(op);
+ }
+ }
+ }
+
+}
+
+void DWriter::getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opList ) {
+ UMLOperationList yetImplementedOpList;
+ UMLOperationList toBeImplementedOpList;
+
+ getSuperImplementedOperations(c,yetImplementedOpList, toBeImplementedOpList);
+ for (UMLOperation *op = toBeImplementedOpList.first(); op; op = toBeImplementedOpList.next())
+ {
+ if ( ! DWriter::dMethodInList(op, yetImplementedOpList) && ! DWriter::dMethodInList(op, opList) )
+ opList.append(op);
+ }
+}
+
+void DWriter::writeOperations(UMLClassifier *c, QTextStream &d) {
+ UMLOperationList opl;
+ UMLOperationList oppub,opprot,oppriv;
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ opl = c->getOpList();
+ if (! c->isInterface()) {
+ getInterfacesOperationsToBeImplemented(c, opl);
+ }
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default: //TODO: package, export
+ break;
+ }
+ }
+
+ // do people REALLY want these comments? Hmm.
+ /*
+ if(forceSections() || oppub.count())
+ {
+ writeComment("public operations",m_indentation,d);
+ writeBlankLine(d);
+ }
+ */
+
+ if (oppub.count() > 0) {
+ writeProtectionMod(Uml::Visibility::Public, d);
+
+ writeOperations(oppub,d);
+ }
+
+ if (opprot.count() > 0) {
+ writeProtectionMod(Uml::Visibility::Protected, d);
+
+ writeOperations(opprot, d);
+ }
+
+ if (oppriv.count() > 0) {
+ writeProtectionMod(Uml::Visibility::Private, d);
+
+ writeOperations(oppriv, d);
+ }
+
+}
+
+void DWriter::writeOperations(UMLOperationList &oplist, QTextStream &d) {
+ UMLAttributeList atl;
+ QString str;
+
+ // generate method decl for each operation given
+ for(UMLOperation *op=oplist.first(); op; op=oplist.next()) {
+ QString returnStr = "";
+ // write documentation
+
+ QString methodReturnType = fixTypeName(op->getTypeName());
+
+ //TODO: return type comment
+ if(methodReturnType != "void") {
+ returnStr += "@return " + methodReturnType + m_endl;
+ }
+
+ str = ""; // reset for next method
+ if (op->getAbstract() && !isInterface) str += "abstract ";
+ if (op->getStatic()) str += "static ";
+
+ str += methodReturnType + ' ' +cleanName(op->getName()) + '(';
+
+ atl = op->getParmList();
+ int i = atl.count();
+ int j = 0;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next(), j++) {
+ QString typeName = fixTypeName(at->getTypeName());
+ QString atName = cleanName(at->getName());
+ str += typeName + ' ' + atName +
+ (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""))
+ + ((j < i-1)?", ":"");
+ returnStr += "@param " + atName+' '+at->getDoc() + m_endl;
+ }
+
+ str+= ')';
+
+ // method only gets a body IF its not abstract
+ if (op->getAbstract() || isInterface)
+ str += ';'; // terminate now
+ else
+ str += startline + '{' + startline + '}'; // empty method body
+
+ // write it out
+ writeDocumentation("", op->getDoc(), returnStr, m_indentation, d);
+ d << m_indentation << str << m_endl << m_endl;
+ }
+}
+
+QString DWriter::fixInitialStringDeclValue(QString value, QString type) {
+ // check for strings only
+ if (!value.isEmpty() && type == "String") {
+ if (!value.startsWith("\""))
+ value.prepend("\"");
+ if (!value.endsWith("\""))
+ value.append("\"");
+ }
+ return value;
+}
+
+QString DWriter::scopeToDDecl(Uml::Visibility scope) {
+ QString scopeString;
+
+ switch(scope) {
+ case Uml::Visibility::Public: scopeString = "public"; break;
+ case Uml::Visibility::Protected: scopeString = "protected"; break;
+ case Uml::Visibility::Private: scopeString = "private"; break;
+ default: break; //TODO: package and export
+ }
+
+ return scopeString;
+}
+
+// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
+QString DWriter::getUMLObjectName(UMLObject *obj) {
+ return(obj!=0)?obj->getName():QString("NULL");
+}
+
+QString DWriter::deCapitaliseFirstLetter(QString string) {
+ string.replace( 0, 1, string[0].lower());
+ return string;
+}
+
+QString DWriter::pluralize(QString string) {
+ return string + (string.right(1) == "s" ? "es" : "s");
+}
+
+QString DWriter::unPluralize(QString string) {
+ // does not handle special cases liek datum -> data, etc.
+
+ if (string.length() > 2 && string.right(3) == "ses") {
+ return string.left(string.length() - 2);
+ }
+
+ if (string.right(1) == "s") {
+ return string.left(string.length() - 1);
+ }
+
+ return string;
+}
+
+void DWriter::writeBlankLine(QTextStream &d) {
+ d << m_endl;
+}
+
diff --git a/umbrello/umbrello/codegenerators/dwriter.h b/umbrello/umbrello/codegenerators/dwriter.h
new file mode 100644
index 00000000..38828359
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/dwriter.h
@@ -0,0 +1,276 @@
+
+/***************************************************************************
+ * *
+ * 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) 2007 Jari-Matti Mäkelä <jmjm@iki.fi> *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/***************************************************************************
+ This is the "old" code generator that does not support code editing
+ in the Modeller but uses significantly less file space because the
+ source code is not replicated in the XMI file.
+ ***************************************************************************/
+
+#ifndef DWRITER_H
+#define DWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+#include "../umlassociationlist.h"
+
+class UMLOperation;
+
+/**
+ * class DWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate a d source file for
+ * that concept
+ */
+class DWriter : public SimpleCodeGenerator {
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ DWriter();
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~DWriter();
+
+ /**
+ * call this method to generate d code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "D"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * Overrides method from class CodeGenerator
+ */
+ QStringList defaultDatatypes();
+
+private:
+
+ /**
+ * Writes the module declaration.
+ */
+ void writeModuleDecl(UMLClassifier *c, QTextStream &d);
+
+ /**
+ * Writes the module imports.
+ */
+ void writeModuleImports(UMLClassifier *c, QTextStream &d);
+
+ /**
+ * Writes class's documentation then the class header
+ * public abstract class Foo extents {
+ */
+ void writeClassDecl(UMLClassifier *c, QTextStream &d);
+
+ /**
+ * Writes the comment and class constructor
+ */
+ void writeConstructor(UMLClassifier *c, QTextStream &d);
+
+ /**
+ * return true if the two operations have the same name and the same parameters
+ * @param op1 first operation to be compared
+ * @param op2 second operation to be compared
+ */
+ static bool compareDMethod(UMLOperation *op1, UMLOperation *op2);
+
+ /**
+ * return true if the operation is in the list
+ * @param umlOp operation to be searched
+ * @param opl list of operations
+ */
+ static bool dMethodInList(UMLOperation *umlOp, UMLOperationList &opl);
+
+ /**
+ * get all operations which a given class inherit from all its super interfaces and get all operations
+ * which this given class inherit from all its super classes
+ * @param c the class for which we are generating code
+ * @param yetImplementedOpList the list of yet implemented operations
+ * @param toBeImplementedOpList the list of to be implemented operations
+ * @param noClassInPath tells if there is a class between the base class and the current interface
+ */
+ void getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath = true);
+
+ /**
+ * get all operations which a given class inherit from all its super interfaces and that should be implemented
+ * @param c the class for which we are generating code
+ * @param opl the list of operations used to append the operations
+ */
+ void getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opl);
+
+ /**
+ * write all operations for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * write a list of operations for a given class
+ * @param list the list of operations you want to write
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLOperationList &list, QTextStream &j);
+
+ /**
+ * write all attributes for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * Writes the protection modifier line.
+ * @param visibility protection modifier
+ * @param d text stream
+ */
+ void writeProtectionMod(Uml::Visibility visibility, QTextStream &d);
+
+ /**
+ * Writes attribute declarations with a specific
+ * protection modifier.
+ * @param prot the protection modifier
+ * @param atlist attribute list
+ * @param d text stream
+ */
+ void writeAttributeDecl(Uml::Visibility visibility, UMLAttributeList &atlist, QTextStream &d);
+
+ /**
+ * writes the Attribute declarations
+ * @param atpub List of public attributes
+ * @param atprot list of protected attributes
+ * @param atpriv list of private attributes
+ * @param d text stream
+ */
+ void writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
+ UMLAttributeList &atpriv, QTextStream &d );
+
+ /**
+ * Searches a list of associations for appropriate ones to write out as attributes
+ */
+ void writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &d);
+
+ /**
+ * Writes out an association as an attribute using Vector
+ */
+ void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi,
+ QString doc, Uml::Visibility visib, QTextStream &d);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in atpub
+ */
+ void writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &d);
+
+ /**
+ * calls @ref writeAssociationRoleMethod() on each of the associations in the given list
+ */
+ void writeAssociationMethods(UMLAssociationList associations, UMLClassifier *thisClass,
+ QTextStream &d);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() or @ref
+ * writeVectorAttributeAccessorMethods() on the assocaition
+ * role
+ */
+ void writeAssociationRoleMethod(QString fieldClassName, QString roleName, QString multi,
+ QString description, Uml::Visibility visib, Uml::Changeability_Type change,
+ QTextStream &d);
+
+ /**
+ * Writes getFoo() and setFoo() accessor methods for the attribute
+ */
+ void writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ bool isFinal, QTextStream &d);
+
+ /**
+ * Writes addFoo() and removeFoo() accessor methods for the Vector attribute
+ */
+ void writeVectorAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ QTextStream &d);
+
+ /**
+ * Writes a // style comment
+ */
+ void writeComment(const QString &text, const QString &indent, QTextStream &d, bool dDocStyle=false);
+
+ /**
+ * Writes a documentation comment
+ */
+ void writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &d);
+
+ /**
+ * Returns the name of the given object (if it exists)
+ */
+ QString getUMLObjectName(UMLObject *obj);
+
+ /**
+ * Lowers the case of the first letter in the given string
+ */
+ QString deCapitaliseFirstLetter(QString string);
+
+ /**
+ * Returns the plural form of a subject.
+ */
+ QString pluralize(QString string);
+
+ /**
+ * Returns the non-plural form of a subject.
+ */
+ QString unPluralize(QString string);
+
+ /**
+ * Replaces `string' with `String' and `bool' with `boolean'
+ */
+ QString fixTypeName(const QString& string);
+
+ /**
+ * check that initial values of strings have quotes around them
+ */
+ QString fixInitialStringDeclValue(QString value, QString type);
+
+ /**
+ * Write a blank line
+ */
+ void writeBlankLine(QTextStream& d);
+
+ /**
+ * a little method for converting scope to string value
+ */
+ QString scopeToDDecl(Uml::Visibility scope);
+
+ /**
+ * A \n, used at the end of each line
+ */
+ QString startline;
+
+ /**
+ * Whether or not this concept is an interface.
+ */
+ bool isInterface;
+
+};
+
+
+#endif // DWRITER_H
+
diff --git a/umbrello/umbrello/codegenerators/idlwriter.cpp b/umbrello/umbrello/codegenerators/idlwriter.cpp
new file mode 100644
index 00000000..a893acc3
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/idlwriter.cpp
@@ -0,0 +1,482 @@
+/***************************************************************************
+ * copyright (C) 2003-2005 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "idlwriter.h"
+
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../classifierlistitem.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../package.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+IDLWriter::IDLWriter() : SimpleCodeGenerator(false) {
+}
+
+IDLWriter::~IDLWriter() {}
+
+bool IDLWriter::isOOClass(UMLClassifier *c) {
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant" || stype == "CORBAEnum" ||
+ stype == "CORBAStruct" || stype == "CORBAUnion" ||
+ stype == "CORBASequence" || stype == "CORBAArray" ||
+ stype == "CORBATypedef")
+ return false;
+
+ // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are
+ // assumed to be OO classes.
+ return true;
+}
+
+bool IDLWriter::assocTypeIsMappableToAttribute(Uml::Association_Type at) {
+ return (at == Uml::at_Aggregation || at == Uml::at_Association ||
+ at == Uml::at_Composition || at == Uml::at_UniAssociation);
+}
+
+/**
+ * returns "IDL"
+ */
+Uml::Programming_Language IDLWriter::getLanguage() {
+ return Uml::pl_IDL;
+}
+
+void IDLWriter::computeAssocTypeAndRole
+(UMLAssociation *a, UMLClassifier *c, QString& typeName, QString& roleName)
+{
+ // Determine which is the "remote" end of the association:
+ bool IAmRoleA = true;
+ UMLObject *other = a->getObject(Uml::B);
+ Uml::Association_Type at = a->getAssocType();
+ if (c->getName() == other->getName()) {
+ if (at == Uml::at_Aggregation || at == Uml::at_Composition ||
+ at == Uml::at_UniAssociation) {
+ // Assuming unidirectional association, and we are
+ // at the "wrong" side.
+ // Returning roleName = QString::null tells caller to
+ // skip this association at this side.
+ roleName = QString();
+ return;
+ }
+ IAmRoleA = false;
+ other = a->getObject(Uml::A);
+ }
+ // Construct the type name:
+ typeName = cleanName(other->getName());
+ QString multiplicity;
+ if (IAmRoleA)
+ multiplicity = a->getMulti(Uml::B);
+ else
+ multiplicity = a->getMulti(Uml::A);
+ if (!multiplicity.isEmpty() && multiplicity != "1")
+ typeName.append("Vector");
+ // Construct the member name:
+ if (IAmRoleA)
+ roleName = a->getRoleName(Uml::B);
+ else
+ roleName = a->getRoleName(Uml::A);
+ if (roleName.isEmpty()) {
+ roleName = a->getName();
+ if (roleName.isEmpty()) {
+ roleName = "m_" + typeName;
+ }
+ }
+}
+
+void IDLWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ const bool isClass = !c->isInterface();
+ QString classname = cleanName(c->getName());
+
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".idl");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile file;
+ if (!openFile(file, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // Start generating the code.
+
+ QTextStream idl(&file);
+ //try to find a heading file(license, comments, etc)
+ QString str;
+ str = getHeadingFile(".idl");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), file.name());
+ idl << str << m_endl;
+ }
+
+ // Write includes.
+ UMLPackageList includes;
+ findObjectsRelated(c, includes);
+ if (includes.count()) {
+ for (UMLPackage *conc = includes.first(); conc; conc = includes.next()) {
+ if (conc->getBaseType() == Uml::ot_Datatype)
+ continue;
+ QString incName = findFileName(conc, ".idl");
+ if (!incName.isEmpty())
+ idl << "#include \"" << incName << "\"" << m_endl;
+ }
+ idl << m_endl;
+ }
+
+ // Generate the module declaration(s) for the package(s) in which
+ // we are embedded.
+ UMLPackageList pkgList = c->getPackages();
+ UMLPackage *pkg;
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ idl << getIndent() << "module " << pkg->getName() << " {" << m_endl << m_endl;
+ m_indentLevel++;
+ }
+
+ // Write class Documentation if non-empty or if force option set.
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ idl << "//" << m_endl;
+ idl << "// class " << classname << m_endl;
+ idl << formatDoc(c->getDoc(), "// ");
+ idl << m_endl;
+ }
+
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLClassifierListItemList litList = c->getFilteredList(Uml::ot_EnumLiteral);
+ uint i = 0;
+ idl << getIndent() << "enum " << classname << " {" << m_endl;
+ m_indentLevel++;
+ for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ idl << getIndent() << enumLiteral;
+ if (++i < litList.count())
+ idl << ",";
+ idl << m_endl;
+ }
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ // Close the modules inside which we might be nested.
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ }
+ return;
+ }
+ if (! isOOClass(c)) {
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant") {
+ kError() << "The stereotype " << stype << " cannot be applied to "
+ << c->getName() << ", but only to attributes." << endl;
+ return;
+ }
+ if (!isClass) {
+ kError() << "The stereotype " << stype
+ << " cannot be applied to " << c->getName()
+ << ", but only to classes." << endl;
+ return;
+ }
+ if (stype == "CORBAEnum") {
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ idl << getIndent() << "enum " << classname << " {" << m_endl;
+ m_indentLevel++;
+ uint i = 0;
+ for (at = atl.first(); at; at = atl.next()) {
+ QString enumLiteral = cleanName(at->getName());
+ idl << getIndent() << enumLiteral;
+ if (++i < atl.count())
+ idl << ",";
+ idl << m_endl;
+ }
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ } else if (stype == "CORBAStruct") {
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ idl << getIndent() << "struct " << classname << " {" << m_endl;
+ m_indentLevel++;
+ for (at = atl.first(); at; at = atl.next()) {
+ QString name = cleanName(at->getName());
+ idl << getIndent() << at->getTypeName() << " " << name << ";" << m_endl;
+ // Initial value not possible in IDL.
+ }
+ UMLAssociationList compositions = c->getCompositions();
+ if (!compositions.isEmpty()) {
+ idl << getIndent() << "// Compositions." << m_endl;
+ for (UMLAssociation *a = compositions.first(); a; a = compositions.next()) {
+ QString memberType, memberName;
+ computeAssocTypeAndRole(a, c, memberType, memberName);
+ idl << getIndent() << memberType << " " << memberName << ";" << m_endl;
+ }
+ }
+ UMLAssociationList aggregations = c->getAggregations();
+ if (!aggregations.isEmpty()) {
+ idl << getIndent() << "// Aggregations." << m_endl;
+ for (UMLAssociation *a = aggregations.first(); a; a = aggregations.next()) {
+ QString memberType, memberName;
+ computeAssocTypeAndRole(a, c, memberType, memberName);
+ idl << getIndent() << memberType << " " << memberName << ";" << m_endl;
+ }
+ }
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ } else if (stype == "CORBAUnion") {
+ idl << getIndent() << "// " << stype << " " << c->getName()
+ << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if (stype == "CORBATypedef") {
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLClassifier* firstParent = superclasses.first();
+ idl << getIndent() << "typedef " << firstParent->getName() << " "
+ << c->getName() << ";" << m_endl << m_endl;
+ } else {
+ idl << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl;
+ }
+ // Close the modules inside which we might be nested.
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ }
+ return;
+ }
+
+ idl << getIndent();
+ if (c->getAbstract())
+ idl << "abstract ";
+ bool isValuetype = (c->getStereotype() == "CORBAValue");
+ if (isValuetype)
+ idl << "valuetype ";
+ else
+ idl << "interface ";
+ idl << c->getName();
+ UMLClassifierList superclasses = c->getSuperClasses();
+ if (! superclasses.isEmpty()) {
+ idl << " : ";
+ UMLClassifier *parent = superclasses.first();
+ int n_parents = superclasses.count();
+ while (n_parents--) {
+ idl << parent->getFullyQualifiedName("::");
+ if (n_parents)
+ idl << ", ";
+ parent = superclasses.next();
+ }
+ }
+ idl << " {" << m_endl << m_endl;
+ m_indentLevel++;
+
+ // Generate auxiliary declarations for multiplicity of associations
+ UMLAssociation *a;
+ bool didComment = false;
+ UMLAssociationList assocs = c->getAssociations();
+ for (a = assocs.first(); a; a = assocs.next()) {
+ if (! assocTypeIsMappableToAttribute(a->getAssocType()))
+ continue;
+ QString multiplicity = a->getMulti(Uml::A);
+ if (multiplicity.isEmpty() || multiplicity == "1")
+ continue;
+ if (!didComment) {
+ idl << getIndent() << "// Types for association multiplicities" << m_endl << m_endl;
+ didComment = true;
+ }
+ UMLClassifier* other = (UMLClassifier*)a->getObject(Uml::A);
+ QString bareName = cleanName(other->getName());
+ idl << getIndent() << "typedef sequence<" << other->getFullyQualifiedName("::")
+ << "> " << bareName << "Vector;" << m_endl << m_endl;
+ }
+
+ // Generate public attributes.
+ if (isClass) {
+ UMLAttributeList atl = c->getAttributeList();
+ if (forceSections() || atl.count()) {
+ idl << getIndent() << "// Attributes:" << m_endl << m_endl;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ QString attName = cleanName(at->getName());
+ Uml::Visibility scope = at->getVisibility();
+ idl << getIndent();
+ if (isValuetype) {
+ if (scope == Uml::Visibility::Public)
+ idl << "public ";
+ else
+ idl << "private ";
+ } else {
+ if (scope != Uml::Visibility::Public) {
+ idl << "// visibility should be: "
+ << scope.toString()
+ << m_endl;
+ idl << getIndent();
+ }
+ idl << "attribute ";
+ }
+ idl << at->getTypeName() << " " << attName << ";"
+ << m_endl << m_endl;
+ }
+ }
+ }
+
+ // Generate public operations.
+ UMLOperationList opl(c->getOpList());
+ UMLOperationList oppub;
+ UMLOperation *op;
+ for (op = opl.first(); op; op = opl.next()) {
+ if (op->getVisibility() == Uml::Visibility::Public)
+ oppub.append(op);
+ }
+ if (forceSections() || oppub.count()) {
+ idl << getIndent() << "// Public methods:" << m_endl << m_endl;
+ for (op = oppub.first(); op; op = oppub.next())
+ writeOperation(op, idl);
+ idl << m_endl;
+ }
+
+
+ if (forceSections() || !assocs.isEmpty()) {
+ idl << getIndent() << "// Associations:" << m_endl << m_endl;
+ for (a = assocs.first(); a; a = assocs.next()) {
+ Uml::Association_Type at = a->getAssocType();
+ if (! assocTypeIsMappableToAttribute(at))
+ continue;
+ QString typeName, roleName;
+ computeAssocTypeAndRole(a, c, typeName, roleName);
+ if (roleName.isEmpty()) // presumably because we are at the "wrong" end
+ continue;
+ idl << getIndent() << "// " << UMLAssociation::typeAsString(at) << m_endl;
+ idl << getIndent();
+ if (isValuetype)
+ idl << "public ";
+ else
+ idl << "attribute ";
+ idl << typeName << " " << roleName << ";" << m_endl;
+ }
+ idl << m_endl;
+ }
+
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+
+ // Close the modules inside which we might be nested.
+ for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
+ m_indentLevel--;
+ idl << getIndent() << "};" << m_endl << m_endl;
+ }
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+
+void IDLWriter::writeOperation(UMLOperation *op, QTextStream &idl, bool is_comment) {
+ UMLAttributeList atl = op->getParmList();
+ QString rettype = op->getTypeName();
+
+ if (rettype.isEmpty())
+ rettype = "void";
+ idl << getIndent();
+ if (is_comment)
+ idl << "// ";
+ idl << rettype << " " << cleanName(op->getName()) << " (";
+ if (atl.count()) {
+ idl << m_endl;
+ m_indentLevel++;
+ uint i = 0;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ idl << getIndent();
+ if (is_comment)
+ idl << "// ";
+ Uml::Parameter_Direction pk = at->getParmKind();
+ if (pk == Uml::pd_Out)
+ idl << "out ";
+ else if (pk == Uml::pd_InOut)
+ idl << "inout ";
+ else
+ idl << "in ";
+ idl << at->getTypeName() << " " << cleanName(at->getName());
+ if (++i < atl.count())
+ idl << "," << m_endl;
+ }
+ m_indentLevel--;
+ }
+ idl << ");" << m_endl << m_endl;
+}
+
+QStringList IDLWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("boolean");
+ l.append("char");
+ l.append("octet");
+ l.append("short");
+ l.append("unsigned short");
+ l.append("long");
+ l.append("unsigned long");
+ l.append("float");
+ l.append("double");
+ l.append("string");
+ l.append("any");
+ return l;
+}
+
+const QStringList IDLWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "any"
+ << "attribute"
+ << "boolean"
+ << "case"
+ << "char"
+ << "const"
+ << "context"
+ << "default"
+ << "double"
+ << "enum"
+ << "exception"
+ << "FALSE"
+ << "float"
+ << "in"
+ << "inout"
+ << "interface"
+ << "long"
+ << "module"
+ << "octet"
+ << "oneway"
+ << "out"
+ << "raises"
+ << "readonly"
+ << "sequence"
+ << "short"
+ << "string"
+ << "struct"
+ << "switch"
+ << "TRUE"
+ << "typedef"
+ << "union"
+ << "unsigned"
+ << "void";
+ }
+
+ return keywords;
+}
+
+
diff --git a/umbrello/umbrello/codegenerators/idlwriter.h b/umbrello/umbrello/codegenerators/idlwriter.h
new file mode 100644
index 00000000..c44cabd6
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/idlwriter.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ idlwriter.h - description
+ -------------------
+ begin : Sat Jan 4 2003
+ copyright : (C) 2003 by Oliver Kellogg
+ email : okellogg@users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef IDLWRITER_H
+#define IDLWRITER_H
+
+#include "simplecodegenerator.h"
+
+class UMLAssociation;
+class UMLOperation;
+
+/**
+ * Class IDLWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate an IDL interface for that
+ * concept.
+ */
+class IDLWriter : public SimpleCodeGenerator {
+public:
+
+ IDLWriter ();
+ virtual ~IDLWriter ();
+
+ /**
+ * call this method to generate IDL code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass (UMLClassifier *c);
+
+ /**
+ * returns "IDL"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ QStringList defaultDatatypes();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * write one operation
+ * @param op the class for which we are generating code
+ * @param idl the stream associated with the output file
+ */
+ void writeOperation(UMLOperation* op, QTextStream& idl, bool is_comment = false);
+
+ void computeAssocTypeAndRole(UMLAssociation* a, UMLClassifier *c,
+ QString& typeName, QString& roleName);
+
+ static bool isOOClass(UMLClassifier* c);
+
+ static bool assocTypeIsMappableToAttribute(Uml::Association_Type at);
+
+};
+
+#endif // IDLWRITER_H
diff --git a/umbrello/umbrello/codegenerators/javaantcodedocument.cpp b/umbrello/umbrello/codegenerators/javaantcodedocument.cpp
new file mode 100644
index 00000000..a3a174a3
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaantcodedocument.cpp
@@ -0,0 +1,312 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jun 24 2003
+ */
+
+// own header
+#include "javaantcodedocument.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "javacodegenerator.h"
+#include "xmlcodecomment.h"
+#include "xmlelementcodeblock.h"
+#include "codegenfactory.h"
+#include "../umldoc.h"
+#include "../uml.h"
+
+
+// Constructors/Destructors
+//
+
+JavaANTCodeDocument::JavaANTCodeDocument ( )
+{
+ setFileName("build"); // default name
+ setFileExtension(".xml");
+ setID("ANTDOC"); // default id tag for this type of document
+}
+
+JavaANTCodeDocument::~JavaANTCodeDocument ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+/**
+ * create a new CodeBlockWithComments object belonging to this CodeDocument.
+ * @return CodeBlockWithComments
+ */
+/*
+CodeBlockWithComments * JavaANTCodeDocument::newCodeBlockWithComments ( ) {
+ return new XMLElementCodeBlock(this,"empty");
+}
+*/
+
+HierarchicalCodeBlock * JavaANTCodeDocument::newHierarchicalCodeBlock ( ) {
+ return new XMLElementCodeBlock(this,"empty");
+}
+
+// Sigh. NOT optimal. The only reason that we need to have this
+// is so we can create the XMLNodes, if needed.
+// would be better if we could create a handler interface that each
+// codeblock used so all we have to do here is add the handler
+void JavaANTCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root)
+{
+
+ QDomNode tnode = root.firstChild();
+ QDomElement telement = tnode.toElement();
+ bool loadCheckForChildrenOK = false;
+ while( !telement.isNull() ) {
+ QString nodeName = telement.tagName();
+
+ if( nodeName == "textblocks" ) {
+
+ QDomNode node = telement.firstChild();
+ QDomElement element = node.toElement();
+
+ // if there is nothing to begin with, then we don't worry about it
+ loadCheckForChildrenOK = element.isNull() ? true : false;
+
+ while( !element.isNull() ) {
+ QString name = element.tagName();
+
+ if( name == "codecomment" ) {
+ CodeComment * block = new XMLCodeComment(this);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeComment to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeaccessormethod" ||
+ name == "ccfdeclarationcodeblock"
+ ) {
+ QString acctag = element.attribute("tag","");
+ // search for our method in the
+ TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
+ if(!tb || !addTextBlock(tb))
+ {
+ kError()<<"Unable to add codeclassfield child method to:"<<this<<endl;
+ // DON'T delete
+ } else
+ loadCheckForChildrenOK= true;
+
+ } else
+ if( name == "codeblock" ) {
+ CodeBlock * block = newCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeBlock to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeblockwithcomments" ) {
+ CodeBlockWithComments * block = newCodeBlockWithComments();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add codeBlockwithcomments to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "header" ) {
+ // do nothing.. this is treated elsewhere
+ } else
+ if( name == "hierarchicalcodeblock" ) {
+ HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeoperation" ) {
+ // find the code operation by id
+ QString id = element.attribute("parent_id","-1");
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+ if(op) {
+ CodeOperation * block = 0;
+ kError() << "TODO: implement CodeGenFactory::newCodeOperation() for JavaANTCodeDocument" << endl;
+ break; // remove when above is implemented
+ block->loadFromXMI(element);
+ if(addTextBlock(block))
+ loadCheckForChildrenOK= true;
+ else
+ {
+ kError()<<"Unable to add codeoperation to:"<<this<<endl;
+ block->deleteLater();
+ }
+ } else
+ kError()<<"Unable to find operation create codeoperation for:"<<this<<endl;
+ } else
+ if( name == "xmlelementblock" ) {
+ QString xmltag = element.attribute("nodeName","UNKNOWN");
+ XMLElementCodeBlock * block = new XMLElementCodeBlock(this,xmltag);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add XMLelement to Java ANT document:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ }
+ /*
+ // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
+ else
+ kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl;
+ */
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+ break;
+ }
+
+ tnode = telement.nextSibling();
+ telement = tnode.toElement();
+ }
+
+ if(!loadCheckForChildrenOK)
+ {
+ CodeDocument * test = dynamic_cast<CodeDocument*>(this);
+ if(test)
+ {
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
+ } else {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
+ if(hb)
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
+ else
+ kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
+ }
+ }
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void JavaANTCodeDocument::setAttributesFromNode ( QDomElement & root)
+{
+
+ // superclass save
+ CodeDocument::setAttributesFromNode(root);
+
+ // now set local attributes
+ // setPackage(root.attribute("package",""));
+
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void JavaANTCodeDocument::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void JavaANTCodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement)
+{
+
+ // superclass call
+ CodeDocument::setAttributesOnNode(doc,docElement);
+
+ // now set local attributes/fields
+ //FIX
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void JavaANTCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement docElement = doc.createElement( "codedocument" );
+
+ setAttributesOnNode(doc, docElement);
+
+ root.appendChild( docElement );
+}
+
+// we add in our code blocks that describe how to generate
+// the project here...
+void JavaANTCodeDocument::updateContent( ) {
+ // FIX : fill in more content based on classes
+ // which exist
+ CodeBlockWithComments * xmlDecl = getCodeBlockWithComments("xmlDecl","",0);
+ xmlDecl->setText("<?xml version=\"1.0\"?>");
+ addTextBlock(xmlDecl);
+
+ XMLElementCodeBlock * rootNode = new XMLElementCodeBlock(this, "project", "Java ANT build document");
+ rootNode->setTag("projectDecl");
+ addTextBlock(rootNode);
+
+ // <project name="XDF" default="help" basedir=".">
+ //HierarchicalCodeBlock * projDecl = xmlDecl->getHierarchicalCodeBlock("projectDecl", "Java ANT build document", 1);
+
+ // set some global properties for the build
+ /*
+ <!-- set global properties for this build -->
+ <!-- paths -->
+ <property name="docApi.dir" value="docs/api"/>
+ <property name="path" value="gov/nasa/gsfc/adc/xdf"/>
+ <property name="src" value="src/${path}/"/>
+ <property name="top" value="."/>
+ <property name="build" value="${top}/gov"/>
+ <property name="buildDir" value="${path}"/>
+ <!-- compiler directives -->
+ <property name="build.compiler" value="modern"/>
+ <property name="useDeprecation" value="no"/>
+ <property name="jarname" value="${project}.jar"/>
+ */
+
+}
+
+// We overwritten by Java language implementation to get lowercase path
+QString JavaANTCodeDocument::getPath ( )
+{
+
+ QString path = getPackage();
+
+ // Replace all white spaces with blanks
+ path.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ path.replace(QRegExp(" "), "_");
+
+ path.replace(QRegExp("\\."),"/");
+ path.replace(QRegExp("::"), "/");
+
+ path.lower();
+
+ return path;
+
+}
+
+
+#include "javaantcodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/javaantcodedocument.h b/umbrello/umbrello/codegenerators/javaantcodedocument.h
new file mode 100644
index 00000000..9d7372f3
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaantcodedocument.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Jun 24 2003
+ */
+
+
+
+#ifndef JAVAANTCODEDOCUMENT_H
+#define JAVAANTCODEDOCUMENT_H
+
+#include <qstring.h>
+#include <qdom.h>
+
+#include "../codedocument.h"
+
+/**
+ * class JavaANTCodeDocument
+ * Represents
+ */
+
+class JavaANTCodeDocument : public CodeDocument
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ JavaANTCodeDocument ( );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaANTCodeDocument ( );
+
+ QString getPath ( );
+
+ void updateContent();
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /**
+ * create a new HierarchicalCodeBlock object belonging to this CodeDocument.
+ * @return HierarchicalCodeBlock
+ */
+ virtual HierarchicalCodeBlock * newHierarchicalCodeBlock ( );
+
+ /**
+ * create a new CodeBlockWithComments object belonging to this CodeDocument.
+ * @return CodeBlockWithComments
+ */
+ // virtual CodeBlockWithComments * newCodeBlockWithComments ( );
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /**
+ * need to overwrite this for java since we need to pick up the
+ * xml declaration blocks.
+ */
+ virtual void loadChildTextBlocksFromNode ( QDomElement & root);
+
+private:
+
+
+
+};
+
+#endif // JAVAANTCODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp
new file mode 100644
index 00000000..0e4ccdbf
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 16 2003
+ */
+#include "javaclassdeclarationblock.h"
+#include "javacodedocumentation.h"
+#include "../codegenerator.h"
+#include "../codegenerationpolicy.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+JavaClassDeclarationBlock::JavaClassDeclarationBlock
+ ( JavaClassifierCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment)
+ : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment)
+{
+ init(parentDoc, comment);
+}
+
+JavaClassDeclarationBlock::~JavaClassDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void JavaClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "javaclassdeclarationblock" );
+
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void JavaClassDeclarationBlock::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * update the start and end text for this ownedhierarchicalcodeblock.
+ */
+void JavaClassDeclarationBlock::updateContent ( )
+{
+
+ JavaClassifierCodeDocument *parentDoc = dynamic_cast<JavaClassifierCodeDocument*>(getParentDocument());
+ UMLClassifier *c = parentDoc->getParentClassifier();
+ CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
+ QString endLine = commonPolicy->getNewLineEndingChars();
+ bool isInterface = parentDoc->parentIsInterface(); // a little shortcut
+ QString JavaClassName = parentDoc->getJavaClassName(c->getName());
+
+ // COMMENT
+ if(isInterface)
+ getComment()->setText("Interface "+JavaClassName+endLine+c->getDoc());
+ else
+ getComment()->setText("Class "+JavaClassName+endLine+c->getDoc());
+
+ bool forceDoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
+ if(forceDoc || !c->getDoc().isEmpty())
+ getComment()->setWriteOutText(true);
+ else
+ getComment()->setWriteOutText(false);
+
+
+ // Now set START/ENDING Text
+ QString startText = "";
+ // In Java, we need declare abstract only on classes
+ if (c->getAbstract() && !isInterface)
+ startText.append("abstract ");
+
+ if (c->getVisibility() != Uml::Visibility::Public) {
+ // We should probably emit a warning in here .. java doesn't like to allow
+ // private/protected classes. The best we can do (I believe)
+ // is to let these declarations default to "package visibility"
+ // which is a level between traditional "private" and "protected"
+ // scopes. To get this visibility level we just print nothing..
+ } else
+ startText.append("public ");
+
+ if(parentDoc->parentIsInterface())
+ startText.append("interface ");
+ else
+ startText.append("class ");
+
+ startText.append(JavaClassName);
+
+ // write inheritances out
+ UMLClassifierList superclasses =
+ c->findSuperClassConcepts(UMLClassifier::CLASS);
+ UMLClassifierList superinterfaces =
+ c->findSuperClassConcepts(UMLClassifier::INTERFACE);
+ int nrof_superclasses = superclasses.count();
+ int nrof_superinterfaces = superinterfaces.count();
+
+ // write out inheritance
+ int i = 0;
+ if(nrof_superclasses >0)
+ startText.append(" extends ");
+ for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next())
+ {
+ startText.append(parentDoc->cleanName(concept->getName()));
+ if(i != (nrof_superclasses-1))
+ startText.append(", ");
+ i++;
+ }
+
+ // write out what we 'implement'
+ i = 0;
+ if(nrof_superinterfaces >0)
+ {
+ // In Java interfaces "extend" other interfaces. Classes "implement" interfaces
+ if(isInterface)
+ startText.append(" extends ");
+ else
+ startText.append(" implements ");
+ }
+ for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next())
+ {
+ startText.append(parentDoc->cleanName(concept->getName()));
+ if(i != (nrof_superinterfaces-1))
+ startText.append(", ");
+ i++;
+ }
+
+ // Set the header and end text for the hier.codeblock
+ setStartText(startText+" {");
+
+ // setEndText("}"); // not needed
+
+}
+
+void JavaClassDeclarationBlock::init (JavaClassifierCodeDocument *parentDoc, const QString &comment)
+{
+
+ setComment(new JavaCodeDocumentation(parentDoc));
+ getComment()->setText(comment);
+
+ setEndText("}");
+
+ updateContent();
+
+}
+
+
+#include "javaclassdeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h
new file mode 100644
index 00000000..136df809
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h
@@ -0,0 +1,66 @@
+
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 16 2003
+ */
+
+#ifndef JAVACLASSDECLARATIONBLOCK_H
+#define JAVACLASSDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "javaclassifiercodedocument.h"
+#include "../ownedhierarchicalcodeblock.h"
+
+class JavaClassDeclarationBlock : public OwnedHierarchicalCodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ explicit JavaClassDeclarationBlock ( JavaClassifierCodeDocument * parentDoc, const QString &start = "", const QString &endText = "}", const QString &comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaClassDeclarationBlock ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+protected:
+
+ /**
+ * Update the start/end text of this codeblock.
+ */
+ void updateContent ( );
+
+private:
+
+ void init (JavaClassifierCodeDocument * parent, const QString &comment);
+
+};
+
+#endif // JAVACLASSDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp
new file mode 100644
index 00000000..44e6f242
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+/**
+ We carve the Java document up into sections as follows:
+
+ * header
+ * package declaration
+ * import statements
+ * class declaration
+ * guts of the class (e.g. field decl, accessor methods, operations, dependant classes)
+*/
+
+// own header
+#include "javaclassifiercodedocument.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <qregexp.h>
+
+// local includes
+#include "javacodegenerator.h"
+#include "javacodecomment.h"
+#include "javaclassdeclarationblock.h"
+#include "javacodeclassfielddeclarationblock.h"
+#include "codegen_utils.h"
+#include "../classifier.h"
+#include "../codegenerationpolicy.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+JavaClassifierCodeDocument::JavaClassifierCodeDocument ( UMLClassifier * concept )
+ : ClassifierCodeDocument (concept) {
+ init();
+}
+
+JavaClassifierCodeDocument::~JavaClassifierCodeDocument ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// Make it easier on ourselves
+JavaCodeGenerationPolicy * JavaClassifierCodeDocument::getJavaPolicy() {
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ JavaCodeGenerationPolicy * policy = dynamic_cast<JavaCodeGenerationPolicy*>(pe);
+ return policy;
+}
+
+/**
+ * Get the dialog widget which allows user interaction with the object parameters.
+ * @return CodeDocumentDialog
+ */
+/*
+CodeDocumentDialog JavaClassifierCodeDocument::getDialog ( ) {
+
+}
+*/
+
+bool JavaClassifierCodeDocument::forceDoc () {
+ return UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
+}
+
+// We overwritten by Java language implementation to get lowercase path
+QString JavaClassifierCodeDocument::getPath ( )
+{
+
+ QString path = getPackage();
+
+ // Replace all white spaces with blanks
+ path.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ path.replace(QRegExp(" "), "_");
+
+ path.replace(QRegExp("\\."),"/");
+ path.replace(QRegExp("::"), "/");
+
+ path.lower();
+
+ return path;
+
+}
+
+
+// Other methods
+//
+
+QString JavaClassifierCodeDocument::getJavaClassName (const QString &name) {
+ return Codegen_Utils::capitalizeFirstLetter(CodeGenerator::cleanName(name));
+}
+
+// Initialize this java classifier code document
+void JavaClassifierCodeDocument::init ( ) {
+
+ setFileExtension(".java");
+
+ //initCodeClassFields(); // this is dubious because it calls down to
+ // CodeGenFactory::newCodeClassField(this)
+ // but "this" is still in construction at that time.
+
+ classDeclCodeBlock = 0;
+ operationsBlock = 0;
+ constructorBlock = 0;
+
+ // this will call updateContent() as well as other things that sync our document.
+ synchronize();
+}
+
+/**
+ * @param op
+ */
+// in the vannilla version, we just tack all operations on the end
+// of the document
+bool JavaClassifierCodeDocument::addCodeOperation (CodeOperation * op ) {
+
+ if(!op->getParentOperation()->isLifeOperation())
+ return operationsBlock->addTextBlock(op);
+ else
+ return constructorBlock->addTextBlock(op);
+}
+
+// Sigh. NOT optimal. The only reason that we need to have this
+// is so we can create the JavaClassDeclarationBlock.
+// would be better if we could create a handler interface that each
+// codeblock used so all we have to do here is add the handler
+// for "javaclassdeclarationblock"
+void JavaClassifierCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root)
+{
+
+ QDomNode tnode = root.firstChild();
+ QDomElement telement = tnode.toElement();
+ bool loadCheckForChildrenOK = false;
+ while( !telement.isNull() ) {
+ QString nodeName = telement.tagName();
+
+ if( nodeName == "textblocks" ) {
+
+ QDomNode node = telement.firstChild();
+ QDomElement element = node.toElement();
+
+ // if there is nothing to begin with, then we don't worry about it
+ loadCheckForChildrenOK = element.isNull() ? true : false;
+
+ while( !element.isNull() ) {
+ QString name = element.tagName();
+
+ if( name == "codecomment" ) {
+ CodeComment * block = new JavaCodeComment(this);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeComment to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeaccessormethod" ||
+ name == "ccfdeclarationcodeblock"
+ ) {
+ QString acctag = element.attribute("tag","");
+ // search for our method in the
+ TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
+ if(!tb || !addTextBlock(tb))
+ {
+ kError()<<"loadFromXMI : unable to add codeclassfield child method to:"<<this<<endl;
+ // DON'T delete
+ } else
+ loadCheckForChildrenOK= true;
+
+ } else
+ if( name == "codeblock" ) {
+ CodeBlock * block = newCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeblockwithcomments" ) {
+ CodeBlockWithComments * block = newCodeBlockWithComments();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "header" ) {
+ // do nothing.. this is treated elsewhere
+ } else
+ if( name == "hierarchicalcodeblock" ) {
+ HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeoperation" ) {
+ // find the code operation by id
+ QString id = element.attribute("parent_id","-1");
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+ if(op) {
+ CodeOperation * block = new JavaCodeOperation(this, op);
+ block->loadFromXMI(element);
+ if(addTextBlock(block))
+ loadCheckForChildrenOK= true;
+ else
+ {
+ kError()<<"Unable to add codeoperation to:"<<this<<endl;
+ block->deleteLater();
+ }
+ } else
+ kError()<<"Unable to find operation create codeoperation for:"<<this<<endl;
+ } else
+ if( name == "javaclassdeclarationblock" )
+ {
+ JavaClassDeclarationBlock * block = getClassDecl();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add java code declaration block to:"<<this<<endl;
+ // DON'T delete.
+ // block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ }
+ // This last item is only needed for extreme debugging conditions
+ // (E.g. making new codeclassdocument loader)
+ // else
+ // kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl;
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+ break;
+ }
+
+ tnode = telement.nextSibling();
+ telement = tnode.toElement();
+ }
+
+ if(!loadCheckForChildrenOK)
+ {
+ CodeDocument * test = dynamic_cast<CodeDocument*>(this);
+ if(test)
+ {
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
+ } else {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
+ if(hb)
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
+ else
+ kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
+ }
+ }
+
+
+}
+
+QString JavaClassifierCodeDocument::scopeToJavaDecl(Uml::Visibility scope)
+{
+ QString scopeString;
+ switch(scope)
+ {
+ case Uml::Visibility::Public:
+ scopeString = "public";
+ break;
+ case Uml::Visibility::Protected:
+ scopeString = "protected";
+ break;
+ case Uml::Visibility::Private:
+ case Uml::Visibility::Implementation:
+ default:
+ scopeString = "private";
+ break;
+ }
+ return scopeString;
+}
+
+JavaClassDeclarationBlock * JavaClassifierCodeDocument::getClassDecl()
+{
+ if(!classDeclCodeBlock)
+ {
+ classDeclCodeBlock = new JavaClassDeclarationBlock (this);
+ classDeclCodeBlock->setTag("ClassDeclBlock");
+ }
+ return classDeclCodeBlock;
+}
+
+void JavaClassifierCodeDocument::resetTextBlocks()
+{
+
+ // all special pointers to text blocks need to be zero'd out
+ operationsBlock = 0;
+ constructorBlock = 0;
+ classDeclCodeBlock = 0;
+
+ // now do traditional release of text blocks.
+ ClassifierCodeDocument::resetTextBlocks();
+}
+
+// This method will cause the class to rebuild its text representation.
+// based on the parent classifier object.
+// For any situation in which this is called, we are either building the code
+// document up, or replacing/regenerating the existing auto-generated parts. As
+// such, we will want to insert everything we resonablely will want
+// during creation. We can set various parts of the document (esp. the
+// comments) to appear or not, as needed.
+void JavaClassifierCodeDocument::updateContent( )
+{
+ // Gather info on the various fields and parent objects of this class...
+ UMLClassifier * c = getParentClassifier();
+ CodeGenerationPolicy * commonPolicy = UMLApp::app()->getCommonPolicy();
+ CodeGenPolicyExt * pe = UMLApp::app()->getPolicyExt();
+ JavaCodeGenerationPolicy * policy = dynamic_cast<JavaCodeGenerationPolicy*>(pe);
+
+ // first, set the global flag on whether or not to show classfield info
+ // This depends on whether or not we have attribute/association classes
+ CodeClassFieldList * cfList = getCodeClassFieldList();
+ for(CodeClassField * field = cfList->first(); field; field = cfList->next())
+ if(field->parentIsAttribute())
+ field->setWriteOutMethods(policy->getAutoGenerateAttribAccessors());
+ else
+ field->setWriteOutMethods(policy->getAutoGenerateAssocAccessors());
+
+ // attribute-based ClassFields
+ // we do it this way to have the static fields sorted out from regular ones
+ CodeClassFieldList staticAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true);
+ CodeClassFieldList attribClassFields = getSpecificClassFields (CodeClassField::Attribute, false);
+ // association-based ClassFields
+ // don't care if they are static or not..all are lumped together
+ CodeClassFieldList plainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation );
+ CodeClassFieldList aggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation );
+ CodeClassFieldList compositionClassFields = getSpecificClassFields ( CodeClassField::Composition );
+
+ bool isInterface = parentIsInterface();
+ bool hasOperationMethods = c->getOpList().last() ? true : false;
+ QString endLine = commonPolicy->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time
+
+ //
+ // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
+ //
+
+ //
+ // PACKAGE CODE BLOCK
+ //
+ QString pkgs = getPackage();
+ pkgs.replace(QRegExp("::"), ".");
+ QString packageText = getPackage().isEmpty() ? "" : "package "+pkgs+';'+endLine;
+ CodeBlockWithComments * pblock = addOrUpdateTaggedCodeBlockWithComments("packages", packageText, "", 0, false);
+ if(packageText.isEmpty() && pblock->getContentType() == CodeBlock::AutoGenerated)
+ pblock->setWriteOutText(false);
+ else
+ pblock->setWriteOutText(true);
+
+ // IMPORT CODEBLOCK
+ //
+ // Q: Why all utils? Isnt just List and Vector the only classes we are using?
+ // A: doesn't matter at all; its more readable to just include '*' and java compilers
+ // don't slow down or anything. (TZ)
+ QString importStatement = "";
+ if ( hasObjectVectorClassFields() )
+ importStatement.append("import java.util.*;");
+
+ //only import classes in a different package from this class
+ UMLPackageList imports;
+ QMap<UMLPackage*, QString> packageMap; // so we don't repeat packages
+
+ CodeGenerator::findObjectsRelated(c,imports);
+ for(UMLPackage *con = imports.first(); con ; con = imports.next())
+ // NO (default) datatypes in the import statement.. use defined
+ // ones whould be possible, but no idea how to do that...at least for now.
+ // Dynamic casting is slow..not an optimal way to do this.
+ if (!packageMap.contains(con) && con->getBaseType() != Uml::ot_Datatype)
+ {
+ packageMap.insert(con, con->getPackage());
+
+ // now, we DON'T need to import classes that are already in our own package
+ // (that is, IF a package is specified). Otherwise, we should have a declaration.
+ if (con->getPackage() != c->getPackage() ||
+ (c->getPackage().isEmpty() && con->getPackage().isEmpty()))
+ {
+ importStatement.append(endLine+"import ");
+ if(!con->getPackage().isEmpty())
+ importStatement.append(con->getPackage()+'.');
+ importStatement.append(CodeGenerator::cleanName(con->getName())+';');
+ }
+ }
+ // now, add/update the imports codeblock
+ CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments("imports", importStatement, "", 0, false);
+ if(importStatement.isEmpty() && iblock->getContentType() == CodeBlock::AutoGenerated)
+ iblock->setWriteOutText(false);
+ else
+ iblock->setWriteOutText(true);
+
+ // CLASS DECLARATION BLOCK
+ //
+
+ // get the declaration block. If its not already present, add it too
+ JavaClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
+ addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
+
+ // NOW create document in sections..
+ // now we want to populate the body of our class
+ // our layout is the following general groupings of code blocks:
+
+ // start java classifier document
+
+ // header comment
+
+ // package code block
+
+ // import code block
+
+ // class declaration
+
+ // section:
+ // - class field declaration section comment
+ // - class field declarations (0+ codeblocks)
+
+ // section:
+ // - methods section comment
+
+ // sub-section: constructor ops
+ // - constructor method section comment
+ // - constructor methods (0+ codeblocks)
+
+ // sub-section: accessors
+ // - accessor method section comment
+ // - static accessor methods (0+ codeblocks)
+ // - non-static accessor methods (0+ codeblocks)
+
+ // sub-section: non-constructor ops
+ // - operation method section comment
+ // - operations (0+ codeblocks)
+
+ // end class declaration
+
+ // end java classifier document
+
+
+ // Q: Why use the more complicated scheme of arranging code blocks within codeblocks?
+ // A: This will allow us later to preserve the format of our document so that if
+ // codeblocks are added, they may be easily added in the correct place, rather than at
+ // the end of the document, or by using a difficult algorithm to find the location of
+ // the last appropriate code block sibling (which may not exist.. for example user adds
+ // a constructor operation, but there currently are no constructor code blocks
+ // within the document).
+
+ //
+ // * CLASS FIELD declaration section
+ //
+
+ // get/create the field declaration code block
+ HierarchicalCodeBlock * fieldDeclBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("fieldsDecl", "Fields", 1);
+
+ // Update the comment: we only set comment to appear under the following conditions
+ CodeComment * fcomment = fieldDeclBlock->getComment();
+ if (isInterface || (!forceDoc() && !hasClassFields()) )
+ fcomment->setWriteOutText(false);
+ else
+ fcomment->setWriteOutText(true);
+
+ // now actually declare the fields within the appropriate HCodeBlock
+ declareClassFields(staticAttribClassFields, fieldDeclBlock);
+ declareClassFields(attribClassFields, fieldDeclBlock);
+ declareClassFields(plainAssocClassFields, fieldDeclBlock);
+ declareClassFields(aggregationClassFields, fieldDeclBlock);
+ declareClassFields(compositionClassFields, fieldDeclBlock);
+
+ //
+ // METHODS section
+ //
+
+ // get/create the method codeblock
+ HierarchicalCodeBlock * methodsBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("methodsBlock", "Methods", 1);
+
+ // Update the section comment
+ CodeComment * methodsComment = methodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forceDoc() && !hasClassFields() && !hasOperationMethods)
+ methodsComment->setWriteOutText(false);
+ else
+ methodsComment->setWriteOutText(true);
+
+ // METHODS sub-section : constructor methods
+ //
+
+ // get/create the constructor codeblock
+ HierarchicalCodeBlock * constBlock = methodsBlock->getHierarchicalCodeBlock("constructorMethods", "Constructors", 1);
+ constructorBlock = constBlock; // record this codeblock for later, when operations are updated
+
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * constComment = constBlock->getComment();
+ CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
+ if (!forceDoc() && (isInterface || !pol->getAutoGenerateConstructors()))
+ constComment->setWriteOutText(false);
+ else
+ constComment->setWriteOutText(true);
+
+ // add/get the empty constructor
+ QString JavaClassName = getJavaClassName(c->getName());
+ QString emptyConstStatement = "public "+JavaClassName+" ( ) { }";
+ CodeBlockWithComments * emptyConstBlock =
+ constBlock->addOrUpdateTaggedCodeBlockWithComments("emptyconstructor", emptyConstStatement, "Empty Constructor", 1, false);
+ // Now, as an additional condition we only show the empty constructor block
+ // IF it was desired to be shown
+ if(parentIsClass() && pol->getAutoGenerateConstructors())
+ emptyConstBlock->setWriteOutText(true);
+ else
+ emptyConstBlock->setWriteOutText(false);
+
+ // METHODS subsection : ACCESSOR METHODS
+ //
+
+ // get/create the accessor codeblock
+ HierarchicalCodeBlock * accessorBlock = methodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+
+ // set conditions for showing section comment
+ CodeComment * accessComment = accessorBlock->getComment();
+ if (!forceDoc() && !hasClassFields())
+ accessComment->setWriteOutText(false);
+ else
+ accessComment->setWriteOutText(true);
+
+ // now, 2 sub-sub sections in accessor block
+ // add/update accessor methods for attributes
+ HierarchicalCodeBlock * staticAccessors = accessorBlock->getHierarchicalCodeBlock("staticAccessorMethods", "", 1);
+ staticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ staticAccessors->addCodeClassFieldMethods(staticAttribClassFields);
+ staticAccessors->addCodeClassFieldMethods(attribClassFields);
+
+ // add/update accessor methods for associations
+ HierarchicalCodeBlock * regularAccessors = accessorBlock->getHierarchicalCodeBlock("regularAccessorMethods", "", 1);
+ regularAccessors->getComment()->setWriteOutText(false); // never write block comment
+ regularAccessors->addCodeClassFieldMethods(plainAssocClassFields);
+ regularAccessors->addCodeClassFieldMethods(aggregationClassFields);
+ regularAccessors->addCodeClassFieldMethods(compositionClassFields);
+
+ // METHODS subsection : Operation methods (which arent constructors)
+ //
+
+ // get/create the operations codeblock
+ operationsBlock = methodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+
+ // set conditions for showing section comment
+ CodeComment * ocomment = operationsBlock->getComment();
+ if (!forceDoc() && !hasOperationMethods )
+ ocomment->setWriteOutText(false);
+ else
+ ocomment->setWriteOutText(true);
+
+}
+
+
+#include "javaclassifiercodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h
new file mode 100644
index 00000000..ddad6e1a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+
+
+#ifndef JAVACLASSIFIERCODEDOCUMENT_H
+#define JAVACLASSIFIERCODEDOCUMENT_H
+
+#include <qstring.h>
+
+#include "../codeclassfieldlist.h"
+#include "../classifiercodedocument.h"
+#include "../classifier.h"
+#include "../hierarchicalcodeblock.h"
+#include "classifierinfo.h"
+#include "javacodeclassfield.h"
+#include "javacodeoperation.h"
+
+class JavaClassDeclarationBlock;
+class JavaCodeGenerationPolicy;
+
+/**
+ * class JavaClassifierCodeDocument
+ * A Java UMLClassifier Code Document.
+ */
+
+class JavaClassifierCodeDocument : public ClassifierCodeDocument
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructor
+ */
+ JavaClassifierCodeDocument (UMLClassifier * classifier);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaClassifierCodeDocument ( );
+
+ /**
+ * Get the dialog widget which allows user interaction with the object parameters.
+ * @return CodeDocumentDialog
+ */
+ //CodeDocumentDialog getDialog ( );
+
+ QString scopeToJavaDecl(Uml::Visibility scope);
+
+ // Make it easier on ourselves
+ JavaCodeGenerationPolicy * getJavaPolicy();
+
+ QString getJavaClassName (const QString &name);
+
+ QString getPath();
+
+ /** add a code operation to this java classifier code document.
+ * @return bool which is true IF the code operation was added successfully
+ */
+ bool addCodeOperation (CodeOperation * op );
+
+protected:
+
+ // reset/clear our inventory of textblocks in this document
+ void resetTextBlocks();
+
+ /**
+ * need to overwrite this for java since we need to pick up the
+ * java class declaration block.
+ */
+ virtual void loadChildTextBlocksFromNode ( QDomElement & root);
+
+ void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, JavaClassDeclarationBlock * codeBlock);
+
+ bool forceDoc ();
+
+ void updateContent();
+
+private:
+
+ JavaClassDeclarationBlock * classDeclCodeBlock;
+ HierarchicalCodeBlock * constructorBlock;
+ HierarchicalCodeBlock * operationsBlock;
+
+ ClassifierInfo * info;
+
+ void init ( );
+ JavaClassDeclarationBlock * getClassDecl();
+
+
+};
+
+#endif // JAVACLASSIFIERCODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp
new file mode 100644
index 00000000..524e6a48
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp
@@ -0,0 +1,223 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+// own header
+#include "javacodeaccessormethod.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "../attribute.h"
+#include "../codegenerator.h"
+#include "../codegenerationpolicy.h"
+#include "../classifiercodedocument.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+#include "codegen_utils.h"
+#include "javaclassifiercodedocument.h"
+#include "javacodegenerationpolicy.h"
+#include "javacodeclassfield.h"
+#include "javacodedocumentation.h"
+
+// Constructors/Destructors
+//
+
+JavaCodeAccessorMethod::JavaCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type)
+ : CodeAccessorMethod ( field )
+{
+ setType(type);
+
+ // lets use full-blown comment
+ JavaClassifierCodeDocument* jccd = dynamic_cast<JavaClassifierCodeDocument*>(field->getParentDocument());
+ setComment(new JavaCodeDocumentation(jccd));
+}
+
+JavaCodeAccessorMethod::~JavaCodeAccessorMethod ( ) { }
+
+// Other methods
+//
+
+void JavaCodeAccessorMethod::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement)
+{
+
+ // set super-class attributes
+ CodeAccessorMethod::setAttributesOnNode(doc, blockElement);
+
+ // set local attributes now
+}
+
+void JavaCodeAccessorMethod::setAttributesFromNode( QDomElement & root)
+{
+
+ // set attributes from superclass method the XMI
+ CodeAccessorMethod::setAttributesFromNode(root);
+
+ // load local stuff
+
+}
+
+void JavaCodeAccessorMethod::updateContent( )
+{
+
+ CodeClassField * parentField = getParentClassField();
+ JavaCodeClassField * javafield = dynamic_cast<JavaCodeClassField*>(parentField);
+ QString fieldName = javafield->getFieldName();
+
+ QString text = "";
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ {
+ int maxOccurs = javafield->maximumListOccurances();
+ QString fieldType = javafield->getTypeName();
+ QString indent = getIndentation();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ if(maxOccurs > 0)
+ text += "if ("+fieldName+".size() < "+ QString::number(maxOccurs)+") {"+endLine+indent;
+ text += fieldName+".add(value);";
+ if(maxOccurs > 0)
+ {
+ text += endLine+"} else {"+endLine;
+ text += indent + "System.err.println(\"ERROR: Cant add"+fieldType+" to "+fieldName+", minimum number of items reached.\");"+endLine+'}'+endLine;
+ }
+ break;
+ }
+ case CodeAccessorMethod::GET:
+ text = "return "+fieldName+';';
+ break;
+ case CodeAccessorMethod::LIST:
+ text = "return (List) "+fieldName+';';
+ break;
+ case CodeAccessorMethod::REMOVE:
+ {
+ int minOccurs = javafield->minimumListOccurances();
+ QString fieldType = javafield->getTypeName();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ QString indent = getIndentation();
+
+ if(minOccurs > 0)
+ text += "if ("+fieldName+".size() >= "+ QString::number(minOccurs)+") {"+endLine+indent;
+ text += fieldName+".remove(value);";
+ if(minOccurs > 0)
+ {
+ text += endLine+"} else {"+endLine;
+ text += indent + "System.err.println(\"ERROR: Cant remove"+fieldType+" from "+fieldName+", minimum number of items reached.\");"+endLine+'}'+endLine;
+ }
+ break;
+ }
+ case CodeAccessorMethod::SET:
+ text = fieldName+" = value;";
+ break;
+ default:
+ // do nothing
+ break;
+ }
+
+ setText(text);
+
+}
+
+void JavaCodeAccessorMethod::updateMethodDeclaration()
+{
+
+ JavaCodeClassField * javafield = dynamic_cast<JavaCodeClassField*>(getParentClassField());
+ JavaClassifierCodeDocument * javadoc = dynamic_cast<JavaClassifierCodeDocument*>(javafield->getParentDocument());
+ CodeGenerationPolicy *commonpolicy = UMLApp::app()->getCommonPolicy();
+
+ // gather defs
+ CodeGenerationPolicy::ScopePolicy scopePolicy = commonpolicy->getAttributeAccessorScope();
+ QString strVis = javadoc->scopeToJavaDecl(javafield->getVisibility());
+ QString fieldName = javafield->getFieldName();
+ QString fieldType = javafield->getTypeName();
+ QString objectType = javafield->getListObjectType();
+ if(objectType.isEmpty())
+ objectType = fieldName;
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ // set scope of this accessor appropriately..if its an attribute,
+ // we need to be more sophisticated
+ if(javafield->parentIsAttribute())
+ switch (scopePolicy) {
+ case CodeGenerationPolicy::Public:
+ case CodeGenerationPolicy::Private:
+ case CodeGenerationPolicy::Protected:
+ strVis = javadoc->scopeToJavaDecl((Uml::Visibility::Value) scopePolicy);
+ break;
+ default:
+ case CodeGenerationPolicy::FromParent:
+ // do nothing..already have taken parent value
+ break;
+ }
+
+ // some variables we will need to populate
+ QString headerText = "";
+ QString methodReturnType = "";
+ QString methodName = "";
+ QString methodParams = "";
+
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ methodName = "add" + Codegen_Utils::capitalizeFirstLetter(fieldType);
+ methodReturnType = "void";
+ methodParams = objectType+" value ";
+ headerText = "Add an object of type "+objectType+" to the List "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return void";
+ break;
+ case CodeAccessorMethod::GET:
+ methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldName);
+ methodReturnType = fieldType;
+ headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName;
+ break;
+ case CodeAccessorMethod::LIST:
+ methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldType)+"List";
+ methodReturnType = "List";
+ headerText = "Get the list of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return List of "+fieldName;
+ break;
+ case CodeAccessorMethod::REMOVE:
+ methodName = "remove" + Codegen_Utils::capitalizeFirstLetter(fieldType);
+ methodReturnType = "void";
+ methodParams = objectType+" value ";
+ headerText = "Remove an object of type "+objectType+" from the List "+fieldName+endLine+getParentObject()->getDoc();
+ break;
+ case CodeAccessorMethod::SET:
+ methodName = "set" + Codegen_Utils::capitalizeFirstLetter(fieldName);
+ methodReturnType = "void";
+ methodParams = fieldType + " value ";
+ headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine;
+ break;
+ default:
+ // do nothing..no idea what this is
+ kWarning()<<"Warning: cant generate JavaCodeAccessorMethod for type: "<<getType()<<endl;
+ break;
+ }
+
+ // set header once.
+ if(getComment()->getText().isEmpty())
+ getComment()->setText(headerText);
+
+ // set start/end method text
+ setStartMethodText(strVis+' '+methodReturnType+' '+methodName+" ( "+methodParams+" ) {");
+ setEndMethodText("}");
+
+}
+
+void JavaCodeAccessorMethod::update()
+{
+ updateMethodDeclaration();
+ updateContent();
+}
+
+#include "javacodeaccessormethod.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodeaccessormethod.h b/umbrello/umbrello/codegenerators/javacodeaccessormethod.h
new file mode 100644
index 00000000..5a109b59
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeaccessormethod.h
@@ -0,0 +1,65 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Oct 2 2003
+ */
+
+#ifndef JAVACODEACCESSORMETHOD_H
+#define JAVACODEACCESSORMETHOD_H
+
+#include <qstring.h>
+
+#include "../codeaccessormethod.h"
+
+class CodeClassField;
+
+class JavaCodeAccessorMethod : public CodeAccessorMethod
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ JavaCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeAccessorMethod ( );
+
+ /**
+ * Must be called before this object is usable
+ */
+ void update();
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent();
+
+};
+
+#endif // JAVACODEACCESSORMETHOD_H
diff --git a/umbrello/umbrello/codegenerators/javacodeclassfield.cpp b/umbrello/umbrello/codegenerators/javacodeclassfield.cpp
new file mode 100644
index 00000000..627b9b3e
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeclassfield.cpp
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 30 2003
+ */
+
+// own header
+#include "javacodeclassfield.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "javacodecomment.h"
+#include "javacodegenerator.h"
+
+#include "../attribute.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+
+// #include "javacodeaccessormethod.h"
+#include "javaclassifiercodedocument.h"
+
+// Constructors/Destructors
+//
+
+JavaCodeClassField::JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role)
+ : CodeClassField(parentDoc, role)
+{
+
+}
+
+JavaCodeClassField::JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib)
+ : CodeClassField(parentDoc, attrib)
+{
+
+}
+
+JavaCodeClassField::~JavaCodeClassField ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+QString JavaCodeClassField::getFieldName() {
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = (UMLAttribute*) getParentObject();
+ return cleanName(at->getName());
+ }
+ else
+ {
+ UMLRole * role = (UMLRole*) getParentObject();
+ QString roleName = role->getName();
+ if(fieldIsSingleValue()) {
+ return roleName.replace(0, 1, roleName.left(1).lower());
+ } else {
+ return roleName.lower() + "Vector";
+ }
+ }
+}
+
+
+QString JavaCodeClassField::getInitialValue() {
+
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() );
+ if (at) {
+ return fixInitialStringDeclValue(at->getInitialValue(), getTypeName());
+ } else {
+ kError() << "JavaodeClassField::getInitialValue: parent object is not a UMLAttribute"
+ << endl;
+ return "";
+ }
+ return fixInitialStringDeclValue(at->getInitialValue(), getTypeName());
+ }
+ else
+ {
+ if(fieldIsSingleValue()) {
+ // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1,
+ // then we can just return 'empty' string (minor problem).
+ return QString("");
+ } else {
+ return " new "+JavaCodeGenerator::getListFieldClassName()+"( )";
+ }
+ }
+
+}
+
+QString JavaCodeClassField::getTypeName ( )
+{
+ return JavaCodeGenerator::fixTypeName(CodeClassField::getTypeName());
+}
+
+#include "javacodeclassfield.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodeclassfield.h b/umbrello/umbrello/codegenerators/javacodeclassfield.h
new file mode 100644
index 00000000..5ed1cea4
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeclassfield.h
@@ -0,0 +1,59 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 30 2003
+ */
+
+
+
+#ifndef JAVACODECLASSFIELD_H
+#define JAVACODECLASSFIELD_H
+
+#include <qstring.h>
+
+#include "../codeclassfield.h"
+
+class ClassifierCodeDocument;
+
+class JavaCodeClassField : public CodeClassField
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role);
+ JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeClassField ( );
+
+ QString getFieldType();
+ QString getFieldName();
+ QString getInitialValue();
+
+ QString getTypeName ( );
+protected:
+
+private:
+
+ // void initDeclCodeBlock ();
+
+};
+
+#endif // JAVACODECLASSFIELD_H
diff --git a/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp
new file mode 100644
index 00000000..87ebf78a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jul 25 2003
+ */
+
+#include "javacodeclassfielddeclarationblock.h"
+
+#include "javacodeclassfield.h"
+#include "javaclassifiercodedocument.h"
+#include "javacodegenerationpolicy.h"
+#include "../codegenerator.h"
+#include "../classifier.h"
+#include "../umlrole.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+JavaCodeClassFieldDeclarationBlock::JavaCodeClassFieldDeclarationBlock ( CodeClassField * parent )
+ : CodeClassFieldDeclarationBlock ( parent )
+{
+ setOverallIndentationLevel(1);
+ updateContent();
+}
+
+JavaCodeClassFieldDeclarationBlock::~JavaCodeClassFieldDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+
+
+// Other methods
+//
+
+/**
+ */
+void JavaCodeClassFieldDeclarationBlock::updateContent( )
+{
+
+ CodeClassField * cf = getParentClassField();
+ ClassifierCodeDocument * doc = cf->getParentDocument();
+ JavaCodeClassField * jcf = dynamic_cast<JavaCodeClassField*>(cf);
+ JavaClassifierCodeDocument* jdoc = dynamic_cast<JavaClassifierCodeDocument*>(doc);
+ CodeGenerationPolicy * commonpolicy = UMLApp::app()->getCommonPolicy();
+
+ CodeGenerationPolicy::ScopePolicy scopePolicy = commonpolicy->getAssociationFieldScope();
+
+ // Set the comment
+ QString notes = getParentObject()->getDoc();
+ getComment()->setText(notes);
+
+ // Set the body
+ QString staticValue = getParentObject()->getStatic() ? "static " : "";
+ QString scopeStr = jdoc->scopeToJavaDecl(getParentObject()->getVisibility());
+
+ // IF this is from an association, then scope taken as appropriate to policy
+ if(!jcf->parentIsAttribute())
+ {
+ switch (scopePolicy) {
+ case CodeGenerationPolicy::Public:
+ case CodeGenerationPolicy::Private:
+ case CodeGenerationPolicy::Protected:
+ scopeStr = jdoc->scopeToJavaDecl((Uml::Visibility::Value) scopePolicy);
+ break;
+ default:
+ case CodeGenerationPolicy::FromParent:
+ // do nothing here... will leave as from parent object
+ break;
+ }
+ }
+
+ QString typeName = jcf->getTypeName();
+ QString fieldName = jcf->getFieldName();
+ QString initialV = jcf->getInitialValue();
+
+ if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue())
+ typeName = "List";
+
+ QString body = staticValue+scopeStr+' '+typeName+' '+fieldName;
+ if (!initialV.isEmpty())
+ body.append(" = " + initialV);
+ else if (!cf->parentIsAttribute())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject());
+ if (role->getObject()->getBaseType() == Uml::ot_Interface)
+ {
+ // do nothing.. can't instanciate an interface
+ } else {
+
+ // FIX?: IF a constructor method exists in the classifiercodedoc
+ // of the parent Object, then we can use that instead (if its empty).
+ if(cf->fieldIsSingleValue())
+ {
+ if(!typeName.isEmpty())
+ body.append(" = new " + typeName + " ( )");
+ } else
+ body.append(" = new Vector ( )");
+ }
+ }
+
+ setText(body+';');
+
+}
+
+#include "javacodeclassfielddeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h
new file mode 100644
index 00000000..8166fced
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h
@@ -0,0 +1,51 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jul 25 2003
+ */
+
+#ifndef JAVACODECLASSFIELDDECLARATIONBLOCK_H
+#define JAVACODECLASSFIELDDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "../codeclassfielddeclarationblock.h"
+
+class JavaCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ JavaCodeClassFieldDeclarationBlock ( CodeClassField * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeClassFieldDeclarationBlock ( );
+
+protected:
+
+ // this will be called by syncToParent whenever the parent object is "modified"
+ void updateContent ( );
+
+private:
+
+
+};
+
+#endif // JAVACODECLASSFIELDDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/javacodecomment.cpp b/umbrello/umbrello/codegenerators/javacodecomment.cpp
new file mode 100644
index 00000000..bec0e87b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodecomment.cpp
@@ -0,0 +1,84 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+#include "javacodecomment.h"
+#include <qregexp.h>
+
+// Constructors/Destructors
+//
+
+JavaCodeComment::JavaCodeComment ( CodeDocument * doc, const QString & text )
+ : CodeComment (doc, text)
+{
+
+}
+
+JavaCodeComment::~JavaCodeComment ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+// Other methods
+//
+
+QString JavaCodeComment::getNewEditorLine ( int amount ) {
+ QString line = getIndentationString(amount) + "// ";
+ return line;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString JavaCodeComment::unformatText ( const QString & text , const QString & indent)
+{
+
+ // remove leading or trailing comment stuff
+ QString mytext = TextBlock::unformatText(text, indent);
+
+ // now leading slashes
+ mytext.remove(QRegExp("^\\/\\/\\s*"));
+ return mytext;
+}
+
+/**
+ * @return QString
+ */
+QString JavaCodeComment::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ output.append(formatMultiLineText (getText(), indent +"// ", endLine));
+ }
+
+ return output;
+}
+
+
+#include "javacodecomment.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodecomment.h b/umbrello/umbrello/codegenerators/javacodecomment.h
new file mode 100644
index 00000000..1f9b1d8d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodecomment.h
@@ -0,0 +1,77 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+
+
+#ifndef JAVACODECOMMENT_H
+#define JAVACODECOMMENT_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+/**
+ * class JavaCodeComment
+ * A Java code comment. There is only a single styles of comments:
+ * these are simply started with double slash sequence and no terminating
+ * characters
+ */
+
+class JavaCodeComment : virtual public CodeComment
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit JavaCodeComment ( CodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeComment ( );
+
+ // Public attributes
+ //
+
+
+ // other
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the "//" sequence as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+protected:
+
+private:
+
+};
+
+#endif // JAVACODECOMMENT_H
diff --git a/umbrello/umbrello/codegenerators/javacodedocumentation.cpp b/umbrello/umbrello/codegenerators/javacodedocumentation.cpp
new file mode 100644
index 00000000..e831d885
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodedocumentation.cpp
@@ -0,0 +1,143 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+// own header
+#include "javacodedocumentation.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "javaclassifiercodedocument.h"
+#include "../codegenerationpolicy.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+JavaCodeDocumentation::JavaCodeDocumentation ( JavaClassifierCodeDocument * doc, const QString & text )
+ : CodeComment(doc, text)
+{
+
+}
+
+JavaCodeDocumentation::~JavaCodeDocumentation ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void JavaCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "javacodedocumentation" );
+ setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may
+ // just use parent TextBlock method
+ root.appendChild( blockElement );
+}
+
+/**
+ * @return QString
+ */
+QString JavaCodeDocumentation::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ bool useDoubleDashOutput = true;
+
+ // need to figure out output type from java policy
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ useDoubleDashOutput = false;
+
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ QString body = getText();
+ if(useDoubleDashOutput)
+ {
+ if(!body.isEmpty())
+ output.append(formatMultiLineText (body, indent +"// ", endLine));
+ } else {
+ output.append(indent+"/**"+endLine);
+ output.append(formatMultiLineText (body, indent +" * ", endLine));
+ output.append(indent+" */"+endLine);
+ }
+ }
+
+ return output;
+}
+
+QString JavaCodeDocumentation::getNewEditorLine ( int amount )
+{
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return getIndentationString(amount) + " * ";
+ else
+ return getIndentationString(amount) + "// ";
+}
+
+int JavaCodeDocumentation::firstEditableLine() {
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return 1;
+ return 0;
+}
+
+int JavaCodeDocumentation::lastEditableLine() {
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ return -1; // very last line is NOT editable
+ }
+ return 0;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString JavaCodeDocumentation::unformatText ( const QString & text , const QString & indent)
+{
+
+ QString mytext = TextBlock::unformatText(text, indent);
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ // remove leading or trailing comment stuff
+ mytext.remove(QRegExp('^'+indent));
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ mytext.remove(QRegExp("^\\/\\*\\*\\s*\n?"));
+ mytext.remove(QRegExp("\\s*\\*\\/\\s*\n?$"));
+ mytext.remove(QRegExp("^\\s*\\*\\s*"));
+ } else
+ mytext.remove(QRegExp("^\\/\\/\\s*"));
+
+ return mytext;
+}
+
+
+#include "javacodedocumentation.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodedocumentation.h b/umbrello/umbrello/codegenerators/javacodedocumentation.h
new file mode 100644
index 00000000..246b87a6
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodedocumentation.h
@@ -0,0 +1,95 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+
+
+#ifndef JAVACODEDOCUMENTATION_H
+#define JAVACODEDOCUMENTATION_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+class JavaClassifierCodeDocument;
+
+/**
+ * class JavaCodeDocumentation
+ * A Java code comment. There is only a single styles of comments:
+ * these are simply started with double slash sequence and no terminating
+ * characters
+ */
+
+class JavaCodeDocumentation : virtual public CodeComment
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit JavaCodeDocumentation ( JavaClassifierCodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeDocumentation ( );
+
+ // Public attributes
+ //
+
+ // Other
+ //
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the " * " sequence as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+ /** Ush. These are terrifically bad and must one day go away.
+ * Both methods indicate the range of lines in this textblock
+ * which may be edited by the codeeditor (assuming that any are
+ * actually editable). The default case is no lines are editable.
+ * The line numbering starts with '0' and a '-1' means no line
+ * qualifies.
+ */
+ virtual int firstEditableLine();
+ virtual int lastEditableLine();
+
+
+protected:
+
+private:
+
+};
+
+#endif // JAVACODEDOCUMENTATION_H
diff --git a/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui b/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui
new file mode 100644
index 00000000..cd39611a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui
@@ -0,0 +1,277 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>JavaCodeGenerationFormBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>462</width>
+ <height>376</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="3" column="0">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Project Generation</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_makeANTDocumentCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Create ANT build document</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="2" column="0">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Auto-Generate Methods</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_generateConstructors</cstring>
+ </property>
+ <property name="text">
+ <string>Empty constructor methods</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>m_generateAssocAccessors</cstring>
+ </property>
+ <property name="text">
+ <string>Association accessor methods</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>m_generateAttribAccessors</cstring>
+ </property>
+ <property name="text">
+ <string>Attribute accessor methods</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Private</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Protected</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>From Parent Object</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_accessorScopeCB</cstring>
+ </property>
+ <property name="currentItem">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Default attribute accessor scope:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Default association field scope:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Private</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Protected</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>From Parent Role</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_assocFieldScopeCB</cstring>
+ </property>
+ <property name="currentItem">
+ <number>3</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Documentation</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Style:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>Slash-Slash (//)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Slash-Star (/** */)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_SelectCommentStyle</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;Java Code Generation&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp
new file mode 100644
index 00000000..2dcc834e
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp
@@ -0,0 +1,188 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+// own header
+#include "javacodegenerationpolicy.h"
+// qt/kde includes
+#include <kconfig.h>
+// app includes
+#include "javacodegenerationpolicypage.h"
+#include "javacodegenerator.h"
+#include "../uml.h"
+
+const bool JavaCodeGenerationPolicy::DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS = true;
+const bool JavaCodeGenerationPolicy::DEFAULT_AUTO_GEN_ASSOC_ACCESSORS = true;
+
+// Constructors/Destructors
+/*
+
+JavaCodeGenerationPolicy::JavaCodeGenerationPolicy(CodeGenerationPolicy *defaults)
+ : CodeGenerationPolicy(defaults)
+{
+ init();
+ setDefaults(defaults,false);
+}
+ */
+
+JavaCodeGenerationPolicy::JavaCodeGenerationPolicy(KConfig *config)
+ // : CodeGenerationPolicy(config)
+{
+ init();
+ setDefaults(config,false);
+}
+
+JavaCodeGenerationPolicy::~JavaCodeGenerationPolicy ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// Public attribute accessor methods
+//
+
+/**
+ * Set the value of m_autoGenerateAttribAccessors
+ * @param new_var the new value
+ */
+void JavaCodeGenerationPolicy::setAutoGenerateAttribAccessors( bool var ) {
+ m_autoGenerateAttribAccessors = var;
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+/**
+ * Set the value of m_autoGenerateAssocAccessors
+ * @param new_var the new value
+ */
+void JavaCodeGenerationPolicy::setAutoGenerateAssocAccessors( bool var ) {
+ m_autoGenerateAssocAccessors = var;
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_autoGenerateAttribAccessors
+ * @return the value of m_autoGenerateAttribAccessors
+ */
+bool JavaCodeGenerationPolicy::getAutoGenerateAttribAccessors( ){
+ return m_autoGenerateAttribAccessors;
+}
+
+/**
+ * Get the value of m_autoGenerateAssocAccessors
+ * @return the value of m_autoGenerateAssocAccessors
+ */
+bool JavaCodeGenerationPolicy::getAutoGenerateAssocAccessors( ){
+ return m_autoGenerateAssocAccessors;
+}
+
+// Other methods
+//
+
+void JavaCodeGenerationPolicy::writeConfig ( KConfig * config )
+{
+
+ // write ONLY the Java specific stuff
+ config->setGroup("Java Code Generation");
+
+ config->writeEntry("autoGenAccessors",getAutoGenerateAttribAccessors());
+ config->writeEntry("autoGenAssocAccessors",getAutoGenerateAssocAccessors());
+
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen);
+ if (javacodegen)
+ config->writeEntry("buildANTDocument", javacodegen->getCreateANTBuildFile());
+
+}
+
+void JavaCodeGenerationPolicy::setDefaults ( CodeGenPolicyExt * clone, bool emitUpdateSignal )
+{
+
+ JavaCodeGenerationPolicy * jclone;
+ if (!clone)
+ return;
+
+ // NOW block signals for java param setting
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+
+ // now do java-specific stuff IF our clone is also a JavaCodeGenerationPolicy object
+ if((jclone = dynamic_cast<JavaCodeGenerationPolicy*>(clone)))
+ {
+ setAutoGenerateAttribAccessors(jclone->getAutoGenerateAttribAccessors());
+ setAutoGenerateAssocAccessors(jclone->getAutoGenerateAssocAccessors());
+ }
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ m_commonPolicy->emitModifiedCodeContentSig();
+
+}
+
+void JavaCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal )
+{
+
+ if(!config)
+ return;
+
+ // call method at the common policy to init default stuff
+ m_commonPolicy->setDefaults(config, false);
+
+ // NOW block signals (because call to super-class method will leave value at "true")
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ // now do java specific stuff
+ config -> setGroup("Java Code Generation");
+
+ setAutoGenerateAttribAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS));
+ setAutoGenerateAssocAccessors(config->readBoolEntry("autoGenAssocAccessors",DEFAULT_AUTO_GEN_ASSOC_ACCESSORS));
+
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen);
+ if (javacodegen) {
+ bool mkant = config->readBoolEntry("buildANTDocument", JavaCodeGenerator::DEFAULT_BUILD_ANT_DOC);
+ javacodegen->setCreateANTBuildFile(mkant);
+ }
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+
+/**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+CodeGenerationPolicyPage * JavaCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) {
+ return new JavaCodeGenerationPolicyPage ( parent, name, this );
+}
+
+void JavaCodeGenerationPolicy::init() {
+ m_commonPolicy = UMLApp::app()->getCommonPolicy();
+ m_autoGenerateAttribAccessors = DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS;
+ m_autoGenerateAssocAccessors = DEFAULT_AUTO_GEN_ASSOC_ACCESSORS;
+}
+
+
+#include "javacodegenerationpolicy.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h
new file mode 100644
index 00000000..2a40cb57
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 23 2003
+ */
+
+#ifndef JAVACODEGENERATIONPOLICY_H
+#define JAVACODEGENERATIONPOLICY_H
+
+#include <qstring.h>
+#include "codegenpolicyext.h"
+#include "../codegenerationpolicy.h"
+
+class KConfig;
+class CodeGenerationPolicyPage;
+
+class JavaCodeGenerationPolicy : public CodeGenPolicyExt
+{
+ Q_OBJECT
+public:
+
+ static const bool DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS;
+ static const bool DEFAULT_AUTO_GEN_ASSOC_ACCESSORS;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ //JavaCodeGenerationPolicy (CodeGenerationPolicy * defaults = 0);
+ JavaCodeGenerationPolicy (KConfig * config = 0);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeGenerationPolicy ( );
+
+ // Public attributes
+ //
+
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_autoGenerateAttribAccessors
+ * @param var the new value
+ */
+ void setAutoGenerateAttribAccessors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateAttribAccessors
+ * @return value the boolean value of m_autoGenerateAttribAccessors
+ */
+ bool getAutoGenerateAttribAccessors( );
+
+ /**
+ * Set the value of m_autoGenerateAssocAccessors
+ * @param var the new value
+ */
+ void setAutoGenerateAssocAccessors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateAssocAccessors
+ * @return value the boolean value of m_autoGenerateAssocAccessors
+ */
+ bool getAutoGenerateAssocAccessors( );
+
+ /**
+ * set the defaults for this code generator from the passed generator.
+ */
+ virtual void setDefaults (CodeGenPolicyExt * defaults, bool emitUpdateSignal = true);
+
+ /**
+ * set the defaults from a config file for this code generator from the passed KConfig pointer.
+ */
+ virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true);
+
+ /**
+ * write Default params to passed KConfig pointer.
+ */
+ virtual void writeConfig (KConfig * config);
+
+ /**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+ CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0);
+
+protected:
+
+ /**
+ */
+ void init ( );
+
+private:
+
+ CodeGenerationPolicy *m_commonPolicy;
+ bool m_autoGenerateConstructors;
+ bool m_autoGenerateAttribAccessors;
+ bool m_autoGenerateAssocAccessors;
+
+};
+
+#endif // JAVACODEGENERATIONPOLICY_H
diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp
new file mode 100644
index 00000000..fd6d2ae3
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 30 2003
+ */
+
+// own header
+#include "javacodegenerationpolicypage.h"
+// qt/kde includes
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <kdebug.h>
+#include <klocale.h>
+// app includes
+#include "javacodegenerationformbase.h"
+#include "../uml.h"
+
+JavaCodeGenerationPolicyPage::JavaCodeGenerationPolicyPage( QWidget *parent, const char *name, JavaCodeGenerationPolicy * policy )
+ : CodeGenerationPolicyPage(parent, name, policy)
+{
+ CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
+ form = new JavaCodeGenerationFormBase(this);
+ form->m_SelectCommentStyle->setCurrentItem((int)(commonPolicy->getCommentStyle()));
+ form->m_generateConstructors->setChecked(commonPolicy->getAutoGenerateConstructors());
+ form->m_generateAttribAccessors->setChecked(policy->getAutoGenerateAttribAccessors());
+ form->m_generateAssocAccessors->setChecked(policy->getAutoGenerateAssocAccessors());
+ form->m_accessorScopeCB->setCurrentItem(commonPolicy->getAttributeAccessorScope() - 200);
+ form->m_assocFieldScopeCB->setCurrentItem(commonPolicy->getAssociationFieldScope() - 200);
+
+ /**
+ * @todo unclean - CreateANTBuildFile attribute should be in java policy
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen);
+ if (javacodegen)
+ form->m_makeANTDocumentCheckBox->setChecked(javacodegen->getCreateANTBuildFile());
+ */
+}
+
+JavaCodeGenerationPolicyPage::~JavaCodeGenerationPolicyPage()
+{
+}
+
+void JavaCodeGenerationPolicyPage::apply()
+{
+ CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
+ JavaCodeGenerationPolicy * parent = (JavaCodeGenerationPolicy*) m_parentPolicy;
+
+ // block signals so we don't cause too many update content calls to code documents
+ commonPolicy->blockSignals(true);
+
+ commonPolicy->setCommentStyle((CodeGenerationPolicy::CommentStyle ) form->m_SelectCommentStyle->currentItem());
+ commonPolicy->setAttributeAccessorScope((CodeGenerationPolicy::ScopePolicy) (form->m_accessorScopeCB->currentItem()+200));
+ commonPolicy->setAssociationFieldScope((CodeGenerationPolicy::ScopePolicy) (form->m_assocFieldScopeCB->currentItem()+200));
+ commonPolicy->setAutoGenerateConstructors(form->m_generateConstructors->isChecked());
+ parent->setAutoGenerateAttribAccessors(form->m_generateAttribAccessors->isChecked());
+ parent->setAutoGenerateAssocAccessors(form->m_generateAssocAccessors->isChecked());
+
+ /**
+ * @todo unclean - CreateANTBuildFile attribute should be in java policy
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen);
+ if (javacodegen)
+ javacodegen->setCreateANTBuildFile(form->m_makeANTDocumentCheckBox->isChecked());
+ */
+ commonPolicy->blockSignals(false);
+
+ // now send out modified code content signal
+ commonPolicy->emitModifiedCodeContentSig();
+
+}
+
+
+#include "javacodegenerationpolicypage.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h
new file mode 100644
index 00000000..3b6f85e0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 30 2003
+ */
+
+#ifndef JAVACODEGENERATIONPOLICYPAGE_H
+#define JAVACODEGENERATIONPOLICYPAGE_H
+
+#include "../dialogs/codegenerationpolicypage.h"
+#include "javacodegenerationformbase.h"
+
+#include "javacodegenerationpolicy.h"
+
+/**
+ * @author Brian Thomas
+ */
+
+class JavaCodeGenerationPolicyPage : public CodeGenerationPolicyPage {
+ Q_OBJECT
+public:
+
+ explicit JavaCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, JavaCodeGenerationPolicy * policy = 0);
+
+ virtual ~JavaCodeGenerationPolicyPage();
+
+protected:
+
+ JavaCodeGenerationFormBase * form;
+
+public slots:
+
+ void apply();
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codegenerators/javacodegenerator.cpp b/umbrello/umbrello/codegenerators/javacodegenerator.cpp
new file mode 100644
index 00000000..167804af
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerator.cpp
@@ -0,0 +1,339 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+// own header
+#include "javacodegenerator.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// local includes
+#include "javacodecomment.h"
+#include "codeviewerdialog.h"
+#include "../uml.h"
+
+const bool JavaCodeGenerator::DEFAULT_BUILD_ANT_DOC = false;
+
+// Constructors/Destructors
+//
+
+JavaCodeGenerator::JavaCodeGenerator (QDomElement & elem)
+ : CodeGenerator(elem)
+{
+ init();
+}
+
+JavaCodeGenerator::JavaCodeGenerator ()
+{
+ init();
+}
+
+JavaCodeGenerator::~JavaCodeGenerator ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// return our language
+Uml::Programming_Language JavaCodeGenerator::getLanguage() {
+ return Uml::pl_Java;
+}
+
+/**
+ * Set the value of m_createANTBuildFile
+ * @param new_var the new value of m_createANTBuildFile
+ */
+void JavaCodeGenerator::setCreateANTBuildFile ( bool buildIt) {
+ m_createANTBuildFile = buildIt;
+ CodeDocument * antDoc = findCodeDocumentByID("ANTDOC");
+ if (antDoc)
+ antDoc->setWriteOutCode(buildIt);
+}
+
+/**
+ * Get the value of m_createANTBuildFile
+ * @return the value of m_createANTBuildFile
+ */
+bool JavaCodeGenerator::getCreateANTBuildFile ( ) {
+ return m_createANTBuildFile;
+}
+
+// In the Java version, we make the ANT build file also available.
+CodeViewerDialog * JavaCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc,
+ Settings::CodeViewerState state)
+{
+ CodeViewerDialog *dialog = new CodeViewerDialog(parent, doc, state);
+ if(getCreateANTBuildFile())
+ dialog->addCodeDocument(findCodeDocumentByID("ANTDOC"));
+ return dialog;
+}
+
+
+JavaCodeGenerationPolicy * JavaCodeGenerator::getJavaPolicy() {
+ return dynamic_cast<JavaCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt());
+}
+
+bool JavaCodeGenerator::getAutoGenerateAttribAccessors ( )
+{
+ return getJavaPolicy()->getAutoGenerateAttribAccessors ();
+}
+
+bool JavaCodeGenerator::getAutoGenerateAssocAccessors ( )
+{
+ return getJavaPolicy()->getAutoGenerateAssocAccessors ();
+}
+
+QString JavaCodeGenerator::getListFieldClassName () {
+ return QString("Vector");
+}
+
+// Other methods
+//
+
+// IF the type is "string" we need to declare it as
+// the Java Object "String" (there is no string primative in Java).
+// Same thing again for "bool" to "boolean"
+QString JavaCodeGenerator::fixTypeName(const QString &string)
+{
+ if (string.isEmpty() || string.contains(QRegExp("^\\s+$")))
+ return "void";
+ if (string == "string")
+ return "String";
+ if (string == "bool")
+ return "boolean";
+ return cleanName(string);
+}
+
+/**
+ * @return JavaANTCodeDocument
+ */
+JavaANTCodeDocument * JavaCodeGenerator::newANTCodeDocument ( ) {
+ return new JavaANTCodeDocument();
+}
+
+/**
+ * @return ClassifierCodeDocument
+ * @param classifier
+ */
+CodeDocument * JavaCodeGenerator::newClassifierCodeDocument ( UMLClassifier * c)
+{
+ JavaClassifierCodeDocument * doc = new JavaClassifierCodeDocument(c);
+ doc->initCodeClassFields();
+ return doc;
+}
+
+void JavaCodeGenerator::init() {
+ // load Classifier documents from parent document
+ //initFromParentDocument();
+
+ // add in an ANT document
+ JavaANTCodeDocument * buildDoc = newANTCodeDocument( );
+ addCodeDocument(buildDoc);
+
+ // set our 'writeout' policy for that code document
+ setCreateANTBuildFile(DEFAULT_BUILD_ANT_DOC);
+}
+
+QStringList JavaCodeGenerator::defaultDatatypes() {
+ QStringList l;
+ l.append("int");
+ l.append("char");
+ l.append("boolean");
+ l.append("float");
+ l.append("double");
+ l.append("byte");
+ l.append("short");
+ l.append("long");
+ l.append("String");
+ return l;
+}
+
+const QStringList JavaCodeGenerator::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "abstract"
+ << "AbstractMethodError"
+ << "ArithmeticException"
+ << "ArrayIndexOutOfBoundsException"
+ << "ArrayStoreException"
+ << "assert"
+ << "AssertionError"
+ << "auto"
+ << "boolean"
+ << "Boolean"
+ << "break"
+ << "byte"
+ << "Byte"
+ << "catch"
+ << "char"
+ << "Character"
+ << "CharSequence"
+ << "Class"
+ << "ClassCastException"
+ << "ClassCircularityError"
+ << "ClassFormatError"
+ << "ClassLoader"
+ << "ClassNotFoundException"
+ << "clone"
+ << "Cloneable"
+ << "CloneNotSupportedException"
+ << "Comparable"
+ << "Compiler"
+ << "const"
+ << "continue"
+ << "default"
+ << "delete"
+ << "do"
+ << "double"
+ << "Double"
+ << "else"
+ << "enum"
+ << "equals"
+ << "Error"
+ << "Exception"
+ << "ExceptionInInitializerError"
+ << "extends"
+ << "extern"
+ << "false"
+ << "final"
+ << "finalize"
+ << "finally"
+ << "float"
+ << "Float"
+ << "for"
+ << "friend"
+ << "getClass"
+ << "goto"
+ << "hashCode"
+ << "if"
+ << "IllegalAccessError"
+ << "IllegalAccessException"
+ << "IllegalArgumentException"
+ << "IllegalMonitorStateException"
+ << "IllegalStateException"
+ << "IllegalThreadStateException"
+ << "implements"
+ << "import"
+ << "IncompatibleClassChangeError"
+ << "IndexOutOfBoundsException"
+ << "InheritableThreadLocal"
+ << "inline"
+ << "instanceof"
+ << "InstantiationError"
+ << "InstantiationException"
+ << "int"
+ << "Integer"
+ << "interface"
+ << "InternalError"
+ << "InterruptedException"
+ << "LinkageError"
+ << "long"
+ << "Long"
+ << "Math"
+ << "native"
+ << "NegativeArraySizeException"
+ << "new"
+ << "nextgroup=javaUserLabelRef"
+ << "NoClassDefFoundError"
+ << "NoSuchFieldError"
+ << "NoSuchFieldException"
+ << "NoSuchMethodError"
+ << "NoSuchMethodException"
+ << "notify"
+ << "notifyAll"
+ << "null"
+ << "NullPointerException"
+ << "Number"
+ << "NumberFormatException"
+ << "Object"
+ << "operator"
+ << "OutOfMemoryError"
+ << "package"
+ << "Package"
+ << "private"
+ << "Process"
+ << "protected"
+ << "public"
+ << "redeclared"
+ << "register"
+ << "return"
+ << "Runnable"
+ << "Runtime"
+ << "RuntimeException"
+ << "RuntimePermission"
+ << "SecurityException"
+ << "SecurityManager"
+ << "serializable"
+ << "short"
+ << "Short"
+ << "signed"
+ << "sizeof"
+ << "skipwhite"
+ << "StackOverflowError"
+ << "StackTraceElement"
+ << "static"
+ << "strictfp"
+ << "StrictMath"
+ << "String"
+ << "StringBuffer"
+ << "StringIndexOutOfBoundsException"
+ << "struct"
+ << "super"
+ << "switch"
+ << "synchronized"
+ << "template"
+ << "this"
+ << "Thread"
+ << "ThreadDeath"
+ << "ThreadGroup"
+ << "ThreadLocal"
+ << "throw"
+ << "Throwable"
+ << "throws"
+ << "toString"
+ << "transient"
+ << "true"
+ << "try"
+ << "typedef"
+ << "union"
+ << "UnknownError"
+ << "UnsatisfiedLinkError"
+ << "unsigned"
+ << "UnsupportedClassVersionError"
+ << "UnsupportedOperationException"
+ << "VerifyError"
+ << "VirtualMachineError"
+ << "void"
+ << "Void"
+ << "volatile"
+ << "wait"
+ << "while";
+ }
+
+ return keywords;
+}
+
+#include "javacodegenerator.moc"
+
diff --git a/umbrello/umbrello/codegenerators/javacodegenerator.h b/umbrello/umbrello/codegenerators/javacodegenerator.h
new file mode 100644
index 00000000..29edb16f
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodegenerator.h
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Jun 19 2003
+ */
+
+
+
+#ifndef JAVACODEGENERATOR_H
+#define JAVACODEGENERATOR_H
+
+#include <qstring.h>
+#include "../codeviewerstate.h"
+#include "../codegenerator.h"
+#include "../codeblockwithcomments.h"
+#include "../umldoc.h"
+
+#include "classifierinfo.h"
+#include "javaclassifiercodedocument.h"
+#include "javaantcodedocument.h"
+
+#include "javacodegenerationpolicy.h"
+
+class CodeViewerDialog;
+
+class JavaCodeGenerator : public CodeGenerator
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ static const bool DEFAULT_BUILD_ANT_DOC;
+
+ /**
+ * Empty Constructor
+ */
+ JavaCodeGenerator ();
+ JavaCodeGenerator (QDomElement & element);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeGenerator ( );
+
+ // Public attributes
+ //
+
+
+ // Public attribute accessor methods
+ //
+
+
+ /**
+ * Set the value of m_createANTBuildFile
+ * @param new_var the new value of m_createANTBuildFile
+ */
+ void setCreateANTBuildFile ( bool new_var );
+
+ /**
+ * Get the value of m_createANTBuildFile
+ * @return the value of m_createANTBuildFile
+ */
+ bool getCreateANTBuildFile ( );
+
+ /**
+ * A utility method to get the javaCodeGenerationPolicy()->getAutoGenerateAttribAccessors() value.
+ */
+ bool getAutoGenerateAttribAccessors( );
+
+ /**
+ * A utility method to get the javaCodeGenerationPolicy()->getAutoGenerateAssocAccessors() value.
+ */
+ bool getAutoGenerateAssocAccessors( );
+
+ /**
+ * Get the list variable class name to use. For Java, we have set this to "Vector".
+ */
+ static QString getListFieldClassName();
+
+ /** Get the editing dialog for this code document
+ */
+ virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc,
+ Settings::CodeViewerState state);
+
+ // Other methods
+ //
+
+ /**
+ * Utility function for getting the java code generation policy.
+ */
+ JavaCodeGenerationPolicy * getJavaPolicy();
+
+ /**
+ * @return ClassifierCodeDocument
+ * @param classifier
+ */
+ CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+
+ // return "Java"
+ Uml::Programming_Language getLanguage();
+
+ /**
+ * Adds Java's primitives as datatypes
+ */
+ virtual QStringList defaultDatatypes();
+
+ /**
+ * IF the type is "string" we need to declare it as
+ * the Java Object "String" (there is no string primative in Java).
+ * Same thing again for "bool" to "boolean".
+ */
+ static QString fixTypeName(const QString &string);
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+protected:
+
+ /** create the codeblock that will represent the class declaration
+ * for this classifier
+ */
+ CodeBlockWithComments * createClassDecl ( UMLClassifier *c, ClassifierInfo *info, JavaClassifierCodeDocument * doc);
+
+ /**
+ * @return JavaANTCodeDocument
+ */
+ JavaANTCodeDocument * newANTCodeDocument ( );
+
+private:
+
+ void init();
+
+ bool m_createANTBuildFile;
+};
+
+#endif // JAVACODEGENERATOR_H
diff --git a/umbrello/umbrello/codegenerators/javacodeoperation.cpp b/umbrello/umbrello/codegenerators/javacodeoperation.cpp
new file mode 100644
index 00000000..84ce0331
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeoperation.cpp
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 30 2003
+ */
+
+#include "javacodeoperation.h"
+
+#include "javaclassifiercodedocument.h"
+#include "javacodedocumentation.h"
+#include "javacodegenerator.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+JavaCodeOperation::JavaCodeOperation
+ ( JavaClassifierCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment )
+ : CodeOperation (doc, parent, body, comment)
+{
+ // lets not go with the default comment and instead use
+ // full-blown java documentation object instead
+ setComment(new JavaCodeDocumentation(doc));
+
+ // these things never change..
+ setOverallIndentationLevel(1);
+
+ updateMethodDeclaration();
+ updateContent();
+}
+
+JavaCodeOperation::~JavaCodeOperation ( ) { }
+
+// Other methods
+//
+
+// we basically want to update the doc and start text of this method
+void JavaCodeOperation::updateMethodDeclaration()
+{
+
+ CodeDocument * doc = getParentDocument();
+ JavaClassifierCodeDocument * javadoc = dynamic_cast<JavaClassifierCodeDocument*>(doc);
+ UMLOperation * o = getParentOperation();
+ bool isInterface = javadoc->getParentClassifier()->isInterface();
+ QString endLine = getNewLineEndingChars();
+
+ // now, the starting text.
+ QString strVis = javadoc->scopeToJavaDecl(o->getVisibility());
+ // no return type for constructors
+ QString fixedReturn = JavaCodeGenerator::fixTypeName(o->getTypeName());
+ QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" "));
+ QString methodName = o->getName();
+ QString paramStr = QString("");
+
+ // assemble parameters
+ UMLAttributeList list = getParentOperation()->getParmList();
+ int nrofParam = list.count();
+ int paramNum = 0;
+ for(UMLAttribute* parm = list.first(); parm; parm=list.next())
+ {
+ QString rType = parm->getTypeName();
+ QString paramName = parm->getName();
+ paramStr += rType + ' ' + paramName;
+ paramNum++;
+
+ if (paramNum != nrofParam )
+ paramStr += ", ";
+ }
+ QString maybeStatic;
+ if (o->getStatic())
+ maybeStatic = "static ";
+ QString startText = strVis + ' ' + maybeStatic + returnType + methodName + " (" + paramStr + ')';
+
+ // IF the parent is an interface, our operations look different
+ // e.g. they have no body
+ if(isInterface) {
+ startText += ';';
+ setEndMethodText("");
+ } else {
+ startText += " {";
+ setEndMethodText("}");
+ }
+
+ setStartMethodText(startText);
+
+ // Lastly, for text content generation, we fix the comment on the
+ // operation, IF the codeop is autogenerated & currently empty
+ QString comment = o->getDoc();
+ if(comment.isEmpty() && getContentType() == CodeBlock::AutoGenerated)
+ {
+ UMLAttributeList parameters = o->getParmList();
+ for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
+ comment += endLine + "@param " + iterator.current()->getName() + ' ';
+ comment += iterator.current()->getDoc();
+ }
+ // add a returns statement too
+ if(!returnType.isEmpty())
+ comment += endLine + "@return " + returnType + ' ';
+ getComment()->setText(comment);
+ }
+
+
+ // In Java, for interfaces..we DON'T write out non-public
+ // method declarations.
+ if(isInterface)
+ {
+ UMLOperation * o = getParentOperation();
+ if(o->getVisibility() != Uml::Visibility::Public)
+ setWriteOutText(false);
+ }
+
+}
+
+int JavaCodeOperation::lastEditableLine() {
+ ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ if(doc->parentIsInterface())
+ return -1; // very last line is NOT editable as its a one-line declaration w/ no body in
+ // an interface.
+ return 0;
+}
+
+#include "javacodeoperation.moc"
diff --git a/umbrello/umbrello/codegenerators/javacodeoperation.h b/umbrello/umbrello/codegenerators/javacodeoperation.h
new file mode 100644
index 00000000..08a555d8
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javacodeoperation.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Jun 30 2003
+ */
+
+
+#ifndef JAVACODEOPERATION_H
+#define JAVACODEOPERATION_H
+
+#include <qstring.h>
+#include "../codeoperation.h"
+
+class JavaClassifierCodeDocument;
+
+class JavaCodeOperation : virtual public CodeOperation
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ JavaCodeOperation ( JavaClassifierCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~JavaCodeOperation ( );
+
+ virtual int lastEditableLine();
+
+protected:
+
+ void updateMethodDeclaration();
+
+};
+
+#endif // JAVACODEOPERATION_H
diff --git a/umbrello/umbrello/codegenerators/javawriter.cpp b/umbrello/umbrello/codegenerators/javawriter.cpp
new file mode 100644
index 00000000..3e945c60
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javawriter.cpp
@@ -0,0 +1,936 @@
+/***************************************************************************
+ javawriter.cpp - description
+ This is the "old" code generator that does not support code editing
+ in the Modeller but uses significantly less file space because the
+ source code is not replicated in the XMI file.
+ -------------------
+ copyright : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov
+ (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// own header
+#include "javawriter.h"
+// qt includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+// kde includes
+#include <kdebug.h>
+// app includes
+#include "codegen_utils.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../association.h"
+#include "../template.h"
+#include "../umltemplatelist.h"
+
+JavaWriter::JavaWriter() {
+ startline = m_endl + m_indentation;
+}
+
+JavaWriter::~JavaWriter() {}
+
+Uml::Programming_Language JavaWriter::getLanguage() {
+ return Uml::pl_Java;
+}
+
+void JavaWriter::writeClass(UMLClassifier *c)
+{
+
+ if (!c) {
+ kDebug()<<"Cannot write class of NULL concept!\n";
+ return;
+ }
+
+ isInterface = c->isInterface();
+
+ QString fileName = cleanName(c->getName().lower());
+
+ //find an appropriate name for our file
+ fileName = findFileName(c,".java");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // check that we may open that file for writing
+ QFile file;
+ if ( !openFile(file, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // Preparations
+ //
+
+ // sort attributes by Scope
+ UMLAttributeList atl;
+ UMLAttributeList atpub, atprot, atpriv;
+ UMLAttributeList final_atpub, final_atprot, final_atpriv;
+ atpub.setAutoDelete(false);
+ final_atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ final_atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ final_atpriv.setAutoDelete(false);
+
+ if (!isInterface) {
+ UMLAttributeList atl = c->getAttributeList();
+ for (UMLAttribute *at = atl.first(); at ; at = atl.next()) {
+ switch(at->getVisibility())
+ {
+ case Uml::Visibility::Public:
+ if(at->getStatic())
+ final_atpub.append(at);
+ else
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ if(at->getStatic())
+ final_atprot.append(at);
+ else
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ if(at->getStatic())
+ final_atpriv.append(at);
+ else
+ atpriv.append(at);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // another preparation, determine what we have
+ UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
+ UMLAssociationList uniAssociations = c->getUniAssociationToBeImplemented();
+
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ bool hasAssociations = aggregations.count() > 0 || associations.count() > 0 || compositions.count() > 0 || uniAssociations.count() > 0;
+ bool hasAttributes = (atl.count() > 0);
+ bool hasAccessorMethods = hasAttributes || hasAssociations;
+ bool hasOperationMethods = (c->getOpList().count() > 0);
+ // this is a bit too simplistic..some associations are for
+ // SINGLE objects, and WONT be declared as Vectors, so this
+ // is a bit overly inclusive
+ bool hasVectorFields = hasAssociations ? true : false;
+
+ // open text stream to file
+ QTextStream java(&file);
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".java");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),file.name());
+ java<<str<<m_endl;
+ }
+
+ if(!c->getPackage().isEmpty())
+ java<<"package "<<c->getPackage()<<";"<<m_endl;
+
+ // IMPORT statements
+ // Q: Why all utils? Isnt just List and Vector the only classes we are using?
+ // A: doesn't matter at all; its more readable to just include '*' and java compilers
+ // don't slow down or anything. (TZ)
+ if (hasVectorFields )
+ {
+ writeBlankLine(java);
+ java<<"import java.util.*;"<<m_endl;
+ }
+
+ //only import classes in a different package as this class
+ UMLPackageList imports;
+ findObjectsRelated(c,imports);
+ for (UMLPackage *con = imports.first(); con; con = imports.next()) {
+ if (con->getBaseType() == Uml::ot_Datatype)
+ continue;
+ QString pkg = con->getPackage();
+ if (!pkg.isEmpty() && pkg != c->getPackage())
+ java << "import " << pkg << "." << cleanName(con->getName()) << ";"
+ << m_endl;
+ }
+ writeBlankLine(java);
+
+ // write the opening declaration for the class incl any documentation,
+ // interfaces and/or inheritence issues we have
+ writeClassDecl(c, java);
+
+ // start body of class
+ java<<" {"<<m_endl;
+
+ // ATTRIBUTES
+ //
+
+ // write comment for section IF needed
+ if (forceDoc() || hasAccessorMethods)
+ {
+ writeComment("", m_indentation, java);
+ writeComment("Fields", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ }
+
+ writeAttributeDecls(final_atpub, final_atprot, final_atpriv, java);
+ writeAttributeDecls(atpub, atprot, atpriv, java);
+
+ writeAssociationDecls(associations, c->getID(), java);
+ writeAssociationDecls(uniAssociations, c->getID(), java);
+ writeAssociationDecls(aggregations, c->getID(), java);
+ writeAssociationDecls(compositions, c->getID(), java);
+
+ // Constructors: anything we more we need to do here ?
+ //
+ if(!isInterface)
+ writeConstructor(c, java);
+
+ // METHODS
+ //
+
+ // write comment for section IF needed
+ if (forceDoc() || hasAccessorMethods || hasOperationMethods)
+ {
+
+ java<<startline;
+ writeComment("", m_indentation, java);
+ writeComment("Methods", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ writeBlankLine(java);
+ }
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || hasAccessorMethods )
+ {
+ writeComment("", m_indentation, java);
+ writeComment("Accessor methods", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ }
+
+ // Accessors for attributes
+ writeAttributeMethods(final_atpub, Uml::Visibility::Public, java);
+ writeAttributeMethods(final_atprot, Uml::Visibility::Protected, java);
+ writeAttributeMethods(final_atpriv, Uml::Visibility::Private, java);
+ writeAttributeMethods(atpub, Uml::Visibility::Public, java);
+ writeAttributeMethods(atprot, Uml::Visibility::Protected, java);
+ writeAttributeMethods(atpriv, Uml::Visibility::Private, java);
+
+ // accessor methods for associations
+
+ // first: determine the name of the other class
+ writeAssociationMethods(associations, c, java);
+ writeAssociationMethods(uniAssociations, c, java);
+ writeAssociationMethods(aggregations, c, java);
+ writeAssociationMethods(compositions, c, java);
+
+ // Other operation methods
+ // all other operations are now written
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || hasOperationMethods)
+ {
+ writeComment("", m_indentation, java);
+ writeComment("Other methods", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ }
+ writeOperations(c,java);
+
+ writeBlankLine(java);
+ java<<"}"<<m_endl; // end class
+
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+void JavaWriter::writeClassDecl(UMLClassifier *c, QTextStream &java)
+{
+
+ QString classname = cleanName(c->getName()); // our class name
+
+ // write documentation for class, if any, first
+ if(forceDoc() || !c->getDoc().isEmpty())
+ {
+ if(isInterface)
+ writeDocumentation("Interface "+classname,c->getDoc(),"","",java);
+ else
+ writeDocumentation("Class "+classname,c->getDoc(),"","",java);
+
+ writeBlankLine(java);
+ }
+
+ // Now write the actual class declaration
+ QString scope = ""; // = scopeToJavaDecl(c->getVisibility());
+ if (c->getVisibility() != Uml::Visibility::Public) {
+ // We should emit a warning in here .. java doesn't like to allow
+ // private/protected classes. The best we can do (I believe)
+ // is to let these declarations default to "package visibility"
+ // which is a level between traditional "private" and "protected"
+ // scopes. To get this visibility level we just print nothing..
+ } else
+ scope = "public ";
+
+ java<<((c->getAbstract() && !isInterface) ? QString("abstract ") : QString(""))<<scope;
+ if(isInterface)
+ java<<"interface ";
+ else
+ java<<"class ";
+
+ java<<classname;
+
+ // Generics
+ UMLTemplateList template_params = c->getTemplateList();
+ if (template_params.count()) {
+ java << "<";
+ for (UMLTemplate *t = template_params.first(); t; ) {
+ QString formalName = t->getName();
+ java << formalName;
+ QString typeName = t->getTypeName();
+ if (typeName != "class") {
+ java << " extends " << typeName;
+ }
+ if ((t = template_params.next()) != NULL)
+ java << ", ";
+ }
+ java << ">" << m_endl;
+ }
+
+ // write inheritances out
+ UMLClassifier *concept;
+ UMLClassifierList superclasses = c->findSuperClassConcepts(UMLClassifier::CLASS);
+
+ int i = 0;
+ for (concept= superclasses.first(); concept; concept = superclasses.next())
+ {
+ if (i == 0)
+ {
+ java<< " extends ";
+ }
+ else
+ {
+ //The java generated code is wrong ! : No multiple inheritence of class
+ java<< ", " ;
+ }
+ java<< cleanName(concept->getName());
+ i++;
+ }
+
+ UMLClassifierList superInterfaces = c->findSuperClassConcepts(UMLClassifier::INTERFACE);
+ i = 0;
+ for (concept= superInterfaces.first(); concept; concept = superInterfaces.next())
+ {
+ if (i == 0)
+ {
+ if (isInterface)
+ java<< " extends ";
+ else
+ java<< " implements ";
+ }
+ else
+ {
+ //The java generated code is OK ! : multiple inheritence of interface
+ java<< ", " ;
+ }
+ java<< cleanName(concept->getName());
+ i++;
+ }
+
+}
+
+void JavaWriter::writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
+ UMLAttributeList &atpriv, QTextStream &java )
+{
+ UMLAttribute *at;
+
+ for(at=atpub.first(); at; at=atpub.next())
+ {
+ QString documentation = at->getDoc();
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString typeName = fixTypeName(at->getTypeName());
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"public "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+ for(at=atprot.first();at;at=atprot.next())
+ {
+ QString documentation = at->getDoc();
+ QString typeName = fixTypeName(at->getTypeName());
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"protected "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+ for(at=atpriv.first();at;at=atpriv.next())
+ {
+ QString documentation = at->getDoc();
+ QString typeName = fixTypeName(at->getTypeName());
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"private "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+}
+
+void JavaWriter::writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &java)
+{
+
+ UMLAttribute *at;
+ for(at=atpub.first(); at; at=atpub.next())
+ {
+ QString fieldName = cleanName(at->getName());
+ // force capitalizing the field name, this is silly,
+ // from what I can tell, this IS the default behavior for
+ // cleanName. I dunno why its not working -b.t.
+ fieldName.stripWhiteSpace();
+ fieldName.replace(0,1,fieldName.at(0).upper());
+
+ writeSingleAttributeAccessorMethods(at->getTypeName(),
+ cleanName(at->getName()),
+ fieldName,
+ at->getDoc(),
+ visibility, Uml::chg_Changeable, at->getStatic(), java);
+ }
+
+}
+
+void JavaWriter::writeComment(const QString &comment, const QString &myIndent,
+ QTextStream &java, bool javaDocStyle)
+{
+ // in the case we have several line comment..
+ // NOTE: this part of the method has the problem of adopting UNIX newline,
+ // need to resolve for using with MAC/WinDoze eventually I assume
+ if (comment.contains(QRegExp("\n"))) {
+
+ if(javaDocStyle)
+ java << myIndent << "/**" << m_endl;
+ QStringList lines = QStringList::split( "\n", comment);
+ for(uint i= 0; i < lines.count(); i++)
+ {
+ writeBlankLine(java);
+ if(javaDocStyle)
+ java<<myIndent<<" * ";
+ else
+ java<<myIndent<<"// ";
+ java << lines[i];
+ }
+ if(javaDocStyle)
+ java << myIndent << " */" << m_endl;
+ } else {
+ // this should be more fancy in the future, breaking it up into 80 char
+ // lines so that it doesn't look too bad
+ writeBlankLine(java);
+ if(javaDocStyle)
+ java << myIndent << "/**" << m_endl << myIndent << " *";
+ else
+ java<<myIndent<<"//";
+ if(comment.length() > 0)
+ java << " " << comment;
+ if(javaDocStyle)
+ java << m_endl << myIndent << " */";
+ }
+}
+
+void JavaWriter::writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &java)
+{
+ writeBlankLine(java);
+ java<<indent<<"/**"<<m_endl;
+ if (!header.isEmpty())
+ java<<formatDoc(header, indent+" * ");
+ if (!body.isEmpty())
+ java<<formatDoc(body, indent+" * ");
+ if (!end.isEmpty())
+ {
+ QStringList lines = QStringList::split( "\n", end);
+ for(uint i= 0; i < lines.count(); i++)
+ java<<formatDoc(lines[i], indent+" * ");
+ }
+ java<<indent<<" */";
+}
+
+void JavaWriter::writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &java)
+{
+
+ if( forceSections() || !associations.isEmpty() )
+ {
+ bool printRoleA = false, printRoleB = false;
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == id)
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id)
+ printRoleA = true;
+
+ // First: we insert documentaion for association IF it has either role AND some documentation (!)
+ if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
+ writeComment(a->getDoc(), m_indentation, java);
+
+ // print RoleB decl
+ if (printRoleB)
+ {
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::B)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), a->getMulti(Uml::B), a->getRoleDoc(Uml::B), a->getVisibility(Uml::B), java);
+ }
+
+ // print RoleA decl
+ if (printRoleA)
+ {
+ QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::A)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), a->getMulti(Uml::A), a->getRoleDoc(Uml::A), a->getVisibility(Uml::A), java);
+ }
+ }
+ }
+}
+
+void JavaWriter::writeAssociationRoleDecl(QString fieldClassName,
+ QString roleName, QString multi,
+ QString doc, Uml::Visibility visib, QTextStream &java)
+{
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty())
+ return;
+
+ QString scope = scopeToJavaDecl(visib);
+
+ // always put space between this and prior decl, if any
+ writeBlankLine(java);
+
+ if (!doc.isEmpty())
+ writeComment(doc, m_indentation, java);
+
+ // declare the association based on whether it is this a single variable
+ // or a List (Vector). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
+ java<<startline<<scope<<" "<<fieldClassName<<" "<<fieldVarName<<";";
+ }
+ else
+ {
+ QString fieldVarName = roleName.lower() + "Vector";
+ java<<startline<<scope<<" Vector "<<fieldVarName<<" = new Vector();";
+ // from here we could initialize default values, or put in an init() section
+ // of the constructors
+ }
+
+}
+
+void JavaWriter::writeAssociationMethods (UMLAssociationList associations, UMLClassifier *thisClass, QTextStream &java)
+{
+ if( forceSections() || !associations.isEmpty() )
+ {
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+
+ // insert the methods to access the role of the other
+ // class in the code of this one
+ if (a->getObjectId(Uml::A) == thisClass->getID())
+ {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::B).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::B));
+ writeAssociationRoleMethod(fieldClassName,
+ a->getRoleName(Uml::B),
+ a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
+ a->getVisibility(Uml::B),
+ a->getChangeability(Uml::B), java);
+ }
+ }
+
+ if (a->getObjectId(Uml::B) == thisClass->getID())
+ {
+ // only write out IF there is a rolename given
+ if(!a->getRoleName(Uml::A).isEmpty()) {
+ QString fieldClassName = getUMLObjectName(a->getObject(Uml::A));
+ writeAssociationRoleMethod(fieldClassName, a->getRoleName(Uml::A),
+ a->getMulti(Uml::A),
+ a->getRoleDoc(Uml::A),
+ a->getVisibility(Uml::A),
+ a->getChangeability(Uml::A),
+ java);
+ }
+ }
+
+ }
+ }
+}
+
+void JavaWriter::writeAssociationRoleMethod (QString fieldClassName, QString roleName, QString multi,
+ QString description, Uml::Visibility visib, Uml::Changeability_Type change,
+ QTextStream &java)
+{
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
+ writeSingleAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, visib, change, false, java);
+ }
+ else
+ {
+ QString fieldVarName = roleName.lower() + "Vector";
+ writeVectorAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, visib, change, java);
+ }
+}
+
+void JavaWriter::writeVectorAttributeAccessorMethods (QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type changeType,
+ QTextStream &java)
+{
+
+ fieldClassName = fixTypeName(fieldClassName);
+ fieldName = Codegen_Utils::capitalizeFirstLetter(fieldName);
+ QString strVis = scopeToJavaDecl(visibility);
+
+ // ONLY IF changeability is NOT Frozen
+ if (changeType != Uml::chg_Frozen)
+ {
+ writeDocumentation("Add a "+fieldName+" object to the "+fieldVarName+" List",description,"",m_indentation,java);
+ java<<startline<<strVis<<" void add"<<fieldName<<" ( "<<fieldClassName<<" new_object ) {";
+ java<<startline<<m_indentation<<fieldVarName<<".add(new_object);";
+ java<<startline<<"}"<<m_endl;
+ }
+
+ // ONLY IF changeability is Changeable
+ if (changeType == Uml::chg_Changeable)
+ {
+ writeDocumentation("Remove a "+fieldName+" object from "+fieldVarName+" List",description,"",m_indentation,java);
+ java<<startline<<strVis<<" void remove"<<fieldName<<" ( "<<fieldClassName<<" new_object )";
+ java<<startline<<"{";
+ java<<startline<<m_indentation<<fieldVarName<<".remove(new_object);";
+ java<<startline<<"}"<<m_endl;
+ }
+
+ // always allow getting the list of stuff
+ writeDocumentation("Get the List of "+fieldName+" objects held by "+fieldVarName,description,"@return List of "+fieldName+" objects held by "+fieldVarName,m_indentation,java);
+ java<<startline<<strVis<<" List get"<<fieldName<<"List ( ) {";
+ java<<startline<<m_indentation<<"return (List) "<<fieldVarName<<";";
+ java<<startline<<"}"<<m_endl;
+ writeBlankLine(java);
+}
+
+
+void JavaWriter::writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ bool isFinal, QTextStream &java)
+{
+
+ QString strVis = scopeToJavaDecl(visibility);
+ fieldClassName = fixTypeName(fieldClassName);
+ fieldName = Codegen_Utils::capitalizeFirstLetter(fieldName);
+
+ // set method
+ if (change == Uml::chg_Changeable && !isFinal) {
+ writeDocumentation("Set the value of "+fieldVarName,description,"@param newVar the new value of "+fieldVarName,m_indentation,java);
+ java<<startline<<strVis<<" void set"<<fieldName<<" ( "<<fieldClassName<<" newVar ) {";
+ java<<startline<<m_indentation<<fieldVarName<<" = newVar;";
+ java<<startline<<"}"<<m_endl;
+ }
+
+ // get method
+ writeDocumentation("Get the value of "+fieldVarName,description,"@return the value of "+fieldVarName,m_indentation,java);
+ java<<startline<<strVis<<" "<<fieldClassName<<" get"<<fieldName<<" ( ) {";
+ java<<startline<<m_indentation<<"return "<<fieldVarName<<";";
+ java<<startline<<"}";
+ writeBlankLine(java);
+}
+
+void JavaWriter::writeConstructor(UMLClassifier *c, QTextStream &java)
+{
+
+ if (forceDoc())
+ {
+ java<<startline;
+ writeComment("", m_indentation, java);
+ writeComment("Constructors", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ }
+
+ // write the first constructor
+ QString className = cleanName(c->getName());
+ java<<m_indentation<<"public "<<className<<" () { };";
+
+}
+
+// IF the type is "string" we need to declare it as
+// the Java Object "String" (there is no string primative in Java).
+// Same thing again for "bool" to "boolean"
+QString JavaWriter::fixTypeName(const QString& string)
+{
+ if (string.isEmpty())
+ return "void";
+ if (string == "string")
+ return "String";
+ if (string == "bool")
+ return "boolean";
+ return string;
+}
+
+QStringList JavaWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("int");
+ l.append("char");
+ l.append("boolean");
+ l.append("float");
+ l.append("double");
+ l.append("byte");
+ l.append("short");
+ l.append("long");
+ l.append("String");
+ return l;
+}
+
+
+bool JavaWriter::compareJavaMethod(UMLOperation *op1, UMLOperation *op2)
+{
+ if (op1 == NULL || op2 == NULL)
+ return false;
+ if (op1 == op2)
+ return true;
+ if (op1->getName() != op2->getName())
+ return false;
+ UMLAttributeList atl1 = op1->getParmList();
+ UMLAttributeList atl2 = op2->getParmList();
+ if (atl1.count() != atl2.count())
+ return false;
+ UMLAttribute *at1;
+ UMLAttribute *at2;
+ for (at1 = atl1.first(), at2 = atl2.first(); at1 && at2 ; at1 = atl1.next(),at2 = atl2.next())
+ {
+ if (at1->getTypeName() != at2->getTypeName())
+ return false;
+ }
+ return true;
+
+}
+
+bool JavaWriter::javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl)
+{
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ if (JavaWriter::compareJavaMethod(op, umlOp)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void JavaWriter::getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath)
+{
+ UMLClassifierList superClasses = c->findSuperClassConcepts();
+
+ for (UMLClassifier *concept= superClasses.first(); concept; concept = superClasses.next())
+ {
+ getSuperImplementedOperations(concept, yetImplementedOpList, toBeImplementedOpList, (concept->isInterface() && noClassInPath));
+ UMLOperationList opl = concept->getOpList();
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ if (concept->isInterface() && noClassInPath) {
+ if (!JavaWriter::javaMethodInList(op,toBeImplementedOpList))
+ toBeImplementedOpList.append(op);
+ }
+ else
+ {
+ if (!JavaWriter::javaMethodInList(op, yetImplementedOpList))
+ yetImplementedOpList.append(op);
+ }
+ }
+ }
+
+}
+
+void JavaWriter::getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opList )
+{
+ UMLOperationList yetImplementedOpList;
+ UMLOperationList toBeImplementedOpList;
+
+ getSuperImplementedOperations(c,yetImplementedOpList, toBeImplementedOpList);
+ for (UMLOperation *op = toBeImplementedOpList.first(); op; op = toBeImplementedOpList.next())
+ {
+ if ( ! JavaWriter::javaMethodInList(op, yetImplementedOpList) && ! JavaWriter::javaMethodInList(op, opList) )
+ opList.append(op);
+ }
+}
+
+void JavaWriter::writeOperations(UMLClassifier *c, QTextStream &java) {
+ UMLOperationList opl;
+ UMLOperationList oppub,opprot,oppriv;
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ opl = c->getOpList();
+ if (! c->isInterface()) {
+ getInterfacesOperationsToBeImplemented(c, opl);
+ }
+ for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // do people REALLY want these comments? Hmm.
+ /*
+ if(forceSections() || oppub.count())
+ {
+ writeComment("public operations",m_indentation,java);
+ writeBlankLine(java);
+ }
+ */
+ writeOperations(oppub,java);
+
+ /*
+ if(forceSections() || opprot.count())
+ {
+ writeComment("protected operations",m_indentation,java);
+ writeBlankLine(java);
+ }
+ */
+ writeOperations(opprot,java);
+
+ /*
+ if(forceSections() || oppriv.count())
+ {
+ writeComment("private operations",m_indentation,java);
+ writeBlankLine(java);
+ }
+ */
+ writeOperations(oppriv,java);
+
+}
+
+void JavaWriter::writeOperations(UMLOperationList &oplist, QTextStream &java) {
+ UMLOperation *op;
+ UMLAttributeList atl;
+ UMLAttribute *at;
+ int i,j;
+ QString str;
+
+ // generate method decl for each operation given
+ for( op=oplist.first(); op ;op=oplist.next())
+ {
+
+ QString returnStr = "";
+ // write documentation
+
+ QString methodReturnType = fixTypeName(op->getTypeName());
+ if(methodReturnType != "void")
+ returnStr += "@return "+methodReturnType+"\n";
+
+ str = ""; // reset for next method
+ str += ((op->getAbstract() && !isInterface) ? "abstract ":"");
+ str += scopeToJavaDecl(op->getVisibility()) + ' ';
+ str += (op->getStatic() ? "static ":"");
+ str += methodReturnType + ' ' +cleanName(op->getName()) + "( ";
+
+ atl = op->getParmList();
+ i= atl.count();
+ j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ QString typeName = fixTypeName(at->getTypeName());
+ QString atName = cleanName(at->getName());
+ str += typeName + ' ' + atName +
+ (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""))
+ + ((j < i-1)?", ":"");
+ returnStr += "@param "+atName+' '+at->getDoc()+"\n";
+ }
+ str+= " )";
+
+ // method only gets a body IF its not abstract
+ if (op->getAbstract() || isInterface)
+ str+=";\n\n"; // terminate now
+ else
+ str+=startline+"{\n\n"+m_indentation+"}\n\n"; // empty method body
+
+ // write it out
+ writeDocumentation("", op->getDoc(), returnStr, m_indentation, java);
+ java<<startline<<str;
+ }
+}
+
+QString JavaWriter::fixInitialStringDeclValue(QString value, QString type)
+{
+ // check for strings only
+ if (!value.isEmpty() && type == "String") {
+ if (!value.startsWith("\""))
+ value.prepend("\"");
+ if (!value.endsWith("\""))
+ value.append("\"");
+ }
+ return value;
+}
+
+QString JavaWriter::scopeToJavaDecl(Uml::Visibility scope)
+{
+ QString scopeString;
+ switch(scope)
+ {
+ case Uml::Visibility::Public:
+ scopeString = "public";
+ break;
+ case Uml::Visibility::Protected:
+ scopeString = "protected";
+ break;
+ case Uml::Visibility::Private:
+ default:
+ scopeString = "private";
+ break;
+ }
+ return scopeString;
+}
+
+// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
+QString JavaWriter::getUMLObjectName(UMLObject *obj)
+{
+ return(obj!=0)?obj->getName():QString("NULL");
+}
+
+void JavaWriter::writeBlankLine(QTextStream &java)
+{
+ java<<m_endl;
+}
+
diff --git a/umbrello/umbrello/codegenerators/javawriter.h b/umbrello/umbrello/codegenerators/javawriter.h
new file mode 100644
index 00000000..2469f6d0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javawriter.h
@@ -0,0 +1,236 @@
+/***************************************************************************
+ javawriter.h - description
+ This is the "old" code generator that does not support code editing
+ in the Modeller but uses significantly less file space because the
+ source code is not replicated in the XMI file.
+ -------------------
+ copyright : (C) 2003 Brian Thomas
+ (C) 2004 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef JAVAWRITER_H
+#define JAVAWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+#include "../umlassociationlist.h"
+
+class UMLOperation;
+
+/**
+ * class JavaWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate a java source file for
+ * that concept
+ */
+class JavaWriter : public SimpleCodeGenerator {
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ JavaWriter();
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~JavaWriter();
+
+ /**
+ * call this method to generate java code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "Java"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * Overrides method from class CodeGenerator
+ */
+ QStringList defaultDatatypes();
+
+private:
+
+ /**
+ * Writes class's documentation then the class header
+ * public abstract class Foo extents {
+ */
+ void writeClassDecl(UMLClassifier *c, QTextStream &java);
+
+ /**
+ * Writes the comment and class constructor
+ */
+ void writeConstructor(UMLClassifier *c, QTextStream &java);
+
+ /**
+ * return true if the two operations have the same name and the same parameters
+ * @param op1 first operation to be compared
+ * @param op2 second operation to be compared
+ */
+ static bool compareJavaMethod(UMLOperation *op1, UMLOperation *op2);
+
+ /**
+ * return true if the operation is in the list
+ * @param umlOp operation to be searched
+ * @param opl list of operations
+ */
+ static bool javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl);
+
+ /**
+ * get all operations which a given class inherit from all its super interfaces and get all operations
+ * which this given class inherit from all its super classes
+ * @param c the class for which we are generating code
+ * @param yetImplementedOpList the list of yet implemented operations
+ * @param toBeImplementedOpList the list of to be implemented operations
+ * @param noClassInPath tells if there is a class between the base class and the current interface
+ */
+ void getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath = true);
+
+ /**
+ * get all operations which a given class inherit from all its super interfaces and that should be implemented
+ * @param c the class for which we are generating code
+ * @param opl the list of operations used to append the operations
+ */
+ void getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opl);
+
+ /**
+ * write all operations for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * write a list of operations for a given class
+ * @param list the list of operations you want to write
+ * @param j the stream associated with the output file
+ */
+ void writeOperations(UMLOperationList &list, QTextStream &j);
+
+ /**
+ * write all attributes for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * writes the Attribute declarations
+ * @param atpub List of public attributes
+ * @param atprot list of protected attributes
+ * @param atpriv list of private attributes
+ * @param java text stream
+ */
+ void writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
+ UMLAttributeList &atpriv, QTextStream &java );
+
+ /**
+ * Searches a list of associations for appropriate ones to write out as attributes
+ */
+ void writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &java);
+
+ /**
+ * Writes out an association as an attribute using Vector
+ */
+ void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi,
+ QString doc, Uml::Visibility visib, QTextStream &java);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in atpub
+ */
+ void writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &java);
+
+ /**
+ * calls @ref writeAssociationRoleMethod() on each of the associations in the given list
+ */
+ void writeAssociationMethods(UMLAssociationList associations, UMLClassifier *thisClass,
+ QTextStream &java);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() or @ref
+ * writeVectorAttributeAccessorMethods() on the assocaition
+ * role
+ */
+ void writeAssociationRoleMethod(QString fieldClassName, QString roleName, QString multi,
+ QString description, Uml::Visibility visib, Uml::Changeability_Type change,
+ QTextStream &java);
+
+ /**
+ * Writes getFoo() and setFoo() accessor methods for the attribute
+ */
+ void writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ bool isFinal, QTextStream &java);
+
+ /**
+ * Writes addFoo() and removeFoo() accessor methods for the Vector attribute
+ */
+ void writeVectorAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ QTextStream &java);
+
+ /**
+ * Writes a // style comment
+ */
+ void writeComment(const QString &text, const QString &indent, QTextStream &java, bool javaDocStyle=false);
+
+ /**
+ * Writes a documentation comment
+ */
+ void writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &java);
+
+ /**
+ * Returns the name of the given object (if it exists)
+ */
+ QString getUMLObjectName(UMLObject *obj);
+
+ /**
+ * Replaces `string' with `String' and `bool' with `boolean'
+ */
+ QString fixTypeName(const QString& string);
+
+ /**
+ * check that initial values of strings have quotes around them
+ */
+ QString fixInitialStringDeclValue(QString value, QString type);
+
+ /**
+ * Write a blank line
+ */
+ void writeBlankLine(QTextStream& java);
+
+ /**
+ * a little method for converting scope to string value
+ */
+ QString scopeToJavaDecl(Uml::Visibility scope);
+
+ /**
+ * A \n, used at the end of each line
+ */
+ QString startline;
+
+ /**
+ * Whether or not this concept is an interface.
+ */
+ bool isInterface;
+
+};
+
+
+#endif // JAVAWRITER_H
+
diff --git a/umbrello/umbrello/codegenerators/jswriter.cpp b/umbrello/umbrello/codegenerators/jswriter.cpp
new file mode 100644
index 00000000..1dbb45d6
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/jswriter.cpp
@@ -0,0 +1,308 @@
+/***************************************************************************
+ begin : Sat Feb 08 2003
+ copyright : (C) 2003 by Alexander Blum
+ email : blum@kewbee.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License js published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "jswriter.h"
+#include "../association.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umldoc.h"
+#include "../attribute.h"
+
+#include <kdebug.h>
+
+#include <qregexp.h>
+#include <qtextstream.h>
+
+JSWriter::JSWriter() {
+}
+
+JSWriter::~JSWriter() {}
+
+
+void JSWriter::writeClass(UMLClassifier *c)
+{
+ if(!c)
+ {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+ QString fileName = c->getName().lower();
+
+ //find an appropriate name for our file
+ fileName = findFileName(c,".js");
+ if (fileName.isEmpty())
+ {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile filejs;
+ if(!openFile(filejs, fileName))
+ {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream js(&filejs);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".js");
+ if(!str.isEmpty())
+ {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),filejs.name());
+ js << str << m_endl;
+ }
+
+
+ //write includes
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ for (UMLPackage *conc = includes.first(); conc; conc = includes.next())
+ {
+ QString headerName = findFileName(conc, ".js");
+ if ( !headerName.isEmpty() )
+ {
+ js << "#include \"" << headerName << "\"" << m_endl;
+ }
+ }
+ js << m_endl;
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty())
+ {
+ js << m_endl << "/**" << m_endl;
+ js << " * class " << classname << m_endl;
+ js << formatDoc(c->getDoc()," * ");
+ js << " */" << m_endl << m_endl;
+ }
+
+
+ //check if class is abstract and / or has abstract methods
+ if(c->getAbstract() && !hasAbstractOps(c))
+ js << "/******************************* Abstract Class ****************************" << m_endl << " "
+ << classname << " does not have any pure virtual methods, but its author" << m_endl
+ << " defined it as an abstract class, so you should not use it directly." << m_endl
+ << " Inherit from it instead and create only objects from the derived classes" << m_endl
+ << "*****************************************************************************/" << m_endl << m_endl;
+
+ js << classname << " = function ()" << m_endl;
+ js << "{" << m_endl;
+ js << m_indentation << "this._init ();" << m_endl;
+ js << "}" << m_endl;
+ js << m_endl;
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ for (UMLClassifier *obj = superclasses.first();
+ obj; obj = superclasses.next()) {
+ js << classname << ".prototype = new " << cleanName(obj->getName()) << " ();" << m_endl;
+ }
+
+ js << m_endl;
+
+ if (! c->isInterface()) {
+ UMLAttributeList atl = c->getAttributeList();
+
+ js << "/**" << m_endl;
+ QString temp = "_init sets all " + classname + " attributes to their default value."
+ " Make sure to call this method within your class constructor";
+ js << formatDoc(temp, " * ");
+ js << " */" << m_endl;
+ js << classname << ".prototype._init = function ()" << m_endl;
+ js << "{" << m_endl;
+ for(UMLAttribute *at = atl.first(); at ; at = atl.next())
+ {
+ if (forceDoc() || !at->getDoc().isEmpty())
+ {
+ js << m_indentation << "/**" << m_endl
+ << formatDoc(at->getDoc(), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+ if(!at->getInitialValue().isEmpty())
+ {
+ js << m_indentation << "this.m_" << cleanName(at->getName()) << " = " << at->getInitialValue() << ";" << m_endl;
+ }
+ else
+ {
+ js << m_indentation << "this.m_" << cleanName(at->getName()) << " = \"\";" << m_endl;
+ }
+ }
+ }
+
+ //associations
+ UMLAssociationList aggregations = c->getAggregations();
+ if (forceSections() || !aggregations.isEmpty ())
+ {
+ js << m_endl << m_indentation << "/**Aggregations: */" << m_endl;
+ writeAssociation(classname, aggregations , js );
+
+ }
+ UMLAssociationList compositions = c->getCompositions();
+ if( forceSections() || !compositions.isEmpty())
+ {
+ js << m_endl << m_indentation << "/**Compositions: */" << m_endl;
+ writeAssociation(classname, compositions , js );
+
+ }
+ js << m_endl;
+ js << "}" << m_endl;
+ js << m_endl;
+
+ //operations
+ UMLOperationList ops(c->getOpList());
+ writeOperations(classname, &ops, js);
+
+ js << m_endl;
+
+ //finish file
+
+ //close files and notfiy we are done
+ filejs.close();
+ emit codeGenerated(c, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void JSWriter::writeAssociation(QString& classname, UMLAssociationList& assocList , QTextStream &js)
+{
+ for (UMLAssociation *a = assocList.first(); a; a = assocList.next()) {
+ // association side
+ Uml::Role_Type role = (a->getObject(Uml::A)->getName() == classname ? Uml::B : Uml::A);
+
+ QString roleName(cleanName(a->getRoleName(role)));
+
+ if (!roleName.isEmpty()) {
+
+ // association doc
+ if (forceDoc() || !a->getDoc().isEmpty())
+ {
+ js << m_indentation << "/**" << m_endl
+ << formatDoc(a->getDoc(), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+
+ // role doc
+ if (forceDoc() || !a->getRoleDoc(role).isEmpty())
+ {
+ js << m_indentation << "/**" << m_endl
+ << formatDoc(a->getRoleDoc(role), m_indentation + " * ")
+ << m_indentation << " */" << m_endl;
+ }
+
+ bool okCvt;
+ int nMulti = a->getMulti(role).toInt(&okCvt,10);
+ bool isNotMulti = a->getMulti(role).isEmpty() || (okCvt && nMulti == 1);
+
+ QString typeName(cleanName(a->getObject(role)->getName()));
+
+ if (isNotMulti)
+ js << m_indentation << "this.m_" << roleName << " = new " << typeName << "();" << m_endl;
+ else
+ js << m_indentation << "this.m_" << roleName << " = new Array();" << m_endl;
+
+ // role visibility
+ }
+ }
+}
+
+void JSWriter::writeOperations(QString classname, UMLOperationList *opList, QTextStream &js)
+{
+ UMLOperation *op;
+ UMLAttribute *at;
+
+ for(op = opList->first(); op; op = opList->next())
+ {
+ UMLAttributeList atl = op->getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ if( writeDoc ) //write method documentation
+ {
+ js << "/**" << m_endl << formatDoc(op->getDoc()," * ");
+
+ for (at = atl.first(); at; at = atl.next()) //write parameter documentation
+ {
+ if(forceDoc() || !at->getDoc().isEmpty())
+ {
+ js << " * @param " + cleanName(at->getName())<<m_endl;
+ js << formatDoc(at->getDoc()," * ");
+ }
+ }//end for : write parameter documentation
+ js << " */" << m_endl;
+ }//end if : write method documentation
+
+ js << classname << ".prototype." << cleanName(op->getName()) << " = function " << "(";
+
+ int i = atl.count();
+ int j=0;
+ for (at = atl.first(); at ;at = atl.next(),j++)
+ {
+ js << cleanName(at->getName())
+ << (!(at->getInitialValue().isEmpty()) ? (QString(" = ")+at->getInitialValue()) : QString(""))
+ << ((j < i-1)?", ":"");
+ }
+ js << ")" << m_endl << "{" << m_endl <<
+ m_indentation << m_endl << "}" << m_endl;
+ js << m_endl << m_endl;
+ }//end for
+}
+
+/**
+ * returns "JavaScript"
+ */
+Uml::Programming_Language JSWriter::getLanguage() {
+ return Uml::pl_JavaScript;
+}
+
+const QStringList JSWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "break"
+ << "case"
+ << "const"
+ << "continue"
+ << "default"
+ << "else"
+ << "false"
+ << "for"
+ << "function"
+ << "if"
+ << "in"
+ << "new"
+ << "return"
+ << "switch"
+ << "this"
+ << "true"
+ << "var"
+ << "while"
+ << "with";
+ }
+
+ return keywords;
+}
+
+#include "jswriter.moc"
diff --git a/umbrello/umbrello/codegenerators/jswriter.h b/umbrello/umbrello/codegenerators/jswriter.h
new file mode 100644
index 00000000..a9c5ebde
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/jswriter.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ jswriter.h - description
+ -------------------
+ begin : Sat Feb 08 2003
+ copyright : (C) 2003 by Alexander Blum
+ email : blum@kewbee.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef JSWRITER_H
+#define JSWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlassociationlist.h"
+
+/**
+ * class JSWriter is a JavaScript code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class JSWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ JSWriter();
+ virtual ~JSWriter();
+
+ /**
+ * call this method to generate Actionscript code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "JavaScript"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param js output stream for the JS file
+ */
+ void writeOperations(QString classname, UMLOperationList *opList, QTextStream &js);
+
+ /**
+ * write a list of associations
+ *
+ * @param classname the name of the class
+ * @param assocList the list of associations
+ * @param as output stream for the AS file
+ */
+ void writeAssociation(QString& classname, UMLAssociationList& assoclist , QTextStream &js);
+};
+
+#endif //JSWRITER
diff --git a/umbrello/umbrello/codegenerators/pascalwriter.cpp b/umbrello/umbrello/codegenerators/pascalwriter.cpp
new file mode 100644
index 00000000..92a45bd2
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/pascalwriter.cpp
@@ -0,0 +1,542 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "pascalwriter.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../classifierlistitem.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../umltemplatelist.h"
+#include "../folder.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../umlnamespace.h"
+#include "classifierinfo.h"
+
+const QString PascalWriter::defaultPackageSuffix = "_Holder";
+
+PascalWriter::PascalWriter() {
+}
+
+PascalWriter::~PascalWriter() {}
+
+/**
+ * returns "Pascal"
+ */
+Uml::Programming_Language PascalWriter::getLanguage() {
+ return Uml::pl_Pascal;
+}
+
+
+bool PascalWriter::isOOClass(UMLClassifier *c) {
+ Uml::Object_Type ot = c->getBaseType();
+ if (ot == Uml::ot_Interface)
+ return true;
+ if (ot == Uml::ot_Enum)
+ return false;
+ if (ot != Uml::ot_Class) {
+ kDebug() << "PascalWriter::isOOClass: unknown object type " << ot << endl;
+ return false;
+ }
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant" || stype == "CORBATypedef" ||
+ stype == "CORBAStruct" || stype == "CORBAUnion")
+ return false;
+ // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are
+ // assumed to be OO classes.
+ return true;
+}
+
+QString PascalWriter::qualifiedName(UMLPackage *p, bool withType, bool byValue) {
+ UMLPackage *umlPkg = p->getUMLPackage();
+ QString className = cleanName(p->getName());
+ QString retval;
+
+ if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical))
+ umlPkg = NULL;
+
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(p);
+ if (umlPkg == NULL) {
+ retval = className;
+ if (c == NULL || !isOOClass(c))
+ retval.append(defaultPackageSuffix);
+ } else {
+ retval = umlPkg->getFullyQualifiedName(".");
+ if (isOOClass(c)) {
+ retval.append(".");
+ retval.append(className);
+ }
+ }
+ if (! withType)
+ return retval;
+ if (c && isOOClass(c)) {
+ retval.append(".Object");
+ if (! byValue)
+ retval.append("_Ptr");
+ } else {
+ retval.append(".");
+ retval.append(className);
+ }
+ return retval;
+}
+
+void PascalWriter::computeAssocTypeAndRole
+(UMLAssociation *a, QString& typeName, QString& roleName) {
+ roleName = a->getRoleName(Uml::A);
+ if (roleName.isEmpty()) {
+ if (a->getMulti(Uml::A).isEmpty()) {
+ roleName = "M_";
+ roleName.append(typeName);
+ } else {
+ roleName = typeName;
+ roleName.append("_Vector");
+ }
+ }
+ UMLClassifier* c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ if (c == NULL)
+ return;
+ typeName = cleanName(c->getName());
+ if (! a->getMulti(Uml::A).isEmpty())
+ typeName.append("_Array_Access");
+}
+
+void PascalWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ const bool isClass = !c->isInterface();
+ QString classname = cleanName(c->getName());
+ QString fileName = qualifiedName(c).lower();
+ fileName.replace('.', '-');
+
+ //find an appropriate name for our file
+ fileName = overwritableName(c, fileName, ".pas");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile file;
+ if (!openFile(file, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // Start generating the code.
+
+ QTextStream pas(&file);
+ //try to find a heading file(license, comments, etc)
+ QString str;
+ str = getHeadingFile(".pas");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), file.name());
+ pas << str << endl;
+ }
+
+ QString unit = qualifiedName(c);
+ pas << "unit " << unit << ";" << m_endl << m_endl;
+ pas << "INTERFACE" << m_endl << m_endl;
+ // Use referenced classes.
+ UMLPackageList imports;
+ findObjectsRelated(c, imports);
+ if (imports.count()) {
+ pas << "uses" << m_endl;
+ bool first = true;
+ for (UMLPackage *con = imports.first(); con; con = imports.next()) {
+ if (con->getBaseType() != Uml::ot_Datatype) {
+ if (first)
+ first = false;
+ else
+ pas << "," << m_endl;
+ pas << " " << qualifiedName(con);
+ }
+ }
+ pas << ";" << m_endl << m_endl;
+ }
+
+ pas << "type" << m_endl;
+ m_indentLevel++;
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLEnum *ue = static_cast<UMLEnum*>(c);
+ UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral);
+ uint i = 0;
+ pas << getIndent() << classname << " = (" << m_endl;
+ m_indentLevel++;
+ for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ pas << getIndent() << enumLiteral;
+ if (++i < litList.count())
+ pas << "," << m_endl;
+ }
+ m_indentLevel--;
+ pas << ");" << m_endl << m_endl;
+ m_indentLevel--;
+ pas << "end." << m_endl << m_endl;
+ return;
+ }
+ UMLAttributeList atl = c->getAttributeList();
+ if (! isOOClass(c)) {
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBAStruct") {
+ if (isClass) {
+ UMLAttribute *at;
+ pas << getIndent() << classname << " = record" << m_endl;
+ m_indentLevel++;
+ for (at = atl.first(); at; at = atl.next()) {
+ QString name = cleanName(at->getName());
+ QString typeName = at->getTypeName();
+ pas << getIndent() << name << " : " << typeName;
+ QString initialVal = at->getInitialValue();
+ if (initialVal.latin1() && ! initialVal.isEmpty())
+ pas << " := " << initialVal;
+ pas << ";" << m_endl;
+ }
+ m_indentLevel--;
+ pas << "end;" << m_endl << m_endl;
+ }
+ } else if(stype == "CORBAUnion") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBATypedef") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else {
+ pas << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl;
+ }
+ m_indentLevel--;
+ pas << getIndent() << "end." << m_endl << m_endl;
+ return;
+ }
+
+ // Write class Documentation if non-empty or if force option set.
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ pas << "//" << m_endl;
+ pas << "// class " << classname << endl;
+ pas << formatDoc(c->getDoc(), "// ");
+ pas << m_endl;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+
+ pas << getIndent() << classname << " = object";
+ if (!superclasses.isEmpty()) {
+ // FIXME: Multiple inheritance is not yet supported
+ UMLClassifier* parent = superclasses.first();
+ pas << "(" << qualifiedName(parent) << ")";
+ }
+ pas << m_endl;
+
+ ClassifierInfo info(c);
+ UMLAttributeList atpub = info.atpub;
+ if (isClass && (forceSections() || atpub.count())) {
+ pas << getIndent() << "// Public attributes:" << m_endl;
+ UMLAttribute *at;
+ for (at = atpub.first(); at; at = atpub.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ }
+ bool haveAttrs = (isClass && atl.count());
+
+ // Generate public operations.
+ UMLOperationList opl(c->getOpList());
+ UMLOperationList oppub;
+ oppub.setAutoDelete(false);
+ UMLOperation *op;
+ for (op = opl.first(); op; op = opl.next()) {
+ if (op->getVisibility() == Uml::Visibility::Public)
+ oppub.append(op);
+ }
+ if (forceSections() || oppub.count())
+ pas << getIndent() << "// Public methods:" << m_endl << m_endl;
+ for (op = oppub.first(); op; op = oppub.next())
+ writeOperation(op, pas);
+
+ if (info.atprot.count()) {
+ pas << "protected" << m_endl << m_endl;
+ UMLAttribute *at;
+ UMLAttributeList atprot = info.atprot;
+ for (at = atprot.first(); at; at = atprot.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ pas << m_endl;
+ }
+ if (info.atpriv.count()) {
+ pas << "private" << m_endl << m_endl;
+ UMLAttribute *at;
+ UMLAttributeList atpriv = info.atpriv;
+ for (at = atpriv.first(); at; at = atpriv.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ pas << m_endl;
+ }
+ pas << getIndent() << "end;" << m_endl << m_endl;
+
+ pas << getIndent() << "P" << classname << " = ^" << classname <<";" << m_endl << m_endl;
+
+ m_indentLevel--;
+ pas << "end;" << m_endl << m_endl;
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+
+void PascalWriter::writeOperation(UMLOperation *op, QTextStream &pas, bool is_comment) {
+ if (op->getStatic()) {
+ pas << "// TODO: generate status method " << op->getName() << m_endl;
+ return;
+ }
+ UMLAttributeList atl = op->getParmList();
+ QString rettype = op->getTypeName();
+ bool use_procedure = (rettype.isEmpty() || rettype == "void");
+
+ pas << getIndent();
+ if (is_comment)
+ pas << "// ";
+ if (use_procedure)
+ pas << "procedure ";
+ else
+ pas << "function ";
+ pas << cleanName(op->getName()) << " ";
+ if (atl.count()) {
+ pas << "(" << m_endl;
+ uint i = 0;
+ m_indentLevel++;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ pas << getIndent();
+ if (is_comment)
+ pas << "// ";
+ pas << cleanName(at->getName()) << " : ";
+ Uml::Parameter_Direction pk = at->getParmKind();
+ if (pk != Uml::pd_In)
+ pas << "var ";
+ pas << at->getTypeName();
+ if (! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ if (++i < (uint)atl.count())
+ pas << ";" << m_endl;
+ }
+ m_indentLevel--;
+ pas << ")";
+ }
+ if (! use_procedure)
+ pas << " : " << rettype;
+ pas << "; virtual; abstract;" << m_endl << m_endl;
+ // TBH, we make the methods abstract here because we don't have the means
+ // for generating meaningful implementations.
+}
+
+QStringList PascalWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("AnsiString");
+ l.append("Boolean");
+ l.append("Byte");
+ l.append("ByteBool");
+ l.append("Cardinal");
+ l.append("Character");
+ l.append("Currency");
+ l.append("Double");
+ l.append("Extended");
+ l.append("Int64");
+ l.append("Integer");
+ l.append("Longint");
+ l.append("LongBool");
+ l.append("Longword");
+ l.append("QWord");
+ l.append("Real");
+ l.append("Shortint");
+ l.append("ShortString");
+ l.append("Single");
+ l.append("Smallint");
+ l.append("String");
+ l.append("WideString");
+ l.append("Word");
+ return l;
+}
+
+/**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword The string to check.
+ */
+bool PascalWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) {
+
+ const QStringList keywords = reservedKeywords();
+
+ QStringList::ConstIterator it;
+ for (it = keywords.begin(); it != keywords.end(); ++it)
+ if ((*it).lower() == rPossiblyReservedKeyword.lower())
+ return true;
+
+ return false;
+}
+
+/**
+ * get list of reserved keywords
+ */
+const QStringList PascalWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if ( keywords.isEmpty() ) {
+ keywords.append( "absolute" );
+ keywords.append( "abstract" );
+ keywords.append( "and" );
+ keywords.append( "array" );
+ keywords.append( "as" );
+ keywords.append( "asm" );
+ keywords.append( "assembler" );
+ keywords.append( "automated" );
+ keywords.append( "begin" );
+ keywords.append( "case" );
+ keywords.append( "cdecl" );
+ keywords.append( "class" );
+ keywords.append( "const" );
+ keywords.append( "constructor" );
+ keywords.append( "contains" );
+ keywords.append( "default" );
+ keywords.append( "deprecated" );
+ keywords.append( "destructor" );
+ keywords.append( "dispid" );
+ keywords.append( "dispinterface" );
+ keywords.append( "div" );
+ keywords.append( "do" );
+ keywords.append( "downto" );
+ keywords.append( "dynamic" );
+ keywords.append( "else" );
+ keywords.append( "end" );
+ keywords.append( "except" );
+ keywords.append( "export" );
+ keywords.append( "exports" );
+ keywords.append( "external" );
+ keywords.append( "far" );
+ keywords.append( "file" );
+ keywords.append( "final" );
+ keywords.append( "finalization" );
+ keywords.append( "finally" );
+ keywords.append( "for" );
+ keywords.append( "forward" );
+ keywords.append( "function" );
+ keywords.append( "goto" );
+ keywords.append( "if" );
+ keywords.append( "implementation" );
+ keywords.append( "implements" );
+ keywords.append( "in" );
+ keywords.append( "index" );
+ keywords.append( "inherited" );
+ keywords.append( "initialization" );
+ keywords.append( "inline" );
+ keywords.append( "inline" );
+ keywords.append( "interface" );
+ keywords.append( "is" );
+ keywords.append( "label" );
+ keywords.append( "library" );
+ keywords.append( "library" );
+ keywords.append( "local" );
+ keywords.append( "message" );
+ keywords.append( "mod" );
+ keywords.append( "name" );
+ keywords.append( "near" );
+ keywords.append( "nil" );
+ keywords.append( "nodefault" );
+ keywords.append( "not" );
+ keywords.append( "object" );
+ keywords.append( "of" );
+ keywords.append( "or" );
+ keywords.append( "out" );
+ keywords.append( "overload" );
+ keywords.append( "override" );
+ keywords.append( "package" );
+ keywords.append( "packed" );
+ keywords.append( "pascal" );
+ keywords.append( "platform" );
+ keywords.append( "private" );
+ keywords.append( "procedure" );
+ keywords.append( "program" );
+ keywords.append( "property" );
+ keywords.append( "protected" );
+ keywords.append( "public" );
+ keywords.append( "published" );
+ keywords.append( "raise" );
+ keywords.append( "read" );
+ keywords.append( "readonly" );
+ keywords.append( "record" );
+ keywords.append( "register" );
+ keywords.append( "reintroduce" );
+ keywords.append( "repeat" );
+ keywords.append( "requires" );
+ keywords.append( "resident" );
+ keywords.append( "resourcestring" );
+ keywords.append( "safecall" );
+ keywords.append( "sealed" );
+ keywords.append( "set" );
+ keywords.append( "shl" );
+ keywords.append( "shr" );
+ keywords.append( "static" );
+ keywords.append( "stdcall" );
+ keywords.append( "stored" );
+ keywords.append( "string" );
+ keywords.append( "then" );
+ keywords.append( "threadvar" );
+ keywords.append( "to" );
+ keywords.append( "try" );
+ keywords.append( "type" );
+ keywords.append( "unit" );
+ keywords.append( "unsafe" );
+ keywords.append( "until" );
+ keywords.append( "uses" );
+ keywords.append( "var" );
+ keywords.append( "varargs" );
+ keywords.append( "virtual" );
+ keywords.append( "while" );
+ keywords.append( "with" );
+ keywords.append( "write" );
+ keywords.append( "writeonly" );
+ keywords.append( "xor" );
+ }
+
+ return keywords;
+}
+
+#include "pascalwriter.moc"
diff --git a/umbrello/umbrello/codegenerators/pascalwriter.h b/umbrello/umbrello/codegenerators/pascalwriter.h
new file mode 100644
index 00000000..bc34d762
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/pascalwriter.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PASCALWRITER_H
+#define PASCALWRITER_H
+
+#include "simplecodegenerator.h"
+
+class UMLAssociation;
+class UMLOperation;
+
+/**
+ * Pascal class writer
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PascalWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ /**
+ * Basic Constructor
+ */
+ PascalWriter ();
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~PascalWriter ();
+
+ /**
+ * call this method to generate Ada code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass (UMLClassifier *c);
+
+ /**
+ * returns "Pascal"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ QStringList defaultDatatypes();
+
+ /**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword The string to check.
+ */
+ virtual bool isReservedKeyword(const QString & rPossiblyReservedKeyword);
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * write one operation
+ * @param op the class for which we are generating code
+ * @param ada the stream associated with the output file
+ */
+ void writeOperation (UMLOperation *op, QTextStream &ada, bool is_comment = false);
+
+ void computeAssocTypeAndRole (UMLAssociation *a, QString& typeName, QString& roleName);
+
+ bool isOOClass (UMLClassifier *c);
+
+ QString qualifiedName
+ (UMLPackage *p, bool withType = false, bool byValue = false);
+
+ static const QString defaultPackageSuffix;
+
+};
+
+#endif // PASCALWRITER_H
+
diff --git a/umbrello/umbrello/codegenerators/perlwriter.cpp b/umbrello/umbrello/codegenerators/perlwriter.cpp
new file mode 100644
index 00000000..7c8360fa
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/perlwriter.cpp
@@ -0,0 +1,716 @@
+/***************************************************************************
+ begin : Wed Jan 22 2003
+ copyright : (C) 2003 by David Hugh-Jones
+ (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ email : hughjonesd@yahoo.co.uk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "perlwriter.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umldoc.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../uml.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qdir.h>
+#include <qdatetime.h>
+#include <qtextstream.h>
+
+PerlWriter::PerlWriter()
+{
+}
+
+PerlWriter::~PerlWriter() {}
+
+bool PerlWriter::GetUseStatements(UMLClassifier *c, QString &Ret,
+ QString &ThisPkgName){
+
+ if(!c){
+ return(false);
+ }
+
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ UMLPackage *conc;
+ QString AV = "@";
+ QString SV = "$";
+ QString HV = "%";
+ for(conc = includes.first(); conc ;conc = includes.next()) {
+ if (conc->getBaseType() == Uml::ot_Datatype)
+ continue;
+ QString neatName = cleanName(conc->getName());
+ if (neatName != AV && neatName != SV && neatName != HV) {
+ QString OtherPkgName = conc->getPackage(".");
+ OtherPkgName.replace(QRegExp("\\."),"::");
+ QString OtherName = OtherPkgName + "::" + cleanName(conc->getName());
+
+ // Only print out the use statement if the other package isn't the
+ // same as the one we are working on. (This happens for the
+ // "Singleton" design pattern.)
+ if(OtherName != ThisPkgName){
+ Ret += "use ";
+ Ret += OtherName;
+ Ret += ';';
+ Ret += m_endl;
+ }
+ }
+ }
+ UMLClassifierList superclasses = c->getSuperClasses();
+ if (superclasses.count()) {
+ Ret += m_endl;
+ Ret += "use base qw( ";
+ for (UMLClassifier *obj = superclasses.first();
+ obj; obj = superclasses.next()) {
+ QString packageName = obj->getPackage(".");
+ packageName.replace(QRegExp("\\."),"::");
+
+ Ret += packageName + "::" + cleanName(obj->getName()) + ' ';
+ }
+ Ret += ");" + m_endl;
+ }
+
+ return(true);
+}
+
+void PerlWriter::writeClass(UMLClassifier *c) {
+
+ /* if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+ */
+ QString classname = cleanName(c->getName());// this is fine: cleanName is "::-clean"
+ QString packageName = c->getPackage(".");
+ QString fileName;
+
+ // Replace all white spaces with blanks
+ packageName.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ packageName.replace(QRegExp(" "), "_");
+
+ // Replace all dots (".") with double colon scope resolution operators
+ // ("::")
+ packageName.replace(QRegExp("\\."),"::");
+
+ // Store complete package name
+ QString ThisPkgName = packageName + "::" + classname;
+
+ fileName = findFileName(c, ".pm");
+ // the above lower-cases my nice class names. That is bad.
+ // correct solution: refactor,
+ // split massive findFileName up, reimplement
+ // parts here
+ // actual solution: shameful ".pm" hack in codegenerator
+
+ CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
+ QString curDir = pol->getOutputDirectory().absPath();
+ if (fileName.contains("::")) {
+ // create new directories for each level
+ QString newDir;
+ newDir = curDir;
+ QString fragment = fileName;
+ QDir* existing = new QDir (curDir);
+ QRegExp regEx("(.*)(::)");
+ regEx.setMinimal(true);
+ while (regEx.search(fragment) > -1) {
+ newDir = regEx.cap(1);
+ fragment.remove(0, (regEx.pos(2) + 2)); // get round strange minimal matching bug
+ existing->setPath(curDir + '/' + newDir);
+ if (! existing->exists()) {
+ existing->setPath(curDir);
+ if (! existing->mkdir(newDir)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ }
+ curDir += '/' + newDir;
+ }
+ fileName = fragment + ".pm";
+ }
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QString oldDir = pol->getOutputDirectory().absPath();
+ pol->setOutputDirectory(curDir);
+ QFile fileperl;
+ if(!openFile(fileperl, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream perl(&fileperl);
+ pol->setOutputDirectory(oldDir);
+
+ //======================================================================
+ // Start generating the code!!
+ //======================================================================
+
+ // try to find a heading file (license, comments, etc)
+ QString str;
+ bool bPackageDeclared = false;
+ bool bUseStmsWritten = false;
+
+ str = getHeadingFile(".pm"); // what this mean?
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),fileperl.name());
+ str.replace(QRegExp("%year%"),QDate::currentDate().toString("yyyy"));
+ str.replace(QRegExp("%date%"),QDate::currentDate().toString());
+ str.replace(QRegExp("%time%"),QTime::currentTime().toString());
+ str.replace(QRegExp("%package-name%"),ThisPkgName);
+ if(str.find(QRegExp("%PACKAGE-DECLARE%"))){
+ str.replace(QRegExp("%PACKAGE-DECLARE%"),
+ "package " + ThisPkgName + ';'
+ + m_endl + m_endl
+ + "#UML_MODELER_BEGIN_PERSONAL_VARS_" + classname
+ + m_endl + m_endl
+ + "#UML_MODELER_END_PERSONAL_VARS_" + classname
+ + m_endl
+ );
+ bPackageDeclared = true;
+ }
+
+ if(str.find(QRegExp("%USE-STATEMENTS%"))){
+ QString UseStms;
+ if(GetUseStatements(c,UseStms,ThisPkgName)){
+ str.replace(QRegExp("%USE-STATEMENTS%"), UseStms);
+ bUseStmsWritten = true;
+ }
+ }
+
+ perl<<str<<m_endl;
+ }
+
+ // if the package wasn't declared above during keyword substitution,
+ // add it now. (At the end of the file.)
+ if(! bPackageDeclared){
+ perl << m_endl << m_endl << "package " <<ThisPkgName << ";" << m_endl
+ << m_endl;
+ //write includes
+ perl << m_endl << "#UML_MODELER_BEGIN_PERSONAL_VARS_" << classname
+ << m_endl ;
+ perl << m_endl << "#UML_MODELER_END_PERSONAL_VARS_" << classname
+ << m_endl << m_endl ;
+ }
+
+ if(! bUseStmsWritten){
+ QString UseStms;
+ if(GetUseStatements(c,UseStms,ThisPkgName)){
+ perl<<UseStms<<m_endl;
+ }
+ }
+
+ perl << m_endl;
+
+ // Do we really need these for anything???
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ //Write class Documentation
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ perl << m_endl << "=head1";
+ perl << " " << classname.upper() << m_endl << m_endl;
+ perl << c->getDoc();
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ }
+
+ //check if class is abstract and / or has abstract methods
+ if(c->getAbstract())
+ perl << "=head1 ABSTRACT CLASS" << m_endl << m_endl << "=cut" << m_endl;
+
+ //attributes
+ if (! c->isInterface())
+ writeAttributes(c, perl); // keep for documentation's sake
+
+ //operations
+ writeOperations(c,perl);
+
+ perl << m_endl;
+
+ //finish file
+ //perl << m_endl << m_endl << "=cut" << m_endl;
+ perl << m_endl << m_endl << "return 1;" << m_endl;
+
+ //close files and notify we are done
+ fileperl.close();
+ emit codeGenerated(c, true);
+}
+
+/**
+ * returns "Perl"
+ */
+Uml::Programming_Language PerlWriter::getLanguage() {
+ return Uml::pl_Perl;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void PerlWriter::writeOperations(UMLClassifier *c, QTextStream &perl) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ //keep this for documentation only!
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ QString classname(cleanName(c->getName()));
+
+ //write operations to file
+ if(forceSections() || !oppub.isEmpty()) {
+ perl << m_endl << "=head1 PUBLIC METHODS" << m_endl << m_endl ;
+ writeOperations(classname,oppub,perl);
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ }
+
+ if(forceSections() || !opprot.isEmpty()) {
+ perl << m_endl << "=head1 METHODS FOR SUBCLASSING" << m_endl << m_endl ;
+ //perl << "=pod " << m_endl << m_endl << "=head3 " ;
+ writeOperations(classname,opprot,perl);
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ }
+
+ if(forceSections() || !oppriv.isEmpty()) {
+ perl << m_endl << "=head1 PRIVATE METHODS" << m_endl << m_endl ;
+ //perl << "=pod " << m_endl << m_endl << "=head3 " ;
+ writeOperations(classname,oppriv,perl);
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ }
+
+ // moved here for perl
+ if (!c->isInterface() && hasDefaultValueAttr(c)) {
+ UMLAttributeList atl = c->getAttributeList();
+
+ perl << m_endl;
+ perl << m_endl << "=head2 _init" << m_endl << m_endl << m_endl;
+ perl << "_init sets all " + classname + " attributes to their default values unless already set" << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ perl << "sub _init {" << m_endl << m_indentation << "my $self = shift;" << m_endl<<m_endl;
+
+ for(UMLAttribute *at = atl.first(); at ; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty())
+ perl << m_indentation << "defined $self->{" << cleanName(at->getName())<<"}"
+ << " or $self->{" << cleanName(at->getName()) << "} = "
+ << at->getInitialValue() << ";" << m_endl;
+ }
+
+ perl << " }" << m_endl;
+ }
+
+ perl << m_endl << m_endl;
+}
+
+void PerlWriter::writeOperations(const QString &/* classname */, UMLOperationList &opList, QTextStream &perl) {
+ UMLOperation *op;
+ UMLAttribute *at;
+
+ for(op=opList.first(); op ; op=opList.next())
+ {
+ UMLAttributeList atl = op->getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at ; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ if( writeDoc ) //write method documentation
+ {
+ perl << "=pod " << m_endl << m_endl << "=head3 " ;
+ perl << cleanName(op->getName()) << m_endl << m_endl;
+
+ perl << " Parameters :" << m_endl ;
+ //write parameter documentation
+ for (at = atl.first(); at ; at = atl.next()) {
+ if(forceDoc() || !at->getDoc().isEmpty()) {
+ perl << " "
+ << cleanName(at->getName()) << " : "
+ << at->getTypeName() << " : "
+ << at->getDoc()
+ << m_endl;
+ }
+ }//end for : write parameter documentation
+
+ perl << m_endl;
+ perl << " Return : " << m_endl;
+ perl << " " << op->getTypeName();
+ perl << m_endl << m_endl;
+ perl << " Description : " << m_endl;
+ perl << " " << op->getDoc();
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ }//end if : write method documentation
+
+ perl << "sub " << cleanName(op->getName()) << m_endl << "{" << m_endl;
+ perl << " my($self";
+
+ bool bStartPrinted = false;
+ //write parameters
+ for (at = atl.first(); at; at = atl.next()) {
+ if (!bStartPrinted) {
+ bStartPrinted = true;
+ perl << "," << m_endl;
+ }
+ perl << " $"<< cleanName(at->getName()) << ", # "
+ << at->getTypeName() << " : " << at->getDoc() << m_endl;
+ }
+
+ perl << " ) = @_;" << m_endl;
+
+ perl << "#UML_MODELER_BEGIN_PERSONAL_CODE_" << cleanName(op->getName());
+ perl << m_endl << "#UML_MODELER_END_PERSONAL_CODE_" << cleanName(op->getName()) << m_endl;
+ perl << "}" << m_endl;
+ perl << m_endl << m_endl;
+ }//end for
+}
+
+
+void PerlWriter::writeAttributes(UMLClassifier *c, QTextStream &perl) {
+ UMLAttributeList atpub, atprot, atpriv, atdefval;
+ atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ atdefval.setAutoDelete(false);
+
+ //sort attributes by scope and see if they have a default value
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ for(at = atl.first(); at ; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty())
+ atdefval.append(at);
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ atpriv.append(at);
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ if(forceSections() || atpub.count()) {
+ writeAttributes(atpub,perl);
+ }
+ /* not needed as writeAttributes only writes documentation
+ if(forceSections() || atprot.count()) {
+ writeAttributes(atprot,perl);
+ }
+
+ if(forceSections() || atpriv.count()) {
+ writeAttributes(atpriv,perl);
+ }
+ */
+}
+
+
+void PerlWriter::writeAttributes(UMLAttributeList &atList, QTextStream &perl)
+{
+ perl << m_endl << "=head1 PUBLIC ATTRIBUTES" << m_endl << m_endl;
+ perl << "=pod " << m_endl << m_endl ;
+ for (UMLAttribute *at = atList.first(); at ; at = atList.next())
+ {
+ if (forceDoc() || !at->getDoc().isEmpty())
+ {
+ perl << "=head3 " << cleanName(at->getName()) << m_endl << m_endl ;
+ perl << " Description : " << at->getDoc() << m_endl << m_endl;
+ }
+ } // end for
+ perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
+ return;
+}
+
+QStringList PerlWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("$");
+ l.append("@");
+ l.append("%");
+ return l;
+}
+
+const QStringList PerlWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "abs"
+ << "accept"
+ << "alarm"
+ << "and"
+ << "atan2"
+ << "BEGIN"
+ << "bind"
+ << "binmode"
+ << "bless"
+ << "byte"
+ << "caller"
+ << "carp"
+ << "chdir"
+ << "chmod"
+ << "chomp"
+ << "chop"
+ << "chown"
+ << "chr"
+ << "chroot"
+ << "close"
+ << "closedir"
+ << "cmp"
+ << "confess"
+ << "connect"
+ << "continue"
+ << "cos"
+ << "croak"
+ << "crypt"
+ << "dbmclose"
+ << "dbmopen"
+ << "defined"
+ << "delete"
+ << "die"
+ << "do"
+ << "dump"
+ << "each"
+ << "else"
+ << "elsif"
+ << "END"
+ << "endgrent"
+ << "endhostent"
+ << "endnetent"
+ << "endprotoent"
+ << "endpwent"
+ << "endservent"
+ << "eof"
+ << "eq"
+ << "eval"
+ << "exec"
+ << "exists"
+ << "exit"
+ << "exp"
+ << "fcntl"
+ << "fileno"
+ << "flock"
+ << "for"
+ << "foreach"
+ << "fork"
+ << "format"
+ << "formline"
+ << "ge"
+ << "getc"
+ << "getgrent"
+ << "getgrgid"
+ << "getgrnam"
+ << "gethostbyaddr"
+ << "gethostbyname"
+ << "gethostent"
+ << "getlogin"
+ << "getnetbyaddr"
+ << "getnetbyname"
+ << "getnetent"
+ << "getpeername"
+ << "getpgrp"
+ << "getppid"
+ << "getpriority"
+ << "getprotobyname"
+ << "getprotobynumber"
+ << "getprotoent"
+ << "getpwent"
+ << "getpwnam"
+ << "getpwuid"
+ << "getservbyname"
+ << "getservbyport"
+ << "getservent"
+ << "getsockname"
+ << "getsockopt"
+ << "glob"
+ << "gmtime"
+ << "goto"
+ << "grep"
+ << "gt"
+ << "hex"
+ << "if"
+ << "import"
+ << "index"
+ << "int"
+ << "integer"
+ << "ioctl"
+ << "join"
+ << "keys"
+ << "kill"
+ << "last"
+ << "lc"
+ << "lcfirst"
+ << "le"
+ << "length"
+ << "lib"
+ << "link"
+ << "listen"
+ << "local"
+ << "localtime"
+ << "lock"
+ << "log"
+ << "lstat"
+ << "lt"
+ << "map"
+ << "mkdir"
+ << "msgctl"
+ << "msgget"
+ << "msgrcv"
+ << "msgsnd"
+ << "my"
+ << "ne"
+ << "new"
+ << "next"
+ << "no"
+ << "not"
+ << "oct"
+ << "open"
+ << "opendir"
+ << "or"
+ << "ord"
+ << "our"
+ << "pack"
+ << "package"
+ << "pipe"
+ << "pop"
+ << "pos"
+ << "print"
+ << "printf"
+ << "prototype"
+ << "push"
+ << "quotemeta"
+ << "rand"
+ << "read"
+ << "readdir"
+ << "readline"
+ << "readlink"
+ << "readpipe"
+ << "recv"
+ << "redo"
+ << "ref"
+ << "rename"
+ << "require"
+ << "reset"
+ << "return"
+ << "reverse"
+ << "rewinddir"
+ << "rindex"
+ << "rmdir"
+ << "scalar"
+ << "seek"
+ << "seekdir"
+ << "select"
+ << "semctl"
+ << "semget"
+ << "semop"
+ << "send"
+ << "setgrent"
+ << "sethostent"
+ << "setnetent"
+ << "setpgrp"
+ << "setpriority"
+ << "setprotoent"
+ << "setpwent"
+ << "setservent"
+ << "setsockopt"
+ << "shift"
+ << "shmctl"
+ << "shmget"
+ << "shmread"
+ << "shmwrite"
+ << "shutdown"
+ << "sigtrap"
+ << "sin"
+ << "sleep"
+ << "socket"
+ << "socketpair"
+ << "sort"
+ << "splice"
+ << "split"
+ << "sprintf"
+ << "sqrt"
+ << "srand"
+ << "stat"
+ << "strict"
+ << "study"
+ << "sub"
+ << "subs"
+ << "substr"
+ << "switch"
+ << "symlink"
+ << "syscall"
+ << "sysopen"
+ << "sysread"
+ << "sysseek"
+ << "system"
+ << "syswrite"
+ << "tell"
+ << "telldir"
+ << "tie"
+ << "tied"
+ << "time"
+ << "times"
+ << "truncate"
+ << "uc"
+ << "ucfirst"
+ << "umask"
+ << "undef"
+ << "unless"
+ << "unlink"
+ << "unpack"
+ << "unshift"
+ << "untie"
+ << "until"
+ << "use"
+ << "utf8"
+ << "utime"
+ << "values"
+ << "vars"
+ << "vec"
+ << "wait"
+ << "waitpid"
+ << "wantarray"
+ << "warn"
+ << "warnings"
+ << "while"
+ << "write"
+ << "xor";
+ }
+
+ return keywords;
+}
+
+#include "perlwriter.moc"
diff --git a/umbrello/umbrello/codegenerators/perlwriter.h b/umbrello/umbrello/codegenerators/perlwriter.h
new file mode 100644
index 00000000..9dac4e56
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/perlwriter.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ perlwriter.h - description
+ -------------------
+ begin : Wed Jan 22 2003
+ copyright : (C) 2003 by David Hugh-Jones
+ email : hughjonesd@yahoo.co.uk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef PERLWRITER_H
+#define PERLWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+#include "../umloperationlist.h"
+
+class UMLOperation;
+class UMLAttribute;
+class UMLClassifier;
+
+/**
+ * class PerlWriter is a Perl code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class PerlWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ PerlWriter();
+ virtual ~PerlWriter();
+
+ /**
+ * call this method to generate Perl code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "Perl"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+ QStringList defaultDatatypes();
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ * not sure whether this is php specific
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param perl output stream for the Perl file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &perl);
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param perl output stream for the Perl file
+ */
+ void writeOperations(const QString &classname, UMLOperationList &opList,
+ QTextStream &perl);
+
+ /** write all the attributes of a class
+ * @param c the class we are generating code for
+ * @param perl output stream for the Perl file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &perl);
+
+ /** write a list of class attributes
+ * @param atList the list of attributes
+ * @param perl output stream for the Perl file
+ */
+ void writeAttributes(UMLAttributeList &atList, QTextStream &perl);
+
+ bool GetUseStatements(UMLClassifier *c, QString &Ret,
+ QString &ThisPkgName);
+
+};
+
+#endif //PERLWRITER
diff --git a/umbrello/umbrello/codegenerators/php5writer.cpp b/umbrello/umbrello/codegenerators/php5writer.cpp
new file mode 100644
index 00000000..044d3afe
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/php5writer.cpp
@@ -0,0 +1,3418 @@
+/***************************************************************************
+ begin : Thu Oct 17 2002
+ copyright : (C) 2002 by Heiko Nardmann
+ email : h.nardmann@secunet.de
+ (C) 2003-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ php5 version by Thorsten Kunz (tk AT bytecrash DOT net)
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "php5writer.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+static const char *php5words[] =
+ {
+ "abs",
+ "abstract",
+ "acos",
+ "acosh",
+ "add",
+ "addAction",
+ "addColor",
+ "addEntry",
+ "addFill",
+ "addShape",
+ "addString",
+ "add_namespace",
+ "addcslashes",
+ "addslashes",
+ "addstring",
+ "aggregate",
+ "aggregate_info",
+ "aggregate_methods",
+ "aggregate_methods_by_list",
+ "aggregate_methods_by_regexp",
+ "aggregate_properties",
+ "aggregate_properties_by_list",
+ "aggregate_properties_by_regexp",
+ "aggregation_info",
+ "align",
+ "apache_child_terminate",
+ "apache_lookup_uri",
+ "apache_note",
+ "apache_request_headers",
+ "apache_response_headers",
+ "apache_setenv",
+ "append_child",
+ "append_sibling",
+ "array",
+ "array_change_key_case",
+ "array_chunk",
+ "array_count_values",
+ "array_diff",
+ "array_diff_assoc",
+ "array_fill",
+ "array_filter",
+ "array_flip",
+ "array_intersect",
+ "array_intersect_assoc",
+ "array_key_exists",
+ "array_keys",
+ "array_map",
+ "array_merge",
+ "array_merge_recursive",
+ "array_multisort",
+ "array_pad",
+ "array_pop",
+ "array_push",
+ "array_rand",
+ "array_reduce",
+ "array_reverse",
+ "array_search",
+ "array_shift",
+ "array_slice",
+ "array_splice",
+ "array_sum",
+ "array_unique",
+ "array_unshift",
+ "array_values",
+ "array_walk",
+ "arsort",
+ "ascii2ebcdic",
+ "asin",
+ "asinh",
+ "asort",
+ "aspell_check",
+ "aspell_new",
+ "aspell_suggest",
+ "assert",
+ "assert_options",
+ "assign",
+ "atan",
+ "atan2",
+ "atanh",
+ "attreditable",
+ "attributes",
+ "base64_decode",
+ "base64_encode",
+ "base_convert",
+ "basename",
+ "bcadd",
+ "bccomp",
+ "bcdiv",
+ "bcmod",
+ "bcmul",
+ "bcpow",
+ "bcpowmod",
+ "bcscale",
+ "bcsqrt",
+ "bcsub",
+ "bin2hex",
+ "bindec",
+ "bindtextdomain",
+ "bind_textdomain_codeset",
+ "bool",
+ "break",
+ "bzclose",
+ "bzcompress",
+ "bzdecompress",
+ "bzerrno",
+ "bzerror",
+ "bzerrstr",
+ "bzflush",
+ "bzopen",
+ "bzread",
+ "bzwrite",
+ "cal_days_in_month",
+ "cal_from_jd",
+ "cal_info",
+ "call_user_func",
+ "call_user_func_array",
+ "call_user_method",
+ "call_user_method_array",
+ "cal_to_jd",
+ "ccvs_add",
+ "ccvs_auth",
+ "ccvs_command",
+ "ccvs_count",
+ "ccvs_delete",
+ "ccvs_done",
+ "ccvs_init",
+ "ccvs_lookup",
+ "ccvs_new",
+ "ccvs_report",
+ "ccvs_return",
+ "ccvs_reverse",
+ "ccvs_sale",
+ "ccvs_status",
+ "ccvs_textvalue",
+ "ccvs_void",
+ "ceil",
+ "chdir",
+ "checkdate",
+ "checkdnsrr",
+ "checkin",
+ "checkout",
+ "chgrp",
+ "child_nodes",
+ "children",
+ "chmod",
+ "chop",
+ "chown",
+ "chr",
+ "chroot",
+ "chunk_split",
+ "class",
+ "class_exists",
+ "clearstatcache",
+ "clone_node",
+ "closedir",
+ "closelog",
+ "com_addref",
+ "com_get",
+ "com_invoke",
+ "com_isenum",
+ "com_load",
+ "com_load_typelib",
+ "compact",
+ "com_propget",
+ "com_propput",
+ "com_propset",
+ "com_release",
+ "com_set",
+ "connection_aborted",
+ "connection_status",
+ "connection_timeout",
+ "constant",
+ "content",
+ "continue",
+ "convert_cyr_string",
+ "_COOKIE",
+ "copy",
+ "cos",
+ "cosh",
+ "count",
+ "count_chars",
+ "cpdf_add_annotation",
+ "cpdf_add_outline",
+ "cpdf_arc",
+ "cpdf_begin_text",
+ "cpdf_circle",
+ "cpdf_clip",
+ "cpdf_close",
+ "cpdf_closepath",
+ "cpdf_closepath_fill_stroke",
+ "cpdf_closepath_stroke",
+ "cpdf_continue_text",
+ "cpdf_curveto",
+ "cpdf_end_text",
+ "cpdf_fill",
+ "cpdf_fill_stroke",
+ "cpdf_finalize",
+ "cpdf_finalize_page",
+ "cpdf_global_set_document_limits",
+ "cpdf_import_jpeg",
+ "cpdf_lineto",
+ "cpdf_moveto",
+ "cpdf_newpath",
+ "cpdf_open",
+ "cpdf_output_buffer",
+ "cpdf_page_init",
+ "cpdf_place_inline_image",
+ "cpdf_rect",
+ "cpdf_restore",
+ "cpdf_rlineto",
+ "cpdf_rmoveto",
+ "cpdf_rotate",
+ "cpdf_rotate_text",
+ "cpdf_save",
+ "cpdf_save_to_file",
+ "cpdf_scale",
+ "cpdf_set_action_url",
+ "cpdf_set_char_spacing",
+ "cpdf_set_creator",
+ "cpdf_set_current_page",
+ "cpdf_setdash",
+ "cpdf_setflat",
+ "cpdf_set_font",
+ "cpdf_set_font_directories",
+ "cpdf_set_font_map_file",
+ "cpdf_setgray",
+ "cpdf_setgray_fill",
+ "cpdf_setgray_stroke",
+ "cpdf_set_horiz_scaling",
+ "cpdf_set_keywords",
+ "cpdf_set_leading",
+ "cpdf_setlinecap",
+ "cpdf_setlinejoin",
+ "cpdf_setlinewidth",
+ "cpdf_setmiterlimit",
+ "cpdf_set_page_animation",
+ "cpdf_setrgbcolor",
+ "cpdf_setrgbcolor_fill",
+ "cpdf_setrgbcolor_stroke",
+ "cpdf_set_subject",
+ "cpdf_set_text_matrix",
+ "cpdf_set_text_pos",
+ "cpdf_set_text_rendering",
+ "cpdf_set_text_rise",
+ "cpdf_set_title",
+ "cpdf_set_viewer_preferences",
+ "cpdf_set_word_spacing",
+ "cpdf_show",
+ "cpdf_show_xy",
+ "cpdf_stringwidth",
+ "cpdf_stroke",
+ "cpdf_text",
+ "cpdf_translate",
+ "crack_check",
+ "crack_closedict",
+ "crack_getlastmessage",
+ "crack_opendict",
+ "crc32",
+ "create_attribute",
+ "create_cdata_section",
+ "create_comment",
+ "create_element",
+ "create_element_ns",
+ "create_entity_reference",
+ "create_function",
+ "create_processing_instruction",
+ "create_text_node",
+ "crypt",
+ "ctype_alnum",
+ "ctype_alpha",
+ "ctype_cntrl",
+ "ctype_digit",
+ "ctype_graph",
+ "ctype_lower",
+ "ctype_print",
+ "ctype_punct",
+ "ctype_space",
+ "ctype_upper",
+ "ctype_xdigit",
+ "curl_close",
+ "curl_errno",
+ "curl_error",
+ "curl_exec",
+ "curl_getinfo",
+ "curl_init",
+ "curl_setopt",
+ "curl_version",
+ "current",
+ "cybercash_base64_decode",
+ "cybercash_base64_encode",
+ "cybercash_decr",
+ "cybercash_encr",
+ "cybermut_creerformulairecm",
+ "cybermut_creerreponsecm",
+ "cybermut_testmac",
+ "cyrus_authenticate",
+ "cyrus_bind",
+ "cyrus_close",
+ "cyrus_connect",
+ "cyrus_query",
+ "cyrus_unbind",
+ "data",
+ "date",
+ "dba_close",
+ "dba_delete",
+ "dba_exists",
+ "dba_fetch",
+ "dba_firstkey",
+ "dba_handlers",
+ "dba_insert",
+ "dba_list",
+ "dba_nextkey",
+ "dba_open",
+ "dba_optimize",
+ "dba_popen",
+ "dba_replace",
+ "dbase_add_record",
+ "dbase_close",
+ "dbase_create",
+ "dbase_delete_record",
+ "dbase_get_record",
+ "dbase_get_record_with_names",
+ "dbase_numfields",
+ "dbase_numrecords",
+ "dbase_open",
+ "dbase_pack",
+ "dbase_replace_record",
+ "dba_sync",
+ "dblist",
+ "dbmclose",
+ "dbmdelete",
+ "dbmexists",
+ "dbmfetch",
+ "dbmfirstkey",
+ "dbminsert",
+ "dbmnextkey",
+ "dbmopen",
+ "dbmreplace",
+ "dbplus_add",
+ "dbplus_aql",
+ "dbplus_chdir",
+ "dbplus_close",
+ "dbplus_curr",
+ "dbplus_errcode",
+ "dbplus_errno",
+ "dbplus_find",
+ "dbplus_first",
+ "dbplus_flush",
+ "dbplus_freealllocks",
+ "dbplus_freelock",
+ "dbplus_freerlocks",
+ "dbplus_getlock",
+ "dbplus_getunique",
+ "dbplus_info",
+ "dbplus_last",
+ "dbplus_lockrel",
+ "dbplus_next",
+ "dbplus_open",
+ "dbplus_prev",
+ "dbplus_rchperm",
+ "dbplus_rcreate",
+ "dbplus_rcrtexact",
+ "dbplus_rcrtlike",
+ "dbplus_resolve",
+ "dbplus_restorepos",
+ "dbplus_rkeys",
+ "dbplus_ropen",
+ "dbplus_rquery",
+ "dbplus_rrename",
+ "dbplus_rsecindex",
+ "dbplus_runlink",
+ "dbplus_rzap",
+ "dbplus_savepos",
+ "dbplus_setindex",
+ "dbplus_setindexbynumber",
+ "dbplus_sql",
+ "dbplus_tcl",
+ "dbplus_tremove",
+ "dbplus_undo",
+ "dbplus_undoprepare",
+ "dbplus_unlockrel",
+ "dbplus_unselect",
+ "dbplus_update",
+ "dbplus_xlockrel",
+ "dbplus_xunlockrel",
+ "dbstat",
+ "dbx_close",
+ "dbx_compare",
+ "dbx_connect",
+ "dbx_error",
+ "dbx_escape_string",
+ "dbx_query",
+ "dbx_sort",
+ "dcgettext",
+ "dcngettext",
+ "dcstat",
+ "deaggregate",
+ "debug_backtrace",
+ "debugger_off",
+ "debugger_on",
+ "decbin",
+ "dechex",
+ "declare",
+ "decoct",
+ "DEFAULT_INCLUDE_PATH",
+ "define",
+ "defined",
+ "define_syslog_variables",
+ "deg2rad",
+ "delete",
+ "description",
+ "dgettext",
+ "die",
+ "dio_close",
+ "dio_fcntl",
+ "dio_open",
+ "dio_read",
+ "dio_seek",
+ "dio_stat",
+ "dio_tcsetattr",
+ "dio_truncate",
+ "dio_write",
+ "dir",
+ "dirname",
+ "disk_free_space",
+ "diskfreespace",
+ "disk_total_space",
+ "dl",
+ "dngettext",
+ "dns_check_record",
+ "dns_get_mx",
+ "dns_get_record",
+ "do",
+ "doctype",
+ "document_element",
+ "DOCUMENT_ROOT",
+ "domxml_new_doc",
+ "domxml_open_file",
+ "domxml_open_mem",
+ "domxml_version",
+ "domxml_xmltree",
+ "domxml_xslt_stylesheet",
+ "domxml_xslt_stylesheet_doc",
+ "domxml_xslt_stylesheet_file",
+ "dotnet_load",
+ "doubleval",
+ "drawCurve",
+ "drawCurveTo",
+ "drawLine",
+ "drawLineTo",
+ "dstanchors",
+ "dstofsrcanchors",
+ "dump_file",
+ "dump_mem",
+ "dump_node",
+ "each",
+ "E_ALL",
+ "easter_date",
+ "easter_days",
+ "ebcdic2ascii",
+ "echo",
+ "E_COMPILE_ERROR",
+ "E_COMPILE_WARNING",
+ "E_CORE_ERROR",
+ "E_CORE_WARNING",
+ "E_ERROR",
+ "else",
+ "elseif",
+ "empty",
+ "end",
+ "endfor",
+ "endforeach",
+ "endif",
+ "endswitch",
+ "endwhile",
+ "E_NOTICE",
+ "entities",
+ "_ENV",
+ "E_PARSE",
+ "ereg",
+ "eregi",
+ "eregi_replace",
+ "ereg_replace",
+ "error_log",
+ "error_reporting",
+ "escapeshellarg",
+ "escapeshellcmd",
+ "E_USER_ERROR",
+ "E_USER_NOTICE",
+ "E_USER_WARNING",
+ "eval",
+ "E_WARNING",
+ "exec",
+ "exif_imagetype",
+ "exif_read_data",
+ "exif_thumbnail",
+ "exit",
+ "exp",
+ "explode",
+ "expm1",
+ "extension_loaded",
+ "extract",
+ "ezmlm_hash",
+ "FALSE",
+ "fbsql_affected_rows",
+ "fbsql_autocommit",
+ "fbsql_change_user",
+ "fbsql_close",
+ "fbsql_commit",
+ "fbsql_connect",
+ "fbsql_create_blob",
+ "fbsql_create_clob",
+ "fbsql_create_db",
+ "fbsql_database",
+ "fbsql_database_password",
+ "fbsql_data_seek",
+ "fbsql_db_query",
+ "fbsql_db_status",
+ "fbsql_drop_db",
+ "fbsql_errno",
+ "fbsql_error",
+ "fbsql_fetch_array",
+ "fbsql_fetch_assoc",
+ "fbsql_fetch_field",
+ "fbsql_fetch_lengths",
+ "fbsql_fetch_object",
+ "fbsql_fetch_row",
+ "fbsql_field_flags",
+ "fbsql_field_len",
+ "fbsql_field_name",
+ "fbsql_field_seek",
+ "fbsql_field_table",
+ "fbsql_field_type",
+ "fbsql_free_result",
+ "fbsql_get_autostart_info",
+ "fbsql_hostname",
+ "fbsql_insert_id",
+ "fbsql_list_dbs",
+ "fbsql_list_fields",
+ "fbsql_list_tables",
+ "fbsql_next_result",
+ "fbsql_num_fields",
+ "fbsql_num_rows",
+ "fbsql_password",
+ "fbsql_pconnect",
+ "fbsql_query",
+ "fbsql_read_blob",
+ "fbsql_read_clob",
+ "fbsql_result",
+ "fbsql_rollback",
+ "fbsql_select_db",
+ "fbsql_set_lob_mode",
+ "fbsql_set_transaction",
+ "fbsql_start_db",
+ "fbsql_stop_db",
+ "fbsql_tablename",
+ "fbsql_username",
+ "fbsql_warnings",
+ "fclose",
+ "fdf_add_doc_javascript",
+ "fdf_add_template",
+ "fdf_close",
+ "fdf_create",
+ "fdf_errno",
+ "fdf_error",
+ "fdf_get_ap",
+ "fdf_get_attachment",
+ "fdf_get_encoding",
+ "fdf_get_file",
+ "fdf_get_status",
+ "fdf_get_value",
+ "fdf_get_version",
+ "fdf_header",
+ "fdf_next_field_name",
+ "fdf_open",
+ "fdf_open_string",
+ "fdf_save",
+ "fdf_save_string",
+ "fdf_set_ap",
+ "fdf_set_encoding",
+ "fdf_set_file",
+ "fdf_set_flags",
+ "fdf_set_javascript_action",
+ "fdf_set_opt",
+ "fdf_set_status",
+ "fdf_set_submit_form_action",
+ "fdf_set_target_frame",
+ "fdf_set_value",
+ "fdf_set_version",
+ "feof",
+ "fflush",
+ "fgetc",
+ "fgetcsv",
+ "fgets",
+ "fgetss",
+ "file",
+ "__FILE__",
+ "fileatime",
+ "filectime",
+ "file_exists",
+ "file_get_contents",
+ "filegroup",
+ "fileinode",
+ "filemtime",
+ "fileowner",
+ "fileperms",
+ "filepro",
+ "filepro_fieldcount",
+ "filepro_fieldname",
+ "filepro_fieldtype",
+ "filepro_fieldwidth",
+ "filepro_retrieve",
+ "filepro_rowcount",
+ "_FILES",
+ "filesize",
+ "filetype",
+ "find",
+ "first_child",
+ "floatval",
+ "flock",
+ "floor",
+ "flush",
+ "fmod",
+ "fnmatch",
+ "fopen",
+ "for",
+ "foreach",
+ "fpassthru",
+ "fprintf",
+ "fputs",
+ "fread",
+ "frenchtojd",
+ "fribidi_log2vis",
+ "fscanf",
+ "fseek",
+ "fsockopen",
+ "fstat",
+ "ftell",
+ "ftok",
+ "ftp_cdup",
+ "ftp_chdir",
+ "ftp_close",
+ "ftp_connect",
+ "ftp_delete",
+ "ftp_exec",
+ "ftp_fget",
+ "ftp_fput",
+ "ftp_get",
+ "ftp_get_option",
+ "ftp_login",
+ "ftp_mdtm",
+ "ftp_mkdir",
+ "ftp_nb_continue",
+ "ftp_nb_fget",
+ "ftp_nb_fput",
+ "ftp_nb_get",
+ "ftp_nb_put",
+ "ftp_nlist",
+ "ftp_pasv",
+ "ftp_put",
+ "ftp_pwd",
+ "ftp_quit",
+ "ftp_rawlist",
+ "ftp_rename",
+ "ftp_rmdir",
+ "ftp_set_option",
+ "ftp_site",
+ "ftp_size",
+ "ftp_ssl_connect",
+ "ftp_systype",
+ "ftruncate",
+ "ftstat",
+ "func_get_arg",
+ "func_get_args",
+ "func_num_args",
+ "function",
+ "function_exists",
+ "fwrite",
+ "GATEWAY_INTERFACE",
+ "gd_info",
+ "_GET",
+ "getallheaders",
+ "get_attribute",
+ "get_attribute_node",
+ "get_browser",
+ "get_cfg_var",
+ "get_class",
+ "get_class_methods",
+ "get_class_vars",
+ "get_content",
+ "get_current_user",
+ "getcwd",
+ "getdate",
+ "get_declared_classes",
+ "get_defined_constants",
+ "get_defined_functions",
+ "get_defined_vars",
+ "get_element_by_id",
+ "get_elements_by_tagname",
+ "getenv",
+ "get_extension_funcs",
+ "getHeight",
+ "gethostbyaddr",
+ "gethostbyname",
+ "gethostbynamel",
+ "get_html_translation_table",
+ "getimagesize",
+ "get_included_files",
+ "get_include_path",
+ "getlastmod",
+ "get_loaded_extensions",
+ "get_magic_quotes_gpc",
+ "get_magic_quotes_runtime",
+ "get_meta_tags",
+ "getmxrr",
+ "getmygid",
+ "getmyinode",
+ "getmypid",
+ "getmyuid",
+ "get_object_vars",
+ "getopt",
+ "get_parent_class",
+ "getprotobyname",
+ "getprotobynumber",
+ "getrandmax",
+ "get_required_files",
+ "get_resource_type",
+ "getrusage",
+ "getservbyname",
+ "getservbyport",
+ "getshape1",
+ "getshape2",
+ "gettext",
+ "gettimeofday",
+ "gettype",
+ "getwidth",
+ "getWidth",
+ "glob",
+ "global",
+ "GLOBALS",
+ "gmdate",
+ "gmmktime",
+ "gmp_abs",
+ "gmp_add",
+ "gmp_and",
+ "gmp_clrbit",
+ "gmp_cmp",
+ "gmp_com",
+ "gmp_div",
+ "gmp_divexact",
+ "gmp_div_q",
+ "gmp_div_qr",
+ "gmp_div_r",
+ "gmp_fact",
+ "gmp_gcd",
+ "gmp_gcdext",
+ "gmp_hamdist",
+ "gmp_init",
+ "gmp_intval",
+ "gmp_invert",
+ "gmp_jacobi",
+ "gmp_legendre",
+ "gmp_mod",
+ "gmp_mul",
+ "gmp_neg",
+ "gmp_or",
+ "gmp_perfect_square",
+ "gmp_popcount",
+ "gmp_pow",
+ "gmp_powm",
+ "gmp_prob_prime",
+ "gmp_random",
+ "gmp_scan0",
+ "gmp_scan1",
+ "gmp_setbit",
+ "gmp_sign",
+ "gmp_sqrt",
+ "gmp_sqrtrm",
+ "gmp_strval",
+ "gmp_sub",
+ "gmp_xor",
+ "gmstrftime",
+ "gregoriantojd",
+ "gzclose",
+ "gzcompress",
+ "gzdeflate",
+ "gzencode",
+ "gzeof",
+ "gzfile",
+ "gzgetc",
+ "gzgets",
+ "gzgetss",
+ "gzinflate",
+ "gzopen",
+ "gzpassthru",
+ "gzputs",
+ "gzread",
+ "gzrewind",
+ "gzseek",
+ "gztell",
+ "gzuncompress",
+ "gzwrite",
+ "has_attribute",
+ "has_attributess",
+ "has_child_nodes",
+ "header",
+ "headers_sent",
+ "hebrev",
+ "hebrevc",
+ "hexdec",
+ "highlight_file",
+ "highlight_string",
+ "html_dump_mem",
+ "htmlentities",
+ "html_entity_decode",
+ "htmlspecialchars",
+ "HTTP_ACCEPT",
+ "HTTP_ACCEPT_CHARSET",
+ "HTTP_ACCEPT_LANGUAGE",
+ "HTTP_CONNECTION",
+ "HTTP_COOKIE_VARS",
+ "HTTP_ENCODING",
+ "HTTP_ENV_VARS",
+ "HTTP_GET_VARS",
+ "HTTP_HOST",
+ "HTTP_POST_FILES",
+ "HTTP_POST_VARS",
+ "HTTP_RAW_POST_DATA",
+ "HTTP_REFERER",
+ "HTTP_SERVER_VARS",
+ "HTTP_SESSION_VARS",
+ "HTTP_STATE_VARS",
+ "HTTP_USER_AGENT",
+ "hw_api_attribute",
+ "hw_api_content",
+ "hwapi_hgcsp",
+ "hw_api_object",
+ "hw_Array2Objrec",
+ "hw_changeobject",
+ "hw_Children",
+ "hw_ChildrenObj",
+ "hw_Close",
+ "hw_Connect",
+ "hw_connection_info",
+ "hw_Cp",
+ "hw_Deleteobject",
+ "hw_DocByAnchor",
+ "hw_DocByAnchorObj",
+ "hw_Document_Attributes",
+ "hw_Document_BodyTag",
+ "hw_Document_Content",
+ "hw_Document_SetContent",
+ "hw_Document_Size",
+ "hw_dummy",
+ "hw_EditText",
+ "hw_Error",
+ "hw_ErrorMsg",
+ "hw_Free_Document",
+ "hw_GetAnchors",
+ "hw_GetAnchorsObj",
+ "hw_GetAndLock",
+ "hw_GetChildColl",
+ "hw_GetChildCollObj",
+ "hw_GetChildDocColl",
+ "hw_GetChildDocCollObj",
+ "hw_GetObject",
+ "hw_GetObjectByQuery",
+ "hw_GetObjectByQueryColl",
+ "hw_GetObjectByQueryCollObj",
+ "hw_GetObjectByQueryObj",
+ "hw_GetParents",
+ "hw_GetParentsObj",
+ "hw_getrellink",
+ "hw_GetRemote",
+ "hw_GetRemoteChildren",
+ "hw_GetSrcByDestObj",
+ "hw_GetText",
+ "hw_getusername",
+ "hw_Identify",
+ "hw_InCollections",
+ "hw_Info",
+ "hw_InsColl",
+ "hw_InsDoc",
+ "hw_insertanchors",
+ "hw_InsertDocument",
+ "hw_InsertObject",
+ "hw_mapid",
+ "hw_Modifyobject",
+ "hw_Mv",
+ "hw_New_Document",
+ "hw_Objrec2Array",
+ "hw_Output_Document",
+ "hw_pConnect",
+ "hw_PipeDocument",
+ "hw_Root",
+ "hw_setlinkroot",
+ "hw_stat",
+ "hwstat",
+ "hw_Unlock",
+ "hw_Who",
+ "hypot",
+ "ibase_blob_add",
+ "ibase_blob_cancel",
+ "ibase_blob_close",
+ "ibase_blob_create",
+ "ibase_blob_echo",
+ "ibase_blob_get",
+ "ibase_blob_import",
+ "ibase_blob_info",
+ "ibase_blob_open",
+ "ibase_close",
+ "ibase_commit",
+ "ibase_connect",
+ "ibase_errmsg",
+ "ibase_execute",
+ "ibase_fetch_object",
+ "ibase_fetch_row",
+ "ibase_field_info",
+ "ibase_free_query",
+ "ibase_free_result",
+ "ibase_num_fields",
+ "ibase_pconnect",
+ "ibase_prepare",
+ "ibase_query",
+ "ibase_rollback",
+ "ibase_timefmt",
+ "ibase_trans",
+ "iconv",
+ "iconv_get_encoding",
+ "iconv_set_encoding",
+ "identify",
+ "if",
+ "ifx_affected_rows",
+ "ifx_blobinfile_mode",
+ "ifx_byteasvarchar",
+ "ifx_close",
+ "ifx_connect",
+ "ifx_copy_blob",
+ "ifx_create_blob",
+ "ifx_create_char",
+ "ifx_do",
+ "ifx_error",
+ "ifx_errormsg",
+ "ifx_fetch_row",
+ "ifx_fieldproperties",
+ "ifx_fieldtypes",
+ "ifx_free_blob",
+ "ifx_free_char",
+ "ifx_free_result",
+ "ifx_get_blob",
+ "ifx_get_char",
+ "ifx_getsqlca",
+ "ifx_htmltbl_result",
+ "ifx_nullformat",
+ "ifx_num_fields",
+ "ifx_num_rows",
+ "ifx_pconnect",
+ "ifx_prepare",
+ "ifx_query",
+ "ifx_textasvarchar",
+ "ifx_update_blob",
+ "ifx_update_char",
+ "ifxus_close_slob",
+ "ifxus_create_slob",
+ "ifxus_free_slob",
+ "ifxus_open_slob",
+ "ifxus_read_slob",
+ "ifxus_seek_slob",
+ "ifxus_tell_slob",
+ "ifxus_write_slob",
+ "ignore_user_abort",
+ "image2wbmp",
+ "imagealphablending",
+ "imagearc",
+ "imagechar",
+ "imagecharup",
+ "imagecolorallocate",
+ "imagecolorallocatealpha",
+ "imagecolorat",
+ "imagecolorclosest",
+ "imagecolorclosestalpha",
+ "imagecolorclosesthwb",
+ "imagecolordeallocate",
+ "imagecolorexact",
+ "imagecolorexactalpha",
+ "imagecolorresolve",
+ "imagecolorresolvealpha",
+ "imagecolorset",
+ "imagecolorsforindex",
+ "imagecolorstotal",
+ "imagecolortransparent",
+ "imagecopy",
+ "imagecopymerge",
+ "imagecopymergegray",
+ "imagecopyresampled",
+ "imagecopyresized",
+ "imagecreate",
+ "imagecreatefromgd",
+ "imagecreatefromgd2",
+ "imagecreatefromgd2part",
+ "imagecreatefromgif",
+ "imagecreatefromjpeg",
+ "imagecreatefrompng",
+ "imagecreatefromstring",
+ "imagecreatefromwbmp",
+ "imagecreatefromxbm",
+ "imagecreatefromxpm",
+ "imagecreatetruecolor",
+ "imagedashedline",
+ "imagedestroy",
+ "imageellipse",
+ "imagefill",
+ "imagefilledarc",
+ "imagefilledellipse",
+ "imagefilledpolygon",
+ "imagefilledrectangle",
+ "imagefilltoborder",
+ "imagefontheight",
+ "imagefontwidth",
+ "imageftbbox",
+ "imagefttext",
+ "imagegammacorrect",
+ "imagegd",
+ "imagegd2",
+ "imagegif",
+ "imageinterlace",
+ "imagejpeg",
+ "imageline",
+ "imageloadfont",
+ "imagepalettecopy",
+ "imagepng",
+ "imagepolygon",
+ "imagepsbbox",
+ "imagepscopyfont",
+ "imagepsencodefont",
+ "imagepsextendfont",
+ "imagepsfreefont",
+ "imagepsloadfont",
+ "imagepsslantfont",
+ "imagepstext",
+ "imagerectangle",
+ "imagerotate",
+ "imagesetbrush",
+ "imagesetpixel",
+ "imagesetstyle",
+ "imagesetthickness",
+ "imagesettile",
+ "imagestring",
+ "imagestringup",
+ "imagesx",
+ "imagesy",
+ "imagetruecolortopalette",
+ "imagettfbbox",
+ "imagettftext",
+ "imagetypes",
+ "image_type_to_mime_type",
+ "imagewbmp",
+ "imap_8bit",
+ "imap_alerts",
+ "imap_append",
+ "imap_base64",
+ "imap_binary",
+ "imap_body",
+ "imap_bodystruct",
+ "imap_check",
+ "imap_clearflag_full",
+ "imap_close",
+ "imap_createmailbox",
+ "imap_delete",
+ "imap_deletemailbox",
+ "imap_errors",
+ "imap_expunge",
+ "imap_fetchbody",
+ "imap_fetchheader",
+ "imap_fetch_overview",
+ "imap_fetchstructure",
+ "imap_getmailboxes",
+ "imap_get_quota",
+ "imap_get_quotaroot",
+ "imap_getsubscribed",
+ "imap_header",
+ "imap_headerinfo",
+ "imap_headers",
+ "imap_last_error",
+ "imap_list",
+ "imap_listmailbox",
+ "imap_listscan",
+ "imap_listsubscribed",
+ "imap_lsub",
+ "imap_mail",
+ "imap_mailboxmsginfo",
+ "imap_mail_compose",
+ "imap_mail_copy",
+ "imap_mail_move",
+ "imap_mime_header_decode",
+ "imap_msgno",
+ "imap_num_msg",
+ "imap_num_recent",
+ "imap_open",
+ "imap_ping",
+ "imap_qprint",
+ "imap_renamemailbox",
+ "imap_reopen",
+ "imap_rfc822_parse_adrlist",
+ "imap_rfc822_parse_headers",
+ "imap_rfc822_write_address",
+ "imap_scanmailbox",
+ "imap_search",
+ "imap_setacl",
+ "imap_setflag_full",
+ "imap_set_quota",
+ "imap_sort",
+ "imap_status",
+ "imap_subscribe",
+ "imap_thread",
+ "imap_uid",
+ "imap_undelete",
+ "imap_unsubscribe",
+ "imap_utf7_decode",
+ "imap_utf7_encode",
+ "imap_utf8",
+ "implements",
+ "implode",
+ "import_request_variables",
+ "in_array",
+ "include",
+ "include_once",
+ "info",
+ "ingres_autocommit",
+ "ingres_close",
+ "ingres_commit",
+ "ingres_connect",
+ "ingres_fetch_array",
+ "ingres_fetch_object",
+ "ingres_fetch_row",
+ "ingres_field_length",
+ "ingres_field_name",
+ "ingres_field_nullable",
+ "ingres_field_precision",
+ "ingres_field_scale",
+ "ingres_field_type",
+ "ingres_num_fields",
+ "ingres_num_rows",
+ "ingres_pconnect",
+ "ingres_query",
+ "ingres_rollback",
+ "ini_alter",
+ "ini_get",
+ "ini_get_all",
+ "ini_restore",
+ "ini_set",
+ "insert",
+ "insertanchor",
+ "insert_before",
+ "insertcollection",
+ "insertdocument",
+ "int",
+ "interface",
+ "internal_subset",
+ "intval",
+ "ip2long",
+ "iptcembed",
+ "iptcparse",
+ "ircg_channel_mode",
+ "ircg_disconnect",
+ "ircg_fetch_error_msg",
+ "ircg_get_username",
+ "ircg_html_encode",
+ "ircg_ignore_add",
+ "ircg_ignore_del",
+ "ircg_is_conn_alive",
+ "ircg_join",
+ "ircg_kick",
+ "ircg_lookup_format_messages",
+ "ircg_msg",
+ "ircg_nick",
+ "ircg_nickname_escape",
+ "ircg_nickname_unescape",
+ "ircg_notice",
+ "ircg_part",
+ "ircg_pconnect",
+ "ircg_register_format_messages",
+ "ircg_set_current",
+ "ircg_set_file",
+ "ircg_set_on_die",
+ "ircg_topic",
+ "ircg_whois",
+ "is_a",
+ "is_array",
+ "is_blank_node",
+ "is_bool",
+ "is_callable",
+ "is_dir",
+ "is_double",
+ "is_executable",
+ "is_file",
+ "is_finite",
+ "is_float",
+ "is_infinite",
+ "is_int",
+ "is_integer",
+ "is_link",
+ "is_long",
+ "is_nan",
+ "is_null",
+ "is_numeric",
+ "is_object",
+ "is_readable",
+ "is_real",
+ "is_resource",
+ "is_scalar",
+ "isset",
+ "is_string",
+ "is_subclass_of",
+ "is_uploaded_file",
+ "is_writable",
+ "is_writeable",
+ "java_last_exception_clear",
+ "java_last_exception_get",
+ "jddayofweek",
+ "jdmonthname",
+ "jdtofrench",
+ "jdtogregorian",
+ "jdtojewish",
+ "jdtojulian",
+ "jdtounix",
+ "jewishtojd",
+ "join",
+ "jpeg2wbmp",
+ "juliantojd",
+ "key",
+ "krsort",
+ "ksort",
+ "langdepvalue",
+ "last_child",
+ "lcg_value",
+ "ldap_8859_to_t61",
+ "ldap_add",
+ "ldap_bind",
+ "ldap_close",
+ "ldap_compare",
+ "ldap_connect",
+ "ldap_count_entries",
+ "ldap_delete",
+ "ldap_dn2ufn",
+ "ldap_err2str",
+ "ldap_errno",
+ "ldap_error",
+ "ldap_explode_dn",
+ "ldap_first_attribute",
+ "ldap_first_entry",
+ "ldap_first_reference",
+ "ldap_free_result",
+ "ldap_get_attributes",
+ "ldap_get_dn",
+ "ldap_get_entries",
+ "ldap_get_option",
+ "ldap_get_values",
+ "ldap_get_values_len",
+ "ldap_list",
+ "ldap_mod_add",
+ "ldap_mod_del",
+ "ldap_modify",
+ "ldap_mod_replace",
+ "ldap_next_attribute",
+ "ldap_next_entry",
+ "ldap_next_reference",
+ "ldap_parse_reference",
+ "ldap_parse_result",
+ "ldap_read",
+ "ldap_rename",
+ "ldap_search",
+ "ldap_set_option",
+ "ldap_set_rebind_proc",
+ "ldap_sort",
+ "ldap_start_tls",
+ "ldap_t61_to_8859",
+ "ldap_unbind",
+ "levenshtein",
+ "__LINE__",
+ "link",
+ "linkinfo",
+ "list",
+ "localeconv",
+ "localtime",
+ "lock",
+ "log",
+ "log10",
+ "log1p",
+ "long2ip",
+ "lstat",
+ "ltrim",
+ "mail",
+ "mailparse_determine_best_xfer_encoding",
+ "mailparse_msg_create",
+ "mailparse_msg_extract_part",
+ "mailparse_msg_extract_part_file",
+ "mailparse_msg_free",
+ "mailparse_msg_get_part",
+ "mailparse_msg_get_part_data",
+ "mailparse_msg_get_structure",
+ "mailparse_msg_parse",
+ "mailparse_msg_parse_file",
+ "mailparse_rfc822_parse_addresses",
+ "mailparse_stream_encode",
+ "mailparse_uudecode_all",
+ "main",
+ "max",
+ "mb_convert_case",
+ "mb_convert_encoding",
+ "mb_convert_kana",
+ "mb_convert_variables",
+ "mb_decode_mimeheader",
+ "mb_decode_numericentity",
+ "mb_detect_encoding",
+ "mb_detect_order",
+ "mb_encode_mimeheader",
+ "mb_encode_numericentity",
+ "mb_ereg",
+ "mb_eregi",
+ "mb_eregi_replace",
+ "mb_ereg_match",
+ "mb_ereg_replace",
+ "mb_ereg_search",
+ "mb_ereg_search_getpos",
+ "mb_ereg_search_getregs",
+ "mb_ereg_search_init",
+ "mb_ereg_search_pos",
+ "mb_ereg_search_regs",
+ "mb_ereg_search_setpos",
+ "mb_get_info",
+ "mb_http_input",
+ "mb_http_output",
+ "mb_internal_encoding",
+ "mb_language",
+ "mb_output_handler",
+ "mb_parse_str",
+ "mb_preferred_mime_name",
+ "mb_regex_encoding",
+ "mb_regex_set_options",
+ "mb_send_mail",
+ "mb_split",
+ "mb_strcut",
+ "mb_strimwidth",
+ "mb_strlen",
+ "mb_strpos",
+ "mb_strrpos",
+ "mb_strtolower",
+ "mb_strtoupper",
+ "mb_strwidth",
+ "mb_substitute_character",
+ "mb_substr",
+ "mb_substr_count",
+ "mcal_append_event",
+ "mcal_close",
+ "mcal_create_calendar",
+ "mcal_date_compare",
+ "mcal_date_valid",
+ "mcal_day_of_week",
+ "mcal_day_of_year",
+ "mcal_days_in_month",
+ "mcal_delete_calendar",
+ "mcal_delete_event",
+ "mcal_event_add_attribute",
+ "mcal_event_init",
+ "mcal_event_set_alarm",
+ "mcal_event_set_category",
+ "mcal_event_set_class",
+ "mcal_event_set_description",
+ "mcal_event_set_end",
+ "mcal_event_set_recur_daily",
+ "mcal_event_set_recur_monthly_mday",
+ "mcal_event_set_recur_monthly_wday",
+ "mcal_event_set_recur_none",
+ "mcal_event_set_recur_weekly",
+ "mcal_event_set_recur_yearly",
+ "mcal_event_set_start",
+ "mcal_event_set_title",
+ "mcal_expunge",
+ "mcal_fetch_current_stream_event",
+ "mcal_fetch_event",
+ "mcal_is_leap_year",
+ "mcal_list_alarms",
+ "mcal_list_events",
+ "mcal_next_recurrence",
+ "mcal_open",
+ "mcal_popen",
+ "mcal_rename_calendar",
+ "mcal_reopen",
+ "mcal_snooze",
+ "mcal_store_event",
+ "mcal_time_valid",
+ "mcal_week_of_year",
+ "mcrypt_cbc",
+ "mcrypt_cfb",
+ "mcrypt_create_iv",
+ "mcrypt_decrypt",
+ "mcrypt_ecb",
+ "mcrypt_enc_get_algorithms_name",
+ "mcrypt_enc_get_block_size",
+ "mcrypt_enc_get_iv_size",
+ "mcrypt_enc_get_key_size",
+ "mcrypt_enc_get_modes_name",
+ "mcrypt_enc_get_supported_key_sizes",
+ "mcrypt_enc_is_block_algorithm",
+ "mcrypt_enc_is_block_algorithm_mode",
+ "mcrypt_enc_is_block_mode",
+ "mcrypt_encrypt",
+ "mcrypt_enc_self_test",
+ "mcrypt_generic",
+ "mcrypt_generic_deinit",
+ "mcrypt_generic_end",
+ "mcrypt_generic_init",
+ "mcrypt_get_block_size",
+ "mcrypt_get_cipher_name",
+ "mcrypt_get_iv_size",
+ "mcrypt_get_key_size",
+ "mcrypt_list_algorithms",
+ "mcrypt_list_modes",
+ "mcrypt_module_close",
+ "mcrypt_module_get_algo_block_size",
+ "mcrypt_module_get_algo_key_size",
+ "mcrypt_module_get_supported_key_sizes",
+ "mcrypt_module_is_block_algorithm",
+ "mcrypt_module_is_block_algorithm_mode",
+ "mcrypt_module_is_block_mode",
+ "mcrypt_module_open",
+ "mcrypt_module_self_test",
+ "mcrypt_ofb",
+ "mcve_adduser",
+ "mcve_adduserarg",
+ "mcve_bt",
+ "mcve_checkstatus",
+ "mcve_chkpwd",
+ "mcve_chngpwd",
+ "mcve_completeauthorizations",
+ "mcve_connect",
+ "mcve_connectionerror",
+ "mcve_deleteresponse",
+ "mcve_deletetrans",
+ "mcve_deleteusersetup",
+ "mcve_deluser",
+ "mcve_destroyconn",
+ "mcve_destroyengine",
+ "mcve_disableuser",
+ "mcve_edituser",
+ "mcve_enableuser",
+ "mcve_force",
+ "mcve_getcell",
+ "mcve_getcellbynum",
+ "mcve_getcommadelimited",
+ "mcve_getheader",
+ "mcve_getuserarg",
+ "mcve_getuserparam",
+ "mcve_gft",
+ "mcve_gl",
+ "mcve_gut",
+ "mcve_initconn",
+ "mcve_initengine",
+ "mcve_initusersetup",
+ "mcve_iscommadelimited",
+ "mcve_liststats",
+ "mcve_listusers",
+ "mcve_maxconntimeout",
+ "mcve_monitor",
+ "mcve_numcolumns",
+ "mcve_numrows",
+ "mcve_override",
+ "mcve_parsecommadelimited",
+ "mcve_ping",
+ "mcve_preauth",
+ "mcve_preauthcompletion",
+ "mcve_qc",
+ "mcve_responseparam",
+ "mcve_return",
+ "mcve_returncode",
+ "mcve_returnstatus",
+ "mcve_sale",
+ "mcve_setblocking",
+ "mcve_setdropfile",
+ "mcve_setip",
+ "mcve_setssl",
+ "mcve_settimeout",
+ "mcve_settle",
+ "mcve_text_avs",
+ "mcve_text_code",
+ "mcve_text_cv",
+ "mcve_transactionauth",
+ "mcve_transactionavs",
+ "mcve_transactionbatch",
+ "mcve_transactioncv",
+ "mcve_transactionid",
+ "mcve_transactionitem",
+ "mcve_transactionssent",
+ "mcve_transactiontext",
+ "mcve_transinqueue",
+ "mcve_transnew",
+ "mcve_transparam",
+ "mcve_transsend",
+ "mcve_ub",
+ "mcve_uwait",
+ "mcve_verifyconnection",
+ "mcve_verifysslcert",
+ "mcve_void",
+ "md5",
+ "md5_file",
+ "mdecrypt_generic",
+ "memory_get_usage",
+ "metaphone",
+ "method_exists",
+ "mhash",
+ "mhash_count",
+ "mhash_get_block_size",
+ "mhash_get_hash_name",
+ "mhash_keygen_s2k",
+ "microtime",
+ "mime_content_type",
+ "mimetype",
+ "min",
+ "ming_setcubicthreshold",
+ "ming_setscale",
+ "ming_useswfversion",
+ "mkdir",
+ "mktime",
+ "money_format",
+ "move",
+ "movePen",
+ "movePenTo",
+ "moveTo",
+ "move_uploaded_file",
+ "msession_connect",
+ "msession_count",
+ "msession_create",
+ "msession_destroy",
+ "msession_disconnect",
+ "msession_find",
+ "msession_get",
+ "msession_get_array",
+ "msession_getdata",
+ "msession_inc",
+ "msession_list",
+ "msession_listvar",
+ "msession_lock",
+ "msession_plugin",
+ "msession_randstr",
+ "msession_set",
+ "msession_set_array",
+ "msession_setdata",
+ "msession_timeout",
+ "msession_uniq",
+ "msession_unlock",
+ "msg_get_queue",
+ "msg_receive",
+ "msg_remove_queue",
+ "msg_send",
+ "msg_set_queue",
+ "msg_stat_queue",
+ "msql",
+ "msql_affected_rows",
+ "msql_close",
+ "msql_connect",
+ "msql_create_db",
+ "msql_createdb",
+ "msql_data_seek",
+ "msql_dbname",
+ "msql_drop_db",
+ "msql_dropdb",
+ "msql_error",
+ "msql_fetch_array",
+ "msql_fetch_field",
+ "msql_fetch_object",
+ "msql_fetch_row",
+ "msql_fieldflags",
+ "msql_fieldlen",
+ "msql_fieldname",
+ "msql_field_seek",
+ "msql_fieldtable",
+ "msql_fieldtype",
+ "msql_free_result",
+ "msql_freeresult",
+ "msql_list_dbs",
+ "msql_listdbs",
+ "msql_list_fields",
+ "msql_listfields",
+ "msql_list_tables",
+ "msql_listtables",
+ "msql_num_fields",
+ "msql_numfields",
+ "msql_num_rows",
+ "msql_numrows",
+ "msql_pconnect",
+ "msql_query",
+ "msql_regcase",
+ "msql_result",
+ "msql_select_db",
+ "msql_selectdb",
+ "msql_tablename",
+ "mssql_bind",
+ "mssql_close",
+ "mssql_connect",
+ "mssql_data_seek",
+ "mssql_execute",
+ "mssql_fetch_array",
+ "mssql_fetch_assoc",
+ "mssql_fetch_batch",
+ "mssql_fetch_field",
+ "mssql_fetch_object",
+ "mssql_fetch_row",
+ "mssql_field_length",
+ "mssql_field_name",
+ "mssql_field_seek",
+ "mssql_field_type",
+ "mssql_free_result",
+ "mssql_free_statement",
+ "mssql_get_last_message",
+ "mssql_guid_string",
+ "mssql_init",
+ "mssql_min_error_severity",
+ "mssql_min_message_severity",
+ "mssql_next_result",
+ "mssql_num_fields",
+ "mssql_num_rows",
+ "mssql_pconnect",
+ "mssql_query",
+ "mssql_result",
+ "mssql_rows_affected",
+ "mssql_select_db",
+ "mt_getrandmax",
+ "mt_rand",
+ "mt_srand",
+ "multColor",
+ "muscat_close",
+ "muscat_get",
+ "muscat_give",
+ "muscat_setup",
+ "muscat_setup_net",
+ "mysql_affected_rows",
+ "mysql_change_user",
+ "mysql_client_encoding",
+ "mysql_close",
+ "mysql_connect",
+ "mysql_create_db",
+ "mysql_data_seek",
+ "mysql_db_name",
+ "mysql_db_query",
+ "mysql_drop_db",
+ "mysql_errno",
+ "mysql_error",
+ "mysql_escape_string",
+ "mysql_fetch_array",
+ "mysql_fetch_assoc",
+ "mysql_fetch_field",
+ "mysql_fetch_lengths",
+ "mysql_fetch_object",
+ "mysql_fetch_row",
+ "mysql_field_flags",
+ "mysql_field_len",
+ "mysql_field_name",
+ "mysql_field_seek",
+ "mysql_field_table",
+ "mysql_field_type",
+ "mysql_free_result",
+ "mysql_get_client_info",
+ "mysql_get_host_info",
+ "mysql_get_proto_info",
+ "mysql_get_server_info",
+ "mysql_info",
+ "mysql_insert_id",
+ "mysql_list_dbs",
+ "mysql_list_fields",
+ "mysql_list_processes",
+ "mysql_list_tables",
+ "mysql_num_fields",
+ "mysql_num_rows",
+ "mysql_pconnect",
+ "mysql_ping",
+ "mysql_query",
+ "mysql_real_escape_string",
+ "mysql_result",
+ "mysql_select_db",
+ "mysql_stat",
+ "mysql_tablename",
+ "mysql_thread_id",
+ "mysql_unbuffered_query",
+ "name",
+ "natcasesort",
+ "natsort",
+ "ncurses_addch",
+ "ncurses_addchnstr",
+ "ncurses_addchstr",
+ "ncurses_addnstr",
+ "ncurses_addstr",
+ "ncurses_assume_default_colors",
+ "ncurses_attroff",
+ "ncurses_attron",
+ "ncurses_attrset",
+ "ncurses_baudrate",
+ "ncurses_beep",
+ "ncurses_bkgd",
+ "ncurses_bkgdset",
+ "ncurses_border",
+ "ncurses_can_change_color",
+ "ncurses_cbreak",
+ "ncurses_clear",
+ "ncurses_clrtobot",
+ "ncurses_clrtoeol",
+ "ncurses_color_set",
+ "ncurses_curs_set",
+ "ncurses_define_key",
+ "ncurses_def_prog_mode",
+ "ncurses_def_shell_mode",
+ "ncurses_delay_output",
+ "ncurses_delch",
+ "ncurses_deleteln",
+ "ncurses_delwin",
+ "ncurses_doupdate",
+ "ncurses_echo",
+ "ncurses_echochar",
+ "ncurses_end",
+ "ncurses_erase",
+ "ncurses_erasechar",
+ "ncurses_filter",
+ "ncurses_flash",
+ "ncurses_flushinp",
+ "ncurses_getch",
+ "ncurses_getmouse",
+ "ncurses_halfdelay",
+ "ncurses_has_colors",
+ "ncurses_has_ic",
+ "ncurses_has_il",
+ "ncurses_has_key",
+ "ncurses_hline",
+ "ncurses_inch",
+ "ncurses_init",
+ "ncurses_init_color",
+ "ncurses_init_pair",
+ "ncurses_insch",
+ "ncurses_insdelln",
+ "ncurses_insertln",
+ "ncurses_insstr",
+ "ncurses_instr",
+ "ncurses_isendwin",
+ "ncurses_keyok",
+ "ncurses_killchar",
+ "ncurses_longname",
+ "ncurses_mouseinterval",
+ "ncurses_mousemask",
+ "ncurses_move",
+ "ncurses_mvaddch",
+ "ncurses_mvaddchnstr",
+ "ncurses_mvaddchstr",
+ "ncurses_mvaddnstr",
+ "ncurses_mvaddstr",
+ "ncurses_mvcur",
+ "ncurses_mvdelch",
+ "ncurses_mvgetch",
+ "ncurses_mvhline",
+ "ncurses_mvinch",
+ "ncurses_mvvline",
+ "ncurses_mvwaddstr",
+ "ncurses_napms",
+ "ncurses_newwin",
+ "ncurses_nl",
+ "ncurses_nocbreak",
+ "ncurses_noecho",
+ "ncurses_nonl",
+ "ncurses_noqiflush",
+ "ncurses_noraw",
+ "ncurses_putp",
+ "ncurses_qiflush",
+ "ncurses_raw",
+ "ncurses_refresh",
+ "ncurses_resetty",
+ "ncurses_savetty",
+ "ncurses_scr_dump",
+ "ncurses_scr_init",
+ "ncurses_scrl",
+ "ncurses_scr_restore",
+ "ncurses_scr_set",
+ "ncurses_slk_attr",
+ "ncurses_slk_attroff",
+ "ncurses_slk_attron",
+ "ncurses_slk_attrset",
+ "ncurses_slk_clear",
+ "ncurses_slk_color",
+ "ncurses_slk_init",
+ "ncurses_slk_noutrefresh",
+ "ncurses_slk_refresh",
+ "ncurses_slk_restore",
+ "ncurses_slk_touch",
+ "ncurses_standend",
+ "ncurses_standout",
+ "ncurses_start_color",
+ "ncurses_termattrs",
+ "ncurses_termname",
+ "ncurses_timeout",
+ "ncurses_typeahead",
+ "ncurses_ungetch",
+ "ncurses_ungetmouse",
+ "ncurses_use_default_colors",
+ "ncurses_use_env",
+ "ncurses_use_extended_names",
+ "ncurses_vidattr",
+ "ncurses_vline",
+ "ncurses_wrefresh",
+ "new",
+ "next",
+ "nextframe",
+ "next_sibling",
+ "ngettext",
+ "nl2br",
+ "nl_langinfo",
+ "node_name",
+ "node_type",
+ "node_value",
+ "notations",
+ "notes_body",
+ "notes_copy_db",
+ "notes_create_db",
+ "notes_create_note",
+ "notes_drop_db",
+ "notes_find_note",
+ "notes_header_info",
+ "notes_list_msgs",
+ "notes_mark_read",
+ "notes_mark_unread",
+ "notes_nav_create",
+ "notes_search",
+ "notes_unread",
+ "notes_version",
+ "NULL",
+ "number_format",
+ "ob_clean",
+ "ob_end_clean",
+ "ob_end_flush",
+ "ob_flush",
+ "ob_get_contents",
+ "ob_get_length",
+ "ob_get_level",
+ "ob_get_status",
+ "ob_gzhandler",
+ "ob_iconv_handler",
+ "ob_implicit_flush",
+ "object",
+ "objectbyanchor",
+ "ob_start",
+ "ocibindbyname",
+ "ocicancel",
+ "OCICollAppend",
+ "ocicollassign",
+ "ocicollassignelem",
+ "ocicollgetelem",
+ "ocicollmax",
+ "ocicollsize",
+ "ocicolltrim",
+ "ocicolumnisnull",
+ "ocicolumnname",
+ "ocicolumnprecision",
+ "ocicolumnscale",
+ "ocicolumnsize",
+ "ocicolumntype",
+ "ocicolumntyperaw",
+ "ocicommit",
+ "ocidefinebyname",
+ "ocierror",
+ "ociexecute",
+ "ocifetch",
+ "ocifetchinto",
+ "ocifetchstatement",
+ "ocifreecollection",
+ "ocifreecursor",
+ "OCIFreeDesc",
+ "ocifreestatement",
+ "ociinternaldebug",
+ "ociloadlob",
+ "ocilogoff",
+ "ocilogon",
+ "ocinewcollection",
+ "ocinewcursor",
+ "ocinewdescriptor",
+ "ocinlogon",
+ "ocinumcols",
+ "ociparse",
+ "ociplogon",
+ "ociresult",
+ "ocirollback",
+ "ocirowcount",
+ "ocisavelob",
+ "ocisavelobfile",
+ "ociserverversion",
+ "ocisetprefetch",
+ "ocistatementtype",
+ "ociwritelobtofile",
+ "octdec",
+ "odbc_autocommit",
+ "odbc_binmode",
+ "odbc_close",
+ "odbc_close_all",
+ "odbc_columnprivileges",
+ "odbc_columns",
+ "odbc_commit",
+ "odbc_connect",
+ "odbc_cursor",
+ "odbc_data_source",
+ "odbc_do",
+ "odbc_error",
+ "odbc_errormsg",
+ "odbc_exec",
+ "odbc_execute",
+ "odbc_fetch_array",
+ "odbc_fetch_into",
+ "odbc_fetch_object",
+ "odbc_fetch_row",
+ "odbc_field_len",
+ "odbc_field_name",
+ "odbc_field_num",
+ "odbc_field_precision",
+ "odbc_field_scale",
+ "odbc_field_type",
+ "odbc_foreignkeys",
+ "odbc_free_result",
+ "odbc_gettypeinfo",
+ "odbc_longreadlen",
+ "odbc_next_result",
+ "odbc_num_fields",
+ "odbc_num_rows",
+ "odbc_pconnect",
+ "odbc_prepare",
+ "odbc_primarykeys",
+ "odbc_procedurecolumns",
+ "odbc_procedures",
+ "odbc_result",
+ "odbc_result_all",
+ "odbc_rollback",
+ "odbc_setoption",
+ "odbc_specialcolumns",
+ "odbc_statistics",
+ "odbc_tableprivileges",
+ "odbc_tables",
+ "opendir",
+ "openlog",
+ "openssl_csr_export",
+ "openssl_csr_export_to_file",
+ "openssl_csr_new",
+ "openssl_csr_sign",
+ "openssl_error_string",
+ "openssl_free_key",
+ "openssl_get_privatekey",
+ "openssl_get_publickey",
+ "openssl_open",
+ "openssl_pkcs7_decrypt",
+ "openssl_pkcs7_encrypt",
+ "openssl_pkcs7_sign",
+ "openssl_pkcs7_verify",
+ "openssl_pkey_export",
+ "openssl_pkey_export_to_file",
+ "openssl_pkey_get_private",
+ "openssl_pkey_get_public",
+ "openssl_pkey_new",
+ "openssl_private_decrypt",
+ "openssl_private_encrypt",
+ "openssl_public_decrypt",
+ "openssl_public_encrypt",
+ "openssl_seal",
+ "openssl_sign",
+ "openssl_verify",
+ "openssl_x509_check_private_key",
+ "openssl_x509_checkpurpose",
+ "openssl_x509_export",
+ "openssl_x509_export_to_file",
+ "openssl_x509_free",
+ "openssl_x509_parse",
+ "openssl_x509_read",
+ "ora_bind",
+ "ora_close",
+ "ora_columnname",
+ "ora_columnsize",
+ "ora_columntype",
+ "ora_commit",
+ "ora_commitoff",
+ "ora_commiton",
+ "ora_do",
+ "ora_error",
+ "ora_errorcode",
+ "ora_exec",
+ "ora_fetch",
+ "ora_fetch_into",
+ "ora_getcolumn",
+ "ora_logoff",
+ "ora_logon",
+ "ora_numcols",
+ "ora_numrows",
+ "ora_open",
+ "ora_parse",
+ "ora_plogon",
+ "ora_rollback",
+ "ord",
+ "output",
+ "overload",
+ "ovrimos_close",
+ "ovrimos_commit",
+ "ovrimos_connect",
+ "ovrimos_cursor",
+ "ovrimos_exec",
+ "ovrimos_execute",
+ "ovrimos_fetch_into",
+ "ovrimos_fetch_row",
+ "ovrimos_field_len",
+ "ovrimos_field_name",
+ "ovrimos_field_num",
+ "ovrimos_field_type",
+ "ovrimos_free_result",
+ "ovrimos_longreadlen",
+ "ovrimos_num_fields",
+ "ovrimos_num_rows",
+ "ovrimos_prepare",
+ "ovrimos_result",
+ "ovrimos_result_all",
+ "ovrimos_rollback",
+ "owner_document",
+ "pack",
+ "parent_node",
+ "parents",
+ "parse_ini_file",
+ "parse_str",
+ "parse_url",
+ "passthru",
+ "pathinfo",
+ "PATH_TRANSLATED",
+ "pclose",
+ "pcntl_exec",
+ "pcntl_fork",
+ "pcntl_signal",
+ "pcntl_waitpid",
+ "pcntl_wexitstatus",
+ "pcntl_wifexited",
+ "pcntl_wifsignaled",
+ "pcntl_wifstopped",
+ "pcntl_wstopsig",
+ "pcntl_wtermsig",
+ "pdf_add_annotation",
+ "pdf_add_bookmark",
+ "pdf_add_launchlink",
+ "pdf_add_locallink",
+ "pdf_add_note",
+ "pdf_add_outline",
+ "pdf_add_pdflink",
+ "pdf_add_thumbnail",
+ "pdf_add_weblink",
+ "pdf_arc",
+ "pdf_arcn",
+ "pdf_attach_file",
+ "pdf_begin_page",
+ "pdf_begin_pattern",
+ "pdf_begin_template",
+ "pdf_circle",
+ "pdf_clip",
+ "pdf_close",
+ "pdf_close_image",
+ "pdf_closepath",
+ "pdf_closepath_fill_stroke",
+ "pdf_closepath_stroke",
+ "pdf_close_pdi",
+ "pdf_close_pdi_page",
+ "pdf_concat",
+ "pdf_continue_text",
+ "pdf_curveto",
+ "pdf_delete",
+ "pdf_end_page",
+ "pdf_endpath",
+ "pdf_end_pattern",
+ "pdf_end_template",
+ "pdf_fill",
+ "pdf_fill_stroke",
+ "pdf_findfont",
+ "pdf_get_buffer",
+ "pdf_get_font",
+ "pdf_get_fontname",
+ "pdf_get_fontsize",
+ "pdf_get_image_height",
+ "pdf_get_image_width",
+ "pdf_get_majorversion",
+ "pdf_get_minorversion",
+ "pdf_get_parameter",
+ "pdf_get_pdi_parameter",
+ "pdf_get_pdi_value",
+ "pdf_get_value",
+ "pdf_initgraphics",
+ "pdf_lineto",
+ "pdf_makespotcolor",
+ "pdf_moveto",
+ "pdf_new",
+ "pdf_open",
+ "pdf_open_CCITT",
+ "pdf_open_file",
+ "pdf_open_gif",
+ "pdf_open_image",
+ "pdf_open_image_file",
+ "pdf_open_jpeg",
+ "pdf_open_memory_image",
+ "pdf_open_pdi",
+ "pdf_open_pdi_page",
+ "pdf_open_png",
+ "pdf_open_tiff",
+ "pdf_place_image",
+ "pdf_place_pdi_page",
+ "pdf_rect",
+ "pdf_restore",
+ "pdf_rotate",
+ "pdf_save",
+ "pdf_scale",
+ "pdf_set_border_color",
+ "pdf_set_border_dash",
+ "pdf_set_border_style",
+ "pdf_set_char_spacing",
+ "pdf_setcolor",
+ "pdf_setdash",
+ "pdf_set_duration",
+ "pdf_setflat",
+ "pdf_set_font",
+ "pdf_setfont",
+ "pdf_setgray",
+ "pdf_setgray_fill",
+ "pdf_setgray_stroke",
+ "pdf_set_horiz_scaling",
+ "pdf_set_info",
+ "pdf_set_info_author",
+ "pdf_set_info_creator",
+ "pdf_set_info_keywords",
+ "pdf_set_info_subject",
+ "pdf_set_info_title",
+ "pdf_set_leading",
+ "pdf_setlinecap",
+ "pdf_setlinejoin",
+ "pdf_setlinewidth",
+ "pdf_setmatrix",
+ "pdf_setmiterlimit",
+ "pdf_set_parameter",
+ "pdf_setpolydash",
+ "pdf_setrgbcolor",
+ "pdf_setrgbcolor_fill",
+ "pdf_setrgbcolor_stroke",
+ "pdf_set_text_matrix",
+ "pdf_set_text_pos",
+ "pdf_set_text_rendering",
+ "pdf_set_text_rise",
+ "pdf_set_value",
+ "pdf_set_word_spacing",
+ "pdf_show",
+ "pdf_show_boxed",
+ "pdf_show_xy",
+ "pdf_skew",
+ "pdf_stringwidth",
+ "pdf_stroke",
+ "pdf_translate",
+ "PEAR_EXTENSION_DIR",
+ "PEAR_INSTALL_DIR",
+ "pfpro_cleanup",
+ "pfpro_init",
+ "pfpro_process",
+ "pfpro_process_raw",
+ "pfpro_version",
+ "pfsockopen",
+ "pg_affected_rows",
+ "pg_cancel_query",
+ "pg_client_encoding",
+ "pg_close",
+ "pg_connect",
+ "pg_connection_busy",
+ "pg_connection_reset",
+ "pg_connection_status",
+ "pg_convert",
+ "pg_copy_from",
+ "pg_copy_to",
+ "pg_dbname",
+ "pg_delete",
+ "pg_end_copy",
+ "pg_escape_bytea",
+ "pg_escape_string",
+ "pg_fetch_all",
+ "pg_fetch_array",
+ "pg_fetch_assoc",
+ "pg_fetch_object",
+ "pg_fetch_result",
+ "pg_fetch_row",
+ "pg_field_is_null",
+ "pg_field_name",
+ "pg_field_num",
+ "pg_field_prtlen",
+ "pg_field_size",
+ "pg_field_type",
+ "pg_free_result",
+ "pg_get_notify",
+ "pg_get_pid",
+ "pg_get_result",
+ "pg_host",
+ "pg_insert",
+ "pg_last_error",
+ "pg_last_notice",
+ "pg_last_oid",
+ "pg_lo_close",
+ "pg_lo_create",
+ "pg_lo_export",
+ "pg_lo_import",
+ "pg_lo_open",
+ "pg_lo_read",
+ "pg_lo_read_all",
+ "pg_lo_seek",
+ "pg_lo_tell",
+ "pg_lo_unlink",
+ "pg_lo_write",
+ "pg_meta_data",
+ "pg_num_fields",
+ "pg_num_rows",
+ "pg_options",
+ "pg_pconnect",
+ "pg_ping",
+ "pg_port",
+ "pg_put_line",
+ "pg_query",
+ "pg_result_error",
+ "pg_result_seek",
+ "pg_result_status",
+ "pg_select",
+ "pg_send_query",
+ "pg_set_client_encoding",
+ "pg_trace",
+ "pg_tty",
+ "pg_unescape_bytea",
+ "pg_untrace",
+ "pg_update",
+ "PHP_BINDIR",
+ "PHP_CONFIG_FILE_PATH",
+ "phpcredits",
+ "PHP_DATADIR",
+ "PHP_ERRMSG",
+ "PHP_EXTENSION_DIR",
+ "phpinfo",
+ "php_ini_scanned_files",
+ "PHP_LIBDIR",
+ "PHP_LOCALSTATEDIR",
+ "php_logo_guid",
+ "PHP_OS",
+ "PHP_OUTPUT_HANDLER_CONT",
+ "PHP_OUTPUT_HANDLER_END",
+ "PHP_OUTPUT_HANDLER_START",
+ "php_sapi_name",
+ "PHP_SELF",
+ "PHP_SYSCONFDIR",
+ "php_uname",
+ "phpversion",
+ "PHP_VERSION",
+ "pi",
+ "png2wbmp",
+ "popen",
+ "pos",
+ "posix_ctermid",
+ "posix_getcwd",
+ "posix_getegid",
+ "posix_geteuid",
+ "posix_getgid",
+ "posix_getgrgid",
+ "posix_getgrnam",
+ "posix_getgroups",
+ "posix_getlogin",
+ "posix_getpgid",
+ "posix_getpgrp",
+ "posix_getpid",
+ "posix_getppid",
+ "posix_getpwnam",
+ "posix_getpwuid",
+ "posix_getrlimit",
+ "posix_getsid",
+ "posix_getuid",
+ "posix_isatty",
+ "posix_kill",
+ "posix_mkfifo",
+ "posix_setegid",
+ "posix_seteuid",
+ "posix_setgid",
+ "posix_setpgid",
+ "posix_setsid",
+ "posix_setuid",
+ "posix_times",
+ "posix_ttyname",
+ "posix_uname",
+ "_POST",
+ "pow",
+ "prefix",
+ "preg_grep",
+ "preg_match",
+ "preg_match_all",
+ "preg_quote",
+ "preg_replace",
+ "preg_replace_callback",
+ "preg_split",
+ "prev",
+ "previous_sibling",
+ "print",
+ "printer_abort",
+ "printer_close",
+ "printer_create_brush",
+ "printer_create_dc",
+ "printer_create_font",
+ "printer_create_pen",
+ "printer_delete_brush",
+ "printer_delete_dc",
+ "printer_delete_font",
+ "printer_delete_pen",
+ "printer_draw_bmp",
+ "printer_draw_chord",
+ "printer_draw_elipse",
+ "printer_draw_line",
+ "printer_draw_pie",
+ "printer_draw_rectangle",
+ "printer_draw_roundrect",
+ "printer_draw_text",
+ "printer_end_doc",
+ "printer_end_page",
+ "printer_get_option",
+ "printer_list",
+ "printer_logical_fontheight",
+ "printer_open",
+ "printer_select_brush",
+ "printer_select_font",
+ "printer_select_pen",
+ "printer_set_option",
+ "printer_start_doc",
+ "printer_start_page",
+ "printer_write",
+ "printf",
+ "print_r",
+ "private",
+ "proc_close",
+ "process",
+ "proc_open",
+ "protected",
+ "pspell_add_to_personal",
+ "pspell_add_to_session",
+ "pspell_check",
+ "pspell_clear_session",
+ "pspell_config_create",
+ "pspell_config_ignore",
+ "pspell_config_mode",
+ "pspell_config_personal",
+ "pspell_config_repl",
+ "pspell_config_runtogether",
+ "pspell_config_save_repl",
+ "pspell_new",
+ "pspell_new_config",
+ "pspell_new_personal",
+ "pspell_save_wordlist",
+ "pspell_store_replacement",
+ "pspell_suggest",
+ "public",
+ "public_id",
+ "putenv",
+ "qdom_error",
+ "qdom_tree",
+ "QUERY_STRING",
+ "quoted_printable_decode",
+ "quotemeta",
+ "rad2deg",
+ "rand",
+ "range",
+ "rawurldecode",
+ "rawurlencode",
+ "read",
+ "readdir",
+ "read_exif_data",
+ "readfile",
+ "readgzfile",
+ "readline",
+ "readline_add_history",
+ "readline_clear_history",
+ "readline_completion_function",
+ "readline_info",
+ "readline_list_history",
+ "readline_read_history",
+ "readline_write_history",
+ "readlink",
+ "realpath",
+ "reason",
+ "recode",
+ "recode_file",
+ "recode_string",
+ "register_shutdown_function",
+ "register_tick_function",
+ "REMOTE_ADDR",
+ "REMOTE_PORT",
+ "remove",
+ "remove_attribute",
+ "remove_child",
+ "rename",
+ "replace",
+ "replace_child",
+ "replace_node",
+ "_REQUEST",
+ "REQUEST_METHOD",
+ "REQUEST_URI",
+ "require",
+ "require_once",
+ "reset",
+ "restore_error_handler",
+ "restore_include_path",
+ "result_dump_file",
+ "result_dump_mem",
+ "return",
+ "rewind",
+ "rewinddir",
+ "rmdir",
+ "Rotate",
+ "rotateTo",
+ "round",
+ "rsort",
+ "rtrim",
+ "save",
+ "scale",
+ "scaleTo",
+ "SCRIPT_FILENAME",
+ "SCRIPT_NAME",
+ "sem_acquire",
+ "sem_get",
+ "sem_release",
+ "sem_remove",
+ "serialize",
+ "_SERVER",
+ "SERVER_ADMIN",
+ "SERVER_NAME",
+ "SERVER_PORT",
+ "SERVER_PROTOCOL",
+ "SERVER_SIGNATURE",
+ "SERVER_SOFTWARE",
+ "sesam_affected_rows",
+ "sesam_commit",
+ "sesam_connect",
+ "sesam_diagnostic",
+ "sesam_disconnect",
+ "sesam_errormsg",
+ "sesam_execimm",
+ "sesam_fetch_array",
+ "sesam_fetch_result",
+ "sesam_fetch_row",
+ "sesam_field_array",
+ "sesam_field_name",
+ "sesam_free_result",
+ "sesam_num_fields",
+ "sesam_query",
+ "sesam_rollback",
+ "sesam_seek_row",
+ "sesam_settransaction",
+ "_SESSION",
+ "session_cache_expire",
+ "session_cache_limiter",
+ "session_decode",
+ "session_destroy",
+ "session_encode",
+ "session_get_cookie_params",
+ "session_id",
+ "session_is_registered",
+ "session_module_name",
+ "session_name",
+ "session_readonly",
+ "session_register",
+ "session_save_path",
+ "session_set_cookie_params",
+ "session_set_save_handler",
+ "session_start",
+ "session_unregister",
+ "session_unset",
+ "session_write_close",
+ "setAction",
+ "set_attribute",
+ "setbackground",
+ "setbounds",
+ "setcolor",
+ "setColor",
+ "setcommitedversion",
+ "set_content",
+ "setcookie",
+ "setDepth",
+ "setdimension",
+ "setdown",
+ "set_error_handler",
+ "set_file_buffer",
+ "setFont",
+ "setframes",
+ "setHeight",
+ "setHit",
+ "set_include_path",
+ "setindentation",
+ "setLeftFill",
+ "setLeftMargin",
+ "setLine",
+ "setLineSpacing",
+ "setlocale",
+ "set_magic_quotes_runtime",
+ "setMargins",
+ "set_name",
+ "setname",
+ "setName",
+ "set_namespace",
+ "setOver",
+ "setrate",
+ "setRatio",
+ "setRightFill",
+ "setrightMargin",
+ "setSpacing",
+ "set_time_limit",
+ "settype",
+ "setUp",
+ "sha1",
+ "sha1_file",
+ "shell_exec",
+ "shm_attach",
+ "shm_detach",
+ "shm_get_var",
+ "shmop_close",
+ "shmop_delete",
+ "shmop_open",
+ "shmop_read",
+ "shmop_size",
+ "shmop_write",
+ "shm_put_var",
+ "shm_remove",
+ "shm_remove_var",
+ "show_source",
+ "shuffle",
+ "similar_text",
+ "sin",
+ "sinh",
+ "sizeof",
+ "skewX",
+ "skewXTo",
+ "skewY",
+ "skewYTo",
+ "sleep",
+ "snmpget",
+ "snmp_get_quick_print",
+ "snmprealwalk",
+ "snmpset",
+ "snmp_set_quick_print",
+ "snmpwalk",
+ "snmpwalkoid",
+ "socket_accept",
+ "socket_bind",
+ "socket_clear_error",
+ "socket_close",
+ "socket_connect",
+ "socket_create",
+ "socket_create_listen",
+ "socket_create_pair",
+ "socket_get_option",
+ "socket_getpeername",
+ "socket_getsockname",
+ "socket_get_status",
+ "socket_iovec_add",
+ "socket_iovec_alloc",
+ "socket_iovec_delete",
+ "socket_iovec_fetch",
+ "socket_iovec_free",
+ "socket_iovec_set",
+ "socket_last_error",
+ "socket_listen",
+ "socket_read",
+ "socket_readv",
+ "socket_recv",
+ "socket_recvfrom",
+ "socket_recvmsg",
+ "socket_select",
+ "socket_send",
+ "socket_sendmsg",
+ "socket_sendto",
+ "socket_set_blocking",
+ "socket_set_nonblock",
+ "socket_set_option",
+ "socket_set_timeout",
+ "socket_shutdown",
+ "socket_strerror",
+ "socket_write",
+ "socket_writev",
+ "sort",
+ "soundex",
+ "specified",
+ "split",
+ "spliti",
+ "sprintf",
+ "sql_regcase",
+ "sqrt",
+ "srand",
+ "srcanchors",
+ "srcsofdst",
+ "sscanf",
+ "stat",
+ "static",
+ "stdClass",
+ "strcasecmp",
+ "strchr",
+ "strcmp",
+ "strcoll",
+ "strcspn",
+ "stream_context_create",
+ "stream_context_get_options",
+ "stream_context_set_option",
+ "stream_context_set_params",
+ "stream_filter_append",
+ "stream_filter_prepend",
+ "stream_get_filters",
+ "stream_get_meta_data",
+ "stream_get_wrappers",
+ "streammp3",
+ "stream_register_filter",
+ "stream_register_wrapper",
+ "stream_select",
+ "stream_set_blocking",
+ "stream_set_timeout",
+ "stream_set_write_buffer",
+ "strftime",
+ "stripcslashes",
+ "stripslashes",
+ "strip_tags",
+ "stristr",
+ "strlen",
+ "strnatcasecmp",
+ "strnatcmp",
+ "strncasecmp",
+ "strncmp",
+ "str_pad",
+ "strpos",
+ "strrchr",
+ "str_repeat",
+ "str_replace",
+ "strrev",
+ "str_rot13",
+ "strrpos",
+ "str_shuffle",
+ "strspn",
+ "strstr",
+ "strtok",
+ "strtolower",
+ "strtotime",
+ "strtoupper",
+ "strtr",
+ "strval",
+ "str_word_count",
+ "substr",
+ "substr_count",
+ "substr_replace",
+ "SWFAction",
+ "swf_actiongeturl",
+ "swf_actiongotoframe",
+ "swf_actiongotolabel",
+ "swf_actionnextframe",
+ "swf_actionplay",
+ "swf_actionprevframe",
+ "swf_actionsettarget",
+ "swf_actionstop",
+ "swf_actiontogglequality",
+ "swf_actionwaitforframe",
+ "swf_addbuttonrecord",
+ "swf_addcolor",
+ "SWFBitmap",
+ "SWFbutton",
+ "swfbutton_keypress",
+ "swf_closefile",
+ "swf_definebitmap",
+ "swf_definefont",
+ "swf_defineline",
+ "swf_definepoly",
+ "swf_definerect",
+ "swf_definetext",
+ "SWFDisplayItem",
+ "swf_endbutton",
+ "swf_enddoaction",
+ "swf_endshape",
+ "swf_endsymbol",
+ "SWFFill",
+ "SWFFont",
+ "swf_fontsize",
+ "swf_fontslant",
+ "swf_fonttracking",
+ "swf_getbitmapinfo",
+ "swf_getfontinfo",
+ "swf_getframe",
+ "SWFGradient",
+ "swf_labelframe",
+ "swf_lookat",
+ "swf_modifyobject",
+ "SWFMorph",
+ "SWFMovie",
+ "swf_mulcolor",
+ "swf_nextid",
+ "swf_oncondition",
+ "swf_openfile",
+ "swf_ortho",
+ "swf_ortho2",
+ "swf_perspective",
+ "swf_placeobject",
+ "swf_polarview",
+ "swf_popmatrix",
+ "swf_posround",
+ "swf_pushmatrix",
+ "swf_removeobject",
+ "swf_rotate",
+ "swf_scale",
+ "swf_setfont",
+ "swf_setframe",
+ "SWFShape",
+ "swf_shapearc",
+ "swf_shapecurveto",
+ "swf_shapecurveto3",
+ "swf_shapefillbitmapclip",
+ "swf_shapefillbitmaptile",
+ "swf_shapefilloff",
+ "swf_shapefillsolid",
+ "swf_shapelinesolid",
+ "swf_shapelineto",
+ "swf_shapemoveto",
+ "swf_showframe",
+ "SWFSprite",
+ "swf_startbutton",
+ "swf_startdoaction",
+ "swf_startshape",
+ "swf_startsymbol",
+ "SWFText",
+ "SWFTextField",
+ "swf_textwidth",
+ "swf_translate",
+ "swf_viewport",
+ "switch",
+ "sybase_affected_rows",
+ "sybase_close",
+ "sybase_connect",
+ "sybase_data_seek",
+ "sybase_fetch_array",
+ "sybase_fetch_field",
+ "sybase_fetch_object",
+ "sybase_fetch_row",
+ "sybase_field_seek",
+ "sybase_free_result",
+ "sybase_get_last_message",
+ "sybase_min_client_severity",
+ "sybase_min_error_severity",
+ "sybase_min_message_severity",
+ "sybase_min_server_severity",
+ "sybase_num_fields",
+ "sybase_num_rows",
+ "sybase_pconnect",
+ "sybase_query",
+ "sybase_result",
+ "sybase_select_db",
+ "symlink",
+ "syslog",
+ "system",
+ "system_id",
+ "tagname",
+ "tan",
+ "tanh",
+ "target",
+ "tempnam",
+ "textdomain",
+ "time",
+ "title",
+ "tmpfile",
+ "token_get_all",
+ "token_name",
+ "touch",
+ "trigger_error",
+ "trim",
+ "TRUE",
+ "type",
+ "uasort",
+ "ucfirst",
+ "ucwords",
+ "udm_add_search_limit",
+ "udm_alloc_agent",
+ "udm_api_version",
+ "udm_cat_list",
+ "udm_cat_path",
+ "udm_check_charset",
+ "udm_check_stored",
+ "udm_clear_search_limits",
+ "udm_close_stored",
+ "udm_crc32",
+ "udm_errno",
+ "udm_error",
+ "udm_find",
+ "udm_free_agent",
+ "udm_free_ispell_data",
+ "udm_free_res",
+ "udm_get_doc_count",
+ "udm_get_res_field",
+ "udm_get_res_param",
+ "udm_load_ispell_data",
+ "udm_open_stored",
+ "udm_set_agent_param",
+ "uksort",
+ "umask",
+ "uniqid",
+ "unixtojd",
+ "unlink",
+ "unlink_node",
+ "unlock",
+ "unpack",
+ "unregister_tick_function",
+ "unserialize",
+ "unset",
+ "urldecode",
+ "urlencode",
+ "user",
+ "user_error",
+ "userlist",
+ "usleep",
+ "usort",
+ "utf8_decode",
+ "utf8_encode",
+ "value",
+ "values",
+ "var",
+ "var_dump",
+ "var_export",
+ "version_compare",
+ "virtual",
+ "vpopmail_add_alias_domain",
+ "vpopmail_add_alias_domain_ex",
+ "vpopmail_add_domain",
+ "vpopmail_add_domain_ex",
+ "vpopmail_add_user",
+ "vpopmail_alias_add",
+ "vpopmail_alias_del",
+ "vpopmail_alias_del_domain",
+ "vpopmail_alias_get",
+ "vpopmail_alias_get_all",
+ "vpopmail_auth_user",
+ "vpopmail_del_domain",
+ "vpopmail_del_domain_ex",
+ "vpopmail_del_user",
+ "vpopmail_error",
+ "vpopmail_passwd",
+ "vpopmail_set_user_quota",
+ "vprintf",
+ "vsprintf",
+ "w32api_deftype",
+ "w32api_init_dtype",
+ "w32api_invoke_function",
+ "w32api_register_function",
+ "w32api_set_call_method",
+ "wddx_add_vars",
+ "wddx_deserialize",
+ "wddx_packet_end",
+ "wddx_packet_start",
+ "wddx_serialize_value",
+ "wddx_serialize_vars",
+ "while",
+ "wordwrap",
+ "xinclude",
+ "xml_error_string",
+ "xml_get_current_byte_index",
+ "xml_get_current_column_number",
+ "xml_get_current_line_number",
+ "xml_get_error_code",
+ "xml_parse",
+ "xml_parse_into_struct",
+ "xml_parser_create",
+ "xml_parser_create_ns",
+ "xml_parser_free",
+ "xml_parser_get_option",
+ "xml_parser_set_option",
+ "xmlrpc_decode",
+ "xmlrpc_decode_request",
+ "xmlrpc_encode",
+ "xmlrpc_encode_request",
+ "xmlrpc_get_type",
+ "xmlrpc_parse_method_descriptions",
+ "xmlrpc_server_add_introspection_data",
+ "xmlrpc_server_call_method",
+ "xmlrpc_server_create",
+ "xmlrpc_server_destroy",
+ "xmlrpc_server_register_introspection_callback",
+ "xmlrpc_server_register_method",
+ "xmlrpc_set_type",
+ "xml_set_character_data_handler",
+ "xml_set_default_handler",
+ "xml_set_element_handler",
+ "xml_set_end_namespace_decl_handler",
+ "xml_set_external_entity_ref_handler",
+ "xml_set_notation_decl_handler",
+ "xml_set_object",
+ "xml_set_processing_instruction_handler",
+ "xml_set_start_namespace_decl_handler",
+ "xml_set_unparsed_entity_decl_handler",
+ "xpath_eval",
+ "xpath_eval_expression",
+ "xpath_new_context",
+ "xptr_eval",
+ "xptr_new_context",
+ "xslt_create",
+ "xslt_errno",
+ "xslt_error",
+ "xslt_free",
+ "xslt_output_process",
+ "xslt_set_base",
+ "xslt_set_encoding",
+ "xslt_set_error_handler",
+ "xslt_set_log",
+ "xslt_set_sax_handler",
+ "xslt_set_sax_handlers",
+ "xslt_set_scheme_handler",
+ "xslt_set_scheme_handlers",
+ "yaz_addinfo",
+ "yaz_ccl_conf",
+ "yaz_ccl_parse",
+ "yaz_close",
+ "yaz_connect",
+ "yaz_database",
+ "yaz_element",
+ "yaz_errno",
+ "yaz_error",
+ "yaz_get_option",
+ "yaz_hits",
+ "yaz_itemorder",
+ "yaz_present",
+ "yaz_range",
+ "yaz_record",
+ "yaz_scan",
+ "yaz_scan_result",
+ "yaz_schema",
+ "yaz_search",
+ "yaz_set_option",
+ "yaz_sort",
+ "yaz_syntax",
+ "yaz_wait",
+ "yp_all",
+ "yp_cat",
+ "yp_errno",
+ "yp_err_string",
+ "yp_first",
+ "yp_get_default_domain",
+ "yp_master",
+ "yp_match",
+ "yp_next",
+ "yp_order",
+ "zend_logo_guid",
+ "zend_version",
+ "zend_version",
+ "zip_close",
+ "zip_entry_close",
+ "zip_entry_compressedsize",
+ "zip_entry_compressionmethod",
+ "zip_entry_filesize",
+ "zip_entry_name",
+ "zip_entry_open",
+ "zip_entry_read",
+ "zip_open",
+ "zip_read",
+ 0
+ };
+
+Php5Writer::Php5Writer() {
+}
+
+Php5Writer::~Php5Writer() {}
+
+
+void Php5Writer::writeClass(UMLClassifier *c) {
+ if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".php");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile filephp;
+ if(!openFile(filephp, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream php(&filephp);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".php");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),filephp.name());
+ php<<str<<m_endl;
+ }
+
+
+ //write includes
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ UMLPackage *conc;
+ for(conc = includes.first(); conc ;conc = includes.next()) {
+ QString headerName = findFileName(conc, ".php");
+ if (!headerName.isEmpty()) {
+ php << "require_once '" << headerName << "';" << m_endl;
+ }
+ }
+ php << m_endl;
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ php << m_endl << "/**" << m_endl;
+ php << " * class " << classname << m_endl;
+ php << formatDoc(c->getDoc()," * ");
+ php << " */" << m_endl ;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+ UMLAssociationList realizations = c->getRealizations();
+ UMLAssociation *a;
+ bool isInterface = c->isInterface();
+
+ //check if it is an interface or regular class
+ if(isInterface) {
+ php << "interface " << classname;
+ } else {
+ //check if class is abstract and / or has abstract methods
+ if(c->getAbstract())
+ php << "abstract ";
+ php << "class " << classname << (superclasses.count() > 0 ? " extends ":"");
+ if(superclasses.count() > 0) {
+ //php5 does not support multiple inheritance so only use the first one and print a warning if more are used
+ UMLClassifier *obj = superclasses.first();
+ php << cleanName(obj->getName());
+ if(superclasses.count() > 1)
+ php << m_indentation << "//WARNING: PHP5 does not support multiple inheritance but there is more than 1 superclass defined in your UML model!";
+ }
+ //check for realizations
+ if( !realizations.isEmpty()) {
+ int rc = realizations.count();
+ int ri = rc;
+ for (a = realizations.first(); a; a = realizations.next()) {
+ UMLObject *o = a->getObject(Uml::B);
+ QString typeName = cleanName(o->getName());
+ if(ri == rc)
+ php << m_endl << m_indentation << m_indentation << m_indentation << "implements ";
+ php << typeName << (--rc == 0 ? "" : ", ");
+ }
+ }
+ }
+ php << m_endl << '{' << m_endl;
+
+ //associations
+ if( forceSections() || !aggregations.isEmpty()) {
+ php<< m_endl << m_indentation << "/** Aggregations: */" << m_endl;
+ for (a = aggregations.first(); a; a = aggregations.next()) {
+ php<< m_endl;
+ //maybe we should parse the string here and take multiplicity into account to decide
+ //which container to use.
+ UMLObject *o = a->getObject(Uml::A);
+ if (o == NULL) {
+ kError() << "aggregation role A object is NULL" << endl;
+ continue;
+ }
+ QString typeName = cleanName(o->getName());
+ if (a->getMulti(Uml::A).isEmpty()) {
+ php << m_indentation << "var $m_" << ';' << m_endl;
+ } else {
+ php << m_indentation << "var $m_" << "Vector = array();" << m_endl;
+ }
+ }//end for
+ }
+
+ if( forceSections() || !compositions.isEmpty()) {
+ php<< m_endl << m_indentation << "/** Compositions: */" << m_endl;
+ for (a = compositions.first(); a ; a = compositions.next()) {
+ // see comment on Aggregation about multiplicity...
+ UMLObject *o = a->getObject(Uml::A);
+ if (o == NULL) {
+ kError() << "composition role A object is NULL" << endl;
+ continue;
+ }
+ QString typeName = cleanName(o->getName());
+ if (a->getMulti(Uml::A).isEmpty()) {
+ php << m_indentation << "var $m_" << ';' << m_endl;
+ } else {
+ php << m_indentation << "var $m_" << "Vector = array();" << m_endl;
+ }
+ }
+ }
+
+ //attributes
+ if (!isInterface)
+ writeAttributes(c, php);
+
+ //operations
+ writeOperations(c,php);
+
+ php << m_endl;
+
+ //finish file
+ php << m_endl << "} // end of " << classname << m_endl;
+ php << "?>" << m_endl;
+
+ //close files and notfiy we are done
+ filephp.close();
+ emit codeGenerated(c, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void Php5Writer::writeOperations(UMLClassifier *c, QTextStream &php) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ bool isInterface = c->isInterface();
+ bool generateErrorStub = false;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ QString classname(cleanName(c->getName()));
+
+ //write operations to file
+ if(forceSections() || !oppub.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,oppub,php,isInterface,generateErrorStub);
+ }
+
+ if(forceSections() || !opprot.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,opprot,php,isInterface,generateErrorStub);
+ }
+
+ if(forceSections() || !oppriv.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,oppriv,php,isInterface,generateErrorStub);
+ }
+
+
+ // build an oplist for all of the realized operations
+ UMLOperationList opreal;
+ opreal.setAutoDelete(false);
+
+ // go through each of the realizations, taking each op
+ UMLAssociationList realizations = c->getRealizations();
+ UMLAssociation *a;
+
+ if( !realizations.isEmpty()) {
+ for (a = realizations.first(); a; a = realizations.next()) {
+
+ // we know its a classifier if its in the list
+ UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
+
+ UMLOperationList opl(real->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ opreal.append(op);
+ }
+ }
+ }
+
+ // write out all the realizations operations
+ writeOperations(classname,opreal,php,false,true);
+
+}
+
+void Php5Writer::writeOperations(const QString &/* classname */, UMLOperationList &opList,
+ QTextStream &php, bool isInterface /* = false */,
+ bool generateErrorStub /* = false */) {
+ for (UMLOperation *op=opList.first(); op ; op=opList.next()) {
+ UMLAttributeList atl = op->getParmList();
+ UMLAttribute *at;
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ if( writeDoc ) //write method documentation
+ {
+ php <<m_indentation << "/**" << m_endl <<formatDoc(op->getDoc(),m_indentation + " * ");
+ php << m_indentation << " *" << m_endl;
+
+ for (at = atl.first(); at; at = atl.next()) //write parameter documentation
+ {
+ if(forceDoc() || !at->getDoc().isEmpty()) {
+ php <<m_indentation << " * @param " + at->getTypeName() + ' ' + cleanName(at->getName());
+ php << ' ' + formatDoc(at->getDoc(),"") << m_endl;
+ }
+ }//end for : write parameter documentation
+ php << m_indentation << " * @return " << op->getTypeName() << m_endl;
+ if (op->getAbstract()) php << m_indentation << " * @abstract" << m_endl;
+ if (op->getStatic()) php << m_indentation << " * @static" << m_endl;
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << m_indentation << " * @access public" << m_endl;
+ break;
+ case Uml::Visibility::Protected:
+ php << m_indentation << " * @access protected" << m_endl;
+ break;
+ case Uml::Visibility::Private:
+ php << m_indentation << " * @access private" << m_endl;
+ break;
+ default:
+ break;
+ }
+ php <<m_indentation << " */" << m_endl;
+ }//end if : write method documentation
+
+ php << m_indentation;
+ if (op->getAbstract()) php << "abstract ";
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << "public ";
+ break;
+ case Uml::Visibility::Protected:
+ php << "protected ";
+ break;
+ case Uml::Visibility::Private:
+ php << "private ";
+ break;
+ default:
+ break;
+ }
+ if (op->getStatic()) php << "static ";
+ php << "function " << cleanName(op->getName()) << "(";
+
+ int i= atl.count();
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ php << " $" << cleanName(at->getName())
+ << (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""))
+ << ((j < i-1)?", ":"");
+ }
+ php <<" )";
+ if(!isInterface && !op->getAbstract()) {
+ php << " {" << m_endl << m_indentation << m_indentation;
+ if(generateErrorStub) {
+ php << "trigger_error(\"Implement \" . __FUNCTION__);";
+ }
+ php << m_endl << m_indentation << "} // end of member function " + cleanName(op->getName()) + m_endl;
+ }
+ else {
+ php << ';' + m_endl;
+ }
+ php << m_endl;
+ }//end for
+}
+
+void Php5Writer::writeAttributes(UMLClassifier *c, QTextStream &php) {
+ UMLAttributeList atpub, atprot, atpriv, atdefval;
+ atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ atdefval.setAutoDelete(false);
+
+ //sort attributes by scope and see if they have a default value
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ for(at = atl.first(); at ; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty())
+ atdefval.append(at);
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ atpriv.append(at);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(forceSections() || atl.count())
+ php<< m_endl << m_indentation << " /*** Attributes: ***/" << m_endl <<m_endl;
+
+ if(forceSections() || atpub.count()) {
+ writeAttributes(atpub,php);
+ }
+
+ if(forceSections() || atprot.count()) {
+ writeAttributes(atprot,php);
+ }
+
+ if(forceSections() || atpriv.count()) {
+ writeAttributes(atpriv,php);
+ }
+}
+
+
+void Php5Writer::writeAttributes(UMLAttributeList &atList, QTextStream &php) {
+ for (UMLAttribute *at = atList.first(); at ; at = atList.next()) {
+ bool isStatic = at->getStatic();
+ if (forceDoc() || !at->getDoc().isEmpty()) {
+ php << m_indentation << "/**" << m_endl << formatDoc(at->getDoc(), m_indentation + " * ");
+ if(isStatic) php << m_indentation << " * @static" << m_endl;
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << m_indentation << " * @access public" << m_endl;
+ break;
+ case Uml::Visibility::Protected:
+ php << m_indentation << " * @access protected" << m_endl;
+ break;
+ case Uml::Visibility::Private:
+ php << m_indentation << " * @access private" << m_endl;
+ break;
+ default:
+ break;
+ }
+ php << m_indentation << " */" << m_endl;
+ }
+ php << m_indentation;
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << "public ";
+ break;
+ case Uml::Visibility::Protected:
+ php << "protected ";
+ break;
+ case Uml::Visibility::Private:
+ php << "private ";
+ break;
+ default:
+ break;
+ }
+ if(isStatic) php << "static ";
+ php << "$" << cleanName(at->getName());
+ if(!at->getInitialValue().isEmpty())
+ php << " = " << at->getInitialValue();
+ php << ";" << m_endl << m_endl;
+ } // end for
+ return;
+}
+
+/**
+ * returns "PHP"
+ */
+Uml::Programming_Language Php5Writer::getLanguage() {
+ return Uml::pl_PHP5;
+}
+
+const QStringList Php5Writer::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ for (int i = 0; php5words[i]; i++)
+ keywords.append(php5words[i]);
+ }
+
+ return keywords;
+}
+
+#include "php5writer.moc"
+
diff --git a/umbrello/umbrello/codegenerators/php5writer.h b/umbrello/umbrello/codegenerators/php5writer.h
new file mode 100644
index 00000000..3adc983c
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/php5writer.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ php5writer.h - description
+ -------------------
+ begin : Thu Oct 17 2002
+ copyright : (C) 2002 by Heiko Nardmann
+ email : h.nardmann@secunet.de
+
+ php5 version by Thorsten Kunz (tk AT bytecrash DOT net)
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHP5WRITER_H
+#define PHP5WRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+#include "../umloperationlist.h"
+
+/**
+ * class Php5Writer is a PHP code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class Php5Writer : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ Php5Writer();
+ virtual ~Php5Writer();
+
+ /**
+ * call this method to generate Php code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "PHP"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param php output stream for the PHP file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &php);
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param php output stream for the PHP file
+ * @param interface indicates if the operation is an interface member
+ */
+ void writeOperations(const QString &classname, UMLOperationList &opList,
+ QTextStream &php,
+ bool interface = false, bool generateErrorStub = false);
+
+ /** write all the attributes of a class
+ * @param c the class we are generating code for
+ * @param php output stream for the PHP file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &php);
+
+ /** write a list of class attributes
+ * @param atList the list of attributes
+ * @param php output stream for the PHP file
+ */
+ void writeAttributes(UMLAttributeList &atList, QTextStream &php);
+};
+
+#endif //PHP5WRITER
+
diff --git a/umbrello/umbrello/codegenerators/phpwriter.cpp b/umbrello/umbrello/codegenerators/phpwriter.cpp
new file mode 100644
index 00000000..6d71c102
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/phpwriter.cpp
@@ -0,0 +1,3339 @@
+/***************************************************************************
+ begin : Thu Oct 17 2002
+ copyright : (C) 2002 by Heiko Nardmann
+ email : h.nardmann@secunet.de
+ (C) 2003-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "phpwriter.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+static const char *words[] =
+ {
+ "abs",
+ "acos",
+ "acosh",
+ "add",
+ "addAction",
+ "addColor",
+ "addcslashes",
+ "addEntry",
+ "addFill",
+ "add_namespace",
+ "addShape",
+ "addslashes",
+ "addstring",
+ "addString",
+ "aggregate",
+ "aggregate_info",
+ "aggregate_methods",
+ "aggregate_methods_by_list",
+ "aggregate_methods_by_regexp",
+ "aggregate_properties",
+ "aggregate_properties_by_list",
+ "aggregate_properties_by_regexp",
+ "aggregation_info",
+ "align",
+ "apache_child_terminate",
+ "apache_lookup_uri",
+ "apache_note",
+ "apache_request_headers",
+ "apache_response_headers",
+ "apache_setenv",
+ "append_child",
+ "append_sibling",
+ "array",
+ "array_change_key_case",
+ "array_chunk",
+ "array_count_values",
+ "array_diff",
+ "array_diff_assoc",
+ "array_fill",
+ "array_filter",
+ "array_flip",
+ "array_intersect",
+ "array_intersect_assoc",
+ "array_key_exists",
+ "array_keys",
+ "array_map",
+ "array_merge",
+ "array_merge_recursive",
+ "array_multisort",
+ "array_pad",
+ "array_pop",
+ "array_push",
+ "array_rand",
+ "array_reduce",
+ "array_reverse",
+ "array_search",
+ "array_shift",
+ "array_slice",
+ "array_splice",
+ "array_sum",
+ "array_unique",
+ "array_unshift",
+ "array_values",
+ "array_walk",
+ "arsort",
+ "ascii2ebcdic",
+ "asin",
+ "asinh",
+ "asort",
+ "aspell_check",
+ "aspell_new",
+ "aspell_suggest",
+ "assert",
+ "assert_options",
+ "assign",
+ "atan",
+ "atan2",
+ "atanh",
+ "attreditable",
+ "attributes",
+ "base64_decode",
+ "base64_encode",
+ "base_convert",
+ "basename",
+ "bcadd",
+ "bccomp",
+ "bcdiv",
+ "bcmod",
+ "bcmul",
+ "bcpow",
+ "bcpowmod",
+ "bcscale",
+ "bcsqrt",
+ "bcsub",
+ "bin2hex",
+ "bindec",
+ "bindtextdomain",
+ "bind_textdomain_codeset",
+ "bool",
+ "break",
+ "bzclose",
+ "bzcompress",
+ "bzdecompress",
+ "bzerrno",
+ "bzerror",
+ "bzerrstr",
+ "bzflush",
+ "bzopen",
+ "bzread",
+ "bzwrite",
+ "cal_days_in_month",
+ "cal_from_jd",
+ "cal_info",
+ "call_user_func",
+ "call_user_func_array",
+ "call_user_method",
+ "call_user_method_array",
+ "cal_to_jd",
+ "ccvs_add",
+ "ccvs_auth",
+ "ccvs_command",
+ "ccvs_count",
+ "ccvs_delete",
+ "ccvs_done",
+ "ccvs_init",
+ "ccvs_lookup",
+ "ccvs_new",
+ "ccvs_report",
+ "ccvs_return",
+ "ccvs_reverse",
+ "ccvs_sale",
+ "ccvs_status",
+ "ccvs_textvalue",
+ "ccvs_void",
+ "ceil",
+ "chdir",
+ "checkdate",
+ "checkdnsrr",
+ "checkin",
+ "checkout",
+ "chgrp",
+ "child_nodes",
+ "children",
+ "chmod",
+ "chop",
+ "chown",
+ "chr",
+ "chroot",
+ "chunk_split",
+ "class",
+ "class_exists",
+ "clearstatcache",
+ "clone_node",
+ "closedir",
+ "closelog",
+ "com_addref",
+ "com_get",
+ "com_invoke",
+ "com_isenum",
+ "com_load",
+ "com_load_typelib",
+ "compact",
+ "com_propget",
+ "com_propput",
+ "com_propset",
+ "com_release",
+ "com_set",
+ "connection_aborted",
+ "connection_status",
+ "connection_timeout",
+ "constant",
+ "content",
+ "continue",
+ "convert_cyr_string",
+ "_COOKIE",
+ "copy",
+ "cos",
+ "cosh",
+ "count",
+ "count_chars",
+ "cpdf_add_annotation",
+ "cpdf_add_outline",
+ "cpdf_arc",
+ "cpdf_begin_text",
+ "cpdf_circle",
+ "cpdf_clip",
+ "cpdf_close",
+ "cpdf_closepath",
+ "cpdf_closepath_fill_stroke",
+ "cpdf_closepath_stroke",
+ "cpdf_continue_text",
+ "cpdf_curveto",
+ "cpdf_end_text",
+ "cpdf_fill",
+ "cpdf_fill_stroke",
+ "cpdf_finalize",
+ "cpdf_finalize_page",
+ "cpdf_global_set_document_limits",
+ "cpdf_import_jpeg",
+ "cpdf_lineto",
+ "cpdf_moveto",
+ "cpdf_newpath",
+ "cpdf_open",
+ "cpdf_output_buffer",
+ "cpdf_page_init",
+ "cpdf_place_inline_image",
+ "cpdf_rect",
+ "cpdf_restore",
+ "cpdf_rlineto",
+ "cpdf_rmoveto",
+ "cpdf_rotate",
+ "cpdf_rotate_text",
+ "cpdf_save",
+ "cpdf_save_to_file",
+ "cpdf_scale",
+ "cpdf_set_action_url",
+ "cpdf_set_char_spacing",
+ "cpdf_set_creator",
+ "cpdf_set_current_page",
+ "cpdf_setdash",
+ "cpdf_setflat",
+ "cpdf_set_font",
+ "cpdf_set_font_directories",
+ "cpdf_set_font_map_file",
+ "cpdf_setgray",
+ "cpdf_setgray_fill",
+ "cpdf_setgray_stroke",
+ "cpdf_set_horiz_scaling",
+ "cpdf_set_keywords",
+ "cpdf_set_leading",
+ "cpdf_setlinecap",
+ "cpdf_setlinejoin",
+ "cpdf_setlinewidth",
+ "cpdf_setmiterlimit",
+ "cpdf_set_page_animation",
+ "cpdf_setrgbcolor",
+ "cpdf_setrgbcolor_fill",
+ "cpdf_setrgbcolor_stroke",
+ "cpdf_set_subject",
+ "cpdf_set_text_matrix",
+ "cpdf_set_text_pos",
+ "cpdf_set_text_rendering",
+ "cpdf_set_text_rise",
+ "cpdf_set_title",
+ "cpdf_set_viewer_preferences",
+ "cpdf_set_word_spacing",
+ "cpdf_show",
+ "cpdf_show_xy",
+ "cpdf_stringwidth",
+ "cpdf_stroke",
+ "cpdf_text",
+ "cpdf_translate",
+ "crack_check",
+ "crack_closedict",
+ "crack_getlastmessage",
+ "crack_opendict",
+ "crc32",
+ "create_attribute",
+ "create_cdata_section",
+ "create_comment",
+ "create_element",
+ "create_element_ns",
+ "create_entity_reference",
+ "create_function",
+ "create_processing_instruction",
+ "create_text_node",
+ "crypt",
+ "ctype_alnum",
+ "ctype_alpha",
+ "ctype_cntrl",
+ "ctype_digit",
+ "ctype_graph",
+ "ctype_lower",
+ "ctype_print",
+ "ctype_punct",
+ "ctype_space",
+ "ctype_upper",
+ "ctype_xdigit",
+ "curl_close",
+ "curl_errno",
+ "curl_error",
+ "curl_exec",
+ "curl_getinfo",
+ "curl_init",
+ "curl_setopt",
+ "curl_version",
+ "current",
+ "cybercash_base64_decode",
+ "cybercash_base64_encode",
+ "cybercash_decr",
+ "cybercash_encr",
+ "cybermut_creerformulairecm",
+ "cybermut_creerreponsecm",
+ "cybermut_testmac",
+ "cyrus_authenticate",
+ "cyrus_bind",
+ "cyrus_close",
+ "cyrus_connect",
+ "cyrus_query",
+ "cyrus_unbind",
+ "data",
+ "date",
+ "dba_close",
+ "dba_delete",
+ "dba_exists",
+ "dba_fetch",
+ "dba_firstkey",
+ "dba_handlers",
+ "dba_insert",
+ "dba_list",
+ "dba_nextkey",
+ "dba_open",
+ "dba_optimize",
+ "dba_popen",
+ "dba_replace",
+ "dbase_add_record",
+ "dbase_close",
+ "dbase_create",
+ "dbase_delete_record",
+ "dbase_get_record",
+ "dbase_get_record_with_names",
+ "dbase_numfields",
+ "dbase_numrecords",
+ "dbase_open",
+ "dbase_pack",
+ "dbase_replace_record",
+ "dba_sync",
+ "dblist",
+ "dbmclose",
+ "dbmdelete",
+ "dbmexists",
+ "dbmfetch",
+ "dbmfirstkey",
+ "dbminsert",
+ "dbmnextkey",
+ "dbmopen",
+ "dbmreplace",
+ "dbplus_add",
+ "dbplus_aql",
+ "dbplus_chdir",
+ "dbplus_close",
+ "dbplus_curr",
+ "dbplus_errcode",
+ "dbplus_errno",
+ "dbplus_find",
+ "dbplus_first",
+ "dbplus_flush",
+ "dbplus_freealllocks",
+ "dbplus_freelock",
+ "dbplus_freerlocks",
+ "dbplus_getlock",
+ "dbplus_getunique",
+ "dbplus_info",
+ "dbplus_last",
+ "dbplus_lockrel",
+ "dbplus_next",
+ "dbplus_open",
+ "dbplus_prev",
+ "dbplus_rchperm",
+ "dbplus_rcreate",
+ "dbplus_rcrtexact",
+ "dbplus_rcrtlike",
+ "dbplus_resolve",
+ "dbplus_restorepos",
+ "dbplus_rkeys",
+ "dbplus_ropen",
+ "dbplus_rquery",
+ "dbplus_rrename",
+ "dbplus_rsecindex",
+ "dbplus_runlink",
+ "dbplus_rzap",
+ "dbplus_savepos",
+ "dbplus_setindex",
+ "dbplus_setindexbynumber",
+ "dbplus_sql",
+ "dbplus_tcl",
+ "dbplus_tremove",
+ "dbplus_undo",
+ "dbplus_undoprepare",
+ "dbplus_unlockrel",
+ "dbplus_unselect",
+ "dbplus_update",
+ "dbplus_xlockrel",
+ "dbplus_xunlockrel",
+ "dbstat",
+ "dbx_close",
+ "dbx_compare",
+ "dbx_connect",
+ "dbx_error",
+ "dbx_escape_string",
+ "dbx_query",
+ "dbx_sort",
+ "dcgettext",
+ "dcngettext",
+ "dcstat",
+ "deaggregate",
+ "debug_backtrace",
+ "debugger_off",
+ "debugger_on",
+ "decbin",
+ "dechex",
+ "declare",
+ "decoct",
+ "DEFAULT_INCLUDE_PATH",
+ "define",
+ "defined",
+ "define_syslog_variables",
+ "deg2rad",
+ "delete",
+ "description",
+ "dgettext",
+ "die",
+ "dio_close",
+ "dio_fcntl",
+ "dio_open",
+ "dio_read",
+ "dio_seek",
+ "dio_stat",
+ "dio_tcsetattr",
+ "dio_truncate",
+ "dio_write",
+ "dir",
+ "dirname",
+ "disk_free_space",
+ "diskfreespace",
+ "disk_total_space",
+ "dl",
+ "dngettext",
+ "dns_check_record",
+ "dns_get_mx",
+ "dns_get_record",
+ "do",
+ "doctype",
+ "document_element",
+ "DOCUMENT_ROOT",
+ "domxml_new_doc",
+ "domxml_open_file",
+ "domxml_open_mem",
+ "domxml_version",
+ "domxml_xmltree",
+ "domxml_xslt_stylesheet",
+ "domxml_xslt_stylesheet_doc",
+ "domxml_xslt_stylesheet_file",
+ "dotnet_load",
+ "doubleval",
+ "drawCurve",
+ "drawCurveTo",
+ "drawLine",
+ "drawLineTo",
+ "dstanchors",
+ "dstofsrcanchors",
+ "dump_file",
+ "dump_mem",
+ "dump_node",
+ "each",
+ "E_ALL",
+ "easter_date",
+ "easter_days",
+ "ebcdic2ascii",
+ "echo",
+ "E_COMPILE_ERROR",
+ "E_COMPILE_WARNING",
+ "E_CORE_ERROR",
+ "E_CORE_WARNING",
+ "E_ERROR",
+ "else",
+ "elseif",
+ "empty",
+ "end",
+ "endfor",
+ "endforeach",
+ "endif",
+ "endswitch",
+ "endwhile",
+ "E_NOTICE",
+ "entities",
+ "_ENV",
+ "E_PARSE",
+ "ereg",
+ "eregi",
+ "eregi_replace",
+ "ereg_replace",
+ "error_log",
+ "error_reporting",
+ "escapeshellarg",
+ "escapeshellcmd",
+ "E_USER_ERROR",
+ "E_USER_NOTICE",
+ "E_USER_WARNING",
+ "eval",
+ "E_WARNING",
+ "exec",
+ "exif_imagetype",
+ "exif_read_data",
+ "exif_thumbnail",
+ "exit",
+ "exp",
+ "explode",
+ "expm1",
+ "extension_loaded",
+ "extract",
+ "ezmlm_hash",
+ "FALSE",
+ "fbsql_affected_rows",
+ "fbsql_autocommit",
+ "fbsql_change_user",
+ "fbsql_close",
+ "fbsql_commit",
+ "fbsql_connect",
+ "fbsql_create_blob",
+ "fbsql_create_clob",
+ "fbsql_create_db",
+ "fbsql_database",
+ "fbsql_database_password",
+ "fbsql_data_seek",
+ "fbsql_db_query",
+ "fbsql_db_status",
+ "fbsql_drop_db",
+ "fbsql_errno",
+ "fbsql_error",
+ "fbsql_fetch_array",
+ "fbsql_fetch_assoc",
+ "fbsql_fetch_field",
+ "fbsql_fetch_lengths",
+ "fbsql_fetch_object",
+ "fbsql_fetch_row",
+ "fbsql_field_flags",
+ "fbsql_field_len",
+ "fbsql_field_name",
+ "fbsql_field_seek",
+ "fbsql_field_table",
+ "fbsql_field_type",
+ "fbsql_free_result",
+ "fbsql_get_autostart_info",
+ "fbsql_hostname",
+ "fbsql_insert_id",
+ "fbsql_list_dbs",
+ "fbsql_list_fields",
+ "fbsql_list_tables",
+ "fbsql_next_result",
+ "fbsql_num_fields",
+ "fbsql_num_rows",
+ "fbsql_password",
+ "fbsql_pconnect",
+ "fbsql_query",
+ "fbsql_read_blob",
+ "fbsql_read_clob",
+ "fbsql_result",
+ "fbsql_rollback",
+ "fbsql_select_db",
+ "fbsql_set_lob_mode",
+ "fbsql_set_transaction",
+ "fbsql_start_db",
+ "fbsql_stop_db",
+ "fbsql_tablename",
+ "fbsql_username",
+ "fbsql_warnings",
+ "fclose",
+ "fdf_add_doc_javascript",
+ "fdf_add_template",
+ "fdf_close",
+ "fdf_create",
+ "fdf_errno",
+ "fdf_error",
+ "fdf_get_ap",
+ "fdf_get_attachment",
+ "fdf_get_encoding",
+ "fdf_get_file",
+ "fdf_get_status",
+ "fdf_get_value",
+ "fdf_get_version",
+ "fdf_header",
+ "fdf_next_field_name",
+ "fdf_open",
+ "fdf_open_string",
+ "fdf_save",
+ "fdf_save_string",
+ "fdf_set_ap",
+ "fdf_set_encoding",
+ "fdf_set_file",
+ "fdf_set_flags",
+ "fdf_set_javascript_action",
+ "fdf_set_opt",
+ "fdf_set_status",
+ "fdf_set_submit_form_action",
+ "fdf_set_target_frame",
+ "fdf_set_value",
+ "fdf_set_version",
+ "feof",
+ "fflush",
+ "fgetc",
+ "fgetcsv",
+ "fgets",
+ "fgetss",
+ "file",
+ "__FILE__",
+ "fileatime",
+ "filectime",
+ "file_exists",
+ "file_get_contents",
+ "filegroup",
+ "fileinode",
+ "filemtime",
+ "fileowner",
+ "fileperms",
+ "filepro",
+ "filepro_fieldcount",
+ "filepro_fieldname",
+ "filepro_fieldtype",
+ "filepro_fieldwidth",
+ "filepro_retrieve",
+ "filepro_rowcount",
+ "_FILES",
+ "filesize",
+ "filetype",
+ "find",
+ "first_child",
+ "floatval",
+ "flock",
+ "floor",
+ "flush",
+ "fmod",
+ "fnmatch",
+ "fopen",
+ "for",
+ "foreach",
+ "fpassthru",
+ "fprintf",
+ "fputs",
+ "fread",
+ "frenchtojd",
+ "fribidi_log2vis",
+ "fscanf",
+ "fseek",
+ "fsockopen",
+ "fstat",
+ "ftell",
+ "ftok",
+ "ftp_cdup",
+ "ftp_chdir",
+ "ftp_close",
+ "ftp_connect",
+ "ftp_delete",
+ "ftp_exec",
+ "ftp_fget",
+ "ftp_fput",
+ "ftp_get",
+ "ftp_get_option",
+ "ftp_login",
+ "ftp_mdtm",
+ "ftp_mkdir",
+ "ftp_nb_continue",
+ "ftp_nb_fget",
+ "ftp_nb_fput",
+ "ftp_nb_get",
+ "ftp_nb_put",
+ "ftp_nlist",
+ "ftp_pasv",
+ "ftp_put",
+ "ftp_pwd",
+ "ftp_quit",
+ "ftp_rawlist",
+ "ftp_rename",
+ "ftp_rmdir",
+ "ftp_set_option",
+ "ftp_site",
+ "ftp_size",
+ "ftp_ssl_connect",
+ "ftp_systype",
+ "ftruncate",
+ "ftstat",
+ "func_get_arg",
+ "func_get_args",
+ "func_num_args",
+ "function",
+ "function_exists",
+ "fwrite",
+ "GATEWAY_INTERFACE",
+ "gd_info",
+ "_GET",
+ "getallheaders",
+ "get_attribute",
+ "get_attribute_node",
+ "get_browser",
+ "get_cfg_var",
+ "get_class",
+ "get_class_methods",
+ "get_class_vars",
+ "get_content",
+ "get_current_user",
+ "getcwd",
+ "getdate",
+ "get_declared_classes",
+ "get_defined_constants",
+ "get_defined_functions",
+ "get_defined_vars",
+ "get_element_by_id",
+ "get_elements_by_tagname",
+ "getenv",
+ "get_extension_funcs",
+ "getHeight",
+ "gethostbyaddr",
+ "gethostbyname",
+ "gethostbynamel",
+ "get_html_translation_table",
+ "getimagesize",
+ "get_included_files",
+ "get_include_path",
+ "getlastmod",
+ "get_loaded_extensions",
+ "get_magic_quotes_gpc",
+ "get_magic_quotes_runtime",
+ "get_meta_tags",
+ "getmxrr",
+ "getmygid",
+ "getmyinode",
+ "getmypid",
+ "getmyuid",
+ "get_object_vars",
+ "getopt",
+ "get_parent_class",
+ "getprotobyname",
+ "getprotobynumber",
+ "getrandmax",
+ "get_required_files",
+ "get_resource_type",
+ "getrusage",
+ "getservbyname",
+ "getservbyport",
+ "getshape1",
+ "getshape2",
+ "gettext",
+ "gettimeofday",
+ "gettype",
+ "getwidth",
+ "getWidth",
+ "glob",
+ "global",
+ "GLOBALS",
+ "gmdate",
+ "gmmktime",
+ "gmp_abs",
+ "gmp_add",
+ "gmp_and",
+ "gmp_clrbit",
+ "gmp_cmp",
+ "gmp_com",
+ "gmp_div",
+ "gmp_divexact",
+ "gmp_div_q",
+ "gmp_div_qr",
+ "gmp_div_r",
+ "gmp_fact",
+ "gmp_gcd",
+ "gmp_gcdext",
+ "gmp_hamdist",
+ "gmp_init",
+ "gmp_intval",
+ "gmp_invert",
+ "gmp_jacobi",
+ "gmp_legendre",
+ "gmp_mod",
+ "gmp_mul",
+ "gmp_neg",
+ "gmp_or",
+ "gmp_perfect_square",
+ "gmp_popcount",
+ "gmp_pow",
+ "gmp_powm",
+ "gmp_prob_prime",
+ "gmp_random",
+ "gmp_scan0",
+ "gmp_scan1",
+ "gmp_setbit",
+ "gmp_sign",
+ "gmp_sqrt",
+ "gmp_sqrtrm",
+ "gmp_strval",
+ "gmp_sub",
+ "gmp_xor",
+ "gmstrftime",
+ "gregoriantojd",
+ "gzclose",
+ "gzcompress",
+ "gzdeflate",
+ "gzencode",
+ "gzeof",
+ "gzfile",
+ "gzgetc",
+ "gzgets",
+ "gzgetss",
+ "gzinflate",
+ "gzopen",
+ "gzpassthru",
+ "gzputs",
+ "gzread",
+ "gzrewind",
+ "gzseek",
+ "gztell",
+ "gzuncompress",
+ "gzwrite",
+ "has_attribute",
+ "has_attributess",
+ "has_child_nodes",
+ "header",
+ "headers_sent",
+ "hebrev",
+ "hebrevc",
+ "hexdec",
+ "highlight_file",
+ "highlight_string",
+ "html_dump_mem",
+ "htmlentities",
+ "html_entity_decode",
+ "htmlspecialchars",
+ "HTTP_ACCEPT",
+ "HTTP_ACCEPT_CHARSET",
+ "HTTP_ACCEPT_LANGUAGE",
+ "HTTP_CONNECTION",
+ "HTTP_COOKIE_VARS",
+ "HTTP_ENCODING",
+ "HTTP_ENV_VARS",
+ "HTTP_GET_VARS",
+ "HTTP_HOST",
+ "HTTP_POST_FILES",
+ "HTTP_POST_VARS",
+ "HTTP_RAW_POST_DATA",
+ "HTTP_REFERER",
+ "HTTP_SERVER_VARS",
+ "HTTP_SESSION_VARS",
+ "HTTP_STATE_VARS",
+ "HTTP_USER_AGENT",
+ "hw_api_attribute",
+ "hw_api_content",
+ "hwapi_hgcsp",
+ "hw_api_object",
+ "hw_Array2Objrec",
+ "hw_changeobject",
+ "hw_Children",
+ "hw_ChildrenObj",
+ "hw_Close",
+ "hw_Connect",
+ "hw_connection_info",
+ "hw_Cp",
+ "hw_Deleteobject",
+ "hw_DocByAnchor",
+ "hw_DocByAnchorObj",
+ "hw_Document_Attributes",
+ "hw_Document_BodyTag",
+ "hw_Document_Content",
+ "hw_Document_SetContent",
+ "hw_Document_Size",
+ "hw_dummy",
+ "hw_EditText",
+ "hw_Error",
+ "hw_ErrorMsg",
+ "hw_Free_Document",
+ "hw_GetAnchors",
+ "hw_GetAnchorsObj",
+ "hw_GetAndLock",
+ "hw_GetChildColl",
+ "hw_GetChildCollObj",
+ "hw_GetChildDocColl",
+ "hw_GetChildDocCollObj",
+ "hw_GetObject",
+ "hw_GetObjectByQuery",
+ "hw_GetObjectByQueryColl",
+ "hw_GetObjectByQueryCollObj",
+ "hw_GetObjectByQueryObj",
+ "hw_GetParents",
+ "hw_GetParentsObj",
+ "hw_getrellink",
+ "hw_GetRemote",
+ "hw_GetRemoteChildren",
+ "hw_GetSrcByDestObj",
+ "hw_GetText",
+ "hw_getusername",
+ "hw_Identify",
+ "hw_InCollections",
+ "hw_Info",
+ "hw_InsColl",
+ "hw_InsDoc",
+ "hw_insertanchors",
+ "hw_InsertDocument",
+ "hw_InsertObject",
+ "hw_mapid",
+ "hw_Modifyobject",
+ "hw_Mv",
+ "hw_New_Document",
+ "hw_Objrec2Array",
+ "hw_Output_Document",
+ "hw_pConnect",
+ "hw_PipeDocument",
+ "hw_Root",
+ "hw_setlinkroot",
+ "hw_stat",
+ "hwstat",
+ "hw_Unlock",
+ "hw_Who",
+ "hypot",
+ "ibase_blob_add",
+ "ibase_blob_cancel",
+ "ibase_blob_close",
+ "ibase_blob_create",
+ "ibase_blob_echo",
+ "ibase_blob_get",
+ "ibase_blob_import",
+ "ibase_blob_info",
+ "ibase_blob_open",
+ "ibase_close",
+ "ibase_commit",
+ "ibase_connect",
+ "ibase_errmsg",
+ "ibase_execute",
+ "ibase_fetch_object",
+ "ibase_fetch_row",
+ "ibase_field_info",
+ "ibase_free_query",
+ "ibase_free_result",
+ "ibase_num_fields",
+ "ibase_pconnect",
+ "ibase_prepare",
+ "ibase_query",
+ "ibase_rollback",
+ "ibase_timefmt",
+ "ibase_trans",
+ "iconv",
+ "iconv_get_encoding",
+ "iconv_set_encoding",
+ "identify",
+ "if",
+ "ifx_affected_rows",
+ "ifx_blobinfile_mode",
+ "ifx_byteasvarchar",
+ "ifx_close",
+ "ifx_connect",
+ "ifx_copy_blob",
+ "ifx_create_blob",
+ "ifx_create_char",
+ "ifx_do",
+ "ifx_error",
+ "ifx_errormsg",
+ "ifx_fetch_row",
+ "ifx_fieldproperties",
+ "ifx_fieldtypes",
+ "ifx_free_blob",
+ "ifx_free_char",
+ "ifx_free_result",
+ "ifx_get_blob",
+ "ifx_get_char",
+ "ifx_getsqlca",
+ "ifx_htmltbl_result",
+ "ifx_nullformat",
+ "ifx_num_fields",
+ "ifx_num_rows",
+ "ifx_pconnect",
+ "ifx_prepare",
+ "ifx_query",
+ "ifx_textasvarchar",
+ "ifx_update_blob",
+ "ifx_update_char",
+ "ifxus_close_slob",
+ "ifxus_create_slob",
+ "ifxus_free_slob",
+ "ifxus_open_slob",
+ "ifxus_read_slob",
+ "ifxus_seek_slob",
+ "ifxus_tell_slob",
+ "ifxus_write_slob",
+ "ignore_user_abort",
+ "image2wbmp",
+ "imagealphablending",
+ "imagearc",
+ "imagechar",
+ "imagecharup",
+ "imagecolorallocate",
+ "imagecolorallocatealpha",
+ "imagecolorat",
+ "imagecolorclosest",
+ "imagecolorclosestalpha",
+ "imagecolorclosesthwb",
+ "imagecolordeallocate",
+ "imagecolorexact",
+ "imagecolorexactalpha",
+ "imagecolorresolve",
+ "imagecolorresolvealpha",
+ "imagecolorset",
+ "imagecolorsforindex",
+ "imagecolorstotal",
+ "imagecolortransparent",
+ "imagecopy",
+ "imagecopymerge",
+ "imagecopymergegray",
+ "imagecopyresampled",
+ "imagecopyresized",
+ "imagecreate",
+ "imagecreatefromgd",
+ "imagecreatefromgd2",
+ "imagecreatefromgd2part",
+ "imagecreatefromgif",
+ "imagecreatefromjpeg",
+ "imagecreatefrompng",
+ "imagecreatefromstring",
+ "imagecreatefromwbmp",
+ "imagecreatefromxbm",
+ "imagecreatefromxpm",
+ "imagecreatetruecolor",
+ "imagedashedline",
+ "imagedestroy",
+ "imageellipse",
+ "imagefill",
+ "imagefilledarc",
+ "imagefilledellipse",
+ "imagefilledpolygon",
+ "imagefilledrectangle",
+ "imagefilltoborder",
+ "imagefontheight",
+ "imagefontwidth",
+ "imageftbbox",
+ "imagefttext",
+ "imagegammacorrect",
+ "imagegd",
+ "imagegd2",
+ "imagegif",
+ "imageinterlace",
+ "imagejpeg",
+ "imageline",
+ "imageloadfont",
+ "imagepalettecopy",
+ "imagepng",
+ "imagepolygon",
+ "imagepsbbox",
+ "imagepscopyfont",
+ "imagepsencodefont",
+ "imagepsextendfont",
+ "imagepsfreefont",
+ "imagepsloadfont",
+ "imagepsslantfont",
+ "imagepstext",
+ "imagerectangle",
+ "imagerotate",
+ "imagesetbrush",
+ "imagesetpixel",
+ "imagesetstyle",
+ "imagesetthickness",
+ "imagesettile",
+ "imagestring",
+ "imagestringup",
+ "imagesx",
+ "imagesy",
+ "imagetruecolortopalette",
+ "imagettfbbox",
+ "imagettftext",
+ "imagetypes",
+ "image_type_to_mime_type",
+ "imagewbmp",
+ "imap_8bit",
+ "imap_alerts",
+ "imap_append",
+ "imap_base64",
+ "imap_binary",
+ "imap_body",
+ "imap_bodystruct",
+ "imap_check",
+ "imap_clearflag_full",
+ "imap_close",
+ "imap_createmailbox",
+ "imap_delete",
+ "imap_deletemailbox",
+ "imap_errors",
+ "imap_expunge",
+ "imap_fetchbody",
+ "imap_fetchheader",
+ "imap_fetch_overview",
+ "imap_fetchstructure",
+ "imap_getmailboxes",
+ "imap_get_quota",
+ "imap_get_quotaroot",
+ "imap_getsubscribed",
+ "imap_header",
+ "imap_headerinfo",
+ "imap_headers",
+ "imap_last_error",
+ "imap_list",
+ "imap_listmailbox",
+ "imap_listscan",
+ "imap_listsubscribed",
+ "imap_lsub",
+ "imap_mail",
+ "imap_mailboxmsginfo",
+ "imap_mail_compose",
+ "imap_mail_copy",
+ "imap_mail_move",
+ "imap_mime_header_decode",
+ "imap_msgno",
+ "imap_num_msg",
+ "imap_num_recent",
+ "imap_open",
+ "imap_ping",
+ "imap_qprint",
+ "imap_renamemailbox",
+ "imap_reopen",
+ "imap_rfc822_parse_adrlist",
+ "imap_rfc822_parse_headers",
+ "imap_rfc822_write_address",
+ "imap_scanmailbox",
+ "imap_search",
+ "imap_setacl",
+ "imap_setflag_full",
+ "imap_set_quota",
+ "imap_sort",
+ "imap_status",
+ "imap_subscribe",
+ "imap_thread",
+ "imap_uid",
+ "imap_undelete",
+ "imap_unsubscribe",
+ "imap_utf7_decode",
+ "imap_utf7_encode",
+ "imap_utf8",
+ "implode",
+ "import_request_variables",
+ "in_array",
+ "include",
+ "include_once",
+ "info",
+ "ingres_autocommit",
+ "ingres_close",
+ "ingres_commit",
+ "ingres_connect",
+ "ingres_fetch_array",
+ "ingres_fetch_object",
+ "ingres_fetch_row",
+ "ingres_field_length",
+ "ingres_field_name",
+ "ingres_field_nullable",
+ "ingres_field_precision",
+ "ingres_field_scale",
+ "ingres_field_type",
+ "ingres_num_fields",
+ "ingres_num_rows",
+ "ingres_pconnect",
+ "ingres_query",
+ "ingres_rollback",
+ "ini_alter",
+ "ini_get",
+ "ini_get_all",
+ "ini_restore",
+ "ini_set",
+ "insert",
+ "insertanchor",
+ "insert_before",
+ "insertcollection",
+ "insertdocument",
+ "int",
+ "internal_subset",
+ "intval",
+ "ip2long",
+ "iptcembed",
+ "iptcparse",
+ "ircg_channel_mode",
+ "ircg_disconnect",
+ "ircg_fetch_error_msg",
+ "ircg_get_username",
+ "ircg_html_encode",
+ "ircg_ignore_add",
+ "ircg_ignore_del",
+ "ircg_is_conn_alive",
+ "ircg_join",
+ "ircg_kick",
+ "ircg_lookup_format_messages",
+ "ircg_msg",
+ "ircg_nick",
+ "ircg_nickname_escape",
+ "ircg_nickname_unescape",
+ "ircg_notice",
+ "ircg_part",
+ "ircg_pconnect",
+ "ircg_register_format_messages",
+ "ircg_set_current",
+ "ircg_set_file",
+ "ircg_set_on_die",
+ "ircg_topic",
+ "ircg_whois",
+ "is_a",
+ "is_array",
+ "is_blank_node",
+ "is_bool",
+ "is_callable",
+ "is_dir",
+ "is_double",
+ "is_executable",
+ "is_file",
+ "is_finite",
+ "is_float",
+ "is_infinite",
+ "is_int",
+ "is_integer",
+ "is_link",
+ "is_long",
+ "is_nan",
+ "is_null",
+ "is_numeric",
+ "is_object",
+ "is_readable",
+ "is_real",
+ "is_resource",
+ "is_scalar",
+ "isset",
+ "is_string",
+ "is_subclass_of",
+ "is_uploaded_file",
+ "is_writable",
+ "is_writeable",
+ "java_last_exception_clear",
+ "java_last_exception_get",
+ "jddayofweek",
+ "jdmonthname",
+ "jdtofrench",
+ "jdtogregorian",
+ "jdtojewish",
+ "jdtojulian",
+ "jdtounix",
+ "jewishtojd",
+ "join",
+ "jpeg2wbmp",
+ "juliantojd",
+ "key",
+ "krsort",
+ "ksort",
+ "langdepvalue",
+ "last_child",
+ "lcg_value",
+ "ldap_8859_to_t61",
+ "ldap_add",
+ "ldap_bind",
+ "ldap_close",
+ "ldap_compare",
+ "ldap_connect",
+ "ldap_count_entries",
+ "ldap_delete",
+ "ldap_dn2ufn",
+ "ldap_err2str",
+ "ldap_errno",
+ "ldap_error",
+ "ldap_explode_dn",
+ "ldap_first_attribute",
+ "ldap_first_entry",
+ "ldap_first_reference",
+ "ldap_free_result",
+ "ldap_get_attributes",
+ "ldap_get_dn",
+ "ldap_get_entries",
+ "ldap_get_option",
+ "ldap_get_values",
+ "ldap_get_values_len",
+ "ldap_list",
+ "ldap_mod_add",
+ "ldap_mod_del",
+ "ldap_modify",
+ "ldap_mod_replace",
+ "ldap_next_attribute",
+ "ldap_next_entry",
+ "ldap_next_reference",
+ "ldap_parse_reference",
+ "ldap_parse_result",
+ "ldap_read",
+ "ldap_rename",
+ "ldap_search",
+ "ldap_set_option",
+ "ldap_set_rebind_proc",
+ "ldap_sort",
+ "ldap_start_tls",
+ "ldap_t61_to_8859",
+ "ldap_unbind",
+ "levenshtein",
+ "__LINE__",
+ "link",
+ "linkinfo",
+ "list",
+ "localeconv",
+ "localtime",
+ "lock",
+ "log",
+ "log10",
+ "log1p",
+ "long2ip",
+ "lstat",
+ "ltrim",
+ "mail",
+ "mailparse_determine_best_xfer_encoding",
+ "mailparse_msg_create",
+ "mailparse_msg_extract_part",
+ "mailparse_msg_extract_part_file",
+ "mailparse_msg_free",
+ "mailparse_msg_get_part",
+ "mailparse_msg_get_part_data",
+ "mailparse_msg_get_structure",
+ "mailparse_msg_parse",
+ "mailparse_msg_parse_file",
+ "mailparse_rfc822_parse_addresses",
+ "mailparse_stream_encode",
+ "mailparse_uudecode_all",
+ "main",
+ "max",
+ "mb_convert_case",
+ "mb_convert_encoding",
+ "mb_convert_kana",
+ "mb_convert_variables",
+ "mb_decode_mimeheader",
+ "mb_decode_numericentity",
+ "mb_detect_encoding",
+ "mb_detect_order",
+ "mb_encode_mimeheader",
+ "mb_encode_numericentity",
+ "mb_ereg",
+ "mb_eregi",
+ "mb_eregi_replace",
+ "mb_ereg_match",
+ "mb_ereg_replace",
+ "mb_ereg_search",
+ "mb_ereg_search_getpos",
+ "mb_ereg_search_getregs",
+ "mb_ereg_search_init",
+ "mb_ereg_search_pos",
+ "mb_ereg_search_regs",
+ "mb_ereg_search_setpos",
+ "mb_get_info",
+ "mb_http_input",
+ "mb_http_output",
+ "mb_internal_encoding",
+ "mb_language",
+ "mb_output_handler",
+ "mb_parse_str",
+ "mb_preferred_mime_name",
+ "mb_regex_encoding",
+ "mb_regex_set_options",
+ "mb_send_mail",
+ "mb_split",
+ "mb_strcut",
+ "mb_strimwidth",
+ "mb_strlen",
+ "mb_strpos",
+ "mb_strrpos",
+ "mb_strtolower",
+ "mb_strtoupper",
+ "mb_strwidth",
+ "mb_substitute_character",
+ "mb_substr",
+ "mb_substr_count",
+ "mcal_append_event",
+ "mcal_close",
+ "mcal_create_calendar",
+ "mcal_date_compare",
+ "mcal_date_valid",
+ "mcal_day_of_week",
+ "mcal_day_of_year",
+ "mcal_days_in_month",
+ "mcal_delete_calendar",
+ "mcal_delete_event",
+ "mcal_event_add_attribute",
+ "mcal_event_init",
+ "mcal_event_set_alarm",
+ "mcal_event_set_category",
+ "mcal_event_set_class",
+ "mcal_event_set_description",
+ "mcal_event_set_end",
+ "mcal_event_set_recur_daily",
+ "mcal_event_set_recur_monthly_mday",
+ "mcal_event_set_recur_monthly_wday",
+ "mcal_event_set_recur_none",
+ "mcal_event_set_recur_weekly",
+ "mcal_event_set_recur_yearly",
+ "mcal_event_set_start",
+ "mcal_event_set_title",
+ "mcal_expunge",
+ "mcal_fetch_current_stream_event",
+ "mcal_fetch_event",
+ "mcal_is_leap_year",
+ "mcal_list_alarms",
+ "mcal_list_events",
+ "mcal_next_recurrence",
+ "mcal_open",
+ "mcal_popen",
+ "mcal_rename_calendar",
+ "mcal_reopen",
+ "mcal_snooze",
+ "mcal_store_event",
+ "mcal_time_valid",
+ "mcal_week_of_year",
+ "mcrypt_cbc",
+ "mcrypt_cfb",
+ "mcrypt_create_iv",
+ "mcrypt_decrypt",
+ "mcrypt_ecb",
+ "mcrypt_enc_get_algorithms_name",
+ "mcrypt_enc_get_block_size",
+ "mcrypt_enc_get_iv_size",
+ "mcrypt_enc_get_key_size",
+ "mcrypt_enc_get_modes_name",
+ "mcrypt_enc_get_supported_key_sizes",
+ "mcrypt_enc_is_block_algorithm",
+ "mcrypt_enc_is_block_algorithm_mode",
+ "mcrypt_enc_is_block_mode",
+ "mcrypt_encrypt",
+ "mcrypt_enc_self_test",
+ "mcrypt_generic",
+ "mcrypt_generic_deinit",
+ "mcrypt_generic_end",
+ "mcrypt_generic_init",
+ "mcrypt_get_block_size",
+ "mcrypt_get_cipher_name",
+ "mcrypt_get_iv_size",
+ "mcrypt_get_key_size",
+ "mcrypt_list_algorithms",
+ "mcrypt_list_modes",
+ "mcrypt_module_close",
+ "mcrypt_module_get_algo_block_size",
+ "mcrypt_module_get_algo_key_size",
+ "mcrypt_module_get_supported_key_sizes",
+ "mcrypt_module_is_block_algorithm",
+ "mcrypt_module_is_block_algorithm_mode",
+ "mcrypt_module_is_block_mode",
+ "mcrypt_module_open",
+ "mcrypt_module_self_test",
+ "mcrypt_ofb",
+ "mcve_adduser",
+ "mcve_adduserarg",
+ "mcve_bt",
+ "mcve_checkstatus",
+ "mcve_chkpwd",
+ "mcve_chngpwd",
+ "mcve_completeauthorizations",
+ "mcve_connect",
+ "mcve_connectionerror",
+ "mcve_deleteresponse",
+ "mcve_deletetrans",
+ "mcve_deleteusersetup",
+ "mcve_deluser",
+ "mcve_destroyconn",
+ "mcve_destroyengine",
+ "mcve_disableuser",
+ "mcve_edituser",
+ "mcve_enableuser",
+ "mcve_force",
+ "mcve_getcell",
+ "mcve_getcellbynum",
+ "mcve_getcommadelimited",
+ "mcve_getheader",
+ "mcve_getuserarg",
+ "mcve_getuserparam",
+ "mcve_gft",
+ "mcve_gl",
+ "mcve_gut",
+ "mcve_initconn",
+ "mcve_initengine",
+ "mcve_initusersetup",
+ "mcve_iscommadelimited",
+ "mcve_liststats",
+ "mcve_listusers",
+ "mcve_maxconntimeout",
+ "mcve_monitor",
+ "mcve_numcolumns",
+ "mcve_numrows",
+ "mcve_override",
+ "mcve_parsecommadelimited",
+ "mcve_ping",
+ "mcve_preauth",
+ "mcve_preauthcompletion",
+ "mcve_qc",
+ "mcve_responseparam",
+ "mcve_return",
+ "mcve_returncode",
+ "mcve_returnstatus",
+ "mcve_sale",
+ "mcve_setblocking",
+ "mcve_setdropfile",
+ "mcve_setip",
+ "mcve_setssl",
+ "mcve_settimeout",
+ "mcve_settle",
+ "mcve_text_avs",
+ "mcve_text_code",
+ "mcve_text_cv",
+ "mcve_transactionauth",
+ "mcve_transactionavs",
+ "mcve_transactionbatch",
+ "mcve_transactioncv",
+ "mcve_transactionid",
+ "mcve_transactionitem",
+ "mcve_transactionssent",
+ "mcve_transactiontext",
+ "mcve_transinqueue",
+ "mcve_transnew",
+ "mcve_transparam",
+ "mcve_transsend",
+ "mcve_ub",
+ "mcve_uwait",
+ "mcve_verifyconnection",
+ "mcve_verifysslcert",
+ "mcve_void",
+ "md5",
+ "md5_file",
+ "mdecrypt_generic",
+ "memory_get_usage",
+ "metaphone",
+ "method_exists",
+ "mhash",
+ "mhash_count",
+ "mhash_get_block_size",
+ "mhash_get_hash_name",
+ "mhash_keygen_s2k",
+ "microtime",
+ "mime_content_type",
+ "mimetype",
+ "min",
+ "ming_setcubicthreshold",
+ "ming_setscale",
+ "ming_useswfversion",
+ "mkdir",
+ "mktime",
+ "money_format",
+ "move",
+ "movePen",
+ "movePenTo",
+ "moveTo",
+ "move_uploaded_file",
+ "msession_connect",
+ "msession_count",
+ "msession_create",
+ "msession_destroy",
+ "msession_disconnect",
+ "msession_find",
+ "msession_get",
+ "msession_get_array",
+ "msession_getdata",
+ "msession_inc",
+ "msession_list",
+ "msession_listvar",
+ "msession_lock",
+ "msession_plugin",
+ "msession_randstr",
+ "msession_set",
+ "msession_set_array",
+ "msession_setdata",
+ "msession_timeout",
+ "msession_uniq",
+ "msession_unlock",
+ "msg_get_queue",
+ "msg_receive",
+ "msg_remove_queue",
+ "msg_send",
+ "msg_set_queue",
+ "msg_stat_queue",
+ "msql",
+ "msql_affected_rows",
+ "msql_close",
+ "msql_connect",
+ "msql_create_db",
+ "msql_createdb",
+ "msql_data_seek",
+ "msql_dbname",
+ "msql_drop_db",
+ "msql_dropdb",
+ "msql_error",
+ "msql_fetch_array",
+ "msql_fetch_field",
+ "msql_fetch_object",
+ "msql_fetch_row",
+ "msql_fieldflags",
+ "msql_fieldlen",
+ "msql_fieldname",
+ "msql_field_seek",
+ "msql_fieldtable",
+ "msql_fieldtype",
+ "msql_free_result",
+ "msql_freeresult",
+ "msql_list_dbs",
+ "msql_listdbs",
+ "msql_list_fields",
+ "msql_listfields",
+ "msql_list_tables",
+ "msql_listtables",
+ "msql_num_fields",
+ "msql_numfields",
+ "msql_num_rows",
+ "msql_numrows",
+ "msql_pconnect",
+ "msql_query",
+ "msql_regcase",
+ "msql_result",
+ "msql_select_db",
+ "msql_selectdb",
+ "msql_tablename",
+ "mssql_bind",
+ "mssql_close",
+ "mssql_connect",
+ "mssql_data_seek",
+ "mssql_execute",
+ "mssql_fetch_array",
+ "mssql_fetch_assoc",
+ "mssql_fetch_batch",
+ "mssql_fetch_field",
+ "mssql_fetch_object",
+ "mssql_fetch_row",
+ "mssql_field_length",
+ "mssql_field_name",
+ "mssql_field_seek",
+ "mssql_field_type",
+ "mssql_free_result",
+ "mssql_free_statement",
+ "mssql_get_last_message",
+ "mssql_guid_string",
+ "mssql_init",
+ "mssql_min_error_severity",
+ "mssql_min_message_severity",
+ "mssql_next_result",
+ "mssql_num_fields",
+ "mssql_num_rows",
+ "mssql_pconnect",
+ "mssql_query",
+ "mssql_result",
+ "mssql_rows_affected",
+ "mssql_select_db",
+ "mt_getrandmax",
+ "mt_rand",
+ "mt_srand",
+ "multColor",
+ "muscat_close",
+ "muscat_get",
+ "muscat_give",
+ "muscat_setup",
+ "muscat_setup_net",
+ "mysql_affected_rows",
+ "mysql_change_user",
+ "mysql_client_encoding",
+ "mysql_close",
+ "mysql_connect",
+ "mysql_create_db",
+ "mysql_data_seek",
+ "mysql_db_name",
+ "mysql_db_query",
+ "mysql_drop_db",
+ "mysql_errno",
+ "mysql_error",
+ "mysql_escape_string",
+ "mysql_fetch_array",
+ "mysql_fetch_assoc",
+ "mysql_fetch_field",
+ "mysql_fetch_lengths",
+ "mysql_fetch_object",
+ "mysql_fetch_row",
+ "mysql_field_flags",
+ "mysql_field_len",
+ "mysql_field_name",
+ "mysql_field_seek",
+ "mysql_field_table",
+ "mysql_field_type",
+ "mysql_free_result",
+ "mysql_get_client_info",
+ "mysql_get_host_info",
+ "mysql_get_proto_info",
+ "mysql_get_server_info",
+ "mysql_info",
+ "mysql_insert_id",
+ "mysql_list_dbs",
+ "mysql_list_fields",
+ "mysql_list_processes",
+ "mysql_list_tables",
+ "mysql_num_fields",
+ "mysql_num_rows",
+ "mysql_pconnect",
+ "mysql_ping",
+ "mysql_query",
+ "mysql_real_escape_string",
+ "mysql_result",
+ "mysql_select_db",
+ "mysql_stat",
+ "mysql_tablename",
+ "mysql_thread_id",
+ "mysql_unbuffered_query",
+ "name",
+ "natcasesort",
+ "natsort",
+ "ncurses_addch",
+ "ncurses_addchnstr",
+ "ncurses_addchstr",
+ "ncurses_addnstr",
+ "ncurses_addstr",
+ "ncurses_assume_default_colors",
+ "ncurses_attroff",
+ "ncurses_attron",
+ "ncurses_attrset",
+ "ncurses_baudrate",
+ "ncurses_beep",
+ "ncurses_bkgd",
+ "ncurses_bkgdset",
+ "ncurses_border",
+ "ncurses_can_change_color",
+ "ncurses_cbreak",
+ "ncurses_clear",
+ "ncurses_clrtobot",
+ "ncurses_clrtoeol",
+ "ncurses_color_set",
+ "ncurses_curs_set",
+ "ncurses_define_key",
+ "ncurses_def_prog_mode",
+ "ncurses_def_shell_mode",
+ "ncurses_delay_output",
+ "ncurses_delch",
+ "ncurses_deleteln",
+ "ncurses_delwin",
+ "ncurses_doupdate",
+ "ncurses_echo",
+ "ncurses_echochar",
+ "ncurses_end",
+ "ncurses_erase",
+ "ncurses_erasechar",
+ "ncurses_filter",
+ "ncurses_flash",
+ "ncurses_flushinp",
+ "ncurses_getch",
+ "ncurses_getmouse",
+ "ncurses_halfdelay",
+ "ncurses_has_colors",
+ "ncurses_has_ic",
+ "ncurses_has_il",
+ "ncurses_has_key",
+ "ncurses_hline",
+ "ncurses_inch",
+ "ncurses_init",
+ "ncurses_init_color",
+ "ncurses_init_pair",
+ "ncurses_insch",
+ "ncurses_insdelln",
+ "ncurses_insertln",
+ "ncurses_insstr",
+ "ncurses_instr",
+ "ncurses_isendwin",
+ "ncurses_keyok",
+ "ncurses_killchar",
+ "ncurses_longname",
+ "ncurses_mouseinterval",
+ "ncurses_mousemask",
+ "ncurses_move",
+ "ncurses_mvaddch",
+ "ncurses_mvaddchnstr",
+ "ncurses_mvaddchstr",
+ "ncurses_mvaddnstr",
+ "ncurses_mvaddstr",
+ "ncurses_mvcur",
+ "ncurses_mvdelch",
+ "ncurses_mvgetch",
+ "ncurses_mvhline",
+ "ncurses_mvinch",
+ "ncurses_mvvline",
+ "ncurses_mvwaddstr",
+ "ncurses_napms",
+ "ncurses_newwin",
+ "ncurses_nl",
+ "ncurses_nocbreak",
+ "ncurses_noecho",
+ "ncurses_nonl",
+ "ncurses_noqiflush",
+ "ncurses_noraw",
+ "ncurses_putp",
+ "ncurses_qiflush",
+ "ncurses_raw",
+ "ncurses_refresh",
+ "ncurses_resetty",
+ "ncurses_savetty",
+ "ncurses_scr_dump",
+ "ncurses_scr_init",
+ "ncurses_scrl",
+ "ncurses_scr_restore",
+ "ncurses_scr_set",
+ "ncurses_slk_attr",
+ "ncurses_slk_attroff",
+ "ncurses_slk_attron",
+ "ncurses_slk_attrset",
+ "ncurses_slk_clear",
+ "ncurses_slk_color",
+ "ncurses_slk_init",
+ "ncurses_slk_noutrefresh",
+ "ncurses_slk_refresh",
+ "ncurses_slk_restore",
+ "ncurses_slk_touch",
+ "ncurses_standend",
+ "ncurses_standout",
+ "ncurses_start_color",
+ "ncurses_termattrs",
+ "ncurses_termname",
+ "ncurses_timeout",
+ "ncurses_typeahead",
+ "ncurses_ungetch",
+ "ncurses_ungetmouse",
+ "ncurses_use_default_colors",
+ "ncurses_use_env",
+ "ncurses_use_extended_names",
+ "ncurses_vidattr",
+ "ncurses_vline",
+ "ncurses_wrefresh",
+ "new",
+ "next",
+ "nextframe",
+ "next_sibling",
+ "ngettext",
+ "nl2br",
+ "nl_langinfo",
+ "node_name",
+ "node_type",
+ "node_value",
+ "notations",
+ "notes_body",
+ "notes_copy_db",
+ "notes_create_db",
+ "notes_create_note",
+ "notes_drop_db",
+ "notes_find_note",
+ "notes_header_info",
+ "notes_list_msgs",
+ "notes_mark_read",
+ "notes_mark_unread",
+ "notes_nav_create",
+ "notes_search",
+ "notes_unread",
+ "notes_version",
+ "NULL",
+ "number_format",
+ "ob_clean",
+ "ob_end_clean",
+ "ob_end_flush",
+ "ob_flush",
+ "ob_get_contents",
+ "ob_get_length",
+ "ob_get_level",
+ "ob_get_status",
+ "ob_gzhandler",
+ "ob_iconv_handler",
+ "ob_implicit_flush",
+ "object",
+ "objectbyanchor",
+ "ob_start",
+ "ocibindbyname",
+ "ocicancel",
+ "OCICollAppend",
+ "ocicollassign",
+ "ocicollassignelem",
+ "ocicollgetelem",
+ "ocicollmax",
+ "ocicollsize",
+ "ocicolltrim",
+ "ocicolumnisnull",
+ "ocicolumnname",
+ "ocicolumnprecision",
+ "ocicolumnscale",
+ "ocicolumnsize",
+ "ocicolumntype",
+ "ocicolumntyperaw",
+ "ocicommit",
+ "ocidefinebyname",
+ "ocierror",
+ "ociexecute",
+ "ocifetch",
+ "ocifetchinto",
+ "ocifetchstatement",
+ "ocifreecollection",
+ "ocifreecursor",
+ "OCIFreeDesc",
+ "ocifreestatement",
+ "ociinternaldebug",
+ "ociloadlob",
+ "ocilogoff",
+ "ocilogon",
+ "ocinewcollection",
+ "ocinewcursor",
+ "ocinewdescriptor",
+ "ocinlogon",
+ "ocinumcols",
+ "ociparse",
+ "ociplogon",
+ "ociresult",
+ "ocirollback",
+ "ocirowcount",
+ "ocisavelob",
+ "ocisavelobfile",
+ "ociserverversion",
+ "ocisetprefetch",
+ "ocistatementtype",
+ "ociwritelobtofile",
+ "octdec",
+ "odbc_autocommit",
+ "odbc_binmode",
+ "odbc_close",
+ "odbc_close_all",
+ "odbc_columnprivileges",
+ "odbc_columns",
+ "odbc_commit",
+ "odbc_connect",
+ "odbc_cursor",
+ "odbc_data_source",
+ "odbc_do",
+ "odbc_error",
+ "odbc_errormsg",
+ "odbc_exec",
+ "odbc_execute",
+ "odbc_fetch_array",
+ "odbc_fetch_into",
+ "odbc_fetch_object",
+ "odbc_fetch_row",
+ "odbc_field_len",
+ "odbc_field_name",
+ "odbc_field_num",
+ "odbc_field_precision",
+ "odbc_field_scale",
+ "odbc_field_type",
+ "odbc_foreignkeys",
+ "odbc_free_result",
+ "odbc_gettypeinfo",
+ "odbc_longreadlen",
+ "odbc_next_result",
+ "odbc_num_fields",
+ "odbc_num_rows",
+ "odbc_pconnect",
+ "odbc_prepare",
+ "odbc_primarykeys",
+ "odbc_procedurecolumns",
+ "odbc_procedures",
+ "odbc_result",
+ "odbc_result_all",
+ "odbc_rollback",
+ "odbc_setoption",
+ "odbc_specialcolumns",
+ "odbc_statistics",
+ "odbc_tableprivileges",
+ "odbc_tables",
+ "opendir",
+ "openlog",
+ "openssl_csr_export",
+ "openssl_csr_export_to_file",
+ "openssl_csr_new",
+ "openssl_csr_sign",
+ "openssl_error_string",
+ "openssl_free_key",
+ "openssl_get_privatekey",
+ "openssl_get_publickey",
+ "openssl_open",
+ "openssl_pkcs7_decrypt",
+ "openssl_pkcs7_encrypt",
+ "openssl_pkcs7_sign",
+ "openssl_pkcs7_verify",
+ "openssl_pkey_export",
+ "openssl_pkey_export_to_file",
+ "openssl_pkey_get_private",
+ "openssl_pkey_get_public",
+ "openssl_pkey_new",
+ "openssl_private_decrypt",
+ "openssl_private_encrypt",
+ "openssl_public_decrypt",
+ "openssl_public_encrypt",
+ "openssl_seal",
+ "openssl_sign",
+ "openssl_verify",
+ "openssl_x509_check_private_key",
+ "openssl_x509_checkpurpose",
+ "openssl_x509_export",
+ "openssl_x509_export_to_file",
+ "openssl_x509_free",
+ "openssl_x509_parse",
+ "openssl_x509_read",
+ "ora_bind",
+ "ora_close",
+ "ora_columnname",
+ "ora_columnsize",
+ "ora_columntype",
+ "ora_commit",
+ "ora_commitoff",
+ "ora_commiton",
+ "ora_do",
+ "ora_error",
+ "ora_errorcode",
+ "ora_exec",
+ "ora_fetch",
+ "ora_fetch_into",
+ "ora_getcolumn",
+ "ora_logoff",
+ "ora_logon",
+ "ora_numcols",
+ "ora_numrows",
+ "ora_open",
+ "ora_parse",
+ "ora_plogon",
+ "ora_rollback",
+ "ord",
+ "output",
+ "overload",
+ "ovrimos_close",
+ "ovrimos_commit",
+ "ovrimos_connect",
+ "ovrimos_cursor",
+ "ovrimos_exec",
+ "ovrimos_execute",
+ "ovrimos_fetch_into",
+ "ovrimos_fetch_row",
+ "ovrimos_field_len",
+ "ovrimos_field_name",
+ "ovrimos_field_num",
+ "ovrimos_field_type",
+ "ovrimos_free_result",
+ "ovrimos_longreadlen",
+ "ovrimos_num_fields",
+ "ovrimos_num_rows",
+ "ovrimos_prepare",
+ "ovrimos_result",
+ "ovrimos_result_all",
+ "ovrimos_rollback",
+ "owner_document",
+ "pack",
+ "parent_node",
+ "parents",
+ "parse_ini_file",
+ "parse_str",
+ "parse_url",
+ "passthru",
+ "pathinfo",
+ "PATH_TRANSLATED",
+ "pclose",
+ "pcntl_exec",
+ "pcntl_fork",
+ "pcntl_signal",
+ "pcntl_waitpid",
+ "pcntl_wexitstatus",
+ "pcntl_wifexited",
+ "pcntl_wifsignaled",
+ "pcntl_wifstopped",
+ "pcntl_wstopsig",
+ "pcntl_wtermsig",
+ "pdf_add_annotation",
+ "pdf_add_bookmark",
+ "pdf_add_launchlink",
+ "pdf_add_locallink",
+ "pdf_add_note",
+ "pdf_add_outline",
+ "pdf_add_pdflink",
+ "pdf_add_thumbnail",
+ "pdf_add_weblink",
+ "pdf_arc",
+ "pdf_arcn",
+ "pdf_attach_file",
+ "pdf_begin_page",
+ "pdf_begin_pattern",
+ "pdf_begin_template",
+ "pdf_circle",
+ "pdf_clip",
+ "pdf_close",
+ "pdf_close_image",
+ "pdf_closepath",
+ "pdf_closepath_fill_stroke",
+ "pdf_closepath_stroke",
+ "pdf_close_pdi",
+ "pdf_close_pdi_page",
+ "pdf_concat",
+ "pdf_continue_text",
+ "pdf_curveto",
+ "pdf_delete",
+ "pdf_end_page",
+ "pdf_endpath",
+ "pdf_end_pattern",
+ "pdf_end_template",
+ "pdf_fill",
+ "pdf_fill_stroke",
+ "pdf_findfont",
+ "pdf_get_buffer",
+ "pdf_get_font",
+ "pdf_get_fontname",
+ "pdf_get_fontsize",
+ "pdf_get_image_height",
+ "pdf_get_image_width",
+ "pdf_get_majorversion",
+ "pdf_get_minorversion",
+ "pdf_get_parameter",
+ "pdf_get_pdi_parameter",
+ "pdf_get_pdi_value",
+ "pdf_get_value",
+ "pdf_initgraphics",
+ "pdf_lineto",
+ "pdf_makespotcolor",
+ "pdf_moveto",
+ "pdf_new",
+ "pdf_open",
+ "pdf_open_CCITT",
+ "pdf_open_file",
+ "pdf_open_gif",
+ "pdf_open_image",
+ "pdf_open_image_file",
+ "pdf_open_jpeg",
+ "pdf_open_memory_image",
+ "pdf_open_pdi",
+ "pdf_open_pdi_page",
+ "pdf_open_png",
+ "pdf_open_tiff",
+ "pdf_place_image",
+ "pdf_place_pdi_page",
+ "pdf_rect",
+ "pdf_restore",
+ "pdf_rotate",
+ "pdf_save",
+ "pdf_scale",
+ "pdf_set_border_color",
+ "pdf_set_border_dash",
+ "pdf_set_border_style",
+ "pdf_set_char_spacing",
+ "pdf_setcolor",
+ "pdf_setdash",
+ "pdf_set_duration",
+ "pdf_setflat",
+ "pdf_set_font",
+ "pdf_setfont",
+ "pdf_setgray",
+ "pdf_setgray_fill",
+ "pdf_setgray_stroke",
+ "pdf_set_horiz_scaling",
+ "pdf_set_info",
+ "pdf_set_info_author",
+ "pdf_set_info_creator",
+ "pdf_set_info_keywords",
+ "pdf_set_info_subject",
+ "pdf_set_info_title",
+ "pdf_set_leading",
+ "pdf_setlinecap",
+ "pdf_setlinejoin",
+ "pdf_setlinewidth",
+ "pdf_setmatrix",
+ "pdf_setmiterlimit",
+ "pdf_set_parameter",
+ "pdf_setpolydash",
+ "pdf_setrgbcolor",
+ "pdf_setrgbcolor_fill",
+ "pdf_setrgbcolor_stroke",
+ "pdf_set_text_matrix",
+ "pdf_set_text_pos",
+ "pdf_set_text_rendering",
+ "pdf_set_text_rise",
+ "pdf_set_value",
+ "pdf_set_word_spacing",
+ "pdf_show",
+ "pdf_show_boxed",
+ "pdf_show_xy",
+ "pdf_skew",
+ "pdf_stringwidth",
+ "pdf_stroke",
+ "pdf_translate",
+ "PEAR_EXTENSION_DIR",
+ "PEAR_INSTALL_DIR",
+ "pfpro_cleanup",
+ "pfpro_init",
+ "pfpro_process",
+ "pfpro_process_raw",
+ "pfpro_version",
+ "pfsockopen",
+ "pg_affected_rows",
+ "pg_cancel_query",
+ "pg_client_encoding",
+ "pg_close",
+ "pg_connect",
+ "pg_connection_busy",
+ "pg_connection_reset",
+ "pg_connection_status",
+ "pg_convert",
+ "pg_copy_from",
+ "pg_copy_to",
+ "pg_dbname",
+ "pg_delete",
+ "pg_end_copy",
+ "pg_escape_bytea",
+ "pg_escape_string",
+ "pg_fetch_all",
+ "pg_fetch_array",
+ "pg_fetch_assoc",
+ "pg_fetch_object",
+ "pg_fetch_result",
+ "pg_fetch_row",
+ "pg_field_is_null",
+ "pg_field_name",
+ "pg_field_num",
+ "pg_field_prtlen",
+ "pg_field_size",
+ "pg_field_type",
+ "pg_free_result",
+ "pg_get_notify",
+ "pg_get_pid",
+ "pg_get_result",
+ "pg_host",
+ "pg_insert",
+ "pg_last_error",
+ "pg_last_notice",
+ "pg_last_oid",
+ "pg_lo_close",
+ "pg_lo_create",
+ "pg_lo_export",
+ "pg_lo_import",
+ "pg_lo_open",
+ "pg_lo_read",
+ "pg_lo_read_all",
+ "pg_lo_seek",
+ "pg_lo_tell",
+ "pg_lo_unlink",
+ "pg_lo_write",
+ "pg_meta_data",
+ "pg_num_fields",
+ "pg_num_rows",
+ "pg_options",
+ "pg_pconnect",
+ "pg_ping",
+ "pg_port",
+ "pg_put_line",
+ "pg_query",
+ "pg_result_error",
+ "pg_result_seek",
+ "pg_result_status",
+ "pg_select",
+ "pg_send_query",
+ "pg_set_client_encoding",
+ "pg_trace",
+ "pg_tty",
+ "pg_unescape_bytea",
+ "pg_untrace",
+ "pg_update",
+ "PHP_BINDIR",
+ "PHP_CONFIG_FILE_PATH",
+ "phpcredits",
+ "PHP_DATADIR",
+ "PHP_ERRMSG",
+ "PHP_EXTENSION_DIR",
+ "phpinfo",
+ "php_ini_scanned_files",
+ "PHP_LIBDIR",
+ "PHP_LOCALSTATEDIR",
+ "php_logo_guid",
+ "PHP_OS",
+ "PHP_OUTPUT_HANDLER_CONT",
+ "PHP_OUTPUT_HANDLER_END",
+ "PHP_OUTPUT_HANDLER_START",
+ "php_sapi_name",
+ "PHP_SELF",
+ "PHP_SYSCONFDIR",
+ "php_uname",
+ "phpversion",
+ "PHP_VERSION",
+ "pi",
+ "png2wbmp",
+ "popen",
+ "pos",
+ "posix_ctermid",
+ "posix_getcwd",
+ "posix_getegid",
+ "posix_geteuid",
+ "posix_getgid",
+ "posix_getgrgid",
+ "posix_getgrnam",
+ "posix_getgroups",
+ "posix_getlogin",
+ "posix_getpgid",
+ "posix_getpgrp",
+ "posix_getpid",
+ "posix_getppid",
+ "posix_getpwnam",
+ "posix_getpwuid",
+ "posix_getrlimit",
+ "posix_getsid",
+ "posix_getuid",
+ "posix_isatty",
+ "posix_kill",
+ "posix_mkfifo",
+ "posix_setegid",
+ "posix_seteuid",
+ "posix_setgid",
+ "posix_setpgid",
+ "posix_setsid",
+ "posix_setuid",
+ "posix_times",
+ "posix_ttyname",
+ "posix_uname",
+ "_POST",
+ "pow",
+ "prefix",
+ "preg_grep",
+ "preg_match",
+ "preg_match_all",
+ "preg_quote",
+ "preg_replace",
+ "preg_replace_callback",
+ "preg_split",
+ "prev",
+ "previous_sibling",
+ "print",
+ "printer_abort",
+ "printer_close",
+ "printer_create_brush",
+ "printer_create_dc",
+ "printer_create_font",
+ "printer_create_pen",
+ "printer_delete_brush",
+ "printer_delete_dc",
+ "printer_delete_font",
+ "printer_delete_pen",
+ "printer_draw_bmp",
+ "printer_draw_chord",
+ "printer_draw_elipse",
+ "printer_draw_line",
+ "printer_draw_pie",
+ "printer_draw_rectangle",
+ "printer_draw_roundrect",
+ "printer_draw_text",
+ "printer_end_doc",
+ "printer_end_page",
+ "printer_get_option",
+ "printer_list",
+ "printer_logical_fontheight",
+ "printer_open",
+ "printer_select_brush",
+ "printer_select_font",
+ "printer_select_pen",
+ "printer_set_option",
+ "printer_start_doc",
+ "printer_start_page",
+ "printer_write",
+ "printf",
+ "print_r",
+ "private",
+ "proc_close",
+ "process",
+ "proc_open",
+ "protected",
+ "pspell_add_to_personal",
+ "pspell_add_to_session",
+ "pspell_check",
+ "pspell_clear_session",
+ "pspell_config_create",
+ "pspell_config_ignore",
+ "pspell_config_mode",
+ "pspell_config_personal",
+ "pspell_config_repl",
+ "pspell_config_runtogether",
+ "pspell_config_save_repl",
+ "pspell_new",
+ "pspell_new_config",
+ "pspell_new_personal",
+ "pspell_save_wordlist",
+ "pspell_store_replacement",
+ "pspell_suggest",
+ "public",
+ "public_id",
+ "putenv",
+ "qdom_error",
+ "qdom_tree",
+ "QUERY_STRING",
+ "quoted_printable_decode",
+ "quotemeta",
+ "rad2deg",
+ "rand",
+ "range",
+ "rawurldecode",
+ "rawurlencode",
+ "read",
+ "readdir",
+ "read_exif_data",
+ "readfile",
+ "readgzfile",
+ "readline",
+ "readline_add_history",
+ "readline_clear_history",
+ "readline_completion_function",
+ "readline_info",
+ "readline_list_history",
+ "readline_read_history",
+ "readline_write_history",
+ "readlink",
+ "realpath",
+ "reason",
+ "recode",
+ "recode_file",
+ "recode_string",
+ "register_shutdown_function",
+ "register_tick_function",
+ "REMOTE_ADDR",
+ "REMOTE_PORT",
+ "remove",
+ "remove_attribute",
+ "remove_child",
+ "rename",
+ "replace",
+ "replace_child",
+ "replace_node",
+ "_REQUEST",
+ "REQUEST_METHOD",
+ "REQUEST_URI",
+ "require",
+ "require_once",
+ "reset",
+ "restore_error_handler",
+ "restore_include_path",
+ "result_dump_file",
+ "result_dump_mem",
+ "return",
+ "rewind",
+ "rewinddir",
+ "rmdir",
+ "Rotate",
+ "rotateTo",
+ "round",
+ "rsort",
+ "rtrim",
+ "save",
+ "scale",
+ "scaleTo",
+ "SCRIPT_FILENAME",
+ "SCRIPT_NAME",
+ "sem_acquire",
+ "sem_get",
+ "sem_release",
+ "sem_remove",
+ "serialize",
+ "_SERVER",
+ "SERVER_ADMIN",
+ "SERVER_NAME",
+ "SERVER_PORT",
+ "SERVER_PROTOCOL",
+ "SERVER_SIGNATURE",
+ "SERVER_SOFTWARE",
+ "sesam_affected_rows",
+ "sesam_commit",
+ "sesam_connect",
+ "sesam_diagnostic",
+ "sesam_disconnect",
+ "sesam_errormsg",
+ "sesam_execimm",
+ "sesam_fetch_array",
+ "sesam_fetch_result",
+ "sesam_fetch_row",
+ "sesam_field_array",
+ "sesam_field_name",
+ "sesam_free_result",
+ "sesam_num_fields",
+ "sesam_query",
+ "sesam_rollback",
+ "sesam_seek_row",
+ "sesam_settransaction",
+ "_SESSION",
+ "session_cache_expire",
+ "session_cache_limiter",
+ "session_decode",
+ "session_destroy",
+ "session_encode",
+ "session_get_cookie_params",
+ "session_id",
+ "session_is_registered",
+ "session_module_name",
+ "session_name",
+ "session_readonly",
+ "session_register",
+ "session_save_path",
+ "session_set_cookie_params",
+ "session_set_save_handler",
+ "session_start",
+ "session_unregister",
+ "session_unset",
+ "session_write_close",
+ "setAction",
+ "set_attribute",
+ "setbackground",
+ "setbounds",
+ "setcolor",
+ "setColor",
+ "setcommitedversion",
+ "set_content",
+ "setcookie",
+ "setDepth",
+ "setdimension",
+ "setdown",
+ "set_error_handler",
+ "set_file_buffer",
+ "setFont",
+ "setframes",
+ "setHeight",
+ "setHit",
+ "set_include_path",
+ "setindentation",
+ "setLeftFill",
+ "setLeftMargin",
+ "setLine",
+ "setLineSpacing",
+ "setlocale",
+ "set_magic_quotes_runtime",
+ "setMargins",
+ "set_name",
+ "setname",
+ "setName",
+ "set_namespace",
+ "setOver",
+ "setrate",
+ "setRatio",
+ "setRightFill",
+ "setrightMargin",
+ "setSpacing",
+ "set_time_limit",
+ "settype",
+ "setUp",
+ "sha1",
+ "sha1_file",
+ "shell_exec",
+ "shm_attach",
+ "shm_detach",
+ "shm_get_var",
+ "shmop_close",
+ "shmop_delete",
+ "shmop_open",
+ "shmop_read",
+ "shmop_size",
+ "shmop_write",
+ "shm_put_var",
+ "shm_remove",
+ "shm_remove_var",
+ "show_source",
+ "shuffle",
+ "similar_text",
+ "sin",
+ "sinh",
+ "sizeof",
+ "skewX",
+ "skewXTo",
+ "skewY",
+ "skewYTo",
+ "sleep",
+ "snmpget",
+ "snmp_get_quick_print",
+ "snmprealwalk",
+ "snmpset",
+ "snmp_set_quick_print",
+ "snmpwalk",
+ "snmpwalkoid",
+ "socket_accept",
+ "socket_bind",
+ "socket_clear_error",
+ "socket_close",
+ "socket_connect",
+ "socket_create",
+ "socket_create_listen",
+ "socket_create_pair",
+ "socket_get_option",
+ "socket_getpeername",
+ "socket_getsockname",
+ "socket_get_status",
+ "socket_iovec_add",
+ "socket_iovec_alloc",
+ "socket_iovec_delete",
+ "socket_iovec_fetch",
+ "socket_iovec_free",
+ "socket_iovec_set",
+ "socket_last_error",
+ "socket_listen",
+ "socket_read",
+ "socket_readv",
+ "socket_recv",
+ "socket_recvfrom",
+ "socket_recvmsg",
+ "socket_select",
+ "socket_send",
+ "socket_sendmsg",
+ "socket_sendto",
+ "socket_set_blocking",
+ "socket_set_nonblock",
+ "socket_set_option",
+ "socket_set_timeout",
+ "socket_shutdown",
+ "socket_strerror",
+ "socket_write",
+ "socket_writev",
+ "sort",
+ "soundex",
+ "specified",
+ "split",
+ "spliti",
+ "sprintf",
+ "sql_regcase",
+ "sqrt",
+ "srand",
+ "srcanchors",
+ "srcsofdst",
+ "sscanf",
+ "stat",
+ "static",
+ "stdClass",
+ "strcasecmp",
+ "strchr",
+ "strcmp",
+ "strcoll",
+ "strcspn",
+ "stream_context_create",
+ "stream_context_get_options",
+ "stream_context_set_option",
+ "stream_context_set_params",
+ "stream_filter_append",
+ "stream_filter_prepend",
+ "stream_get_filters",
+ "stream_get_meta_data",
+ "stream_get_wrappers",
+ "streammp3",
+ "stream_register_filter",
+ "stream_register_wrapper",
+ "stream_select",
+ "stream_set_blocking",
+ "stream_set_timeout",
+ "stream_set_write_buffer",
+ "strftime",
+ "stripcslashes",
+ "stripslashes",
+ "strip_tags",
+ "stristr",
+ "strlen",
+ "strnatcasecmp",
+ "strnatcmp",
+ "strncasecmp",
+ "strncmp",
+ "str_pad",
+ "strpos",
+ "strrchr",
+ "str_repeat",
+ "str_replace",
+ "strrev",
+ "str_rot13",
+ "strrpos",
+ "str_shuffle",
+ "strspn",
+ "strstr",
+ "strtok",
+ "strtolower",
+ "strtotime",
+ "strtoupper",
+ "strtr",
+ "strval",
+ "str_word_count",
+ "substr",
+ "substr_count",
+ "substr_replace",
+ "SWFAction",
+ "swf_actiongeturl",
+ "swf_actiongotoframe",
+ "swf_actiongotolabel",
+ "swf_actionnextframe",
+ "swf_actionplay",
+ "swf_actionprevframe",
+ "swf_actionsettarget",
+ "swf_actionstop",
+ "swf_actiontogglequality",
+ "swf_actionwaitforframe",
+ "swf_addbuttonrecord",
+ "swf_addcolor",
+ "SWFBitmap",
+ "SWFbutton",
+ "swfbutton_keypress",
+ "swf_closefile",
+ "swf_definebitmap",
+ "swf_definefont",
+ "swf_defineline",
+ "swf_definepoly",
+ "swf_definerect",
+ "swf_definetext",
+ "SWFDisplayItem",
+ "swf_endbutton",
+ "swf_enddoaction",
+ "swf_endshape",
+ "swf_endsymbol",
+ "SWFFill",
+ "SWFFont",
+ "swf_fontsize",
+ "swf_fontslant",
+ "swf_fonttracking",
+ "swf_getbitmapinfo",
+ "swf_getfontinfo",
+ "swf_getframe",
+ "SWFGradient",
+ "swf_labelframe",
+ "swf_lookat",
+ "swf_modifyobject",
+ "SWFMorph",
+ "SWFMovie",
+ "swf_mulcolor",
+ "swf_nextid",
+ "swf_oncondition",
+ "swf_openfile",
+ "swf_ortho",
+ "swf_ortho2",
+ "swf_perspective",
+ "swf_placeobject",
+ "swf_polarview",
+ "swf_popmatrix",
+ "swf_posround",
+ "swf_pushmatrix",
+ "swf_removeobject",
+ "swf_rotate",
+ "swf_scale",
+ "swf_setfont",
+ "swf_setframe",
+ "SWFShape",
+ "swf_shapearc",
+ "swf_shapecurveto",
+ "swf_shapecurveto3",
+ "swf_shapefillbitmapclip",
+ "swf_shapefillbitmaptile",
+ "swf_shapefilloff",
+ "swf_shapefillsolid",
+ "swf_shapelinesolid",
+ "swf_shapelineto",
+ "swf_shapemoveto",
+ "swf_showframe",
+ "SWFSprite",
+ "swf_startbutton",
+ "swf_startdoaction",
+ "swf_startshape",
+ "swf_startsymbol",
+ "SWFText",
+ "SWFTextField",
+ "swf_textwidth",
+ "swf_translate",
+ "swf_viewport",
+ "switch",
+ "sybase_affected_rows",
+ "sybase_close",
+ "sybase_connect",
+ "sybase_data_seek",
+ "sybase_fetch_array",
+ "sybase_fetch_field",
+ "sybase_fetch_object",
+ "sybase_fetch_row",
+ "sybase_field_seek",
+ "sybase_free_result",
+ "sybase_get_last_message",
+ "sybase_min_client_severity",
+ "sybase_min_error_severity",
+ "sybase_min_message_severity",
+ "sybase_min_server_severity",
+ "sybase_num_fields",
+ "sybase_num_rows",
+ "sybase_pconnect",
+ "sybase_query",
+ "sybase_result",
+ "sybase_select_db",
+ "symlink",
+ "syslog",
+ "system",
+ "system_id",
+ "tagname",
+ "tan",
+ "tanh",
+ "target",
+ "tempnam",
+ "textdomain",
+ "time",
+ "title",
+ "tmpfile",
+ "token_get_all",
+ "token_name",
+ "touch",
+ "trigger_error",
+ "trim",
+ "TRUE",
+ "type",
+ "uasort",
+ "ucfirst",
+ "ucwords",
+ "udm_add_search_limit",
+ "udm_alloc_agent",
+ "udm_api_version",
+ "udm_cat_list",
+ "udm_cat_path",
+ "udm_check_charset",
+ "udm_check_stored",
+ "udm_clear_search_limits",
+ "udm_close_stored",
+ "udm_crc32",
+ "udm_errno",
+ "udm_error",
+ "udm_find",
+ "udm_free_agent",
+ "udm_free_ispell_data",
+ "udm_free_res",
+ "udm_get_doc_count",
+ "udm_get_res_field",
+ "udm_get_res_param",
+ "udm_load_ispell_data",
+ "udm_open_stored",
+ "udm_set_agent_param",
+ "uksort",
+ "umask",
+ "uniqid",
+ "unixtojd",
+ "unlink",
+ "unlink_node",
+ "unlock",
+ "unpack",
+ "unregister_tick_function",
+ "unserialize",
+ "unset",
+ "urldecode",
+ "urlencode",
+ "user",
+ "user_error",
+ "userlist",
+ "usleep",
+ "usort",
+ "utf8_decode",
+ "utf8_encode",
+ "value",
+ "values",
+ "var",
+ "var_dump",
+ "var_export",
+ "version_compare",
+ "virtual",
+ "vpopmail_add_alias_domain",
+ "vpopmail_add_alias_domain_ex",
+ "vpopmail_add_domain",
+ "vpopmail_add_domain_ex",
+ "vpopmail_add_user",
+ "vpopmail_alias_add",
+ "vpopmail_alias_del",
+ "vpopmail_alias_del_domain",
+ "vpopmail_alias_get",
+ "vpopmail_alias_get_all",
+ "vpopmail_auth_user",
+ "vpopmail_del_domain",
+ "vpopmail_del_domain_ex",
+ "vpopmail_del_user",
+ "vpopmail_error",
+ "vpopmail_passwd",
+ "vpopmail_set_user_quota",
+ "vprintf",
+ "vsprintf",
+ "w32api_deftype",
+ "w32api_init_dtype",
+ "w32api_invoke_function",
+ "w32api_register_function",
+ "w32api_set_call_method",
+ "wddx_add_vars",
+ "wddx_deserialize",
+ "wddx_packet_end",
+ "wddx_packet_start",
+ "wddx_serialize_value",
+ "wddx_serialize_vars",
+ "while",
+ "wordwrap",
+ "xinclude",
+ "xml_error_string",
+ "xml_get_current_byte_index",
+ "xml_get_current_column_number",
+ "xml_get_current_line_number",
+ "xml_get_error_code",
+ "xml_parse",
+ "xml_parse_into_struct",
+ "xml_parser_create",
+ "xml_parser_create_ns",
+ "xml_parser_free",
+ "xml_parser_get_option",
+ "xml_parser_set_option",
+ "xmlrpc_decode",
+ "xmlrpc_decode_request",
+ "xmlrpc_encode",
+ "xmlrpc_encode_request",
+ "xmlrpc_get_type",
+ "xmlrpc_parse_method_descriptions",
+ "xmlrpc_server_add_introspection_data",
+ "xmlrpc_server_call_method",
+ "xmlrpc_server_create",
+ "xmlrpc_server_destroy",
+ "xmlrpc_server_register_introspection_callback",
+ "xmlrpc_server_register_method",
+ "xmlrpc_set_type",
+ "xml_set_character_data_handler",
+ "xml_set_default_handler",
+ "xml_set_element_handler",
+ "xml_set_end_namespace_decl_handler",
+ "xml_set_external_entity_ref_handler",
+ "xml_set_notation_decl_handler",
+ "xml_set_object",
+ "xml_set_processing_instruction_handler",
+ "xml_set_start_namespace_decl_handler",
+ "xml_set_unparsed_entity_decl_handler",
+ "xpath_eval",
+ "xpath_eval_expression",
+ "xpath_new_context",
+ "xptr_eval",
+ "xptr_new_context",
+ "xslt_create",
+ "xslt_errno",
+ "xslt_error",
+ "xslt_free",
+ "xslt_output_process",
+ "xslt_set_base",
+ "xslt_set_encoding",
+ "xslt_set_error_handler",
+ "xslt_set_log",
+ "xslt_set_sax_handler",
+ "xslt_set_sax_handlers",
+ "xslt_set_scheme_handler",
+ "xslt_set_scheme_handlers",
+ "yaz_addinfo",
+ "yaz_ccl_conf",
+ "yaz_ccl_parse",
+ "yaz_close",
+ "yaz_connect",
+ "yaz_database",
+ "yaz_element",
+ "yaz_errno",
+ "yaz_error",
+ "yaz_get_option",
+ "yaz_hits",
+ "yaz_itemorder",
+ "yaz_present",
+ "yaz_range",
+ "yaz_record",
+ "yaz_scan",
+ "yaz_scan_result",
+ "yaz_schema",
+ "yaz_search",
+ "yaz_set_option",
+ "yaz_sort",
+ "yaz_syntax",
+ "yaz_wait",
+ "yp_all",
+ "yp_cat",
+ "yp_errno",
+ "yp_err_string",
+ "yp_first",
+ "yp_get_default_domain",
+ "yp_master",
+ "yp_match",
+ "yp_next",
+ "yp_order",
+ "zend_logo_guid",
+ "zend_version",
+ "zend_version",
+ "zip_close",
+ "zip_entry_close",
+ "zip_entry_compressedsize",
+ "zip_entry_compressionmethod",
+ "zip_entry_filesize",
+ "zip_entry_name",
+ "zip_entry_open",
+ "zip_entry_read",
+ "zip_open",
+ "zip_read",
+ 0
+ };
+
+PhpWriter::PhpWriter() {
+}
+
+PhpWriter::~PhpWriter() {}
+
+
+void PhpWriter::writeClass(UMLClassifier *c) {
+ if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".php");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile filephp;
+ if(!openFile(filephp, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream php(&filephp);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".php");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),filephp.name());
+ php<<str<<m_endl;
+ }
+
+
+ //write includes
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ UMLPackage *conc;
+ for(conc = includes.first(); conc ;conc = includes.next()) {
+ QString headerName = findFileName(conc, ".php");
+ if (headerName.isEmpty()) {
+ php << "include '" << headerName << "';" << m_endl;
+ }
+ }
+ php << m_endl;
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ php << m_endl << "/**" << m_endl;
+ php << " * class " << classname << m_endl;
+ php << formatDoc(c->getDoc()," * ");
+ php << " */" << m_endl ;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+ UMLAssociation *a;
+
+ //check if class is abstract and / or has abstract methods
+ //FG if(c->getAbstract() && !hasAbstractOps(c))
+ if(c->getAbstract())
+ php << "/******************************* Abstract Class ****************************" << m_endl << " "
+ << classname << " does not have any pure virtual methods, but its author" << m_endl
+ << " defined it as an abstract class, so you should not use it directly." << m_endl
+ << " Inherit from it instead and create only objects from the derived classes" << m_endl
+ << "*****************************************************************************/" << m_endl << m_endl;
+
+ php << "class " << classname << (superclasses.count() > 0 ? " extends ":"");
+ for (UMLClassifier *obj = superclasses.first();
+ obj; obj = superclasses.next()) {
+ php<<cleanName(obj->getName());
+ }
+ php<< m_endl << "{" << m_endl;
+
+ //associations
+ if( forceSections() || !aggregations.isEmpty()) {
+ php<< m_endl << m_indentation << "/** Aggregations: */" << m_endl;
+ for (a = aggregations.first(); a; a = aggregations.next()) {
+ php<< m_endl;
+ //maybe we should parse the string here and take multiplicity into account to decide
+ //which container to use.
+ UMLObject *o = a->getObject(Uml::A);
+ QString typeName = cleanName(o->getName());
+ if (a->getMulti(Uml::A).isEmpty()) {
+ php << m_indentation << "var $m_" << ";" << m_endl;
+ } else {
+ php << m_indentation << "var $m_" << "Vector = array();" << m_endl;
+ }
+ }//end for
+ }
+
+ if( forceSections() || !compositions.isEmpty()) {
+ php<< m_endl << m_indentation << "/** Compositions: */" << m_endl;
+ for (a = compositions.first(); a ; a = compositions.next()) {
+ // see comment on Aggregation about multiplicity...
+ UMLObject *o = a->getObject(Uml::A);
+ QString typeName = cleanName(o->getName());
+ if (a->getMulti(Uml::A).isEmpty()) {
+ php << m_indentation << "var $m_" << ";" << m_endl;
+ } else {
+ php << m_indentation << "var $m_" << "Vector = array();" << m_endl;
+ }
+ }
+ }
+
+ const bool isClass = !c->isInterface();
+
+ //attributes
+ if (isClass)
+ writeAttributes(c, php);
+
+ //operations
+ writeOperations(c,php);
+
+ if (isClass && hasDefaultValueAttr(c)) {
+ UMLAttributeList atl = c->getAttributeList();
+ php << m_endl;
+
+ php << m_indentation << "/**" << m_endl;
+ QString temp = "initAttributes sets all " + classname + " attributes to its default value."
+ " Make sure to call this method within your class constructor";
+ php << formatDoc(temp,m_indentation + " * ");
+ php << m_indentation << " */" << m_endl;
+ php << m_indentation << "function "<<"initAttributes( )" << m_endl;
+ php << m_indentation << "{" << m_endl;
+ for(UMLAttribute* at = atl.first(); at; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty()) {
+ php << m_indentation << m_indentation << "$this->" << cleanName(at->getName()) << " = " <<
+ at->getInitialValue() << ";" << m_endl;
+ }
+ }
+ php << m_indentation << "}" << m_endl;
+ }
+
+ php << m_endl;
+
+ //finish file
+ php << m_endl << "} // end of " << classname << m_endl;
+ php << "?>" << m_endl;
+
+ //close files and notfiy we are done
+ filephp.close();
+ emit codeGenerated(c, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void PhpWriter::writeOperations(UMLClassifier *c, QTextStream &php) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ QString classname(cleanName(c->getName()));
+
+ //write operations to file
+ if(forceSections() || !oppub.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,oppub,php);
+ }
+
+ if(forceSections() || !opprot.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,opprot,php);
+ }
+
+ if(forceSections() || !oppriv.isEmpty()) {
+ php << m_endl;
+ writeOperations(classname,oppriv,php);
+ }
+}
+
+void PhpWriter::writeOperations(QString /* classname */, UMLOperationList &opList, QTextStream &php) {
+ UMLOperation *op;
+ UMLAttribute *at;
+
+ for(op=opList.first(); op ; op=opList.next()) {
+ UMLAttributeList atl = op->getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ if( writeDoc ) //write method documentation
+ {
+ php <<m_indentation << "/**" << m_endl <<formatDoc(op->getDoc(),m_indentation + " * ");
+ php << m_indentation << " *" << m_endl;
+
+ for (at = atl.first(); at; at = atl.next()) //write parameter documentation
+ {
+ if(forceDoc() || !at->getDoc().isEmpty()) {
+ php <<m_indentation << " * @param " + at->getTypeName() + " " + cleanName(at->getName());
+ php << " " + formatDoc(at->getDoc(),"");
+ }
+ }//end for : write parameter documentation
+ php << m_indentation << " * @return " << op->getTypeName() << m_endl;
+ if (op->getAbstract()) php << m_indentation << " * @abstract" << m_endl;
+ if (op->getStatic()) php << m_indentation << " * @static" << m_endl;
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << m_indentation << " * @access public" << m_endl;
+ break;
+ case Uml::Visibility::Protected:
+ php << m_indentation << " * @access protected" << m_endl;
+ break;
+ case Uml::Visibility::Private:
+ php << m_indentation << " * @access private" << m_endl;
+ break;
+ default:
+ break;
+ }
+ php <<m_indentation << " */" << m_endl;
+ }//end if : write method documentation
+
+ php << m_indentation << "function " << cleanName(op->getName()) << "(";
+
+ int i= atl.count();
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ php << " $" << cleanName(at->getName())
+ << (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""))
+ << ((j < i-1)?", ":"");
+ }
+ php <<" )" << m_endl << m_indentation << "{" << m_endl << m_indentation << m_indentation << m_endl << m_indentation << "} // end of member function " + cleanName(op->getName()) + m_endl;
+ php << m_endl;
+ }//end for
+}
+
+void PhpWriter::writeAttributes(UMLClassifier *c, QTextStream &php) {
+ UMLAttributeList atpub, atprot, atpriv, atdefval;
+ atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ atdefval.setAutoDelete(false);
+
+ //sort attributes by scope and see if they have a default value
+ UMLAttributeList atl = c->getAttributeList();
+ UMLAttribute *at;
+ for(at = atl.first(); at ; at = atl.next()) {
+ if(!at->getInitialValue().isEmpty())
+ atdefval.append(at);
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ atpriv.append(at);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(forceSections() || atl.count())
+ php<< m_endl << m_indentation << " /*** Attributes: ***/" << m_endl <<m_endl;
+
+ if(forceSections() || atpub.count()) {
+ writeAttributes(atpub,php);
+ }
+
+ if(forceSections() || atprot.count()) {
+ writeAttributes(atprot,php);
+ }
+
+ if(forceSections() || atpriv.count()) {
+ writeAttributes(atpriv,php);
+ }
+}
+
+
+void PhpWriter::writeAttributes(UMLAttributeList &atList, QTextStream &php) {
+ for (UMLAttribute *at = atList.first(); at ; at = atList.next()) {
+ if (forceDoc() || !at->getDoc().isEmpty()) {
+ php << m_indentation << "/**" << m_endl << formatDoc(at->getDoc(), m_indentation + " * ");
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ php << m_indentation << " * @access public" << m_endl;
+ break;
+ case Uml::Visibility::Protected:
+ php << m_indentation << " * @access protected" << m_endl;
+ break;
+ case Uml::Visibility::Private:
+ php << m_indentation << " * @access private" << m_endl;
+ break;
+ default:
+ break;
+ }
+
+ php << m_indentation << " */" << m_endl;
+ }
+ php << m_indentation << "var " << "$" << cleanName(at->getName()) << ";" << m_endl;
+
+ } // end for
+ return;
+}
+
+/**
+ * returns "PHP"
+ */
+Uml::Programming_Language PhpWriter::getLanguage() {
+ return Uml::pl_PHP;
+}
+
+const QStringList PhpWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ for (int i = 0; words[i]; i++)
+ keywords.append(words[i]);
+ }
+
+ return keywords;
+}
+
+#include "phpwriter.moc"
+
diff --git a/umbrello/umbrello/codegenerators/phpwriter.h b/umbrello/umbrello/codegenerators/phpwriter.h
new file mode 100644
index 00000000..a3acb68b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/phpwriter.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ phpwriter.h - description
+ -------------------
+ begin : Thu Oct 17 2002
+ copyright : (C) 2002 by Heiko Nardmann
+ email : h.nardmann@secunet.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHPWRITER_H
+#define PHPWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+#include "../umloperationlist.h"
+
+/**
+ * class PhpWriter is a PHP code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class PhpWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ PhpWriter();
+ virtual ~PhpWriter();
+
+ /**
+ * call this method to generate Php code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "PHP"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * we do not want to write the comment "Private methods" twice
+ */
+ bool bPrivateSectionCommentIsWritten;
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param php output stream for the PHP file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &php);
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param php output stream for the PHP file
+ */
+ void writeOperations(QString classname, UMLOperationList &opList,
+ QTextStream &php);
+
+ /** write all the attributes of a class
+ * @param c the class we are generating code for
+ * @param php output stream for the PHP file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &php);
+
+ /** write a list of class attributes
+ * @param atList the list of attributes
+ * @param php output stream for the PHP file
+ */
+ void writeAttributes(UMLAttributeList &atList, QTextStream &php);
+};
+
+#endif //PHPWRITER
diff --git a/umbrello/umbrello/codegenerators/pythonwriter.cpp b/umbrello/umbrello/codegenerators/pythonwriter.cpp
new file mode 100644
index 00000000..a5ac2b28
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/pythonwriter.cpp
@@ -0,0 +1,438 @@
+/***************************************************************************
+ pythonwriter.h - description
+ -------------------
+ begin : Sat Dec 21 2002
+ copyright : Vincent Decorges
+ email : vincent.decorges@eivd.ch
+ (C) 2003-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "pythonwriter.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+
+#include "../umldoc.h"
+#include "../umlattributelist.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../classifier.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+PythonWriter::PythonWriter() : m_bNeedPass(true) {
+}
+
+PythonWriter::~PythonWriter() {}
+
+void PythonWriter::writeClass(UMLClassifier *c) {
+ if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ m_bNeedPass = true;
+
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".py");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QChar first = fileName.at(0);
+ //Replace the first letter of the filename because
+ //python class begin with an upper caracter (convention)
+ first = first.upper();
+ fileName = fileName.replace(0, 1, first);
+
+ QFile fileh;
+ if( !openFile(fileh, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream h(&fileh);
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+
+ str = getHeadingFile(".py");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), fileh.name());
+ h<<str<<m_endl;
+ }
+
+ // generate import statement for superclasses and take packages into account
+ str = cleanName(c->getName());
+ QString pkg = cleanName(c->getPackage());
+ if (!pkg.isEmpty())
+ str.prepend(pkg + '.');
+ QStringList includesList = QStringList(str); //save imported classes
+ int i = superclasses.count();
+ for (UMLClassifier *classifier = superclasses.first();
+ classifier && i; classifier = superclasses.next(), i--) {
+ str = cleanName(classifier->getName());
+ pkg = cleanName(classifier->getPackage());
+ if (!pkg.isEmpty())
+ str.prepend(pkg + '.');
+ includesList.append(str);
+ h << "from " + str + " import *" << m_endl;
+ }
+
+ //write includes and take namespaces into account
+ UMLPackageList includes;
+ findObjectsRelated(c,includes);
+ UMLPackage* conc;
+ for(conc = includes.first(); conc ;conc = includes.next()) {
+ QString headerName = findFileName(conc, ".py");
+ if ( !headerName.isEmpty() ) {
+ headerName.remove(QRegExp(".py$"));
+ first = headerName.at(0);
+ first = first.upper();
+ headerName = headerName.replace(0, 1, first);
+ str = headerName.replace(QChar('/'),QChar('.'));
+ if (includesList.findIndex(str) < 0) // not yet imported
+ h << "from " << str << " import *" << m_endl;
+ }
+ }
+ h<<m_endl;
+
+ h << "class " << classname << (superclasses.count() > 0 ? " (" : "(object)");
+ i = superclasses.count();
+
+ for (UMLClassifier *obj = superclasses.first();
+ obj && i; obj = superclasses.next(), i--) {
+
+ h<<cleanName(obj->getName())<<(i>1?", ":"");
+ }
+
+
+ h<<(superclasses.count() > 0 ? ")":"")<<":"<<m_endl<<m_endl;
+
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ h << m_indentation << "\"\"\"" << m_endl;
+ h << formatDoc(c->getDoc(), m_indentation + ' ') << m_endl;
+ h << m_indentation << ":version:" << m_endl;
+ h << m_indentation << ":author:" << m_endl;
+ h << m_indentation << "\"\"\"" << m_endl << m_endl;
+ m_bNeedPass = false;
+ }
+
+ // attributes
+ writeAttributes(c->getAttributeList(), h);
+
+ //operations
+ writeOperations(c,h);
+
+ if (m_bNeedPass)
+ h << m_indentation << "pass" << m_endl;
+
+ //finish files
+ h<<m_endl<<m_endl;
+
+ //close files and notfiy we are done
+ fileh.close();
+ emit codeGenerated(c, true);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+void PythonWriter::writeAttributes(UMLAttributeList atList, QTextStream &py) {
+ if (!forceDoc() || atList.count() == 0)
+ return;
+ py << m_indentation << "\"\"\" ATTRIBUTES" << m_endl << m_endl;
+ for (UMLAttribute *at = atList.first(); at; at = atList.next()) {
+ py << formatDoc(at->getDoc(), m_indentation + ' ') << m_endl;
+ Uml::Visibility vis = at->getVisibility();
+ py << m_indentation << cleanName(at->getName()) << " ("
+ << vis.toString() << ")" << m_endl << m_endl ;
+ } // end for
+ py << m_indentation << "\"\"\"" << m_endl << m_endl;
+}
+
+void PythonWriter::writeOperations(UMLClassifier *c, QTextStream &h) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ QString classname(cleanName(c->getName()));
+
+ //write operations to file
+ if(forceSections() || !oppub.isEmpty()) {
+ writeOperations(classname,oppub,h,PUBLIC);
+ }
+
+ if(forceSections() || !opprot.isEmpty()) {
+ writeOperations(classname,opprot,h,PROTECTED);
+ }
+
+ if(forceSections() || !oppriv.isEmpty()) {
+ writeOperations(classname,oppriv,h,PRIVATE);
+ }
+
+}
+
+void PythonWriter::writeOperations(const QString& /*classname*/, UMLOperationList &opList,
+ QTextStream &h, Access access) {
+ UMLOperation *op;
+ UMLAttribute *at;
+
+ QString sAccess;
+
+ switch (access) {
+
+ case PUBLIC:
+ sAccess = QString("");
+ break;
+ case PRIVATE:
+ sAccess = QString("__");
+ break;
+ case PROTECTED:
+ sAccess = QString("_");
+ break;
+ }
+
+
+ for(op=opList.first(); op ; op=opList.next()) {
+ UMLAttributeList atl = op->getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ for (at = atl.first(); at; at = atl.next())
+ writeDoc |= !at->getDoc().isEmpty();
+
+ h<< m_indentation << "def "<< sAccess + cleanName(op->getName()) << "(self";
+
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ h << ", " << cleanName(at->getName())
+ << (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""));
+ }
+
+ h<<"):"<<m_endl;
+
+ if( writeDoc ) //write method documentation
+ {
+ h << m_indentation << m_indentation << "\"\"\"" << m_endl;
+ h << formatDoc(op->getDoc(), m_indentation + m_indentation + ' ') << m_endl;
+
+ for (at = atl.first(); at; at = atl.next()) //write parameter documentation
+ {
+ if(forceDoc() || !at->getDoc().isEmpty()) {
+ h<<m_indentation<<m_indentation<<"@param "<<at->getTypeName()<<
+ " " << cleanName(at->getName());
+ h<<" : "<<at->getDoc()<<m_endl;
+ }
+ }//end for : write parameter documentation
+ h<<m_indentation<<m_indentation<<"@return " + op->getTypeName()<<" :"<<m_endl;
+ h<<m_indentation<<m_indentation<<"@author"<<m_endl;
+ h<<m_indentation<<m_indentation<<"\"\"\""<<m_endl;
+ }
+ h<<m_indentation<<m_indentation<<"pass"<<m_endl<<m_endl;
+ m_bNeedPass = false;
+ }//end for
+}
+
+/**
+ * returns "Python"
+ */
+Uml::Programming_Language PythonWriter::getLanguage() {
+ return Uml::pl_Python;
+}
+
+const QStringList PythonWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "abs"
+ << "and"
+ << "apply"
+ << "ArithmeticError"
+ << "assert"
+ << "AssertionError"
+ << "AttributeError"
+ << "break"
+ << "buffer"
+ << "callable"
+ << "chr"
+ << "class"
+ << "classmethod"
+ << "cmp"
+ << "coerce"
+ << "compile"
+ << "complex"
+ << "continue"
+ << "def"
+ << "del"
+ << "delattr"
+ << "DeprecationWarning"
+ << "dict"
+ << "dir"
+ << "divmod"
+ << "elif"
+ << "Ellipsis"
+ << "else"
+ << "EnvironmentError"
+ << "EOFError"
+ << "eval"
+ << "except"
+ << "Exception"
+ << "exec"
+ << "execfile"
+ << "file"
+ << "filter"
+ << "finally"
+ << "float"
+ << "FloatingPointError"
+ << "for"
+ << "from"
+ << "getattr"
+ << "global"
+ << "globals"
+ << "hasattr"
+ << "hash"
+ << "hex"
+ << "id"
+ << "if"
+ << "import"
+ << "__import__"
+ << "ImportError"
+ << "in"
+ << "IndentationError"
+ << "IndexError"
+ << "input"
+ << "int"
+ << "intern"
+ << "IOError"
+ << "is"
+ << "isinstance"
+ << "issubclass"
+ << "iter"
+ << "KeyboardInterrupt"
+ << "KeyError"
+ << "lambda"
+ << "len"
+ << "list"
+ << "locals"
+ << "long"
+ << "LookupError"
+ << "map"
+ << "max"
+ << "MemoryError"
+ << "min"
+ << "NameError"
+ << "None"
+ << "not"
+ << "NotImplemented"
+ << "NotImplementedError"
+ << "object"
+ << "oct"
+ << "open"
+ << "or"
+ << "ord"
+ << "OSError"
+ << "OverflowError"
+ << "OverflowWarning"
+ << "pass"
+ << "pow"
+ << "print"
+ << "property"
+ << "raise"
+ << "range"
+ << "raw_input"
+ << "reduce"
+ << "ReferenceError"
+ << "reload"
+ << "repr"
+ << "return"
+ << "round"
+ << "RuntimeError"
+ << "RuntimeWarning"
+ << "setattr"
+ << "slice"
+ << "StandardError"
+ << "staticmethod"
+ << "StopIteration"
+ << "str"
+ << "super"
+ << "SyntaxError"
+ << "SyntaxWarning"
+ << "SystemError"
+ << "SystemExit"
+ << "TabError"
+ << "try"
+ << "tuple"
+ << "type"
+ << "TypeError"
+ << "UnboundLocalError"
+ << "unichr"
+ << "unicode"
+ << "UnicodeError"
+ << "UserWarning"
+ << "ValueError"
+ << "vars"
+ << "Warning"
+ << "while"
+ << "WindowsError"
+ << "xrange"
+ << "yield"
+ << "ZeroDivisionError"
+ << "zip";
+ }
+
+ return keywords;
+}
+
+#include "pythonwriter.moc"
diff --git a/umbrello/umbrello/codegenerators/pythonwriter.h b/umbrello/umbrello/codegenerators/pythonwriter.h
new file mode 100644
index 00000000..f9e5b31a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/pythonwriter.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ pythonwriter.h - description
+ -------------------
+ begin : Sat Dec 21 2002
+ author : Vincent Decorges
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PYTHONWRITER_H
+#define PYTHONWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+#include "../umloperationlist.h"
+
+enum Access {PRIVATE, PUBLIC, PROTECTED};
+
+/**
+ * class PythonWriter is a python code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class PythonWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ PythonWriter();
+ virtual ~PythonWriter();
+
+ /**
+ * call this method to generate C++ code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "Python"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * write all attributes for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param py output stream for the header file
+ */
+ void writeAttributes(UMLAttributeList atList, QTextStream &py);
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param h output stream for the header file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &h);
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param h output stream for the header file
+ */
+ void writeOperations(const QString& classname, UMLOperationList &opList,
+ QTextStream &h, Access access);
+
+ bool m_bNeedPass; ///< True as long as no "pass" has been written
+};
+
+#endif //PYTHONWRITER
diff --git a/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp
new file mode 100644
index 00000000..cae5d322
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp
@@ -0,0 +1,147 @@
+/***************************************************************************
+ rubyclassdeclarationblock.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "rubyclassdeclarationblock.h"
+#include "rubycodedocumentation.h"
+#include "rubycodegenerator.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyClassDeclarationBlock::RubyClassDeclarationBlock
+ ( RubyClassifierCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment)
+ : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment)
+{
+ init(parentDoc, comment);
+}
+
+RubyClassDeclarationBlock::~RubyClassDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void RubyClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "rubyclassdeclarationblock" );
+
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void RubyClassDeclarationBlock::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * update the start and end text for this ownedhierarchicalcodeblock.
+ */
+void RubyClassDeclarationBlock::updateContent ( )
+{
+
+ RubyClassifierCodeDocument *parentDoc = dynamic_cast<RubyClassifierCodeDocument*>(getParentDocument());
+ UMLClassifier *c = parentDoc->getParentClassifier();
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ QString endLine = p->getNewLineEndingChars();
+ bool isInterface = parentDoc->parentIsInterface(); // a little shortcut
+ QString RubyClassName = parentDoc->getRubyClassName(c->getName());
+ bool forceDoc = p->getCodeVerboseDocumentComments();
+
+ // COMMENT
+ QString comment = c->getDoc();
+ comment.replace("@ref ", "");
+ comment.replace("@see", "_See_");
+ comment.replace("@short", "_Summary_");
+ comment.replace("@author", "_Author_");
+
+ if (isInterface)
+ getComment()->setText("Module " + RubyClassName + endLine + comment);
+ else
+ getComment()->setText("Class " + RubyClassName + endLine + comment);
+
+ if(forceDoc || !c->getDoc().isEmpty())
+ getComment()->setWriteOutText(true);
+ else
+ getComment()->setWriteOutText(false);
+
+
+ // Now set START/ENDING Text
+ QString startText = "";
+
+ if (parentDoc->parentIsInterface()) {
+ startText.append("module ");
+ } else {
+ startText.append("class ");
+ }
+
+ UMLClassifierList superclasses = c->findSuperClassConcepts(UMLClassifier::CLASS);
+ UMLClassifierList superinterfaces = c->findSuperClassConcepts(UMLClassifier::INTERFACE);
+
+ // write out inheritance
+ startText.append(RubyClassName);
+
+ int i = 0;
+ for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) {
+ if (i == 0) {
+ startText.append(QString(" < ") + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine);
+ } else {
+ // After the first superclass name in the list, assume the classes
+ // are ruby modules that can be mixed in,
+ startText.append("include " + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine);
+ }
+ i++;
+ }
+
+ // Write out the interfaces we 'implement'. Are these modules to be mixed in, in Ruby?
+ for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next()) {
+ startText.append(QString("include ") + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine);
+ }
+
+ // Set the header and end text for the hier.codeblock
+ setStartText(startText);
+}
+
+void RubyClassDeclarationBlock::init (RubyClassifierCodeDocument *parentDoc, const QString &comment)
+{
+
+ setComment(new RubyCodeDocumentation(parentDoc));
+ getComment()->setText(comment);
+
+ setEndText("end");
+
+ updateContent();
+
+}
+
+
+#include "rubyclassdeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h
new file mode 100644
index 00000000..a7732662
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h
@@ -0,0 +1,74 @@
+
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jul 16 2003
+ */
+
+#ifndef RUBYCLASSDECLARATIONBLOCK_H
+#define RUBYCLASSDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+/***************************************************************************
+ rubyclassdeclarationblock.h
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+#include "rubyclassifiercodedocument.h"
+#include "../ownedhierarchicalcodeblock.h"
+
+class RubyClassDeclarationBlock : public OwnedHierarchicalCodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ explicit RubyClassDeclarationBlock ( RubyClassifierCodeDocument * parentDoc, const QString &start = "", const QString &endText = "end", const QString &comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyClassDeclarationBlock ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+protected:
+
+ /**
+ * Update the start/end text of this codeblock.
+ */
+ void updateContent ( );
+
+private:
+
+ void init (RubyClassifierCodeDocument * parent, const QString &comment);
+
+};
+
+#endif // RUBYCLASSDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp
new file mode 100644
index 00000000..1c136df8
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp
@@ -0,0 +1,646 @@
+/***************************************************************************
+ rubyclassifiercodedocument.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/**
+ We carve the Ruby document up into sections as follows:
+
+ * header
+ * class declaration
+ * guts of the class (e.g. accessor methods, operations, dependant classes)
+*/
+
+// own header
+#include "rubyclassifiercodedocument.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "rubycodegenerator.h"
+#include "rubycodecomment.h"
+#include "rubyclassdeclarationblock.h"
+#include "rubycodeclassfielddeclarationblock.h"
+#include "rubycodeoperation.h"
+#include "codegen_utils.h"
+#include "../classifier.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyClassifierCodeDocument::RubyClassifierCodeDocument ( UMLClassifier * concept )
+ : ClassifierCodeDocument (concept) {
+ init();
+}
+
+RubyClassifierCodeDocument::~RubyClassifierCodeDocument ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// Make it easier on ourselves
+RubyCodeGenerationPolicy * RubyClassifierCodeDocument::getRubyPolicy() {
+ CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
+ RubyCodeGenerationPolicy * policy = dynamic_cast<RubyCodeGenerationPolicy*>(pe);
+ return policy;
+}
+
+/**
+ * Get the dialog widget which allows user interaction with the object parameters.
+ * @return CodeDocumentDialog
+ */
+/*
+CodeDocumentDialog RubyClassifierCodeDocument::getDialog ( ) {
+
+}
+*/
+
+// We overwritten by Ruby language implementation to get lowercase path
+QString RubyClassifierCodeDocument::getPath ( )
+{
+
+ QString path = getPackage();
+
+ // Replace all white spaces with blanks
+ path.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ path.replace(QRegExp(" "), "_");
+
+ path.replace(QRegExp("\\."),"/");
+ path.replace(QRegExp("::"), "/");
+
+ path.lower();
+
+ return path;
+
+}
+
+
+// Other methods
+//
+
+QString RubyClassifierCodeDocument::getRubyClassName (const QString &name) {
+ CodeGenerator *g = UMLApp::app()->getGenerator();
+ return Codegen_Utils::capitalizeFirstLetter(g->cleanName(name));
+}
+
+// Initialize this ruby classifier code document
+void RubyClassifierCodeDocument::init ( ) {
+
+ setFileExtension(".rb");
+
+ //initCodeClassFields(); // this is dubious because it calls down to
+ // CodeGenFactory::newCodeClassField(this)
+ // but "this" is still in construction at that time.
+
+ classDeclCodeBlock = 0;
+ publicBlock = 0;
+ protectedBlock = 0;
+ privateBlock = 0;
+ pubConstructorBlock = 0;
+ protConstructorBlock = 0;
+ privConstructorBlock = 0;
+ pubOperationsBlock = 0;
+ privOperationsBlock = 0;
+ protOperationsBlock = 0;
+
+ // this will call updateContent() as well as other things that sync our document.
+ synchronize();
+}
+
+/**
+ * @param op
+ */
+// in the vanilla version, we just tack all operations on the end
+// of the document
+bool RubyClassifierCodeDocument::addCodeOperation (CodeOperation * op )
+{
+ Uml::Visibility scope = op->getParentOperation()->getVisibility();
+ if(!op->getParentOperation()->isConstructorOperation())
+ {
+ switch (scope) {
+ default:
+ case Uml::Visibility::Public:
+ return pubOperationsBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Protected:
+ return protOperationsBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Private:
+ return privOperationsBlock->addTextBlock(op);
+ break;
+ }
+ } else {
+ switch (scope) {
+ default:
+ case Uml::Visibility::Public:
+ return pubConstructorBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Protected:
+ return protConstructorBlock->addTextBlock(op);
+ break;
+ case Uml::Visibility::Private:
+ return privConstructorBlock->addTextBlock(op);
+ break;
+ }
+ }
+}
+
+// Sigh. NOT optimal. The only reason that we need to have this
+// is so we can create the RubyClassDeclarationBlock.
+// would be better if we could create a handler interface that each
+// codeblock used so all we have to do here is add the handler
+// for "rubyclassdeclarationblock"
+void RubyClassifierCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root)
+{
+
+ QDomNode tnode = root.firstChild();
+ QDomElement telement = tnode.toElement();
+ bool loadCheckForChildrenOK = false;
+ while( !telement.isNull() ) {
+ QString nodeName = telement.tagName();
+
+ if( nodeName == "textblocks" ) {
+
+ QDomNode node = telement.firstChild();
+ QDomElement element = node.toElement();
+
+ // if there is nothing to begin with, then we don't worry about it
+ loadCheckForChildrenOK = element.isNull() ? true : false;
+
+ while( !element.isNull() ) {
+ QString name = element.tagName();
+
+ if( name == "codecomment" ) {
+ CodeComment * block = new RubyCodeComment(this);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeComment to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeaccessormethod" ||
+ name == "ccfdeclarationcodeblock"
+ ) {
+ QString acctag = element.attribute("tag","");
+ // search for our method in the
+ TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
+ if(!tb || !addTextBlock(tb))
+ {
+ kError()<<"loadFromXMI : unable to add codeclassfield child method to:"<<this<<endl;
+ // DON'T delete
+ } else
+ loadCheckForChildrenOK= true;
+
+ } else
+ if( name == "codeblock" ) {
+ CodeBlock * block = newCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeblockwithcomments" ) {
+ CodeBlockWithComments * block = newCodeBlockWithComments();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "header" ) {
+ // do nothing.. this is treated elsewhere
+ } else
+ if( name == "hierarchicalcodeblock" ) {
+ HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl;
+ block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeoperation" ) {
+ // find the code operation by id
+ QString id = element.attribute("parent_id","-1");
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+ if(op) {
+ CodeOperation * block = new RubyCodeOperation(this, op);
+ block->loadFromXMI(element);
+ if(addTextBlock(block))
+ loadCheckForChildrenOK= true;
+ else
+ {
+ kError()<<"Unable to add codeoperation to:"<<this<<endl;
+ block->deleteLater();
+ }
+ } else
+ kError()<<"Unable to find operation create codeoperation for:"<<this<<endl;
+ } else
+ if( name == "rubyclassdeclarationblock" )
+ {
+ RubyClassDeclarationBlock * block = getClassDecl();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"Unable to add ruby code declaration block to:"<<this<<endl;
+ // DON'T delete.
+ // block->deleteLater();
+ } else
+ loadCheckForChildrenOK= true;
+ }
+ // This last item is only needed for extreme debugging conditions
+ // (E.g. making new codeclassdocument loader)
+ // else
+ // kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl;
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+ break;
+ }
+
+ tnode = telement.nextSibling();
+ telement = tnode.toElement();
+ }
+
+ if(!loadCheckForChildrenOK)
+ {
+ CodeDocument * test = dynamic_cast<CodeDocument*>(this);
+ if(test)
+ {
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
+ } else {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
+ if(hb)
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
+ else
+ kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
+ }
+ }
+
+
+}
+
+QString RubyClassifierCodeDocument::scopeToRubyDecl(Uml::Visibility scope)
+{
+ QString scopeString;
+ switch(scope)
+ {
+ case Uml::Visibility::Public:
+ scopeString = "public";
+ break;
+ case Uml::Visibility::Protected:
+ scopeString = "protected";
+ break;
+ case Uml::Visibility::Private:
+ default:
+ scopeString = "private";
+ break;
+ }
+ return scopeString;
+}
+
+RubyClassDeclarationBlock * RubyClassifierCodeDocument::getClassDecl()
+{
+ if(!classDeclCodeBlock)
+ {
+ classDeclCodeBlock = new RubyClassDeclarationBlock (this);
+ classDeclCodeBlock->setTag("ClassDeclBlock");
+ }
+ return classDeclCodeBlock;
+}
+
+void RubyClassifierCodeDocument::resetTextBlocks()
+{
+
+ // all special pointers to text blocks need to be zero'd out
+ operationsBlock = 0;
+ constructorBlock = 0;
+ classDeclCodeBlock = 0;
+
+ // now do traditional release of text blocks.
+ ClassifierCodeDocument::resetTextBlocks();
+}
+
+// This method will cause the class to rebuild its text representation.
+// based on the parent classifier object.
+// For any situation in which this is called, we are either building the code
+// document up, or replacing/regenerating the existing auto-generated parts. As
+// such, we will want to insert everything we resonablely will want
+// during creation. We can set various parts of the document (esp. the
+// comments) to appear or not, as needed.
+void RubyClassifierCodeDocument::updateContent( )
+{
+ // Gather info on the various fields and parent objects of this class...
+ UMLClassifier * c = getParentClassifier();
+ RubyCodeGenerator * gen = dynamic_cast<RubyCodeGenerator*>(UMLApp::app()->getGenerator());
+
+ // first, set the global flag on whether or not to show classfield info
+ // This depends on whether or not we have attribute/association classes
+ CodeClassFieldList * cfList = getCodeClassFieldList();
+ for(CodeClassField * field = cfList->first(); field; field = cfList->next())
+ if(field->parentIsAttribute())
+ field->setWriteOutMethods(gen->getAutoGenerateAttribAccessors());
+ else
+ field->setWriteOutMethods(gen->getAutoGenerateAssocAccessors());
+
+ // attribute-based ClassFields
+ // we do it this way to have the static fields sorted out from regular ones
+ CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public );
+ CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public );
+ CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected );
+ CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected );
+ CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private );
+ CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private);
+
+ // association-based ClassFields
+ // don't care if they are static or not..all are lumped together
+ CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Public);
+ CodeClassFieldList publicAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Public);
+ CodeClassFieldList publicCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Public );
+
+ CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Protected);
+ CodeClassFieldList protAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Protected);
+ CodeClassFieldList protCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Protected);
+
+ CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Private);
+ CodeClassFieldList privAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Private);
+ CodeClassFieldList privCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Private);
+
+ bool isInterface = parentIsInterface();
+ bool hasOperationMethods = c->getOpList().last() ? true : false;
+ CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
+ QString endLine = pol->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time
+
+ //
+ // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
+ //
+
+
+ // CLASS DECLARATION BLOCK
+ //
+
+ // get the declaration block. If its not already present, add it too
+ RubyClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
+ addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
+
+ // declare public, protected and private methods, attributes (fields).
+ // set the start text ONLY if this is the first time we created the objects.
+ bool createdPublicBlock = publicBlock == 0 ? true : false;
+ publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("publicBlock","Public Items",0);
+ if (createdPublicBlock)
+ publicBlock->setStartText("public");
+
+ bool createdProtBlock = protectedBlock == 0 ? true : false;
+ protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("protectedBlock","Protected Items",0);
+ if(createdProtBlock)
+ protectedBlock->setStartText("protected");
+
+ bool createdPrivBlock = privateBlock == 0 ? true : false;
+ privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("privateBlock","Private Items",0);
+ if(createdPrivBlock)
+ privateBlock->setStartText("private");
+
+ // NOW create document in sections..
+ // now we want to populate the body of our class
+ // our layout is the following general groupings of code blocks:
+
+ // start ruby classifier document
+
+ // header comment
+
+ // class declaration
+
+ // section:
+
+ // section:
+ // - methods section comment
+
+ // sub-section: constructor ops
+ // - constructor method section comment
+ // - constructor methods (0+ codeblocks)
+
+ // sub-section: accessors
+ // - accessor method section comment
+ // - static accessor methods (0+ codeblocks)
+ // - non-static accessor methods (0+ codeblocks)
+
+ // sub-section: non-constructor ops
+ // - operation method section comment
+ // - operations (0+ codeblocks)
+
+ // end class declaration
+
+ // end ruby classifier document
+
+
+ // Q: Why use the more complicated scheme of arranging code blocks within codeblocks?
+ // A: This will allow us later to preserve the format of our document so that if
+ // codeblocks are added, they may be easily added in the correct place, rather than at
+ // the end of the document, or by using a difficult algorithm to find the location of
+ // the last appropriate code block sibling (which may not exist.. for example user adds
+ // a constructor operation, but there currently are no constructor code blocks
+ // within the document).
+
+
+ //
+ // METHODS section
+ //
+
+ // get/create the method codeblock
+ // public methods
+ HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock("pubMethodsBlock", "", 1);
+ CodeComment * pubMethodsComment = pubMethodsBlock->getComment();
+ bool forceDoc = pol->getCodeVerboseDocumentComments();
+ // set conditions for showing this comment
+ if (!forceDoc && !hasClassFields() && !hasOperationMethods)
+ pubMethodsComment->setWriteOutText(false);
+ else
+ pubMethodsComment->setWriteOutText(true);
+
+ // protected methods
+ HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock("protMethodsBlock", "", 1);
+ CodeComment * protMethodsComment = protMethodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forceDoc && !hasClassFields() && !hasOperationMethods)
+ protMethodsComment->setWriteOutText(false);
+ else
+ protMethodsComment->setWriteOutText(true);
+
+ // private methods
+ HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock("privMethodsBlock", "", 1);
+ CodeComment * privMethodsComment = privMethodsBlock->getComment();
+ // set conditions for showing this comment
+ if (!forceDoc && !hasClassFields() && !hasOperationMethods)
+ privMethodsComment->setWriteOutText(false);
+ else
+ privMethodsComment->setWriteOutText(true);
+
+ // METHODS sub-section : constructor methods
+ //
+
+ // public
+ pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * pubConstComment = pubConstructorBlock->getComment();
+ if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ pubConstComment->setWriteOutText(false);
+ else
+ pubConstComment->setWriteOutText(true);
+
+ // protected
+ protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * protConstComment = protConstructorBlock->getComment();
+ if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ protConstComment->setWriteOutText(false);
+ else
+ protConstComment->setWriteOutText(true);
+
+ // private
+ privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
+ // special condiions for showing comment: only when autogenerateding empty constructors
+ // Although, we *should* check for other constructor methods too
+ CodeComment * privConstComment = privConstructorBlock->getComment();
+ if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors()))
+ privConstComment->setWriteOutText(false);
+ else
+ privConstComment->setWriteOutText(true);
+
+ // get/create the accessor codeblock
+ // public
+ HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * pubAccessComment = pubAccessorBlock->getComment();
+ if (!forceDoc && !hasClassFields())
+ pubAccessComment->setWriteOutText(false);
+ else
+ pubAccessComment->setWriteOutText(true);
+
+ // protected
+ HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * protAccessComment = protAccessorBlock->getComment();
+ if (!forceDoc && !hasClassFields())
+ protAccessComment->setWriteOutText(false);
+ else
+ protAccessComment->setWriteOutText(true);
+
+ // private
+ HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
+ // set conditions for showing section comment
+ CodeComment * privAccessComment = privAccessorBlock->getComment();
+ if (!forceDoc && !hasClassFields())
+ privAccessComment->setWriteOutText(false);
+ else
+ privAccessComment->setWriteOutText(true);
+
+ // now, 2 sub-sub sections in accessor block
+ // add/update accessor methods for attributes
+ HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubRegularAccessorMethods", "", 1);
+ pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+
+ HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock("protStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock("protRegularAccessorMethods", "", 1);
+ protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+
+ HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock("privStaticAccessorMethods", "", 1);
+ HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock("privRegularAccessorMethods", "", 1);
+ privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
+ privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
+ // now add in accessors as appropriate
+
+ // public stuff
+ pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields);
+ pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields);
+
+ // protected stuff
+ protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields);
+ protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields);
+
+ // private stuff
+ privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields);
+ privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields);
+
+ // METHODS subsection : Operation methods (which aren't constructors)
+ //
+
+ // setup/get/create the operations codeblock
+
+ // public
+ pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * pubOcomment = pubOperationsBlock->getComment();
+ if (!forceDoc && !hasOperationMethods )
+ pubOcomment->setWriteOutText(false);
+ else
+ pubOcomment->setWriteOutText(true);
+
+ //protected
+ protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * protOcomment = protOperationsBlock->getComment();
+ if (!forceDoc && !hasOperationMethods )
+ protOcomment->setWriteOutText(false);
+ else
+ protOcomment->setWriteOutText(true);
+
+ //private
+ privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
+ // set conditions for showing section comment
+ CodeComment * privOcomment = privOperationsBlock->getComment();
+ if (!forceDoc && !hasOperationMethods )
+ privOcomment->setWriteOutText(false);
+ else
+ privOcomment->setWriteOutText(true);
+
+}
+
+
+#include "rubyclassifiercodedocument.moc"
diff --git a/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h
new file mode 100644
index 00000000..c5f89d07
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ rubyclassdeclarationblock.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef RUBYCLASSIFIERCODEDOCUMENT_H
+#define RUBYCLASSIFIERCODEDOCUMENT_H
+
+#include <qstring.h>
+
+#include "../codeclassfieldlist.h"
+#include "../classifiercodedocument.h"
+#include "../classifier.h"
+#include "../hierarchicalcodeblock.h"
+#include "classifierinfo.h"
+#include "rubycodeclassfield.h"
+#include "rubycodeoperation.h"
+
+class RubyClassDeclarationBlock;
+class RubyCodeGenerationPolicy;
+
+/**
+ * class RubyClassifierCodeDocument
+ * A Ruby UMLClassifier Code Document.
+ */
+
+class RubyClassifierCodeDocument : public ClassifierCodeDocument
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructor
+ */
+ RubyClassifierCodeDocument (UMLClassifier * classifier);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyClassifierCodeDocument ( );
+
+ /**
+ * Get the dialog widget which allows user interaction with the object parameters.
+ * @return CodeDocumentDialog
+ */
+ //CodeDocumentDialog getDialog ( );
+
+ QString scopeToRubyDecl(Uml::Visibility scope);
+
+ // Make it easier on ourselves
+ RubyCodeGenerationPolicy * getRubyPolicy();
+
+ QString getRubyClassName (const QString &name);
+
+ QString getPath();
+
+ /** add a code operation to this ruby classifier code document.
+ * @return bool which is true IF the code operation was added successfully
+ */
+ bool addCodeOperation (CodeOperation * op );
+
+protected:
+
+ // reset/clear our inventory of textblocks in this document
+ void resetTextBlocks();
+
+ /**
+ * need to overwrite this for ruby since we need to pick up the
+ * ruby class declaration block.
+ */
+ virtual void loadChildTextBlocksFromNode ( QDomElement & root);
+
+ void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, RubyClassDeclarationBlock * codeBlock);
+
+ bool forceDoc ();
+
+ void updateContent();
+
+private:
+
+ RubyClassDeclarationBlock * classDeclCodeBlock;
+ HierarchicalCodeBlock * constructorBlock;
+ HierarchicalCodeBlock * operationsBlock;
+
+ HierarchicalCodeBlock * publicBlock;
+ HierarchicalCodeBlock * privateBlock;
+ HierarchicalCodeBlock * protectedBlock;
+
+// HierarchicalCodeBlock * namespaceBlock;
+
+ HierarchicalCodeBlock * pubConstructorBlock;
+ HierarchicalCodeBlock * protConstructorBlock;
+ HierarchicalCodeBlock * privConstructorBlock;
+
+ HierarchicalCodeBlock * pubOperationsBlock;
+ HierarchicalCodeBlock * privOperationsBlock;
+ HierarchicalCodeBlock * protOperationsBlock;
+
+ ClassifierInfo * info;
+
+ void init ( );
+ RubyClassDeclarationBlock * getClassDecl();
+
+
+};
+
+#endif // RUBYCLASSIFIERCODEDOCUMENT_H
diff --git a/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp
new file mode 100644
index 00000000..a3f55c44
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp
@@ -0,0 +1,233 @@
+/***************************************************************************
+ rubycodeaccessormethod.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodeaccessormethod.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "../attribute.h"
+#include "../codegenerator.h"
+#include "../classifiercodedocument.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+#include "codegen_utils.h"
+#include "rubyclassifiercodedocument.h"
+#include "rubycodegenerationpolicy.h"
+#include "rubycodegenerator.h"
+#include "rubycodeclassfield.h"
+#include "rubycodedocumentation.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeAccessorMethod::RubyCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type)
+ : CodeAccessorMethod ( field )
+{
+ setType(type);
+
+ // lets use full-blown comment
+ RubyClassifierCodeDocument *rccd = dynamic_cast<RubyClassifierCodeDocument*>(field->getParentDocument());
+ setComment(new RubyCodeDocumentation(rccd));
+}
+
+RubyCodeAccessorMethod::~RubyCodeAccessorMethod ( ) { }
+
+// Other methods
+//
+
+void RubyCodeAccessorMethod::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement)
+{
+
+ // set super-class attributes
+ CodeAccessorMethod::setAttributesOnNode(doc, blockElement);
+
+ // set local attributes now
+}
+
+void RubyCodeAccessorMethod::setAttributesFromNode( QDomElement & root)
+{
+
+ // set attributes from superclass method the XMI
+ CodeAccessorMethod::setAttributesFromNode(root);
+
+ // load local stuff
+
+}
+
+void RubyCodeAccessorMethod::updateContent( )
+{
+
+ CodeClassField * parentField = getParentClassField();
+ RubyCodeClassField * rubyfield = dynamic_cast<RubyCodeClassField*>(parentField);
+ QString fieldName = rubyfield->getFieldName();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ QString text = "";
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ {
+ int maxOccurs = rubyfield->maximumListOccurances();
+ QString fieldType = rubyfield->getTypeName();
+ QString indent = getIndentation();
+ if(maxOccurs > 0)
+ text += "if "+fieldName+".size() < "+ QString::number(maxOccurs)+' '+endLine+indent;
+ text += fieldName+".push(value)";
+ if(maxOccurs > 0)
+ {
+ text += endLine+"else"+endLine;
+ text += indent + "puts(\"ERROR: Can't add"+fieldType+" to "+fieldName+", minimum number of items reached.\")"+endLine+"end"+endLine;
+ }
+ break;
+ }
+ case CodeAccessorMethod::GET:
+// text = "return "+fieldName;
+ break;
+ case CodeAccessorMethod::LIST:
+ text = "return "+fieldName;
+ break;
+ case CodeAccessorMethod::REMOVE:
+ {
+ int minOccurs = rubyfield->minimumListOccurances();
+ RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(rubyfield->getParentDocument());
+ QString fieldType = rubyfield->getTypeName();
+ QString indent = getIndentation();
+
+ if(minOccurs > 0)
+ text += "if "+fieldName+".size() >= "+ QString::number(minOccurs)+endLine+indent;
+ text += fieldName+".delete(value)";
+ if(minOccurs > 0)
+ {
+ text += endLine+"else"+endLine;
+ text += indent + "puts(\"ERROR: Cant remove"+fieldType+" from "+fieldName+", minimum number of items reached.\")"+endLine+"end"+endLine;
+ }
+ break;
+ }
+ case CodeAccessorMethod::SET:
+// text = fieldName+" = value";
+ break;
+ default:
+ // do nothing
+ break;
+ }
+
+ setText(text);
+
+}
+
+void RubyCodeAccessorMethod::updateMethodDeclaration()
+{
+
+ RubyCodeClassField * rubyfield = dynamic_cast<RubyCodeClassField*>(getParentClassField());
+ RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(rubyfield->getParentDocument());
+
+ // gather defs
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAttributeAccessorScope();
+ QString strVis = rubydoc->scopeToRubyDecl(rubyfield->getVisibility());
+ QString fieldName = RubyCodeGenerator::cppToRubyName(rubyfield->getFieldName());
+ QString fieldType = RubyCodeGenerator::cppToRubyType(rubyfield->getTypeName());
+ QString objectType = rubyfield->getListObjectType();
+ if(objectType.isEmpty())
+ objectType = fieldName;
+ QString endLine = p->getNewLineEndingChars();
+
+ QString description = getParentObject()->getDoc();
+ description.replace(QRegExp("m_[npb](?=[A-Z])"), "");
+ description.replace("m_", "");
+ description.replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine);
+
+ // set scope of this accessor appropriately..if its an attribute,
+ // we need to be more sophisticated
+ if(rubyfield->parentIsAttribute())
+ switch (scopePolicy) {
+ case CodeGenerationPolicy::Public:
+ case CodeGenerationPolicy::Private:
+ case CodeGenerationPolicy::Protected:
+ strVis = rubydoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy);
+ break;
+ default:
+ case CodeGenerationPolicy::FromParent:
+ // do nothing..already have taken parent value
+ break;
+ }
+
+ // some variables we will need to populate
+ QString headerText = "";
+ QString methodReturnType = "";
+ QString methodName = "";
+ QString methodParams = "";
+
+ switch(getType()) {
+ case CodeAccessorMethod::ADD:
+ methodName = "add" + Codegen_Utils::capitalizeFirstLetter(fieldType);
+ methodReturnType = "";
+ methodParams = objectType+" value ";
+ headerText = "Add an object of type "+objectType+" to the Array "+fieldName+endLine+description+endLine+"@return nil";
+ setStartMethodText("def "+ methodName + '(' + methodParams + ')');
+ setEndMethodText("end");
+ break;
+ case CodeAccessorMethod::GET:
+ headerText = "Get the value of " + fieldName + endLine + description;
+ setStartMethodText(QString("attr_reader :") + fieldName);
+ setEndMethodText("");
+ break;
+ case CodeAccessorMethod::LIST:
+ methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldType)+"List";
+ methodReturnType = "";
+ headerText = "Get the list of "+fieldName+endLine+description+endLine+"_returns_ List of "+fieldName;
+ setStartMethodText("def "+ methodName + '(' + methodParams + ')');
+ setEndMethodText("end");
+ break;
+ case CodeAccessorMethod::REMOVE:
+ methodName = "remove" + Codegen_Utils::capitalizeFirstLetter(fieldType);
+ methodReturnType = "";
+ methodParams = objectType+" value ";
+ headerText = "Remove an object of type "+objectType+" from the List "+fieldName+endLine+description;
+ setStartMethodText("def "+ methodName + '(' + methodParams + ')');
+ setEndMethodText("end");
+ break;
+ case CodeAccessorMethod::SET:
+ headerText = "Set the value of " + fieldName + endLine + description;
+ setStartMethodText(QString("attr_writer :") + fieldName);
+ setEndMethodText("");
+ break;
+ default:
+ // do nothing..no idea what this is
+ kWarning()<<"Warning: can't generate RubyCodeAccessorMethod for type: "<<getType()<<endl;
+ break;
+ }
+
+ // set header once.
+ if (getComment()->getText().isEmpty())
+ getComment()->setText(headerText);
+
+}
+
+void RubyCodeAccessorMethod::update()
+{
+ updateMethodDeclaration();
+ updateContent();
+}
+
+#include "rubycodeaccessormethod.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h
new file mode 100644
index 00000000..7eb9c892
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ rubycodeaccessormethod.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Thu Oct 2 2003
+ */
+
+#ifndef RUBYCODEACCESSORMETHOD_H
+#define RUBYCODEACCESSORMETHOD_H
+
+#include <qstring.h>
+
+#include "../codeaccessormethod.h"
+#include "rubycodeclassfield.h"
+
+class RubyCodeAccessorMethod : public CodeAccessorMethod
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ RubyCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeAccessorMethod ( );
+
+ /**
+ * Must be called before this object is usable
+ */
+ void update();
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ virtual void updateMethodDeclaration();
+ virtual void updateContent();
+
+private:
+
+};
+
+#endif // RUBYCODEACCESSORMETHOD_H
diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp b/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp
new file mode 100644
index 00000000..35438abd
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp
@@ -0,0 +1,113 @@
+/***************************************************************************
+ rubycodeclassfield.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodeclassfield.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "rubycodecomment.h"
+#include "rubycodegenerator.h"
+
+#include "../attribute.h"
+#include "../umlobject.h"
+#include "../umlrole.h"
+#include "../uml.h"
+
+#include "rubyclassifiercodedocument.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeClassField::RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role)
+ : CodeClassField(parentDoc, role)
+{
+
+}
+
+RubyCodeClassField::RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib)
+ : CodeClassField(parentDoc, attrib)
+{
+
+}
+
+RubyCodeClassField::~RubyCodeClassField ( ) { }
+
+//
+// Methods
+//
+
+// Other methods
+//
+
+QString RubyCodeClassField::getFieldName() {
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = (UMLAttribute*) getParentObject();
+ return cleanName(at->getName());
+ }
+ else
+ {
+ UMLRole * role = (UMLRole*) getParentObject();
+ QString roleName = role->getName();
+ if(fieldIsSingleValue()) {
+ return roleName.replace(0, 1, roleName.left(1).lower());
+ } else {
+ return roleName.lower() + "Array";
+ }
+ }
+}
+
+
+QString RubyCodeClassField::getInitialValue() {
+
+ if (parentIsAttribute())
+ {
+ UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() );
+ if (at) {
+ return fixInitialStringDeclValue(at->getInitialValue(), getTypeName());
+ } else {
+ kError() << "RubyodeClassField::getInitialValue: parent object is not a UMLAttribute"
+ << endl;
+ return "";
+ }
+ return fixInitialStringDeclValue(at->getInitialValue(), getTypeName());
+ }
+ else
+ {
+ if(fieldIsSingleValue()) {
+ // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1,
+ // then we can just return 'empty' string (minor problem).
+ return QString("");
+ } else {
+ return RubyCodeGenerator::getListFieldClassName()+".new()";
+ }
+ }
+
+}
+
+QString RubyCodeClassField::getTypeName ( )
+{
+ return RubyCodeGenerator::cppToRubyType(CodeClassField::getTypeName());
+}
+
+#include "rubycodeclassfield.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfield.h b/umbrello/umbrello/codegenerators/rubycodeclassfield.h
new file mode 100644
index 00000000..384f0b5d
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeclassfield.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ rubycodeclassfield.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODECLASSFIELD_H
+#define RUBYCODECLASSFIELD_H
+
+#include <qstring.h>
+
+#include "../codeclassfield.h"
+
+class ClassifierCodeDocument;
+
+class RubyCodeClassField : public CodeClassField
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role);
+ RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeClassField ( );
+
+ QString getFieldType();
+ QString getFieldName();
+ QString getInitialValue();
+
+ QString getTypeName ( );
+protected:
+
+private:
+
+ // void initDeclCodeBlock ();
+
+};
+
+#endif // RUBYCODECLASSFIELD_H
diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp
new file mode 100644
index 00000000..380c05e0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp
@@ -0,0 +1,112 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "rubycodeclassfielddeclarationblock.h"
+
+#include "rubycodeclassfield.h"
+#include "rubyclassifiercodedocument.h"
+#include "rubycodegenerationpolicy.h"
+#include "../classifier.h"
+#include "../umlrole.h"
+#include "../codegenerator.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeClassFieldDeclarationBlock::RubyCodeClassFieldDeclarationBlock ( CodeClassField * parent )
+ : CodeClassFieldDeclarationBlock ( parent )
+{
+ setOverallIndentationLevel(1);
+ updateContent();
+}
+
+RubyCodeClassFieldDeclarationBlock::~RubyCodeClassFieldDeclarationBlock ( ) { }
+
+//
+// Methods
+//
+
+
+
+// Other methods
+//
+
+/**
+ */
+void RubyCodeClassFieldDeclarationBlock::updateContent( )
+{
+
+ CodeClassField * cf = getParentClassField();
+ ClassifierCodeDocument * doc = cf->getParentDocument();
+ RubyCodeClassField * rcf = dynamic_cast<RubyCodeClassField*>(cf);
+ RubyClassifierCodeDocument* rdoc = dynamic_cast<RubyClassifierCodeDocument*>(doc);
+ CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy();
+ CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAssociationFieldScope();
+
+ // Set the comment
+ QString notes = getParentObject()->getDoc();
+ getComment()->setText(notes);
+
+ // Set the body
+ QString staticValue = getParentObject()->getStatic() ? "static " : "";
+ QString scopeStr = rdoc->scopeToRubyDecl(getParentObject()->getVisibility());
+
+ // IF this is from an association, then scope taken as appropriate to policy
+ if(!rcf->parentIsAttribute())
+ {
+ switch (scopePolicy) {
+ case CodeGenerationPolicy::Public:
+ case CodeGenerationPolicy::Private:
+ case CodeGenerationPolicy::Protected:
+ scopeStr = rdoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy);
+ break;
+ default:
+ case CodeGenerationPolicy::FromParent:
+ // do nothing here... will leave as from parent object
+ break;
+ }
+ }
+
+ QString typeName = rcf->getTypeName();
+ QString fieldName = rcf->getFieldName();
+ QString initialV = rcf->getInitialValue();
+
+ if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue())
+ typeName = "Array";
+
+ QString body = staticValue+scopeStr+' '+typeName+' '+fieldName;
+ if (!initialV.isEmpty())
+ body.append(" = " + initialV);
+ else if (!cf->parentIsAttribute())
+ {
+ UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject());
+ if (role->getObject()->getBaseType() == Uml::ot_Interface)
+ {
+ // do nothing.. can't instanciate an interface
+ } else {
+
+ // FIX?: IF a constructor method exists in the classifiercodedoc
+ // of the parent Object, then we can use that instead (if its empty).
+ if(cf->fieldIsSingleValue())
+ {
+ if(!typeName.isEmpty())
+ body.append(" = " + typeName + ".new()");
+ } else
+ body.append(" = []");
+ }
+ }
+
+ setText(body);
+
+}
+
+#include "rubycodeclassfielddeclarationblock.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h
new file mode 100644
index 00000000..c3e18a68
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ rubycodeclassfielddeclarationblock.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODECLASSFIELDDECLARATIONBLOCK_H
+#define RUBYCODECLASSFIELDDECLARATIONBLOCK_H
+
+#include <qstring.h>
+
+#include "../codeclassfielddeclarationblock.h"
+
+class RubyCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ RubyCodeClassFieldDeclarationBlock ( CodeClassField * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeClassFieldDeclarationBlock ( );
+
+protected:
+
+ // this will be called by syncToParent whenever the parent object is "modified"
+ void updateContent ( );
+
+private:
+
+
+};
+
+#endif // RUBYCODECLASSFIELDDECLARATIONBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/rubycodecomment.cpp b/umbrello/umbrello/codegenerators/rubycodecomment.cpp
new file mode 100644
index 00000000..46374128
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodecomment.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ rubycodecomment.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "rubycodecomment.h"
+#include <qregexp.h>
+
+// Constructors/Destructors
+//
+
+RubyCodeComment::RubyCodeComment(CodeDocument * doc, const QString & text)
+ : CodeComment(doc, text)
+{
+
+}
+
+RubyCodeComment::~RubyCodeComment( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+// Public attribute accessor methods
+//
+
+// Other methods
+//
+
+QString RubyCodeComment::getNewEditorLine( int amount ) {
+ QString line = getIndentationString(amount) + "# ";
+ return line;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString RubyCodeComment::unformatText(const QString & text, const QString & indent)
+{
+ // remove leading or trailing comment stuff
+ QString mytext = TextBlock::unformatText(text, indent);
+
+ // now leading hash
+ mytext.remove(QRegExp("^#\\s*"));
+ return mytext;
+}
+
+/**
+ * @return QString
+ */
+QString RubyCodeComment::toString( )
+{
+ QString output = "";
+
+ // simple output method
+ if (getWriteOutText()) {
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ output.append(formatMultiLineText(getText(), indent + "# ", endLine + endLine));
+ }
+
+ return output;
+}
+
+
+#include "rubycodecomment.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodecomment.h b/umbrello/umbrello/codegenerators/rubycodecomment.h
new file mode 100644
index 00000000..35fb87a8
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodecomment.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ rubycodecomment.h
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODECOMMENT_H
+#define RUBYCODECOMMENT_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+/**
+ * class RubyCodeComment
+ * A Ruby code comment. There are two styles of comments:
+ * these are simply started with a hash and no terminating
+ * characters, or delimited by '=begin' and '=end' tags at the
+ * start of lines
+ */
+
+class RubyCodeComment : virtual public CodeComment
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructors
+ */
+ explicit RubyCodeComment ( CodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeComment ( );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the "#" as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+protected:
+
+private:
+
+};
+
+#endif // RUBYCODECOMMENT_H
diff --git a/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp b/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp
new file mode 100644
index 00000000..6c69530a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ rubycodedocumentation.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodedocumentation.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// local includes
+#include "rubyclassifiercodedocument.h"
+#include "rubycodegenerationpolicy.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeDocumentation::RubyCodeDocumentation ( RubyClassifierCodeDocument * doc, const QString & text )
+ : CodeComment ((CodeDocument*) doc, text)
+{
+
+}
+
+RubyCodeDocumentation::~RubyCodeDocumentation ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void RubyCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "rubycodedocumentation" );
+ setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may
+ // just use parent TextBlock method
+ root.appendChild( blockElement );
+}
+
+/**
+ * @return QString
+ */
+QString RubyCodeDocumentation::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ bool useHashOutput = true;
+
+ // need to figure out output type from ruby policy
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ useHashOutput = false;
+
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ QString body = getText();
+ if( useHashOutput)
+ {
+ if(!body.isEmpty())
+ output.append(formatMultiLineText (body, indent +"# ", endLine));
+ } else {
+ output.append("=begin rdoc"+endLine);
+ output.append(formatMultiLineText (body, indent +' ', endLine));
+ output.append("=end"+endLine);
+ }
+ }
+
+ return output;
+}
+
+QString RubyCodeDocumentation::getNewEditorLine ( int amount )
+{
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return getIndentationString(amount) + ' ';
+ else
+ return getIndentationString(amount) + "# ";
+}
+
+int RubyCodeDocumentation::firstEditableLine() {
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ return 1;
+ return 0;
+}
+
+int RubyCodeDocumentation::lastEditableLine() {
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ return -1; // very last line is NOT editable
+ }
+ return 0;
+}
+
+/** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+QString RubyCodeDocumentation::unformatText ( const QString & text , const QString & indent)
+{
+
+ QString mytext = TextBlock::unformatText(text, indent);
+ CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy();
+ // remove leading or trailing comment stuff
+ mytext.remove(QRegExp('^'+indent));
+ if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine)
+ {
+ mytext.remove(QRegExp("^=begin\\s*(rdoc)?\\s*\n?"));
+ mytext.remove(QRegExp("^=end\\s*\n?$"));
+ } else
+ mytext.remove(QRegExp("^#\\s*"));
+
+ return mytext;
+}
+
+
+#include "rubycodedocumentation.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodedocumentation.h b/umbrello/umbrello/codegenerators/rubycodedocumentation.h
new file mode 100644
index 00000000..72908f78
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodedocumentation.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+ rubycodedocumentation.h
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODEDOCUMENTATION_H
+#define RUBYCODEDOCUMENTATION_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+class RubyClassifierCodeDocument;
+
+/**
+ * class RubyCodeDocumentation
+ * A Ruby code comment. There is only a single styles of comments:
+ * these are simply started with a hash and no terminating
+ * characters
+ */
+
+class RubyCodeDocumentation : virtual public CodeComment
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit RubyCodeDocumentation ( RubyClassifierCodeDocument * doc, const QString & text = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeDocumentation ( );
+
+ // Public attributes
+ //
+
+ // Other
+ //
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "" );
+
+ /** a special version here because we want to not only indent
+ * the new line, but to add the "# " sequence as well.
+ */
+ virtual QString getNewEditorLine ( int amount );
+
+ /** Ush. These are terrifically bad and must one day go away.
+ * Both methods indicate the range of lines in this textblock
+ * which may be edited by the codeeditor (assuming that any are
+ * actually editable). The default case is no lines are editable.
+ * The line numbering starts with '0' and a '-1' means no line
+ * qualifies.
+ */
+ virtual int firstEditableLine();
+ virtual int lastEditableLine();
+
+
+protected:
+
+private:
+
+};
+
+#endif // RUBYCODEDOCUMENTATION_H
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui b/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui
new file mode 100644
index 00000000..14bcf0f2
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui
@@ -0,0 +1,248 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>RubyCodeGenerationFormBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>462</width>
+ <height>376</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="2" column="0">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Auto-Generate Methods</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_generateConstructors</cstring>
+ </property>
+ <property name="text">
+ <string>Empty constructor methods</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>m_generateAssocAccessors</cstring>
+ </property>
+ <property name="text">
+ <string>Association accessor methods</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>m_generateAttribAccessors</cstring>
+ </property>
+ <property name="text">
+ <string>Attribute accessor methods</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Private</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Protected</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>From Parent Object</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_accessorScopeCB</cstring>
+ </property>
+ <property name="currentItem">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Default attribute accessor scope:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Default association field scope:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Private</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Protected</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>From Parent Role</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_assocFieldScopeCB</cstring>
+ </property>
+ <property name="currentItem">
+ <number>3</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Documentation</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Style:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>Hash (#)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Begin-End (=begin =end)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_SelectCommentStyle</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;Ruby Code Generation&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp
new file mode 100644
index 00000000..1a01421a
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp
@@ -0,0 +1,170 @@
+/***************************************************************************
+ rubycodegenerationpolicy.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodegenerationpolicy.h"
+// qt/kde includes
+#include <kconfig.h>
+// app includes
+#include "rubycodegenerationpolicypage.h"
+#include "rubycodegenerator.h"
+#include "../uml.h"
+
+const bool RubyCodeGenerationPolicy::DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS = true;
+const bool RubyCodeGenerationPolicy::DEFAULT_AUTO_GEN_ASSOC_ACCESSORS = true;
+
+// Constructors/Destructors
+//
+
+RubyCodeGenerationPolicy::RubyCodeGenerationPolicy(KConfig *config)
+{
+ init();
+ setDefaults(config,false);
+}
+
+RubyCodeGenerationPolicy::~RubyCodeGenerationPolicy ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// Public attribute accessor methods
+//
+
+/**
+ * Set the value of m_autoGenerateAttribAccessors
+ * @param new_var the new value
+ */
+void RubyCodeGenerationPolicy::setAutoGenerateAttribAccessors( bool var ) {
+ m_autoGenerateAttribAccessors = var;
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+/**
+ * Set the value of m_autoGenerateAssocAccessors
+ * @param new_var the new value
+ */
+void RubyCodeGenerationPolicy::setAutoGenerateAssocAccessors( bool var ) {
+ m_autoGenerateAssocAccessors = var;
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+/**
+ * Get the value of m_autoGenerateAttribAccessors
+ * @return the value of m_autoGenerateAttribAccessors
+ */
+bool RubyCodeGenerationPolicy::getAutoGenerateAttribAccessors( ){
+ return m_autoGenerateAttribAccessors;
+}
+
+/**
+ * Get the value of m_autoGenerateAssocAccessors
+ * @return the value of m_autoGenerateAssocAccessors
+ */
+bool RubyCodeGenerationPolicy::getAutoGenerateAssocAccessors( ){
+ return m_autoGenerateAssocAccessors;
+}
+
+// Other methods
+//
+
+void RubyCodeGenerationPolicy::writeConfig ( KConfig * config )
+{
+ // @todo do we need to call CodeGenerationPolicy::writeConfig ???
+
+ // write ONLY the Ruby specific stuff
+ config->setGroup("Ruby Code Generation");
+
+ config->writeEntry("autoGenAccessors",getAutoGenerateAttribAccessors());
+ config->writeEntry("autoGenAssocAccessors",getAutoGenerateAssocAccessors());
+}
+
+void RubyCodeGenerationPolicy::setDefaults ( CodeGenPolicyExt * clone, bool emitUpdateSignal )
+{
+
+ RubyCodeGenerationPolicy * rclone;
+ if (!clone)
+ return;
+
+ // NOW block signals for ruby param setting
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+
+ // now do ruby-specific stuff IF our clone is also a RubyCodeGenerationPolicy object
+ if((rclone = dynamic_cast<RubyCodeGenerationPolicy*>(clone)))
+ {
+ setAutoGenerateAttribAccessors(rclone->getAutoGenerateAttribAccessors());
+ setAutoGenerateAssocAccessors(rclone->getAutoGenerateAssocAccessors());
+ }
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ m_commonPolicy->emitModifiedCodeContentSig();
+
+}
+
+void RubyCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal )
+{
+
+ if(!config)
+ return;
+
+ // call the superclass to init default stuff
+ m_commonPolicy->setDefaults(config, false);
+
+ // NOW block signals (because call to super-class method will leave value at "true")
+ blockSignals(true); // we need to do this because otherwise most of these
+ // settors below will each send the modifiedCodeContent() signal
+ // needlessly (we can just make one call at the end).
+
+ // now do ruby specific stuff
+ config -> setGroup("Ruby Code Generation");
+
+ setAutoGenerateAttribAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS));
+ setAutoGenerateAssocAccessors(config->readBoolEntry("autoGenAssocAccessors",DEFAULT_AUTO_GEN_ASSOC_ACCESSORS));
+
+ blockSignals(false); // "as you were citizen"
+
+ if(emitUpdateSignal)
+ m_commonPolicy->emitModifiedCodeContentSig();
+}
+
+
+/**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+CodeGenerationPolicyPage * RubyCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) {
+ return new RubyCodeGenerationPolicyPage ( parent, name, this );
+}
+
+void RubyCodeGenerationPolicy::init() {
+ m_commonPolicy = UMLApp::app()->getCommonPolicy();
+ m_autoGenerateAttribAccessors = DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS;
+ m_autoGenerateAssocAccessors = DEFAULT_AUTO_GEN_ASSOC_ACCESSORS;
+}
+
+
+#include "rubycodegenerationpolicy.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h
new file mode 100644
index 00000000..aa1a7146
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h
@@ -0,0 +1,117 @@
+/***************************************************************************
+ rubycodegenerationpolicy.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODEGENERATIONPOLICY_H
+#define RUBYCODEGENERATIONPOLICY_H
+
+#include <qstring.h>
+#include "codegenpolicyext.h"
+#include "../codegenerationpolicy.h"
+
+class KConfig;
+class CodeGenerationPolicyPage;
+
+class RubyCodeGenerationPolicy : public CodeGenPolicyExt
+{
+ Q_OBJECT
+public:
+
+ static const bool DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS;
+ static const bool DEFAULT_AUTO_GEN_ASSOC_ACCESSORS;
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ RubyCodeGenerationPolicy (KConfig * config = 0);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeGenerationPolicy ( );
+
+ // Public attributes
+ //
+
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_autoGenerateAttribAccessors
+ * @param var the new value
+ */
+ void setAutoGenerateAttribAccessors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateAttribAccessors
+ * @return value the boolean value of m_autoGenerateAttribAccessors
+ */
+ bool getAutoGenerateAttribAccessors( );
+
+ /**
+ * Set the value of m_autoGenerateAssocAccessors
+ * @param var the new value
+ */
+ void setAutoGenerateAssocAccessors ( bool var );
+
+ /**
+ * Get the value of m_autoGenerateAssocAccessors
+ * @return value the boolean value of m_autoGenerateAssocAccessors
+ */
+ bool getAutoGenerateAssocAccessors( );
+
+ /**
+ * set the defaults for this code generator from the passed generator.
+ */
+ virtual void setDefaults (CodeGenPolicyExt * defaults, bool emitUpdateSignal = true);
+
+ /**
+ * set the defaults from a config file for this code generator from the passed KConfig pointer.
+ */
+ virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true);
+
+ /**
+ * write Default params to passed KConfig pointer.
+ */
+ virtual void writeConfig (KConfig * config);
+
+ /**
+ * Create a new dialog interface for this object.
+ * @return dialog object
+ */
+ CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0);
+
+protected:
+
+ /**
+ */
+ void init ( );
+
+private:
+
+ CodeGenerationPolicy *m_commonPolicy;
+ bool m_autoGenerateAttribAccessors;
+ bool m_autoGenerateAssocAccessors;
+
+};
+
+#endif // RUBYCODEGENERATIONPOLICY_H
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp
new file mode 100644
index 00000000..1e9080c9
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp
@@ -0,0 +1,75 @@
+/***************************************************************************
+ rubycodegenerationpolicypage.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodegenerationpolicypage.h"
+// qt/kde includes
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <kdebug.h>
+#include <klocale.h>
+// app includes
+#include "rubycodegenerationformbase.h"
+#include "../codegenerationpolicy.h"
+#include "../uml.h"
+
+RubyCodeGenerationPolicyPage::RubyCodeGenerationPolicyPage( QWidget *parent, const char *name, RubyCodeGenerationPolicy * policy )
+ : CodeGenerationPolicyPage(parent, name, policy)
+{
+ CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy();
+ form = new RubyCodeGenerationFormBase(this);
+ form->m_SelectCommentStyle->setCurrentItem((int)(common->getCommentStyle()));
+ form->m_generateConstructors->setChecked(common->getAutoGenerateConstructors());
+ form->m_generateAttribAccessors->setChecked(policy->getAutoGenerateAttribAccessors());
+ form->m_generateAssocAccessors->setChecked(policy->getAutoGenerateAssocAccessors());
+ form->m_accessorScopeCB->setCurrentItem((common->getAttributeAccessorScope() - 200));
+ form->m_assocFieldScopeCB->setCurrentItem((common->getAssociationFieldScope() - 200));
+}
+
+RubyCodeGenerationPolicyPage::~RubyCodeGenerationPolicyPage()
+{
+}
+
+void RubyCodeGenerationPolicyPage::apply()
+{
+ CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy();
+
+ // now do our ruby-specific configs
+ RubyCodeGenerationPolicy * parent = (RubyCodeGenerationPolicy*) m_parentPolicy;
+
+ // block signals so we don't cause too many update content calls to code documents
+ parent->blockSignals(true);
+
+ common->setCommentStyle((CodeGenerationPolicy::CommentStyle) form->m_SelectCommentStyle->currentItem());
+ common->setAttributeAccessorScope((CodeGenerationPolicy::ScopePolicy) (form->m_accessorScopeCB->currentItem()+200));
+ common->setAssociationFieldScope((CodeGenerationPolicy::ScopePolicy) (form->m_assocFieldScopeCB->currentItem()+200));
+ common->setAutoGenerateConstructors(form->m_generateConstructors->isChecked());
+ parent->setAutoGenerateAttribAccessors(form->m_generateAttribAccessors->isChecked());
+ parent->setAutoGenerateAssocAccessors(form->m_generateAssocAccessors->isChecked());
+
+ parent->blockSignals(false);
+
+ // now send out modified code content signal
+ common->emitModifiedCodeContentSig();
+
+}
+
+
+#include "rubycodegenerationpolicypage.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h
new file mode 100644
index 00000000..6fc06aed
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ rubycodegenerationpolicypage.h
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODEGENERATIONPOLICYPAGE_H
+#define RUBYCODEGENERATIONPOLICYPAGE_H
+
+#include "../dialogs/codegenerationpolicypage.h"
+#include "rubycodegenerationformbase.h"
+
+#include "rubycodegenerationpolicy.h"
+
+/**
+ * @author Brian Thomas
+ */
+
+class RubyCodeGenerationPolicyPage : public CodeGenerationPolicyPage {
+ Q_OBJECT
+public:
+
+ explicit RubyCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, RubyCodeGenerationPolicy * policy = 0);
+
+ virtual ~RubyCodeGenerationPolicyPage();
+
+protected:
+
+ RubyCodeGenerationFormBase * form;
+
+public slots:
+
+ void apply();
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerator.cpp b/umbrello/umbrello/codegenerators/rubycodegenerator.cpp
new file mode 100644
index 00000000..3e20ce50
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerator.cpp
@@ -0,0 +1,186 @@
+/***************************************************************************
+ rubycodegenerator.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodegenerator.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// local includes
+#include "rubycodecomment.h"
+#include "codeviewerdialog.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeGenerator::RubyCodeGenerator (QDomElement & elem )
+ : CodeGenerator(elem)
+{
+}
+
+RubyCodeGenerator::RubyCodeGenerator ()
+{
+}
+
+RubyCodeGenerator::~RubyCodeGenerator ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+// return our language
+Uml::Programming_Language RubyCodeGenerator::getLanguage() {
+ return Uml::pl_Ruby;
+}
+
+// In the Java version, we make the ANT build file also available.
+CodeViewerDialog * RubyCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc,
+ Settings::CodeViewerState state)
+{
+ CodeViewerDialog *dialog = new CodeViewerDialog(parent, doc, state);
+ return dialog;
+}
+
+
+RubyCodeGenerationPolicy * RubyCodeGenerator::getRubyPolicy() {
+ return dynamic_cast<RubyCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt());
+}
+
+bool RubyCodeGenerator::getAutoGenerateAttribAccessors ( )
+{
+ return getRubyPolicy()->getAutoGenerateAttribAccessors ();
+}
+
+bool RubyCodeGenerator::getAutoGenerateAssocAccessors ( )
+{
+ return getRubyPolicy()->getAutoGenerateAssocAccessors ();
+}
+
+QString RubyCodeGenerator::getListFieldClassName () {
+ return QString("Array");
+}
+
+// Other methods
+//
+
+QString RubyCodeGenerator::cppToRubyType(const QString &typeStr) {
+ QString type = cleanName(typeStr);
+ type.replace("const ", "");
+ type.replace(QRegExp("[*&\\s]"), "");
+ type.replace(QRegExp("[<>]"), "_");
+ type.replace("QStringList", "Array");
+ type.replace(QRegExp("^string$"),"String");
+ type.replace("QString", "String");
+ type.replace("bool", "true|false");
+ type.replace(QRegExp("^(uint|int|ushort|short|ulong|long)$"), "Integer");
+ type.replace(QRegExp("^(float|double)$"), "Float");
+ type.replace(QRegExp("^Q(?=[A-Z])"), "Qt::");
+ type.replace(QRegExp("^K(?!(DE|Parts|IO)"), "KDE::");
+
+ return type;
+}
+
+QString RubyCodeGenerator::cppToRubyName(const QString &nameStr) {
+ QString name = cleanName(nameStr);
+ name.replace(QRegExp("^m_"), "");
+ name.replace(QRegExp("^[pbn](?=[A-Z])"), "");
+ name = name.mid(0, 1).lower() + name.mid(1);
+ return name;
+}
+
+/**
+ * @return ClassifierCodeDocument
+ * @param classifier
+ */
+CodeDocument * RubyCodeGenerator::newClassifierCodeDocument ( UMLClassifier * c)
+{
+ RubyClassifierCodeDocument * doc = new RubyClassifierCodeDocument(c);
+ doc->initCodeClassFields();
+ return doc;
+}
+
+/* These initializations are done in CodeGenFactory::createObject()
+void RubyCodeGenerator::initFields() {
+ UMLApp::app()->setPolicyExt ( new RubyCodeGenerationPolicy(UMLApp::app()->getConfig()) );
+ // load Classifier documents from parent document
+ initFromParentDocument();
+}
+ */
+
+const QStringList RubyCodeGenerator::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "__FILE__"
+ << "__LINE__"
+ << "BEGIN"
+ << "END"
+ << "alias"
+ << "and"
+ << "begin"
+ << "break"
+ << "case"
+ << "class"
+ << "def"
+ << "defined?"
+ << "do"
+ << "else"
+ << "elsif"
+ << "end"
+ << "ensure"
+ << "false"
+ << "for"
+ << "if"
+ << "in"
+ << "module"
+ << "next"
+ << "nil"
+ << "not"
+ << "or"
+ << "redo"
+ << "rescue"
+ << "retry"
+ << "return"
+ << "self"
+ << "super"
+ << "then"
+ << "true"
+ << "undef"
+ << "unless"
+ << "until"
+ << "when"
+ << "while"
+ << "yield";
+ }
+
+ return keywords;
+}
+
+#include "rubycodegenerator.moc"
+
diff --git a/umbrello/umbrello/codegenerators/rubycodegenerator.h b/umbrello/umbrello/codegenerators/rubycodegenerator.h
new file mode 100644
index 00000000..9cc878f0
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodegenerator.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ rubycodegenerator.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODEGENERATOR_H
+#define RUBYCODEGENERATOR_H
+
+#include <qstring.h>
+#include "../codeviewerstate.h"
+#include "../codegenerator.h"
+#include "../codeblockwithcomments.h"
+#include "../umldoc.h"
+
+#include "classifierinfo.h"
+#include "rubyclassifiercodedocument.h"
+
+#include "rubycodegenerationpolicy.h"
+
+class CodeViewerDialog;
+
+class RubyCodeGenerator : public CodeGenerator
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ RubyCodeGenerator ();
+ RubyCodeGenerator (QDomElement & element);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeGenerator ( );
+
+ // Public attributes
+ //
+
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * A utility method to get the rubyCodeGenerationPolicy()->getAutoGenerateAttribAccessors() value.
+ */
+ bool getAutoGenerateAttribAccessors( );
+
+ /**
+ * A utility method to get the rubyCodeGenerationPolicy()->getAutoGenerateAssocAccessors() value.
+ */
+ bool getAutoGenerateAssocAccessors( );
+
+ /**
+ * Get the list variable class name to use. For Ruby, we have set this to "Array".
+ */
+ static QString getListFieldClassName();
+
+ /** Get the editing dialog for this code document
+ */
+ virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc,
+ Settings::CodeViewerState state);
+
+ // Other methods
+ //
+
+ /**
+ * Utility function for getting the ruby code generation policy.
+ */
+ RubyCodeGenerationPolicy * getRubyPolicy();
+
+ /**
+ * @return ClassifierCodeDocument
+ * @param classifier
+ */
+ CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+
+ // return "Ruby"
+ Uml::Programming_Language getLanguage();
+
+ /**
+ * Convert a C++ type such as 'int' or 'QWidget' to
+ * ruby types Integer and Qt::Widget
+ *
+ * @param cppType the C++ type to be converted
+ */
+ static QString cppToRubyType(const QString &cppType);
+
+ /**
+ * Convert C++ names such as 'm_foobar' or pFoobar to
+ * just 'foobar' for ruby
+ *
+ * @param cppName the C++ name to be converted
+ */
+ static QString cppToRubyName(const QString &cppName);
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+protected:
+
+ /** create the codeblock that will represent the class declaration
+ * for this classifier
+ */
+ CodeBlockWithComments * createClassDecl ( UMLClassifier *c, ClassifierInfo *info, RubyClassifierCodeDocument * doc);
+
+};
+
+#endif // RUBYCODEGENERATOR_H
diff --git a/umbrello/umbrello/codegenerators/rubycodeoperation.cpp b/umbrello/umbrello/codegenerators/rubycodeoperation.cpp
new file mode 100644
index 00000000..6f16fb96
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeoperation.cpp
@@ -0,0 +1,226 @@
+/***************************************************************************
+ rubycodeoperation.cpp
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "rubycodeoperation.h"
+
+// qt/kde includes
+#include <qregexp.h>
+
+// local includes
+#include "rubyclassifiercodedocument.h"
+#include "rubycodedocumentation.h"
+#include "rubycodegenerator.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+RubyCodeOperation::RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment )
+ : CodeOperation (doc, parent, body, comment)
+{
+ // lets not go with the default comment and instead use
+ // full-blown ruby documentation object instead
+ setComment(new RubyCodeDocumentation(doc));
+
+ // these things never change..
+ setOverallIndentationLevel(1);
+
+ updateMethodDeclaration();
+ updateContent();
+
+}
+
+RubyCodeOperation::~RubyCodeOperation ( ) { }
+
+// Other methods
+//
+
+// we basically want to update the doc and start text of this method
+void RubyCodeOperation::updateMethodDeclaration()
+{
+
+ CodeDocument * doc = getParentDocument();
+ RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(doc);
+ UMLClassifier *c = rubydoc->getParentClassifier();
+ UMLOperation * o = getParentOperation();
+ bool isInterface = rubydoc->getParentClassifier()->isInterface();
+ QString endLine = getNewLineEndingChars();
+
+ // now, the starting text.
+ QString strVis = rubydoc->scopeToRubyDecl(o->getVisibility());
+ // no return type for constructors
+ QString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName());
+ QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" "));
+ QString methodName = o->getName();
+
+ QString RubyClassName = rubydoc->getRubyClassName(c->getName());
+
+ // Skip destructors, and operator methods which
+ // can't be defined in ruby
+ if ( methodName.startsWith("~")
+ || QRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) )
+ {
+ getComment()->setText("");
+ return;
+ }
+
+ if (RubyClassName == methodName) {
+ methodName = "initialize";
+ }
+
+ methodName.replace(QRegExp("operator\\s*"), "");
+ methodName = methodName.mid(0, 1).lower() + methodName.mid(1);
+
+ QString paramStr = QString("");
+ QStringList commentedParams;
+
+ // assemble parameters
+ UMLAttributeList list = getParentOperation()->getParmList();
+ int nrofParam = list.count();
+ int paramNum = 0;
+ for(UMLAttribute* parm = list.first(); parm; parm = list.next())
+ {
+ QString paramName = RubyCodeGenerator::cppToRubyName(parm->getName());
+ paramStr += paramName;
+ if (! parm->getInitialValue().isEmpty()) {
+ paramStr += QString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue());
+ }
+ paramNum++;
+
+ if (paramNum != nrofParam )
+ paramStr += ", ";
+ }
+
+ QString startText;
+ if (isInterface) {
+ // Assume 'isInterface' means a module in Ruby, so
+ // generate module methods
+ startText = "def "+ RubyClassName + '.' + methodName + '(' + paramStr +')';
+ } else {
+ startText = "def "+ methodName + '(' + paramStr +')';
+ }
+
+ startText += "";
+ setEndMethodText("end");
+
+ setStartMethodText(startText);
+
+ // Lastly, for text content generation, we fix the comment on the
+ // operation, IF the codeop is autogenerated & currently empty
+ QString comment = o->getDoc();
+
+ if (comment.isEmpty()) {
+ if (getContentType() == CodeBlock::AutoGenerated) {
+ UMLAttributeList parameters = o->getParmList();
+ for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
+ comment += endLine + "* _" + iterator.current()->getName() + "_ ";
+ comment += (' ' + iterator.current()->getDoc().replace( QRegExp("[\\n\\r]+[\\t ]*"),
+ endLine + " " ) );
+ }
+ // add a returns statement too
+ if(!returnType.isEmpty() && !QRegExp("^void\\s*$").exactMatch(returnType))
+ comment += endLine + "* _returns_ " + returnType + ' ';
+ getComment()->setText(comment);
+ }
+ } else {
+ comment.replace(QRegExp("[\\n\\r]+ *"), endLine);
+ comment.replace(QRegExp("[\\n\\r]+\\t*"), endLine);
+
+ comment.replace(" m_", " ");
+ comment.replace(QRegExp("\\s[npb](?=[A-Z])"), " ");
+ QRegExp re_params("@param (\\w)(\\w*)");
+ int pos = re_params.search(comment);
+ while (pos != -1) {
+ comment.replace( re_params.cap(0),
+ QString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' );
+ commentedParams.append(re_params.cap(1).lower() + re_params.cap(2));
+
+ pos += re_params.matchedLength() + 3;
+ pos = re_params.search(comment, pos);
+ }
+
+ UMLAttributeList parameters = o->getParmList();
+ for (UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
+ // Only write an individual @param entry if one hasn't been found already
+ // in the main doc comment
+ if (commentedParams.contains(RubyCodeGenerator::cppToRubyName(iterator.current()->getName())) == 0) {
+ comment += (endLine + "@param _" + RubyCodeGenerator::cppToRubyName(iterator.current()->getName()) + '_');
+ if (iterator.current()->getDoc().isEmpty()) {
+ comment += (' ' + RubyCodeGenerator::cppToRubyType(iterator.current()->getTypeName()));
+ } else {
+ comment += (' ' + iterator.current()->getDoc().replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine + " "));
+ }
+ }
+ }
+
+ comment.replace("@ref ", "");
+ comment.replace("@param", "*");
+ comment.replace("@return", "* _returns_");
+
+ // All lines after the first one starting with '*' in the doc comment
+ // must be indented correctly. If they aren't a list
+ // item starting with '*', then indent the text with
+ // two spaces, ' ', to line up with the list item.
+ pos = comment.find(endLine + '*');
+ if (pos != -1) {
+ pos += endLine.length() + 1;
+ pos = comment.find(endLine, pos);
+ }
+
+ while (pos > 0) {
+ pos += endLine.length();
+ if (comment[pos] != '*') {
+ comment.insert(pos, " ");
+ pos += 2;
+ }
+
+ pos = comment.find(endLine, pos);
+ }
+
+ QString typeStr = RubyCodeGenerator::cppToRubyType(o->getTypeName());
+ if ( !typeStr.isEmpty()
+ && !QRegExp("^void\\s*$").exactMatch(typeStr)
+ && comment.contains("_returns_") == 0 )
+ {
+ comment += endLine + "* _returns_ " + typeStr;
+ }
+
+ getComment()->setText(comment);
+ }
+
+ // In Java, for interfaces..we DONT write out non-public
+ // method declarations. And for Ruby modules?
+ if (isInterface) {
+ UMLOperation * o = getParentOperation();
+ if(o->getVisibility() != Uml::Visibility::Public)
+ setWriteOutText(false);
+ }
+
+}
+
+int RubyCodeOperation::lastEditableLine() {
+ ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ if(doc->parentIsInterface())
+ return -1; // very last line is NOT editable as its a one-line declaration w/ no body in
+ // an interface.
+ return 0;
+}
+
+#include "rubycodeoperation.moc"
diff --git a/umbrello/umbrello/codegenerators/rubycodeoperation.h b/umbrello/umbrello/codegenerators/rubycodeoperation.h
new file mode 100644
index 00000000..c8e8cea4
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubycodeoperation.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ rubycodeoperation.h
+ Derived from the Java code generator by thomas
+
+ begin : Thur Jul 21 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYCODEOPERATION_H
+#define RUBYCODEOPERATION_H
+
+#include <qstring.h>
+#include "../codeoperation.h"
+
+class RubyClassifierCodeDocument;
+
+class RubyCodeOperation : virtual public CodeOperation
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~RubyCodeOperation ( );
+
+ virtual int lastEditableLine();
+
+protected:
+
+ void updateMethodDeclaration();
+
+};
+
+#endif // RUBYCODEOPERATION_H
diff --git a/umbrello/umbrello/codegenerators/rubywriter.cpp b/umbrello/umbrello/codegenerators/rubywriter.cpp
new file mode 100644
index 00000000..aa9a5271
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubywriter.cpp
@@ -0,0 +1,448 @@
+/***************************************************************************
+ rubywriter.h - description
+ -------------------
+ begin : Sat Dec 21 2002
+ copyright : Vincent Decorges
+ email : vincent.decorges@eivd.ch
+ (C) 2003-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "rubywriter.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+
+#include "classifierinfo.h"
+#include "../umldoc.h"
+#include "../umlattributelist.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+RubyWriter::RubyWriter() {
+}
+
+RubyWriter::~RubyWriter() {}
+
+void RubyWriter::writeClass(UMLClassifier *c) {
+ if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ QString classname = cleanName(c->getName());
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".rb");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile fileh;
+ if( !openFile(fileh, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ QTextStream h(&fileh);
+
+ // preparations
+ classifierInfo = new ClassifierInfo(c);
+ classifierInfo->fileName = fileName;
+ classifierInfo->className = cleanName(c->getName());
+
+ //////////////////////////////
+ //Start generating the code!!
+ /////////////////////////////
+
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+
+ str = getHeadingFile(".rb");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), fileh.name());
+ h<<str<<m_endl;
+ }
+
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ QString docStr = c->getDoc();
+ docStr.replace(QRegExp("\\n"), "\n# ");
+ docStr.replace("@ref ", "");
+ docStr.replace("@see", "_See_");
+ docStr.replace("@short", "_Summary_");
+ docStr.replace("@author", "_Author_");
+ h<<"#"<<m_endl;
+ h<<"# "<<docStr<<m_endl;
+ h<<"#"<<m_endl<<m_endl;
+ }
+
+ // write inheritances out
+ UMLClassifier *concept;
+
+ h<< "class " << cppToRubyType(classname) << (superclasses.count() > 0 ? " < ":"");
+
+ int i = 0;
+ for (concept = superclasses.first(); concept; concept = superclasses.next()) {
+ if (i == 0) {
+ h << cppToRubyType(concept->getName()) << m_endl;
+ } else {
+ // Assume ruby modules that can be mixed in, after the first
+ // superclass name in the list
+ h << m_indentation << "include "<< cppToRubyType(concept->getName()) << m_endl;
+ }
+ i++;
+ }
+
+ h << m_endl;
+
+ // write comment for sub-section IF needed
+ if (forceDoc() || classifierInfo->hasAccessorMethods) {
+ h << m_indentation << "#" << m_endl;
+ h << m_indentation << "# Accessor Methods" << m_endl;
+ h << m_indentation << "#" << m_endl << m_endl;
+
+ // Accessor methods for attributes
+ writeAttributeMethods(&(classifierInfo->atpub), Uml::Visibility::Public, h);
+ writeAttributeMethods(&(classifierInfo->atprot), Uml::Visibility::Protected, h);
+ writeAttributeMethods(&(classifierInfo->atpriv), Uml::Visibility::Private, h);
+ h << m_endl;
+ }
+
+ //operations
+ writeOperations(c, h);
+
+ //finish files
+ h << "end" << m_endl << m_endl;
+
+ //close files and notfiy we are done
+ fileh.close();
+ emit codeGenerated(c, true);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// Helper Methods
+
+QString RubyWriter::cppToRubyType(const QString &typeStr) {
+ QString type = cleanName(typeStr);
+ type.replace("const ", "");
+ type.replace(QRegExp("[*&\\s]"), "");
+ type.replace(QRegExp("[<>]"), "_");
+ type.replace("QStringList", "Array");
+ type.replace("QString", "String");
+ type.replace("bool", "true|false");
+ type.replace(QRegExp("^(uint|int|ushort|short|ulong|long)$"), "Integer");
+ type.replace(QRegExp("^(float|double)$"), "Float");
+ type.replace(QRegExp("^Q(?=[A-Z])"), "Qt::");
+ type.replace(QRegExp("^K(?!(DE|Parts|IO)"), "KDE::");
+
+ return type;
+}
+
+QString RubyWriter::cppToRubyName(const QString &nameStr) {
+ QString name = cleanName(nameStr);
+ name.replace(QRegExp("^m_"), "");
+ name.replace(QRegExp("^[pbn](?=[A-Z])"), "");
+ name = name.mid(0, 1).lower() + name.mid(1);
+ return name;
+}
+
+void RubyWriter::writeOperations(UMLClassifier *c,QTextStream &h) {
+
+ //Lists to store operations sorted by scope
+ UMLOperationList oppub,opprot,oppriv;
+
+ oppub.setAutoDelete(false);
+ opprot.setAutoDelete(false);
+ oppriv.setAutoDelete(false);
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
+ switch(op->getVisibility()) {
+ case Uml::Visibility::Public:
+ oppub.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ opprot.append(op);
+ break;
+ case Uml::Visibility::Private:
+ oppriv.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ QString classname(cleanName(c->getName()));
+
+ //write operations to file
+ if(forceSections() || !oppub.isEmpty()) {
+ writeOperations(classname, oppub, Uml::Visibility::Public, h);
+ }
+
+ if(forceSections() || !opprot.isEmpty()) {
+ writeOperations(classname, opprot, Uml::Visibility::Protected, h);
+ }
+
+ if(forceSections() || !oppriv.isEmpty()) {
+ writeOperations(classname, oppriv, Uml::Visibility::Private, h);
+ }
+
+}
+
+void RubyWriter::writeOperations(const QString &classname, UMLOperationList &opList,
+ Uml::Visibility permitScope, QTextStream &h)
+{
+ UMLOperation *op;
+ UMLAttribute *at;
+
+ switch (permitScope) {
+ case Uml::Visibility::Public:
+ h << m_indentation << "public" << m_endl << m_endl;
+ break;
+ case Uml::Visibility::Protected:
+ h << m_indentation << "protected" << m_endl << m_endl;
+ break;
+ case Uml::Visibility::Private:
+ h << m_indentation << "private" << m_endl << m_endl;
+ break;
+ default:
+ break;
+ }
+
+ for (op=opList.first(); op ; op=opList.next()) {
+ QString methodName = cleanName(op->getName());
+ QStringList commentedParams;
+
+ // Skip destructors, and operator methods which
+ // can't be defined in ruby
+ if ( methodName.startsWith("~")
+ || methodName == "operator ="
+ || methodName == "operator --"
+ || methodName == "operator ++"
+ || methodName == "operator !=" )
+ {
+ continue;
+ }
+
+ if (methodName == classname) {
+ methodName = "initialize";
+ }
+
+ methodName.replace("operator ", "");
+ methodName = methodName.mid(0, 1).lower() + methodName.mid(1);
+
+ UMLAttributeList atl = op->getParmList();
+ //write method doc if we have doc || if at least one of the params has doc
+ bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
+ // Always write out the docs for ruby as the type of the
+ // arguments and return value of the methods is useful
+ writeDoc = true;
+// for (at = atl.first(); at; at = atl.next())
+// writeDoc |= !at->getDoc().isEmpty();
+
+ if (writeDoc) {
+ h << m_indentation << "#" << m_endl;
+ QString docStr = op->getDoc();
+
+ docStr.replace(QRegExp("[\\n\\r]+ *"), m_endl);
+ docStr.replace(QRegExp("[\\n\\r]+\\t*"), m_endl);
+
+ docStr.replace(" m_", " ");
+ docStr.replace(QRegExp("\\s[npb](?=[A-Z])"), " ");
+ QRegExp re_params("@param (\\w)(\\w*)");
+ int pos = re_params.search(docStr);
+ while (pos != -1) {
+ docStr.replace( re_params.cap(0),
+ QString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' );
+ commentedParams.append(re_params.cap(1).lower() + re_params.cap(2));
+
+ pos += re_params.matchedLength() + 3;
+ pos = re_params.search(docStr, pos);
+ }
+
+ docStr.replace("\n", QString("\n") + m_indentation + "# ");
+
+ // Write parameter documentation
+ for (at = atl.first(); at ; at = atl.next()) {
+ // Only write an individual @param entry if one hasn't been found already
+ // in the main doc comment
+ if (commentedParams.contains(cppToRubyName(at->getName())) == 0) {
+ docStr += (m_endl + m_indentation + "# @param _" + cppToRubyName(at->getName()) + '_');
+ if (at->getDoc().isEmpty()) {
+ docStr += (' ' + cppToRubyType(at->getTypeName()));
+ } else {
+ docStr += (' ' + at->getDoc().replace(QRegExp("[\\n\\r]+[\\t ]*"), m_endl + " "));
+ }
+ }
+ }
+
+ docStr.replace("@ref ", "");
+ docStr.replace("@param", "*");
+ docStr.replace("@return", "* _returns_");
+
+ // All lines after the first '# *' in the doc comment
+ // must be indented correctly. If they aren't a list
+ // item starting with '# *', then indent the text with
+ // three spaces, '# ', to line up with the list item.
+ pos = docStr.find("# *");
+ QRegExp re_linestart("# (?!\\*)");
+ pos = re_linestart.search(docStr, pos);
+ while (pos > 0) {
+ docStr.insert(pos + 1, " ");
+
+ pos += re_linestart.matchedLength() + 2;
+ pos = re_linestart.search(docStr, pos);
+ }
+
+ h << m_indentation << "# "<< docStr << m_endl;
+
+ QString typeStr = cppToRubyType(op->getTypeName());
+ if (!typeStr.isEmpty() && typeStr != "void" && docStr.contains("_returns_") == 0) {
+ h << m_indentation << "# * _returns_ " << typeStr << m_endl;
+ }
+ }
+
+ h<< m_indentation << "def " + methodName << "(";
+
+ int j=0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ QString nameStr = cppToRubyName(at->getName());
+ if (j > 0) {
+ h << ", " << nameStr;
+ } else {
+ h << nameStr;
+ }
+ h << (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ") + cppToRubyType(at->getInitialValue())) :
+ QString(""));
+ }
+
+ h <<")" << m_endl;
+
+ h << m_indentation << m_indentation << m_endl;
+
+ h << m_indentation << "end" << m_endl << m_endl;
+
+ }//end for
+
+}
+
+// this is for writing file attribute methods
+//
+void RubyWriter::writeAttributeMethods(UMLAttributeList *attribs,
+ Uml::Visibility visibility, QTextStream &stream)
+{
+ // return now if NO attributes to work on
+ if (attribs->count() == 0 || visibility == Uml::Visibility::Private)
+ return;
+
+ UMLAttribute *at;
+ for(at=attribs->first(); at; at=attribs->next())
+ {
+ QString varName = cppToRubyName(cleanName(at->getName()));
+
+ writeSingleAttributeAccessorMethods(varName, at->getDoc(), stream);
+ }
+
+}
+
+void RubyWriter::writeSingleAttributeAccessorMethods(
+ const QString &fieldName,
+ const QString &descr,
+ QTextStream &h)
+{
+ QString description = descr;
+ description.replace(QRegExp("m_[npb](?=[A-Z])"), "");
+ description.replace("m_", "");
+ description.replace("\n", QString("\n") + m_indentation + "# ");
+
+ if (!description.isEmpty()) {
+ h << m_indentation << "# " << description << m_endl;
+ }
+
+ h << m_indentation << "attr_accessor :" << fieldName << m_endl << m_endl;
+
+ return;
+}
+
+/**
+ * returns "Ruby"
+ */
+Uml::Programming_Language RubyWriter::getLanguage() {
+ return Uml::pl_Ruby;
+}
+
+const QStringList RubyWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "__FILE__"
+ << "__LINE__"
+ << "BEGIN"
+ << "END"
+ << "alias"
+ << "and"
+ << "begin"
+ << "break"
+ << "case"
+ << "class"
+ << "def"
+ << "defined?"
+ << "do"
+ << "else"
+ << "elsif"
+ << "end"
+ << "ensure"
+ << "false"
+ << "for"
+ << "if"
+ << "in"
+ << "module"
+ << "next"
+ << "nil"
+ << "not"
+ << "or"
+ << "redo"
+ << "rescue"
+ << "retry"
+ << "return"
+ << "self"
+ << "super"
+ << "then"
+ << "true"
+ << "undef"
+ << "unless"
+ << "until"
+ << "when"
+ << "while"
+ << "yield";
+ }
+
+ return keywords;
+}
+
+#include "rubywriter.moc"
diff --git a/umbrello/umbrello/codegenerators/rubywriter.h b/umbrello/umbrello/codegenerators/rubywriter.h
new file mode 100644
index 00000000..8f1547ad
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/rubywriter.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+ rubywriter.h - description
+ -------------------
+ begin : Mon Jul 18 2005
+ author : Richard Dale
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef RUBYWRITER_H
+#define RUBYWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+
+#include <qstringlist.h>
+
+class ClassifierInfo;
+
+/**
+ * class RubyWriter is a ruby code generator for UMLClassifier objects
+ * Just call writeClass and feed it a UMLClassifier;
+ */
+class RubyWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ RubyWriter();
+ virtual ~RubyWriter();
+
+ /**
+ * call this method to generate C++ code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "Ruby"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+ /**
+ * Convert a C++ type such as 'int' or 'QWidget' to
+ * ruby types Integer and Qt::Widget
+ *
+ * @param cppType the C++ type to be converted
+ */
+ QString cppToRubyType(const QString &cppType);
+
+ /**
+ * Convert C++ names such as 'm_foobar' or pFoobar to
+ * just 'foobar' for ruby
+ *
+ * @param cppName the C++ name to be converted
+ */
+ QString cppToRubyName(const QString &cppName);
+
+ /**
+ * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in attribs list.
+ */
+ void writeAttributeMethods(UMLAttributeList *attribs,
+ Uml::Visibility visibility, QTextStream &stream);
+
+
+ /**
+ * write all method declarations, for attributes and associations
+ * for the given permitted scope.
+ */
+ void writeSingleAttributeAccessorMethods(const QString &fieldName,
+ const QString &description,
+ QTextStream &h);
+
+ /**
+ * write all operations for a given class
+ *
+ * @param c the concept we are generating code for
+ * @param h output stream for the header file
+ */
+ void writeOperations(UMLClassifier *c, QTextStream &h);
+
+ /**
+ * write a list of class operations
+ *
+ * @param classname the name of the class
+ * @param opList the list of operations
+ * @param h output stream for the header file
+ */
+ void writeOperations(const QString &classname, UMLOperationList &opList,
+ Uml::Visibility permitScope, QTextStream &h);
+
+ /**
+ * Summary information about current classifier.
+ */
+ ClassifierInfo * classifierInfo;
+};
+
+#endif //RUBYWRITER
diff --git a/umbrello/umbrello/codegenerators/simplecodegenerator.cpp b/umbrello/umbrello/codegenerators/simplecodegenerator.cpp
new file mode 100644
index 00000000..98477f15
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/simplecodegenerator.cpp
@@ -0,0 +1,292 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Sep Mon 1 2003
+ */
+
+// own header
+#include "simplecodegenerator.h"
+// system includes
+#include <cstdlib> //to get the user name
+// qt includes
+#include <qdatetime.h>
+#include <qregexp.h>
+#include <qdir.h>
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kapplication.h>
+// app includes
+#include "../dialogs/overwritedialogue.h"
+#include "../model_utils.h"
+#include "../attribute.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+#include "../classifier.h"
+#include "../codedocument.h"
+#include "../codegenerationpolicy.h"
+#include "../operation.h"
+#include "../umldoc.h"
+#include "../uml.h"
+
+// Constructors/Destructors
+//
+
+SimpleCodeGenerator::SimpleCodeGenerator (bool createDirHierarchyForPackages /* =true */)
+{
+ m_indentLevel = 0;
+ UMLDoc * parentDoc = UMLApp::app()->getDocument();
+ parentDoc->disconnect(this); // disconnect from UMLDoc.. we arent planning to be synced at all
+ m_createDirHierarchyForPackages = createDirHierarchyForPackages;
+ initFields(parentDoc);
+}
+
+SimpleCodeGenerator::~SimpleCodeGenerator ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+
+// Other methods
+//
+
+QString SimpleCodeGenerator::getIndent ()
+{
+ QString myIndent;
+ for (int i = 0 ; i < m_indentLevel ; i++)
+ myIndent.append(m_indentation);
+ return myIndent;
+}
+
+QString SimpleCodeGenerator::findFileName(UMLPackage* concept, const QString &ext) {
+
+ //if we already know to which file this class was written/should be written, just return it.
+ if (m_fileMap.contains(concept))
+ return m_fileMap[concept];
+
+ //else, determine the "natural" file name
+ QString name;
+ // Get the package name
+ QString package = concept->getPackage(".");
+
+ // Replace all white spaces with blanks
+ package.simplifyWhiteSpace();
+
+ // Replace all blanks with underscore
+ package.replace(QRegExp(" "), "_");
+
+ // Convert all "::" to "/" : Platform-specific path separator
+ // package.replace(QRegExp("::"), "/");
+
+ // if package is given add this as a directory to the file name
+ if (!package.isEmpty() && m_createDirHierarchyForPackages) {
+ name = package + '.' + concept->getName();
+ name.replace(QRegExp("\\."),"/");
+ package.replace(QRegExp("\\."), "/");
+ package = '/' + package;
+ } else {
+ name = concept->getFullyQualifiedName("-");
+ }
+
+ if (! UMLApp::app()->activeLanguageIsCaseSensitive()) {
+ package = package.lower();
+ name = name.lower();
+ }
+
+ // if a package name exists check the existence of the package directory
+ if (!package.isEmpty() && m_createDirHierarchyForPackages) {
+ QDir pathDir(UMLApp::app()->getCommonPolicy()->getOutputDirectory().absPath() + package);
+ // does our complete output directory exist yet? if not, try to create it
+ if (!pathDir.exists())
+ {
+ QStringList dirs = QStringList::split("/",pathDir.absPath());
+ QString currentDir = "";
+
+ QStringList::iterator end(dirs.end());
+ for (QStringList::iterator dir(dirs.begin()); dir != end; ++dir)
+ {
+ currentDir += '/' + *dir;
+ if (! (pathDir.exists(currentDir)
+ || pathDir.mkdir(currentDir) ) )
+ {
+ KMessageBox::error(0, i18n("Cannot create the folder:\n") +
+ pathDir.absPath() + i18n("\nPlease check the access rights"),
+ i18n("Cannot Create Folder"));
+ return NULL;
+ }
+ }
+ }
+ }
+
+
+ name.simplifyWhiteSpace();
+ name.replace(QRegExp(" "),"_");
+
+ QString extension = ext.simplifyWhiteSpace();
+ extension.replace(' ', '_');
+
+ return overwritableName(concept, name, extension);
+}
+
+QString SimpleCodeGenerator::overwritableName(UMLPackage* concept, const QString &name, const QString &ext) {
+ //check if a file named "name" with extension "ext" already exists
+ CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy();
+ QDir outputDir = commonPolicy->getOutputDirectory();
+ QString filename = name + ext;
+ if(!outputDir.exists(filename)) {
+ m_fileMap.insert(concept,filename);
+ return filename; //if not, "name" is OK and we have not much to to
+ }
+
+ int suffix;
+ OverwriteDialogue overwriteDialogue( filename, outputDir.absPath(),
+ m_applyToAllRemaining, kapp -> mainWidget() );
+ switch(commonPolicy->getOverwritePolicy()) { //if it exists, check the OverwritePolicy we should use
+ case CodeGenerationPolicy::Ok: //ok to overwrite file
+ break;
+ case CodeGenerationPolicy::Ask: //ask if we can overwrite
+ switch(overwriteDialogue.exec()) {
+ case KDialogBase::Yes: //overwrite file
+ if ( overwriteDialogue.applyToAllRemaining() ) {
+ commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Ok);
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ break;
+ case KDialogBase::No: //generate similar name
+ suffix = 1;
+ while (1) {
+ filename = name + "__" + QString::number(suffix) + ext;
+ if (!outputDir.exists(filename))
+ break;
+ suffix++;
+ }
+ if ( overwriteDialogue.applyToAllRemaining() ) {
+ commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Never);
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ break;
+ case KDialogBase::Cancel: //don't output anything
+ if ( overwriteDialogue.applyToAllRemaining() ) {
+ commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Cancel);
+ } else {
+ m_applyToAllRemaining = false;
+ }
+ return NULL;
+ break;
+ }
+
+ break;
+ case CodeGenerationPolicy::Never: //generate similar name
+ suffix = 1;
+ while (1) {
+ filename = name + "__" + QString::number(suffix) + ext;
+ if (!outputDir.exists(filename))
+ break;
+ suffix++;
+ }
+ break;
+ case CodeGenerationPolicy::Cancel: //don't output anything
+ return NULL;
+ break;
+ }
+
+ m_fileMap.insert(concept, filename);
+ return filename;
+}
+
+
+bool SimpleCodeGenerator::hasDefaultValueAttr(UMLClassifier *c) {
+ UMLAttributeList atl = c->getAttributeList();
+ for(UMLAttribute *at = atl.first(); at; at = atl.next())
+ if(!at->getInitialValue().isEmpty())
+ return true;
+ return false;
+}
+
+bool SimpleCodeGenerator::hasAbstractOps(UMLClassifier *c) {
+ UMLOperationList opl(c->getOpList());
+ for(UMLOperation *op = opl.first(); op ; op = opl.next())
+ if(op->getAbstract())
+ return true;
+ return false;
+}
+
+/**
+ * @return ClassifierCodeDocument
+ * @param classifier
+ * @param this This package generator object.
+ */
+CodeDocument * SimpleCodeGenerator::newClassifierCodeDocument(UMLClassifier* /*classifier*/)
+{
+ return (CodeDocument*)NULL;
+}
+
+// write all concepts in project to file
+void SimpleCodeGenerator::writeCodeToFile ( ) {
+ m_fileMap.clear(); // need to do this, else just keep getting same directory to write to.
+ UMLClassifierList concepts = m_doc->getClassesAndInterfaces();
+ for (UMLClassifier *c = concepts.first(); c; c = concepts.next()) {
+ if (! Model_Utils::isCommonDataType(c->getName()))
+ this->writeClass(c); // call the writer for each class.
+ }
+}
+
+// write only selected concepts to file
+void SimpleCodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) {
+ m_fileMap.clear(); // ??
+ for (UMLClassifier *c = concepts.first(); c; c = concepts.next())
+ this->writeClass(c); // call the writer for each class.
+}
+
+void SimpleCodeGenerator::initFields ( UMLDoc * parentDoc ) {
+
+ // load Classifier documents from parent document
+ // initFromParentDocument();
+
+ m_fileMap.clear();
+ m_applyToAllRemaining = true;
+ m_doc = parentDoc;
+
+ // this really is just being used to sync the internal params
+ // to the codegenpolicy as there are no code documents to really sync.
+ syncCodeToDocument();
+}
+
+// a little method to provide some compatability between
+// the newer codegenpolicy object and the older class fields.
+void SimpleCodeGenerator::syncCodeToDocument() {
+
+ CodeGenerationPolicy *policy = UMLApp::app()->getCommonPolicy();
+
+ m_indentation = policy->getIndentation();
+ m_endl = policy->getNewLineEndingChars();
+
+}
+
+
+// override parent method
+void SimpleCodeGenerator::initFromParentDocument( )
+{
+ // Do nothing
+}
+
+
+#include "simplecodegenerator.moc"
diff --git a/umbrello/umbrello/codegenerators/simplecodegenerator.h b/umbrello/umbrello/codegenerators/simplecodegenerator.h
new file mode 100644
index 00000000..d75a0660
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/simplecodegenerator.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Sep Mon 1 2003
+ *
+ * copyright (C) 2004
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ */
+
+
+#ifndef SIMPLECODEGENERATOR_H
+#define SIMPLECODEGENERATOR_H
+
+#include <qstringlist.h>
+#include <qstring.h>
+#include <qmap.h>
+
+#include "../codegenerator.h"
+#include "../umlnamespace.h"
+
+class UMLDoc;
+
+/**
+ * A simple code generator interface designed to work with
+ * the existing codewriters.
+ */
+class SimpleCodeGenerator : public CodeGenerator
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ SimpleCodeGenerator (bool createDirHierarchyForPackages = true);
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~SimpleCodeGenerator ( );
+
+ // Public attribute accessor methods
+ //
+
+ void writeCodeToFile ( UMLClassifierList & concepts);
+ void writeCodeToFile ( );
+
+ /**
+ * call this method to generate code for a UMLClassifier
+ * @param c the class you want to generate code for.
+ */
+ virtual void writeClass(UMLClassifier *c) = 0;
+
+ /**
+ * This is implemented only because we HAVE to.
+ * @return ClassifierCodeDocument
+ * @param classifier
+ */
+ CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+
+protected:
+
+ // compatability methods..
+ QString findFileName(UMLPackage* concept, const QString &ext);
+ QString overwritableName(UMLPackage* concept, const QString &name, const QString &ext);
+ bool hasDefaultValueAttr(UMLClassifier *c);
+ bool hasAbstractOps(UMLClassifier *c);
+
+ /**
+ * Returns the current indent string based on m_indentLevel and m_indentation.
+ */
+ QString getIndent ();
+
+ /**
+ * Maps UMLObjects to filenames. Used for finding out which file
+ * each class was written to.
+ */
+ QMap<UMLPackage*,QString> m_fileMap;
+
+ // the parent document
+ UMLDoc *m_doc;
+
+ /**
+ * For some code generators, it does not make much sense to create a
+ * directory for each package because that would lead to a rather
+ * sparsely populated directory tree (maximum of just one source file
+ * per directory.)
+ */
+ bool m_createDirHierarchyForPackages;
+
+ /* Old Attributes writers will look for */
+ QString m_indentation;
+ int m_indentLevel;
+ QString m_endl;
+
+ // override parent method..we need special handling
+ void initFromParentDocument( );
+
+private:
+
+ void initFields ( UMLDoc * doc) ;
+
+public slots:
+
+ void syncCodeToDocument ( );
+
+};
+
+#endif // SIMPLECODEGENERATOR_H
diff --git a/umbrello/umbrello/codegenerators/sqlwriter.cpp b/umbrello/umbrello/codegenerators/sqlwriter.cpp
new file mode 100644
index 00000000..f01e8bbe
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/sqlwriter.cpp
@@ -0,0 +1,394 @@
+/***************************************************************************
+ begin : 10.02.2003
+ copyright : (C) 2003 Nikolaus Gradwohl
+ email : guru@local-guru.net
+ (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "sqlwriter.h"
+
+#include <kdebug.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+#include "../association.h"
+#include "../attribute.h"
+
+SQLWriter::SQLWriter() {
+}
+
+SQLWriter::~SQLWriter() {}
+
+void SQLWriter::writeClass(UMLClassifier *c) {
+
+ if(!c) {
+ kDebug()<<"Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ const bool isClass = !c->isInterface();
+ QString classname = cleanName(c->getName());
+
+ //find an appropriate name for our file
+ QString fileName = findFileName(c, ".sql");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile file;
+ if( !openFile(file, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ //Start generating the code!!
+
+ QTextStream sql(&file);
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".sql");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%filepath%"),file.name());
+ sql<<str<<m_endl;
+ }
+
+ //Write class Documentation if there is somthing or if force option
+ if(forceDoc() || !c->getDoc().isEmpty()) {
+ sql << m_endl << "--" << m_endl;
+ sql<<"-- TABLE: "<<classname<<m_endl;
+ sql<<formatDoc(c->getDoc(),"-- ");
+ sql << "-- " << m_endl << m_endl;
+ }
+
+ sql << "CREATE TABLE "<< classname << " ( " << m_endl;
+
+ if (isClass)
+ writeAttributes(c, sql);
+
+ sql << m_endl << ");" << m_endl;
+
+ QMap<UMLAssociation*,UMLAssociation*> constraintMap; // so we don't repeat constraint
+ UMLAssociationList aggregations = c->getAggregations();
+ if( forceSections() || !aggregations.isEmpty() ) {
+ for(UMLAssociation* a = aggregations.first(); a; a = aggregations.next()) {
+ UMLObject *objA = a->getObject(Uml::A);
+ UMLObject *objB = a->getObject(Uml::B);
+ if (objA->getID() == c->getID() && objB->getID() != c->getID())
+ continue;
+ constraintMap[a] = a;
+ }
+ }
+
+ QMap<UMLAssociation*,UMLAssociation*>::Iterator itor = constraintMap.begin();
+ for (;itor != constraintMap.end();itor++) {
+ UMLAssociation* a = itor.data();
+ sql << "ALTER TABLE "<< classname
+ << " ADD CONSTRAINT " << a->getName() << " FOREIGN KEY ("
+ << a->getRoleName(Uml::B) << ") REFERENCES "
+ << a->getObject(Uml::A)->getName()
+ << " (" << a->getRoleName(Uml::A) << ");" << m_endl;
+ }
+
+
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+
+void SQLWriter::writeAttributes(UMLClassifier *c, QTextStream &sql) {
+ UMLAttributeList atpub, atprot, atpriv, atimp;
+ atpub.setAutoDelete(false);
+ atprot.setAutoDelete(false);
+ atpriv.setAutoDelete(false);
+ atimp.setAutoDelete(false);
+
+ //sort attributes by scope and see if they have a default value
+ UMLAttributeList atl = c->getAttributeList();
+ for(UMLAttribute* at=atl.first(); at ; at=atl.next()) {
+ switch(at->getVisibility()) {
+ case Uml::Visibility::Public:
+ atpub.append(at);
+ break;
+ case Uml::Visibility::Protected:
+ atprot.append(at);
+ break;
+ case Uml::Visibility::Private:
+ atpriv.append(at);
+ break;
+ case Uml::Visibility::Implementation:
+ atimp.append(at);
+ break;
+ }
+ }
+
+ // now print the attributes; they are sorted by there scope
+ // in front of the first attribute shouldn't be a , -> so we need to find
+ // out, when the first attribute was added
+ bool first = true;
+
+ if (atpub.count() > 0)
+ {
+ printAttributes(sql, atpub, first);
+ first = false;
+ }
+
+ if (atprot.count() > 0)
+ {
+ printAttributes(sql, atprot, first);
+ first = false;
+ }
+
+ if (atpriv.count() > 0)
+ {
+ printAttributes(sql, atpriv, first);
+ first = false;
+ }
+
+ if (atimp.count() > 0)
+ {
+ printAttributes(sql, atimp, first);
+ first = false;
+ }
+
+ return;
+}
+
+void SQLWriter::printAttributes(QTextStream& sql, UMLAttributeList attributeList, bool first) {
+ QString attrDoc = "";
+ UMLAttribute* at;
+
+ for (at=attributeList.first();at;at=attributeList.next())
+ {
+ // print , after attribute
+ if (first == false) {
+ sql <<",";
+ } else {
+ first = false;
+ }
+
+ // print documentation/comment of last attribute at end of line
+ if (attrDoc.isEmpty() == false)
+ {
+ sql << " -- " << attrDoc << m_endl;
+ } else {
+ sql << m_endl;
+ }
+
+ // write the attribute
+ sql << m_indentation << cleanName(at->getName()) << " " << at->getTypeName() << " "
+ << (at->getInitialValue().isEmpty()?QString(""):QString(" DEFAULT ")+at->getInitialValue());
+
+ // now get documentation/comment of current attribute
+ attrDoc = at->getDoc();
+ }
+
+ // print documentation/comment at end of line
+ if (attrDoc.isEmpty() == false)
+ {
+ sql << " -- " << attrDoc << m_endl;
+ } else {
+ sql << m_endl;
+ }
+
+ return;
+}
+
+Uml::Programming_Language SQLWriter::getLanguage() {
+ return Uml::pl_SQL;
+}
+
+QStringList SQLWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("varchar");
+ l.append("tinyint");
+ l.append("smallint");
+ l.append("mediumint");
+ l.append("bigint");
+ l.append("float");
+ l.append("double");
+ l.append("decimal");
+ l.append("date");
+ l.append("datetime");
+ l.append("time");
+ l.append("timestamp");
+ l.append("year");
+ l.append("char");
+ l.append("tinyblob");
+ l.append("blob");
+ l.append("mediumblob");
+ l.append("longblob");
+ l.append("tinytext");
+ l.append("text");
+ l.append("mediumtext");
+ l.append("longtext");
+ l.append("enum");
+ l.append("set");
+ return l;
+}
+
+const QStringList SQLWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "access"
+ << "add"
+ << "all"
+ << "alter"
+ << "analyze"
+ << "and"
+ << "any"
+ << "as"
+ << "asc"
+ << "audit"
+ << "begin"
+ << "between"
+ << "boolean"
+ << "by"
+ << "char"
+ << "character"
+ << "check"
+ << "cluster"
+ << "column"
+ << "comment"
+ << "commit"
+ << "compress"
+ << "connect"
+ << "create"
+ << "current"
+ << "cursor"
+ << "date"
+ << "decimal"
+ << "default"
+ << "delete"
+ << "desc"
+ << "distinct"
+ << "drop"
+ << "else"
+ << "elsif"
+ << "end"
+ << "escape"
+ << "exception"
+ << "exclusive"
+ << "execute"
+ << "exists"
+ << "explain"
+ << "false"
+ << "file"
+ << "float"
+ << "for"
+ << "from"
+ << "function"
+ << "grant"
+ << "group"
+ << "having"
+ << "identified"
+ << "if"
+ << "immediate"
+ << "in"
+ << "increment"
+ << "index"
+ << "initial"
+ << "insert"
+ << "integer"
+ << "intersect"
+ << "into"
+ << "is"
+ << "level"
+ << "like"
+ << "lock"
+ << "long"
+ << "loop"
+ << "maxextents"
+ << "minus"
+ << "mlslabel"
+ << "mode"
+ << "modify"
+ << "noaudit"
+ << "nocompress"
+ << "not"
+ << "nowait"
+ << "null"
+ << "number"
+ << "of"
+ << "offline"
+ << "on"
+ << "online"
+ << "option"
+ << "or"
+ << "order"
+ << "out"
+ << "pctfree"
+ << "prior"
+ << "privileges"
+ << "procedure"
+ << "public"
+ << "raw"
+ << "rename"
+ << "resource"
+ << "return"
+ << "revoke"
+ << "rollback"
+ << "row"
+ << "rowid"
+ << "rowlabel"
+ << "rownum"
+ << "rows"
+ << "savepoint"
+ << "select"
+ << "session"
+ << "set"
+ << "share"
+ << "size"
+ << "smallint"
+ << "some"
+ << "start"
+ << "successful"
+ << "synonym"
+ << "sysdate"
+ << "table"
+ << "then"
+ << "to"
+ << "trigger"
+ << "true"
+ << "truncate"
+ << "type"
+ << "uid"
+ << "union"
+ << "unique"
+ << "update"
+ << "user"
+ << "using"
+ << "validate"
+ << "values"
+ << "varchar"
+ << "varchar2"
+ << "varray"
+ << "view"
+ << "whenever"
+ << "where"
+ << "with";
+ }
+
+ return keywords;
+}
+
+#include "sqlwriter.moc"
diff --git a/umbrello/umbrello/codegenerators/sqlwriter.h b/umbrello/umbrello/codegenerators/sqlwriter.h
new file mode 100644
index 00000000..c500e2e7
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/sqlwriter.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ sqlwriter.h - description
+ -------------------
+ begin : 10.02.2003
+ copyright : (C) 2003 by Nikolaus Gradwohl
+ email : guru@local-guru.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef SQLWRITER_H
+#define SQLWRITER_H
+
+#include "simplecodegenerator.h"
+#include "../umlattributelist.h"
+
+/**
+ * class SQLWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate a sql source file for
+ * that concept
+ */
+class SQLWriter : public SimpleCodeGenerator {
+ Q_OBJECT
+public:
+
+ SQLWriter();
+ virtual ~SQLWriter();
+
+ /**
+ * call this method to generate sql code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "SQL"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * Reimplement method from CodeGenerator.
+ */
+ virtual QStringList defaultDatatypes();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * write all attributes for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * Prints out attributes as columns in the table
+ *
+ * @param sql the stream we should print to
+ * @param attributeList the attributes to be printed
+ * @param first if the attributes are the first one
+ */
+ void printAttributes(QTextStream& sql, UMLAttributeList attributeList, bool first);
+};
+
+#endif // SQLWRITER_H
diff --git a/umbrello/umbrello/codegenerators/tclwriter.cpp b/umbrello/umbrello/codegenerators/tclwriter.cpp
new file mode 100644
index 00000000..d8607aa7
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/tclwriter.cpp
@@ -0,0 +1,951 @@
+/***************************************************************************
+ begin : Thu Jul 26 2005
+ copyright : (C) 2005 by Rene Meyer
+ email : rene.meyer@sturmit.de
+ (C) 2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// own header
+#include "tclwriter.h"
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "classifierinfo.h"
+#include "codegen_utils.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../umltemplatelist.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../classifierlistitem.h"
+#include "../model_utils.h"
+
+static const char *tclwords[] = {
+ "body",
+ "break",
+ "case",
+ "class",
+ "common",
+ "concat",
+ "configbody",
+ "constructor",
+ "continue",
+ "default",
+ "destructor",
+ "else",
+ "elseif",
+ "for",
+ "foreach",
+ "global",
+ "if",
+ "incr",
+ "lappend",
+ "lindex",
+ "list",
+ "llength",
+ "load",
+ "lrange",
+ "lreplace",
+ "method",
+ "namespace",
+ "private",
+ "proc",
+ "protected",
+ "public",
+ "return",
+ "set",
+ "source",
+ "switch",
+ "then",
+ "upvar",
+ "variable",
+ "virtual",
+ "while",
+ 0
+ };
+
+TclWriter::TclWriter()
+{
+}
+
+TclWriter::~TclWriter()
+{
+}
+
+Uml::Programming_Language
+TclWriter::getLanguage()
+{
+ return Uml::pl_Tcl;
+}
+
+void
+TclWriter::writeClass(UMLClassifier * c)
+{
+
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!\n";
+ return;
+ }
+ QFile fileh, filetcl;
+
+ // find an appropriate name for our file
+ QString fileName = findFileName(c, ".tcl");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ if (!openFile(fileh, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ // preparations
+ classifierInfo = new ClassifierInfo(c);
+ classifierInfo->fileName = fileName;
+ classifierInfo->className = cleanName(c->getName());
+ mClass = cleanName(c->getName());
+ if (!c->getPackage().isEmpty()) {
+ mNamespace = "::" + cleanName(c->getPackage());
+ mClassGlobal = mNamespace + "::" + mClass;
+ } else {
+ mNamespace = "::";
+ mClassGlobal = "::" + mClass;
+ }
+
+ // write Header file
+ writeHeaderFile(c, fileh);
+ fileh.close();
+
+ // Determine whether the implementation file is required.
+ // (It is not required if the class is an enumeration.)
+ bool need_impl = true;
+ if (!classifierInfo->isInterface) {
+ if (c->getBaseType() == Uml::ot_Enum)
+ need_impl = false;
+ }
+ if (need_impl) {
+ if (!openFile(filetcl, fileName + "body")) {
+ emit codeGenerated(c, false);
+ return;
+ }
+ // write Source file
+ writeSourceFile(c, filetcl);
+ filetcl.close();
+ }
+ // Wrap up: free classifierInfo, emit done code
+ classifierInfo = 0;
+
+ emit codeGenerated(c, true);
+
+}
+
+void
+TclWriter::writeHeaderFile(UMLClassifier * c, QFile & fileh)
+{
+ // open stream for writing
+ QTextStream stream(&fileh);
+ mStream = &stream;
+
+ // reset the indent level
+ m_indentLevel = 0;
+
+ // write header blurb
+ QString str = getHeadingFile(".tcl");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), classifierInfo->fileName);
+ str.replace(QRegExp("%filepath%"), fileh.name());
+ writeCode(str);
+ }
+ // set current namespace
+ writeCode("namespace eval " + mNamespace + " {");
+ m_indentLevel++;
+
+ // check on already existing
+ writeComm("Do not load twice");
+ writeCode("if {[namespace exist " + mClass + "]} return");
+
+ // source used superclass files
+ UMLClassifierList superclasses = classifierInfo->superclasses;
+ if (superclasses.count() > 0) {
+ writeComm
+ ("Source found and used class files and import class command if necessary");
+
+ for (UMLClassifier * classifier = superclasses.first(); classifier;
+ classifier = superclasses.next()) {
+ writeUse(classifier);
+ }
+ }
+ // write all "source" we need to include other classes, that arent us.
+ if (classifierInfo->hasAssociations) {
+ writeAssociationIncl(classifierInfo->plainAssociations, c->getID(),
+ "Associations");
+ writeAssociationIncl(classifierInfo->aggregations, c->getID(),
+ "Aggregations");
+ writeAssociationIncl(classifierInfo->compositions, c->getID(),
+ "Compositions");
+ }
+ //Write class Documentation
+ writeDocu("\n@class\t" + mClass + m_endl + c->getDoc());
+
+ //check if class is abstract and / or has abstract methods
+ if ((c->getAbstract() || classifierInfo->isInterface)
+ && !hasAbstractOps(c)) {
+ writeComm("TODO abstract class" + mClass +
+ "\nInherit from it and create only objects from the derived classes");
+ }
+ // check on enum classes
+ if (!classifierInfo->isInterface) {
+ // use tcl-list for enum's
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLClassifierListItemList litList =
+ c->getFilteredList(Uml::ot_EnumLiteral);
+ writeCode("set enum_" + mClass + " [list\\");
+ m_indentLevel++;
+ for (UMLClassifierListItem * lit = litList.first(); lit;
+ lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ writeCode(enumLiteral + "\\");
+ }
+ m_indentLevel--;
+ writeCode("];# end of enum");
+ m_indentLevel--;
+ writeCode("};# end of namespace");
+ return;
+ }
+ }
+ // Generate template parameters.
+ UMLTemplateList template_params = c->getTemplateList();
+ if (template_params.count()) {
+ writeCode("#TODO template<");
+ for (UMLTemplate * t = template_params.first(); t;
+ t = template_params.next()) {
+ QString formalName = t->getName();
+ QString typeName = t->getTypeName();
+ writeCode(typeName + "# " + formalName);
+ }
+ }
+ // start my own class
+ writeCode("class " + mClass + " {");
+ m_indentLevel++;
+ if (classifierInfo->superclasses.count() > 0) {
+ QString code = "inherit";
+ for (UMLClassifier * superClass = classifierInfo->superclasses.first();
+ superClass; superClass = classifierInfo->superclasses.next()) {
+ /*
+ if (superClass->getAbstract() || superClass->isInterface())
+ stream << getIndent() << "virtual ";
+ */
+ if (superClass->getPackage().isEmpty()) {
+ code += " ::" + cleanName(superClass->getName());
+ } else {
+ code +=
+ " ::" + cleanName(superClass->getPackage()) + "::" +
+ cleanName(superClass->getName());
+ }
+ }
+ writeCode(code);
+ }
+ //
+ //declarations of operations
+ //
+ // write out field and operations decl grouped by visibility
+ //
+
+ // PUBLIC attribs/methods
+ // for public: constructors are first ops we print out
+ if (!classifierInfo->isInterface) {
+ writeConstructorHeader();
+ writeDestructorHeader();
+ }
+ // attributes
+ writeAttributeDecl(Uml::Visibility::Public, true); // write static attributes first
+ writeAttributeDecl(Uml::Visibility::Public, false);
+ // associations
+ writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Public,
+ c->getID(), "Associations");
+ writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Public, c->getID(),
+ "Aggregations");
+ writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Public, c->getID(),
+ "Compositions");
+ //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, stream);
+ writeOperationHeader(c, Uml::Visibility::Public);
+
+ // PROTECTED attribs/methods
+ //
+ // attributes
+ writeAttributeDecl(Uml::Visibility::Protected, true); // write static attributes first
+ writeAttributeDecl(Uml::Visibility::Protected, false);
+ // associations
+ writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Protected,
+ c->getID(), "Association");
+ writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Protected,
+ c->getID(), "Aggregation");
+ writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Protected,
+ c->getID(), "Composition");
+ //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Protected, stream);
+ writeOperationHeader(c, Uml::Visibility::Protected);
+
+ // PRIVATE attribs/methods
+ //
+ // attributes
+ writeAttributeDecl(Uml::Visibility::Private, true); // write static attributes first
+ writeAttributeDecl(Uml::Visibility::Private, false);
+ // associations
+ writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Private,
+ c->getID(), "Associations");
+ writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Private, c->getID(),
+ "Aggregations");
+ writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Private, c->getID(),
+ "Compositions");
+ //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, stream);
+ writeOperationHeader(c, Uml::Visibility::Private);
+ writeInitAttributeHeader(); // this is always private, used by constructors to initialize class
+
+ // end of class header
+ m_indentLevel--;
+ writeCode("};# end of class");
+
+ // end of class namespace, if any
+ m_indentLevel--;
+ writeCode("};# end of namespace");
+}
+
+void
+TclWriter::writeSourceFile(UMLClassifier * c, QFile & filetcl)
+{
+ // open stream for writing
+ QTextStream stream(&filetcl);
+ mStream = &stream;
+
+ // set the starting indentation at zero
+ m_indentLevel = 0;
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".tclbody");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), classifierInfo->fileName + "body");
+ str.replace(QRegExp("%filepath%"), filetcl.name());
+ writeCode(str);
+ }
+ // Start body of class
+
+ // constructors are first ops we print out
+ if (!classifierInfo->isInterface) {
+ writeConstructorSource();
+ writeDestructorSource();
+ }
+ // Public attributes have in tcl a configbody method
+ writeAttributeSource();
+ // Association access functions
+ writeAssociationSource(classifierInfo->plainAssociations, c->getID());
+ writeAssociationSource(classifierInfo->aggregations, c->getID());
+ writeAssociationSource(classifierInfo->compositions, c->getID());
+ // Procedures and methods
+ writeOperationSource(c, Uml::Visibility::Public);
+ writeOperationSource(c, Uml::Visibility::Protected);
+ writeOperationSource(c, Uml::Visibility::Private);
+ // Yep, bringing up the back of the bus, our initialization method for attributes
+ writeInitAttributeSource();
+}
+
+void
+TclWriter::writeCode(const QString &text)
+{
+ *mStream << getIndent() << text << m_endl;
+}
+
+void
+TclWriter::writeComm(const QString &text)
+{
+ QStringList lines = QStringList::split("\n", text, true);
+ for (uint i = 0; i < lines.count(); i++) {
+ *mStream << getIndent() << "# " << lines[i] << m_endl;
+ }
+}
+
+void
+TclWriter::writeDocu(const QString &text)
+{
+ QStringList lines = QStringList::split("\n", text, true);
+ for (uint i = 0; i < lines.count(); i++) {
+ *mStream << getIndent() << "## " << lines[i] << m_endl;
+ }
+}
+
+// To prevent circular including when both classifiers on either end
+// of an association have roles we need to have forward declaration of
+// the other class...but only IF its not THIS class (as could happen
+// in self-association relationship).
+void
+TclWriter::writeAssociationIncl(UMLAssociationList list, Uml::IDType myId,
+ const QString &type)
+{
+ for (UMLAssociation * a = list.first(); a; a = list.next()) {
+ UMLClassifier *classifier = NULL;
+
+ writeComm(m_endl + type + m_endl + a->toString() + m_endl + a->getDoc());
+ // only use OTHER classes (e.g. we don't need to write includes for ourselves!!
+ // AND only IF the roleName is defined, otherwise, its not meant to be noticed.
+ if (a->getObjectId(Uml::A) == myId && !a->getRoleName(Uml::B).isEmpty()) {
+ classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::B));
+ writeUse(classifier);
+ } else if (a->getObjectId(Uml::B) == myId
+ && !a->getRoleName(Uml::A).isEmpty()) {
+ classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::A));
+ if (classifier->getPackage().isEmpty())
+ writeCode("namespace eval " + cleanName(classifier->getName()) +
+ " {}");
+ } else {
+ // CHECK: This crashes (classifier still NULL from above)
+ /*
+ writeCode("namespace eval " + cleanName(classifier->getPackage()) +
+ "::" + cleanName(classifier->getName()) + " {}");
+ */
+ }
+ }
+}
+
+void
+TclWriter::writeUse(UMLClassifier * c)
+{
+ QString myNs;
+
+ if (!c->getPackage().isEmpty()) {
+ myNs = cleanName(c->getPackage());
+ } else {
+ myNs = "";
+ }
+ // if different package
+ if (("::"+myNs) != mNamespace) {
+ if (c->getPackage().isEmpty()) {
+ writeCode("source " + findFileName(c, ".tcl"));
+ writeCode("namespace import ::" + cleanName(c->getName()));
+ } else {
+ writeCode("package require " + myNs);
+ writeCode("namespace import ::" + myNs + "::" +
+ cleanName(c->getName()));
+ }
+ } else {
+ // source the file
+ writeCode("source " + findFileName(c, ".tcl"));
+ }
+}
+
+void
+TclWriter::writeConstructorHeader()
+{
+
+ writeDocu
+ (m_endl + "@func constructor" + m_endl +
+ "@par args contain all configuration parameters" + m_endl);
+
+ writeCode("constructor {args} {}" + m_endl);
+}
+
+void
+TclWriter::writeConstructorSource()
+{
+ writeComm(mClassGlobal + "::constructor");
+ writeCode(mClassGlobal + "::constructor {args} {");
+ m_indentLevel++;
+ if (classifierInfo->hasAttributes) {
+ writeCode("initAttributes");
+ }
+ writeCode("eval configure $args");
+ m_indentLevel--;
+ writeCode('}' + m_endl);
+}
+
+void
+TclWriter::writeDestructorHeader()
+{
+
+ writeDocu(m_endl + "@func destructor" + m_endl);
+
+ writeCode("destructor {} {}");
+}
+
+void
+TclWriter::writeDestructorSource()
+{
+ writeComm(mClassGlobal + "::destructor");
+ writeCode(mClassGlobal + "::destructor {} {" + m_endl + '}' + m_endl);
+}
+
+void
+TclWriter::writeAttributeDecl(Uml::Visibility visibility, bool writeStatic)
+{
+ if (classifierInfo->isInterface)
+ return;
+
+ QString scope = visibility.toString();
+ QString type;
+ if (writeStatic) {
+ type = "common";
+ } else {
+ type = "variable";
+ }
+ UMLAttributeList *list = NULL;
+ switch (visibility) {
+ case Uml::Visibility::Private:
+ if (writeStatic) {
+ list = &(classifierInfo->static_atpriv);
+ } else {
+ list = &(classifierInfo->atpriv);
+ }
+ break;
+
+ case Uml::Visibility::Protected:
+ if (writeStatic) {
+ list = &(classifierInfo->static_atprot);
+ } else {
+ list = &(classifierInfo->atprot);
+ }
+ break;
+
+ case Uml::Visibility::Public:
+ if (writeStatic) {
+ list = &(classifierInfo->static_atpub);
+ } else {
+ list = &(classifierInfo->atpub);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (list && list->count() > 0) {
+ writeComm(m_endl + scope + ' ' + type + " attributes" + m_endl);
+ // write attrib declarations now
+ QString documentation;
+ for (UMLAttribute * at = list->first(); at; at = list->next()) {
+ documentation = at->getDoc();
+ QString varName = cleanName(at->getName());
+ QString typeName = fixTypeName(at->getTypeName());
+ writeDocu(m_endl + "@var " + scope + ' ' + type + ' ' + typeName + ' ' +
+ varName + m_endl + documentation);
+ writeCode(scope + ' ' + type + ' ' + varName + m_endl);
+ }
+ }
+}
+
+void
+TclWriter::writeAssociationDecl(UMLAssociationList associations,
+ Uml::Visibility permitScope, Uml::IDType id,
+ const QString &/*type*/)
+{
+ if (forceSections() || !associations.isEmpty()) {
+ bool printRoleA = false, printRoleB = false;
+ for (UMLAssociation * a = associations.first(); a;
+ a = associations.next()) {
+
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == id && !a->getRoleName(Uml::B).isEmpty())
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty())
+ printRoleA = true;
+
+ // First: we insert documentaion for association IF it has either role AND some documentation (!)
+ // print RoleB decl
+ if (printRoleB && a->getVisibility(Uml::B) == permitScope) {
+
+ QString fieldClassName =
+ cleanName(getUMLObjectName(a->getObject(Uml::B)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B),
+ a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
+ permitScope.toString());
+ }
+ // print RoleA decl
+ if (printRoleA && a->getVisibility(Uml::A) == permitScope) {
+ QString fieldClassName =
+ cleanName(getUMLObjectName(a->getObject(Uml::A)));
+ writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A),
+ a->getMulti(Uml::A), a->getRoleDoc(Uml::A),
+ permitScope.toString());
+ }
+ // reset for next association in our loop
+ printRoleA = false;
+ printRoleB = false;
+ }
+ }
+}
+
+void
+TclWriter::writeAssociationRoleDecl(const QString &fieldClassName, const QString &roleName,
+ const QString &multi, const QString &doc, const QString &scope)
+{
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty())
+ return;
+
+
+ // declare the association based on whether it is this a single variable
+ // or a List (Vector). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ if (multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
+ QString fieldVarName = roleName.lower();
+
+ // record this for later consideration of initialization IF the
+ // multi value requires 1 of these objects
+ if (ObjectFieldVariables.findIndex(fieldVarName) == -1 &&
+ multi.contains(QRegExp("^1$"))
+ ) {
+ // ugh. UGLY. Storing variable name and its class in pairs.
+ ObjectFieldVariables.append(fieldVarName);
+ ObjectFieldVariables.append(fieldClassName);
+ }
+ writeDocu(m_endl + "@var " + scope + " variable <" + fieldClassName +
+ "> " + fieldVarName + m_endl + doc);
+ writeCode(scope + " variable " + fieldVarName + m_endl);
+ } else {
+ QString fieldVarName = roleName.lower();
+
+ // record unique occurrences for later when we want to check
+ // for initialization of this vector
+ if (VectorFieldVariables.findIndex(fieldVarName) == -1)
+ VectorFieldVariables.append(fieldVarName);
+ writeDocu(m_endl + "@var" + scope + " variable <" + fieldClassName +
+ "*> " + fieldVarName + m_endl + doc);
+ writeCode(scope + " variable " + fieldVarName + m_endl);
+ }
+}
+
+void
+TclWriter::writeInitAttributeHeader()
+{
+ if (classifierInfo->hasAttributes) {
+ writeDocu("@method private initAttributes" + m_endl +
+ "Initialize all internal variables");
+ writeCode("private method initAttributes {}");
+ }
+}
+
+void
+TclWriter::writeInitAttributeSource()
+{
+ // only need to do this under certain conditions
+ if (classifierInfo->hasAttributes) {
+ QString varName;
+
+ writeComm(mClassGlobal + "::initAttributes");
+ writeCode("body " + mClassGlobal + "::initAttributes {} {");
+ m_indentLevel++;
+
+ // first, initiation of fields derived from attributes
+ UMLAttributeList atl = classifierInfo->getAttList();
+ for (UMLAttribute * at = atl.first(); at; at = atl.next()) {
+ if (!at->getInitialValue().isEmpty()) {
+ varName = cleanName(at->getName());
+ writeCode("set " + varName + ' ' + at->getInitialValue());
+ }
+ }
+ // Now initialize the association related fields (e.g. vectors)
+ QStringList::Iterator it;
+ for (it = VectorFieldVariables.begin();
+ it != VectorFieldVariables.end(); ++it) {
+ varName = *it;
+ writeCode("set " + varName + " [list]");
+ }
+
+ for (it = ObjectFieldVariables.begin();
+ it != ObjectFieldVariables.end(); ++it) {
+ varName = *it;
+ it++;
+ QString fieldClassName = *it;
+ writeCode("set " + varName + " [list]");
+ }
+ // clean up
+ ObjectFieldVariables.clear(); // shouldn't be needed?
+ VectorFieldVariables.clear(); // shouldn't be needed?
+
+ m_indentLevel--;
+ writeCode('}' + m_endl);
+ }
+}
+
+void
+TclWriter::writeOperationHeader(UMLClassifier * c, Uml::Visibility permitScope)
+{
+
+ UMLOperationList oplist;
+ UMLOperation *op;
+ UMLAttribute *at;
+ int j;
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList inputlist = c->getOpList();
+ for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) {
+ switch (op->getVisibility()) {
+ case Uml::Visibility::Public:
+ if (permitScope == Uml::Visibility::Public)
+ oplist.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ if (permitScope == Uml::Visibility::Protected)
+ oplist.append(op);
+ break;
+ case Uml::Visibility::Private:
+ if (permitScope == Uml::Visibility::Private)
+ oplist.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // generate method decl for each operation given
+ if (oplist.count() > 0) {
+ writeComm("Operations");
+ }
+ for (op = oplist.first(); op; op = oplist.next()) {
+ QString doc = "";
+ QString code = "";
+ QString methodReturnType = fixTypeName(op->getTypeName());
+ QString name = cleanName(op->getName());
+ QString scope = permitScope.toString();
+ if (op->getAbstract() || classifierInfo->isInterface) {
+ //TODO declare abstract method as 'virtual'
+ // str += "virtual ";
+ }
+ // declaration for header file
+ if (op->getStatic()) {
+ doc = m_endl + "@fn " + scope + " proc " + name + m_endl;
+ code = scope + " proc " + name + " {";
+ } else {
+ doc = m_endl + "@fn " + scope + " method " + name + m_endl;
+ code = scope + " method " + name + " {";
+ }
+ // method parameters
+ UMLAttributeList atl = op->getParmList();
+ j = 0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ QString typeName = fixTypeName(at->getTypeName());
+ QString atName = cleanName(at->getName());
+ if (at->getInitialValue().isEmpty()) {
+ doc +=
+ "@param " + typeName + ' ' + atName + m_endl + at->getDoc() +
+ m_endl;
+ code += ' ' + atName;
+ } else {
+ doc +=
+ "@param " + typeName + ' ' + atName + " (default=" +
+ at->getInitialValue() + ") " + m_endl + at->getDoc() + m_endl;
+ code += " {" + atName + ' ' + at->getInitialValue() + "} ";
+ }
+ }
+ if (methodReturnType != "void") {
+ doc += "@return " + methodReturnType + m_endl;
+ }
+ writeDocu(doc + op->getDoc());
+ writeCode(code + "} {}" + m_endl);
+ }
+}
+
+void
+TclWriter::writeOperationSource(UMLClassifier * c, Uml::Visibility permitScope)
+{
+
+ UMLOperationList oplist;
+ UMLOperation *op;
+ UMLAttribute *at;
+ int j;
+
+ //sort operations by scope first and see if there are abstract methods
+ UMLOperationList inputlist = c->getOpList();
+ for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) {
+ switch (op->getVisibility()) {
+ case Uml::Visibility::Public:
+ if (permitScope == Uml::Visibility::Public)
+ oplist.append(op);
+ break;
+ case Uml::Visibility::Protected:
+ if (permitScope == Uml::Visibility::Protected)
+ oplist.append(op);
+ break;
+ case Uml::Visibility::Private:
+ if (permitScope == Uml::Visibility::Private)
+ oplist.append(op);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // generate source for each operation given
+ for (op = oplist.first(); op; op = oplist.next()) {
+ QString code = "";
+ QString methodReturnType = fixTypeName(op->getTypeName());
+ QString name;
+ // no code needed
+ if (op->getAbstract() || classifierInfo->isInterface) {
+ continue;
+ }
+ name = mClassGlobal + "::" + cleanName(op->getName());
+ writeComm(name);
+ code = "body " + name + " {";
+ // parameters
+ UMLAttributeList atl = op->getParmList();
+ j = 0;
+ for (at = atl.first(); at; at = atl.next(), j++) {
+ QString atName = cleanName(at->getName());
+ if (at->getInitialValue().isEmpty()) {
+ code += ' ' + atName;
+ } else {
+ code += " {" + atName + ' ' + at->getInitialValue() + "} ";
+ }
+ }
+ writeCode(code += "} {");
+ m_indentLevel++;
+ if (methodReturnType != "void") {
+ writeCode("return " + methodReturnType);
+ } else {
+ writeCode("return");
+ }
+ m_indentLevel--;
+ writeCode('}' + m_endl);
+ }
+}
+
+void
+TclWriter::writeAttributeSource()
+{
+ UMLAttributeList *list = &(classifierInfo->atpub);
+ UMLAttribute *at;
+ for (at = list->first(); at; at = list->next()) {
+ QString name = mClassGlobal + "::" + cleanName(at->getName());
+
+ writeComm(name);
+ writeCode("configbody " + name + " {} {" + m_endl + '}' + m_endl);
+ }
+}
+
+void
+TclWriter::writeAssociationSource(UMLAssociationList associations,
+ Uml::IDType id)
+{
+ if (associations.isEmpty()) {
+ return;
+ }
+
+ bool printRoleA = false, printRoleB = false;
+ for (UMLAssociation * a = associations.first(); a; a = associations.next()) {
+
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+ if (a->getObjectId(Uml::A) == id && !a->getRoleName(Uml::B).isEmpty())
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty())
+ printRoleA = true;
+
+ // print RoleB source
+ if (printRoleB && a->getVisibility(Uml::B) == Uml::Visibility::Public) {
+
+ QString fieldClassName =
+ cleanName(getUMLObjectName(a->getObject(Uml::B)));
+ writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::B),
+ a->getMulti(Uml::B));
+ }
+ // print RoleA source
+ if (printRoleA && a->getVisibility(Uml::A) == Uml::Visibility::Public) {
+ QString fieldClassName =
+ cleanName(getUMLObjectName(a->getObject(Uml::A)));
+ writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::A),
+ a->getMulti(Uml::A));
+ }
+ // reset for next association in our loop
+ printRoleA = false;
+ printRoleB = false;
+ }
+}
+
+void
+TclWriter::writeAssociationRoleSource(const QString &fieldClassName,
+ const QString &roleName, const QString &multi)
+{
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty())
+ return;
+
+ // declare the association based on whether it is this a single variable
+ // or a List (Vector). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ if (multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
+ QString fieldVarName = roleName.lower();
+
+ writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {");
+ m_indentLevel++;
+ writeCode("if {![$" + fieldVarName + " isa " + fieldClassName + "]} {");
+ m_indentLevel++;
+ writeCode("return -code error \"expected object of class: " +
+ fieldClassName + "\"");
+ m_indentLevel--;
+ writeCode("}");
+ m_indentLevel--;
+
+ } else {
+ QString fieldVarName = roleName.lower();
+
+ writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {");
+ m_indentLevel++;
+ writeCode("foreach myObj $" + fieldVarName + " {");
+ m_indentLevel++;
+ writeCode("if {![$myObj isa " + fieldClassName + "]} {");
+ m_indentLevel++;
+ writeCode("return -code error \"expected object of class: " +
+ fieldClassName + "\"");
+ m_indentLevel--;
+ writeCode("}");
+ m_indentLevel--;
+ writeCode("}");
+ m_indentLevel--;
+ }
+ writeCode('}' + m_endl);
+}
+
+QString
+TclWriter::fixTypeName(const QString &string)
+{
+ if (string.isEmpty())
+ return "void";
+ return string;
+}
+
+// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
+QString
+TclWriter::getUMLObjectName(UMLObject * obj)
+{
+ return (obj != 0) ? obj->getName() : QString("NULL");
+}
+
+const QStringList
+TclWriter::reservedKeywords() const
+{
+ static QStringList keywords;
+
+ if (keywords.isEmpty())
+ {
+ for (int i = 0; tclwords[i]; i++)
+ keywords.append(tclwords[i]);
+ }
+ return keywords;
+}
+
diff --git a/umbrello/umbrello/codegenerators/tclwriter.h b/umbrello/umbrello/codegenerators/tclwriter.h
new file mode 100644
index 00000000..0c4d71c5
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/tclwriter.h
@@ -0,0 +1,174 @@
+/***************************************************************************
+ tclwriter.h - description
+ -------------------
+ begin : Thu Jul 26 2005
+ copyright : (C) 2005 by Rene Meyer
+ email : rene.meyer@sturmit.de
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef TCLWRITER_H
+#define TCLWRITER_H
+
+#include <qstringlist.h>
+#include "simplecodegenerator.h"
+#include "../umloperationlist.h"
+#include "../umlattributelist.h"
+#include "../umlassociationlist.h"
+
+class QFile;
+class QTextStream;
+class ClassifierInfo;
+
+/**
+ * class TclWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate both a header (.h) and
+ * source (.tcl) file for that classifier.
+ */
+class TclWriter : public SimpleCodeGenerator
+{
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ TclWriter();
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~ TclWriter();
+
+ /**
+ * call this method to generate tcl code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier * c);
+
+ /**
+ * returns "Tcl"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+ /**
+ * Current output stream.
+ */
+ QTextStream * mStream;
+ /**
+ * write the header file for this classifier.
+ */
+ void writeHeaderFile(UMLClassifier * c, QFile & file);
+
+ /**
+ * write the source code body file for this classifier.
+ */
+ void writeSourceFile(UMLClassifier * c, QFile & file);
+
+ /**
+ * write the source codei text.
+ */
+ void writeCode(const QString &text);
+
+ /**
+ * write comment text.
+ */
+ void writeComm(const QString &text);
+
+ /**
+ * write documentation text.
+ */
+ void writeDocu(const QString &text);
+
+ void writeConstructorDecl();
+
+ void writeDestructorDecl();
+
+ /**
+ * Summary information about current classifier.
+ */
+ ClassifierInfo *classifierInfo;
+ QString mNamespace;
+ QString mClass;
+ QString mClassGlobal;
+
+ /**
+ * writes the Attribute declarations
+ * @param visibility the visibility of the attribs to print out
+ * @param writeStatic whether to write static or non-static attributes out
+ * @param stream text stream
+ */
+ void writeAttributeDecl(Uml::Visibility visibility, bool writeStatic);
+
+ void writeAssociationIncl(UMLAssociationList list,
+ Uml::IDType myId, const QString &type);
+ /**
+ * Searches a list of associations for appropriate ones to write out as attributes
+ */
+ void writeAssociationDecl(UMLAssociationList associations,
+ Uml::Visibility permit, Uml::IDType id,
+ const QString &type);
+
+ /**
+ * Writes out an association as an attribute using Vector
+ */
+ void writeAssociationRoleDecl(const QString &fieldClassName,
+ const QString &roleName, const QString &multi, const QString &doc, const QString &docname);
+
+ /**
+ * If needed, write out the declaration for the method to initialize attributes of our class.
+ */
+ void writeInitAttributeHeader();
+ void writeInitAttributeSource();
+
+ void writeConstructorHeader();
+ void writeConstructorSource();
+ void writeDestructorHeader();
+ void writeDestructorSource();
+ void writeOperationHeader(UMLClassifier * c,
+ Uml::Visibility permitScope);
+ void writeOperationSource(UMLClassifier * c,
+ Uml::Visibility permitScope);
+ void writeAttributeSource();
+ void writeAssociationSource(UMLAssociationList associations,
+ Uml::IDType id);
+ void writeAssociationRoleSource(const QString &fieldClassName,
+ const QString &roleName,
+ const QString &multi);
+ void writeUse(UMLClassifier * c);
+
+
+
+ /**
+ * Returns the name of the given object (if it exists)
+ */
+ QString getUMLObjectName(UMLObject * obj);
+
+ /**
+ * Replaces `string' with STRING_TYPENAME.
+ */
+ QString fixTypeName(const QString &string);
+
+ QStringList ObjectFieldVariables;
+ QStringList VectorFieldVariables;
+
+};
+
+
+
+#endif // TCLWRITER_H
diff --git a/umbrello/umbrello/codegenerators/xmlcodecomment.cpp b/umbrello/umbrello/codegenerators/xmlcodecomment.cpp
new file mode 100644
index 00000000..5f44620b
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlcodecomment.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 26 2003
+ */
+
+#include "xmlcodecomment.h"
+
+#include <kdebug.h>
+
+// Constructors/Destructors
+//
+
+XMLCodeComment::XMLCodeComment ( CodeDocument * doc, const QString & text )
+ : CodeComment (doc, text)
+{
+
+}
+
+XMLCodeComment::~XMLCodeComment ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+/**
+ * @return QString
+ */
+QString XMLCodeComment::toString ( )
+{
+
+ QString output = "";
+
+ // simple output method
+ if(getWriteOutText())
+ {
+ QString indent = getIndentationString();
+ QString endLine = getNewLineEndingChars();
+ QString body = getText();
+ output.append(indent+"<!-- ");
+ if(!body.isEmpty())
+ output.append(formatMultiLineText (body, indent, endLine));
+ output.append(indent+"-->"+endLine);
+ }
+
+ return output;
+}
+
+
+#include "xmlcodecomment.moc"
diff --git a/umbrello/umbrello/codegenerators/xmlcodecomment.h b/umbrello/umbrello/codegenerators/xmlcodecomment.h
new file mode 100644
index 00000000..a30bcbab
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlcodecomment.h
@@ -0,0 +1,68 @@
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Mon Sep 26 2003
+ */
+
+
+
+#ifndef XMLCODECOMMENT_H
+#define XMLCODECOMMENT_H
+
+#include <qstring.h>
+#include "../codecomment.h"
+
+class CodeDocument;
+
+/**
+ * class XMLCodeDocumentation
+ * A XML (code) comment.
+ */
+
+class XMLCodeComment: virtual public CodeComment
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ explicit XMLCodeComment ( CodeDocument * doc, const QString & text = "" );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~XMLCodeComment( );
+
+ // Public attributes
+ //
+
+ // Other
+ //
+
+ /**
+ * @return QString
+ */
+ QString toString ( );
+
+
+protected:
+
+private:
+
+};
+
+#endif // XMLCODECOMMENT_H
diff --git a/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp b/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp
new file mode 100644
index 00000000..7e702619
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp
@@ -0,0 +1,166 @@
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Sep 26 2003
+ */
+
+// own header
+#include "xmlelementcodeblock.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "xmlcodecomment.h"
+#include "../attribute.h"
+#include "../codedocument.h"
+
+// Constructors/Destructors
+//
+
+XMLElementCodeBlock::XMLElementCodeBlock ( CodeDocument * parentDoc, const QString & nodeName, const QString & comment)
+ : HierarchicalCodeBlock(parentDoc)
+{
+ init(parentDoc, nodeName, comment);
+}
+
+XMLElementCodeBlock::~XMLElementCodeBlock ( ) { }
+
+//
+// Methods
+//
+
+/**
+ * Save the XMI representation of this object
+ */
+void XMLElementCodeBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "xmlelementblock" );
+
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void XMLElementCodeBlock::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void XMLElementCodeBlock::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement)
+{
+
+ // superclass call
+ HierarchicalCodeBlock::setAttributesOnNode(doc,docElement);
+
+ // now set local attributes/fields
+ docElement.setAttribute("nodeName",getNodeName());
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void XMLElementCodeBlock::setAttributesFromNode ( QDomElement & root) {
+
+ // superclass call
+ HierarchicalCodeBlock::setAttributesFromNode(root);
+
+ // now set local attributes
+ setNodeName(root.attribute("nodeName","UNKNOWN"));
+
+}
+
+// Accessor methods
+//
+
+void XMLElementCodeBlock::setNodeName (const QString &name) {
+ m_nodeName = name;
+}
+
+QString XMLElementCodeBlock::getNodeName () {
+ return m_nodeName;
+}
+
+void XMLElementCodeBlock::addAttribute (UMLAttribute * at) {
+ m_attList.append(at);
+}
+
+UMLAttributeList * XMLElementCodeBlock::getAttributeList() {
+ return & m_attList;
+}
+
+
+// Other methods
+//
+
+/**
+ * update the start and end text for this ownedhierarchicalcodeblock.
+ */
+void XMLElementCodeBlock::updateContent ( )
+{
+
+ QString endLine = getNewLineEndingChars();
+
+ QString nodeName = getNodeName();
+
+ // Now update START/ENDING Text
+ QString startText = '<' + nodeName;
+ QString endText = "";
+
+ UMLAttributeList * alist = getAttributeList();
+ for (UMLAttribute *at = alist->first(); at; at=alist->next())
+ {
+ if(at->getInitialValue().isEmpty())
+ kWarning()<<" XMLElementCodeBlock : cant print out attribute that lacks an initial value"<<endl;
+ else {
+ startText.append(" " +at->getName()+"=\"");
+ startText.append(at->getInitialValue()+"\"");
+ }
+ }
+
+ // now set close of starting/ending node, the style depending on whether we have child text or not
+ if(getTextBlockList()->count())
+ {
+ startText.append(">");
+ endText = "</" + nodeName + '>';
+ } else {
+ startText.append("/>");
+ endText = "";
+ }
+
+ setStartText(startText);
+ setEndText(endText);
+
+}
+
+void XMLElementCodeBlock::init (CodeDocument *parentDoc, const QString &nodeName, const QString &comment)
+{
+
+ setComment(new XMLCodeComment(parentDoc));
+ getComment()->setText(comment);
+
+ m_nodeName = nodeName;
+
+ updateContent();
+
+}
+
+
+#include "xmlelementcodeblock.moc"
diff --git a/umbrello/umbrello/codegenerators/xmlelementcodeblock.h b/umbrello/umbrello/codegenerators/xmlelementcodeblock.h
new file mode 100644
index 00000000..b0acd277
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlelementcodeblock.h
@@ -0,0 +1,88 @@
+
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Sep 26 2003
+ */
+
+#ifndef XMLELEMENTCODEBLOCK_H
+#define XMLELEMENTCODEBLOCK_H
+
+#include <qstring.h>
+
+#include "../umlattributelist.h"
+#include "../hierarchicalcodeblock.h"
+
+class CodeDocument;
+class UMLAttribute;
+
+class XMLElementCodeBlock : public HierarchicalCodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ XMLElementCodeBlock ( CodeDocument * parentDoc, const QString & nodeName, const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~XMLElementCodeBlock ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ virtual UMLAttributeList * getAttributeList();
+
+ virtual void setNodeName (const QString &name);
+ virtual QString getNodeName ();
+
+ void addAttribute (UMLAttribute * at);
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /**
+ * Update the start/end text of this codeblock.
+ */
+ void updateContent ( );
+
+private:
+
+ UMLAttributeList m_attList;
+ QString m_nodeName;
+ void init (CodeDocument * parent, const QString &nodeName, const QString &comment);
+
+};
+
+#endif // XMLELEMENTCODEBLOCK_H
diff --git a/umbrello/umbrello/codegenerators/xmlschemawriter.cpp b/umbrello/umbrello/codegenerators/xmlschemawriter.cpp
new file mode 100644
index 00000000..303d3230
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlschemawriter.cpp
@@ -0,0 +1,809 @@
+/***************************************************************************
+ copyright : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov
+ (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "xmlschemawriter.h"
+
+#include <kdebug.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../umlnamespace.h"
+
+// Constructor
+XMLSchemaWriter::XMLSchemaWriter()
+{
+
+ packageNamespaceTag = "tns";
+ packageNamespaceURI = "http://foo.example.com/";
+ schemaNamespaceTag = "xs";
+ schemaNamespaceURI = "http://www.w3.org/2001/XMLSchema";
+}
+
+// form of..."the Destructor"!!
+XMLSchemaWriter::~XMLSchemaWriter() {
+}
+
+/**
+ * returns "XMLSchema"
+ */
+Uml::Programming_Language XMLSchemaWriter::getLanguage() {
+ return Uml::pl_XMLSchema;
+}
+
+// main method for invoking..
+void XMLSchemaWriter::writeClass(UMLClassifier *c)
+{
+
+ if (!c) {
+ kDebug()<<"Cannot write class of NULL classifier!\n";
+ return;
+ }
+
+ // find an appropriate name for our file
+ QString fileName = findFileName(c,".xsd");
+
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // check that we may open that file for writing
+ QFile file;
+ if ( !openFile(file, fileName) ) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QTextStream XMLschema(&file);
+
+ // set package namespace tag appropriately
+ if(!c->getPackage().isEmpty())
+ packageNamespaceTag = c->getPackage();
+
+ // START WRITING
+
+ // 0. FIRST THING: open the xml processing instruction. This MUST be
+ // the first thing in the file
+ XMLschema<<"<?xml version=\"1.0\"?>"<<m_endl;
+
+ // 1. create the header
+ QString headerText = getHeadingFile(".xsd");
+ if(!headerText.isEmpty()) {
+ headerText.replace(QRegExp("%filename%"),fileName);
+ headerText.replace(QRegExp("%filepath%"),file.name());
+ }
+ if(!headerText.isEmpty())
+ XMLschema<<headerText<<m_endl;
+
+ // 2. Open schema element node with appropriate namespace decl
+ XMLschema<<"<"<<makeSchemaTag("schema");
+ // common namespaces we know will be in the file..
+ XMLschema<<" targetNamespace=\""<<packageNamespaceURI+packageNamespaceTag<<"\""<<m_endl;
+ XMLschema<<" xmlns:"<<schemaNamespaceTag<<"=\""<<schemaNamespaceURI<<"\"";
+ XMLschema<<" xmlns:"<<packageNamespaceTag<<"=\""<<packageNamespaceURI+packageNamespaceTag<<"\"";
+
+ XMLschema<<">"<<m_endl; // close opening declaration
+
+ m_indentLevel++;
+
+ // 3? IMPORT statements -- do we need to do anything here? I suppose if
+ // our document has more than one package, which is possible, we are missing
+ // the correct import statements. Leave that for later at this time.
+ /*
+ //only import classes in a different package as this class
+ UMLPackageList imports;
+ findObjectsRelated(c,imports);
+ for(UMLPackage *con = imports.first(); con ; con = imports.next())
+ if(con->getPackage() != c->getPackage())
+ XMLschema<<"import "<<con->getPackage()<<"."<<cleanName(con->getName())<<";"<<m_endl;
+ */
+
+ // 4. BODY of the schema.
+ // start the writing by sending this classifier, the "root" for this particular
+ // schema, to writeClassifier method, which will subsequently call itself on all
+ // related classifiers and thus populate the schema.
+ writeClassifier(c, XMLschema);
+
+ // 5. What remains is to make the root node declaration
+ XMLschema<<m_endl;
+ writeElementDecl(getElementName(c), getElementTypeName(c), XMLschema);
+
+ // 6. Finished: now we may close schema decl
+ m_indentLevel--;
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("schema")<<">"<<m_endl; // finished.. close schema node
+
+ // bookeeping for code generation
+ emit codeGenerated(c, true);
+
+ // tidy up. no dangling open files please..
+ file.close();
+
+ // need to clear HERE, NOT in the destructor because we want each
+ // schema that we write to have all related classes.
+ writtenClassifiers.clear();
+}
+
+void XMLSchemaWriter::writeElementDecl( const QString &elementName, const QString &elementTypeName, QTextStream &XMLschema)
+{
+ if(forceDoc())
+ writeComment(elementName+" is the root element, declared here.", XMLschema);
+
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("element")
+ <<" name=\""<<elementName<<"\""
+ <<" type=\""<<makePackageTag(elementTypeName)<<"\""
+ <<"/>"<<m_endl;
+
+}
+
+void XMLSchemaWriter::writeClassifier (UMLClassifier *c, QTextStream &XMLschema)
+{
+
+ // NO doing this 2 or more times.
+ if(hasBeenWritten(c))
+ return;
+
+ XMLschema<<m_endl;
+
+ // write documentation for class, if any, first
+ if(forceDoc() || !c->getDoc().isEmpty())
+ writeComment(c->getDoc(),XMLschema);
+
+ if(c->getAbstract() || c->isInterface() )
+ writeAbstractClassifier(c,XMLschema); // if its an interface or abstract class
+ else
+ writeConcreteClassifier(c,XMLschema);
+
+}
+
+UMLAttributeList XMLSchemaWriter::findAttributes (UMLClassifier *c)
+{
+ // sort attributes by Scope
+ UMLAttributeList attribs;
+ attribs.setAutoDelete(false);
+
+ if (!c->isInterface()) {
+ UMLAttributeList atl = c->getAttributeList();
+ for(UMLAttribute *at=atl.first(); at ; at=atl.next()) {
+ switch(at->getVisibility())
+ {
+ case Uml::Visibility::Public:
+ case Uml::Visibility::Protected:
+ attribs.append(at);
+ break;
+ case Uml::Visibility::Private:
+ // DO NOTHING! no way to print in the schema
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return attribs;
+}
+
+// We have to do 2 things with abstract classifiers (e.g. abstract classes and interfaces)
+// which is to:
+// 1) declare it as a complexType so it may be inherited (I can see an option here: to NOT write
+// this complexType declaration IF the classifier itself isnt inherited by or is inheriting
+// from anything because no other element will use this complexType).
+// 2) Create a group so that elements, which obey the abstract class /interface may be placed in
+// aggregation with other elements (again, and option here to NOT write the group if no other
+// element use the interface in element aggregation)
+//
+
+void XMLSchemaWriter::writeAbstractClassifier (UMLClassifier *c, QTextStream &XMLschema)
+{
+
+ // preparations
+ UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what inherits from us
+ UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what we inherit from
+
+ // write the main declaration
+ writeConcreteClassifier (c, XMLschema);
+ writeGroupClassifierDecl (c, subclasses, XMLschema);
+
+ markAsWritten(c);
+
+ // now go back and make sure all sub-classing nodes are declared
+ if(subclasses.count() > 0)
+ {
+
+ QString elementName = getElementName(c);
+ UMLAttributeList attribs = findAttributes(c);
+ QStringList attribGroups = findAttributeGroups(c);
+
+ writeAttributeGroupDecl(elementName, attribs, XMLschema);
+
+ // now write out inheriting classes, as needed
+ for(UMLClassifier * classifier = subclasses.first(); classifier; classifier = subclasses.next())
+ writeClassifier(classifier, XMLschema);
+ }
+
+ // write out any superclasses as needed
+ for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
+ writeClassifier(classifier, XMLschema);
+
+}
+
+void XMLSchemaWriter::writeGroupClassifierDecl (UMLClassifier *c,
+ UMLClassifierList subclasses,
+ QTextStream &XMLschema)
+{
+
+ // name of class, subclassing classifiers
+ QString elementTypeName = getElementGroupTypeName(c);
+
+ // start Writing node but only if it has subclasses? Nah..right now put in empty group
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("group")<<" name=\""<<elementTypeName<<"\">"<<m_endl;
+ m_indentLevel++;
+
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("choice")<<">"<<m_endl;
+ m_indentLevel++;
+
+ for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next()) {
+ writeAssociationRoleDecl(classifier, "1", XMLschema);
+ }
+
+ m_indentLevel--;
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("choice")<<">"<<m_endl;
+
+ m_indentLevel--;
+
+ // finish node
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("group")<<">"<<m_endl;
+
+}
+
+void XMLSchemaWriter::writeComplexTypeClassifierDecl (UMLClassifier *c,
+ UMLAssociationList associations,
+ UMLAssociationList aggregations,
+ UMLAssociationList compositions,
+ UMLClassifierList superclasses,
+ QTextStream &XMLschema)
+{
+
+ // Preparations
+ //
+
+ // sort attributes by Scope
+ UMLAttributeList attribs = findAttributes(c);
+ QStringList attribGroups = findAttributeGroups(c);
+
+ // test for relevant associations
+ bool hasAssociations = determineIfHasChildNodes(c);
+ bool hasSuperclass = superclasses.count()> 0;
+ bool hasAttributes = attribs.count() > 0 || attribGroups.count() > 0;
+
+ // START WRITING
+
+ // start body of element
+ QString elementTypeName = getElementTypeName(c);
+
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexType")<<" name=\""<<elementTypeName<<"\"";
+
+ if(hasAssociations || hasAttributes || hasSuperclass)
+ {
+
+ XMLschema<<">"<<m_endl;
+
+ m_indentLevel++;
+
+ if(hasSuperclass)
+ {
+ QString superClassName = getElementTypeName(superclasses.first());
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexContent")<<">"<<m_endl;
+
+ //PROBLEM: we only treat ONE superclass for inheritence.. bah.
+ m_indentLevel++;
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("extension")<<" base=\""<<makePackageTag(superClassName)
+ <<"\"";
+ if(hasAssociations || hasAttributes )
+ XMLschema<<">"<<m_endl;
+ else
+ XMLschema<<"/>"<<m_endl;
+
+ m_indentLevel++;
+ }
+
+ if(hasAssociations)
+ {
+ // Child Elements (from most associations)
+ //
+ bool didFirstOne = false;
+ didFirstOne = writeAssociationDecls(associations, true, didFirstOne, c->getID(), XMLschema);
+ didFirstOne = writeAssociationDecls(aggregations, false, didFirstOne, c->getID(), XMLschema);
+ didFirstOne = writeAssociationDecls(compositions, false, didFirstOne, c->getID(), XMLschema);
+
+ if (didFirstOne) {
+ m_indentLevel--;
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("sequence")<<">"<<m_endl;
+ }
+ }
+
+ // ATTRIBUTES
+ //
+ if(hasAttributes)
+ {
+ writeAttributeDecls(attribs, XMLschema);
+ for(uint i= 0; i < attribGroups.count(); i++)
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" ref=\""
+ <<makePackageTag(attribGroups[i])<<"\"/>"<<m_endl;
+ }
+
+ if(hasSuperclass)
+ {
+ m_indentLevel--;
+
+ if(hasAssociations || hasAttributes )
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("extension")<<">"<<m_endl;
+
+ m_indentLevel--;
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexContent")<<">"<<m_endl;
+ }
+
+ // close this element decl
+ m_indentLevel--;
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexType")<<">"<<m_endl;
+
+ } else
+ XMLschema<<"/>"<<m_endl; // empty node. just close this element decl
+
+}
+
+void XMLSchemaWriter::writeConcreteClassifier (UMLClassifier *c, QTextStream &XMLschema)
+{
+
+ // preparations.. gather information about this classifier
+ //
+ UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us
+ UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what we inherit from
+ UMLAssociationList aggregations = c->getAggregations();
+ UMLAssociationList compositions = c->getCompositions();
+ // BAD! only way to get "general" associations.
+ UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association);
+
+ // write the main declaration
+ writeComplexTypeClassifierDecl(c, associations, aggregations, compositions, superclasses, XMLschema);
+
+ markAsWritten(c);
+
+ // Now write out any child def's
+ writeChildObjsInAssociation(c, associations, XMLschema);
+ writeChildObjsInAssociation(c, aggregations, XMLschema);
+ writeChildObjsInAssociation(c, compositions, XMLschema);
+
+ // write out any superclasses as needed
+ for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
+ writeClassifier(classifier, XMLschema);
+
+ // write out any subclasses as needed
+ for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next())
+ writeClassifier(classifier, XMLschema);
+}
+
+// these exist for abstract classes only (which become xs:group nodes)
+QStringList XMLSchemaWriter::findAttributeGroups (UMLClassifier *c)
+{
+ // we need to look for any class we inherit from. IF these
+ // have attributes, then we need to notice
+ QStringList list;
+ UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us
+ for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
+ {
+ if(classifier->getAbstract())
+ {
+ // only classes have attributes..
+ if (!classifier->isInterface()) {
+ UMLAttributeList attribs = c->getAttributeList();
+ if (attribs.count() > 0)
+ list.append(getElementName(classifier)+"AttribGroupType");
+ }
+ }
+ }
+ return list;
+}
+
+bool XMLSchemaWriter::determineIfHasChildNodes( UMLClassifier *c)
+{
+ UMLObjectList aggList = findChildObjsInAssociations (c, c->getAggregations());
+ UMLObjectList compList = findChildObjsInAssociations (c, c->getCompositions());
+ UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
+ UMLObjectList assocList = findChildObjsInAssociations (c, associations);
+ return aggList.count() > 0 || compList.count() > 0 || assocList.count() > 0;
+}
+
+void XMLSchemaWriter::writeChildObjsInAssociation (UMLClassifier *c,
+ UMLAssociationList assoc,
+ QTextStream &XMLschema)
+{
+
+ UMLObjectList list = findChildObjsInAssociations (c, assoc);
+ for(UMLObject * obj = list.first(); obj; obj = list.next())
+ {
+ UMLClassifier * thisClassifier = dynamic_cast<UMLClassifier*>(obj);
+ if(thisClassifier)
+ writeClassifier(thisClassifier, XMLschema);
+ }
+}
+
+bool XMLSchemaWriter::hasBeenWritten(UMLClassifier *c) {
+ if (writtenClassifiers.contains(c))
+ return true;
+ else
+ return false;
+}
+
+void XMLSchemaWriter::markAsWritten(UMLClassifier *c) {
+ writtenClassifiers.append(c);
+}
+
+void XMLSchemaWriter::writeAttributeDecls(UMLAttributeList &attribs, QTextStream &XMLschema )
+{
+
+ UMLAttribute *at;
+ for(at=attribs.first(); at; at=attribs.next())
+ {
+ writeAttributeDecl(at,XMLschema);
+ }
+
+}
+
+void XMLSchemaWriter::writeAttributeDecl(UMLAttribute *attrib, QTextStream &XMLschema )
+{
+
+ QString documentation = attrib->getDoc();
+ QString typeName = fixTypeName(attrib->getTypeName());
+ bool isStatic = attrib->getStatic();
+ QString initialValue = fixInitialStringDeclValue(attrib->getInitialValue(), typeName);
+
+ if(!documentation.isEmpty())
+ writeComment(documentation, XMLschema);
+
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("attribute")
+ <<" name=\""<<cleanName(attrib->getName())<<"\""
+ <<" type=\""<<typeName<<"\"";
+
+ // default value?
+ if(!initialValue.isEmpty())
+ {
+ // IF its static, then we use "fixed", otherwise, we use "default" decl.
+ // For the default decl, we _must_ use "optional" decl
+ if(isStatic)
+ XMLschema<<" use=\"required\" fixed=\""<<initialValue<<"\"";
+ else
+ XMLschema<<" use=\"optional\" default=\""<<initialValue<<"\"";
+ }
+
+ // finish decl
+ XMLschema<<"/>"<<m_endl;
+
+}
+
+void XMLSchemaWriter::writeAttributeGroupDecl (const QString &elementName, UMLAttributeList &attribs, QTextStream &XMLschema )
+{
+
+ if (attribs.count()> 0) {
+
+ // write a little documentation
+ writeComment("attributes for element "+elementName,XMLschema);
+
+ // open attribute group
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" name=\""<<elementName+"AttribGroupType"<<"\">"<<m_endl;
+
+ m_indentLevel++;
+
+ for( UMLAttribute *at=attribs.first(); at; at=attribs.next())
+ {
+ writeAttributeDecl(at,XMLschema);
+ }
+
+ m_indentLevel--;
+
+ // close attrib group node
+ XMLschema<<getIndent()<<"</"<<makeSchemaTag("attributeGroup")<<">"<<m_endl;
+ }
+}
+
+void XMLSchemaWriter::writeComment( const QString &comment, QTextStream &XMLschema )
+{
+ // in the case we have several line comment..
+ // NOTE: this part of the method has the problem of adopting UNIX newline,
+ // need to resolve for using with MAC/WinDoze eventually I assume
+ QString indent = getIndent();
+ XMLschema<<indent<<"<!-- ";
+ if (comment.contains(QRegExp("\n"))) {
+ XMLschema<<m_endl;
+ QStringList lines = QStringList::split( "\n", comment);
+ for(uint i= 0; i < lines.count(); i++)
+ XMLschema<<indent<<" "<<lines[i]<<m_endl;
+
+ XMLschema<<indent<<"-->"<<m_endl;
+ } else {
+ // this should be more fancy in the future, breaking it up into 80 char
+ // lines so that it doesn't look too bad
+ XMLschema<<comment<<" -->"<<m_endl;
+ }
+}
+
+// all that matters here is roleA, the role served by the children of this class
+// in any composition or aggregation association. In full associations, I have only
+// considered the case of "self" association, so it shouldn't matter if we use role A or
+// B to find the child class as long as we don't use BOTH roles. I bet this will fail
+// badly for someone using a plain association between 2 different classes. THAT should
+// be done, but isnt yet (this is why I have left role b code in for now). -b.t.
+bool XMLSchemaWriter::writeAssociationDecls(UMLAssociationList associations,
+ bool noRoleNameOK, bool didFirstOne, Uml::IDType id, QTextStream &XMLschema)
+{
+
+ if( !associations.isEmpty() )
+ {
+ bool printRoleA = false, printRoleB = false;
+
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+ // it may seem counter intuitive, but you want to insert the role of the
+ // *other* class into *this* class.
+
+ if (a->getObjectId(Uml::A) == id && a->getVisibility(Uml::B) != Uml::Visibility::Private)
+ printRoleB = true;
+
+ if (a->getObjectId(Uml::B) == id && a->getVisibility(Uml::A) != Uml::Visibility::Private)
+ printRoleA = true;
+
+ // First: we insert documentaion for association IF it has either role
+ // AND some documentation (!)
+ if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
+ writeComment(a->getDoc(), XMLschema);
+
+ // opening for sequence
+ if(!didFirstOne && (printRoleA || printRoleB))
+ {
+ didFirstOne = true;
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("sequence")<<">"<<m_endl;
+ m_indentLevel++;
+ }
+
+ // print RoleB decl
+ /*
+ // As mentioned in the header comment for this method: this block of code is
+ // commented out for now as it will only be needed if/when plain associations
+ // between different classes are to be treated
+ if (printRoleB)
+ {
+ UMLClassifier *classifierB = dynamic_cast<UMLClassifier*>(a->getObjectB());
+ if (classifierB) {
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared
+ if (!a->getRoleNameB().isEmpty() || noRoleNameOK)
+ writeAssociationRoleDecl(classifierB, a->getMultiB(), XMLschema);
+ }
+ }
+ */
+
+ // print RoleA decl
+ if (printRoleA)
+ {
+ UMLClassifier *classifierA = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ if (classifierA) {
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared
+ if (!a->getRoleName(Uml::A).isEmpty() || noRoleNameOK )
+ writeAssociationRoleDecl(classifierA, a->getMulti(Uml::A), XMLschema);
+ }
+ }
+ }
+
+ }
+
+ return didFirstOne;
+}
+
+UMLObjectList XMLSchemaWriter::findChildObjsInAssociations (UMLClassifier *c, UMLAssociationList associations)
+{
+ Uml::IDType id = c->getID();
+ UMLObjectList list;
+ for(UMLAssociation *a = associations.first(); a; a = associations.next())
+ {
+ if (a->getObjectId(Uml::A) == id
+ && a->getVisibility(Uml::B) != Uml::Visibility::Private
+ && !a->getRoleName(Uml::B).isEmpty()
+ )
+ list.append(a->getObject(Uml::B));
+
+ if (a->getObjectId(Uml::B) == id
+ && a->getVisibility(Uml::A) != Uml::Visibility::Private
+ && !a->getRoleName(Uml::A).isEmpty()
+ )
+ list.append(a->getObject(Uml::A));
+ }
+ return list;
+}
+
+void XMLSchemaWriter::writeAssociationRoleDecl( UMLClassifier *c, const QString &multi, QTextStream &XMLschema)
+{
+
+ bool isAbstract = c->getAbstract();
+ bool isInterface = c->isInterface();
+
+ QString elementName = getElementName(c);
+ QString doc = c->getDoc();
+
+ if (!doc.isEmpty())
+ writeComment(doc, XMLschema);
+
+
+ // Min/Max Occurs is based on whether it is this a single element
+ // or a List (maxoccurs>1). One day this will be done correctly with special
+ // multiplicity object that we don't have to figure out what it means via regex.
+ QString minOccurs = "0";
+ QString maxOccurs = "unbounded";
+ if (multi.isEmpty())
+ {
+ // in this case, association will only specify ONE element can exist
+ // as a child
+ minOccurs = "1";
+ maxOccurs = "1";
+ }
+ else
+ {
+ QStringList values = QStringList::split( QRegExp("[^\\d{1,}|\\*]"), multi);
+
+ // could use some improvement here.. for sequences like "0..1,3..5,10" we
+ // don't capture the whole "richness" of the multi. Instead we translate it
+ // now to minOccurs="0" maxOccurs="10"
+ if (values.count() > 0)
+ {
+ // populate both with the actual value as long as our value isnt an asterix
+ // In that case, use special value (from above)
+ if(values[0].contains(QRegExp("\\d{1,}")))
+ minOccurs = values[0]; // use first number in sequence
+
+ if(values[values.count()-1].contains(QRegExp("\\d{1,}")))
+ maxOccurs = values[values.count()-1]; // use only last number in sequence
+ }
+ }
+
+ // Now declare the class in the association as an element or group.
+ //
+ // In a semi-arbitrary way, we have decided to make abstract classes into
+ // "groups" and concrete classes into "complexTypes".
+ //
+ // This is because about the only thing you can do with an abstract
+ // class (err. node) is inherit from it with a "concrete" element. Therefore,
+ // in this manner, we need a group node for abstract classes to lay out the child
+ // element choices so that the child, concrete class may be plugged into whatever spot
+ // it parent could go. The tradeoff is that "group" nodes may not be extended, so the
+ // choices that you lay out here are it (e.g. no more nodes may inherit" from this group)
+ //
+ // The flipside for concrete classes is that we want to use them as elements in our document.
+ // Unfortunately, about all you can do with complexTypes in terms of inheritance, is to
+ // use these as the basis for a new node type. This is NOT full inheritence because the new
+ // class (err. element node) wont be able to go into the document where it parent went without
+ // you heavily editing the schema.
+ //
+ // Therefore, IF a group is abstract, but has no inheriting sub-classes, there are no choices, and its nigh
+ // on pointless to declare it as a group, in this special case, abstract classes get declared
+ // as complexTypes.
+ //
+ // Of course, in OO methodology, you should be able to inherit from
+ // any class, but schema just don't allow use to have full inheritence using either groups
+ // or complexTypes. Thus we have taken a middle rode. If someone wants to key me into a
+ // better way to represent this, I'd be happy to listen. =b.t.
+ //
+ // UPDATE: partial solution to the above: as of 13-Mar-2003 we now write BOTH a complexType
+ // AND a group declaration for interfaces AND classes which are inherited from.
+ //
+ if ((isAbstract || isInterface ) && c->findSubClassConcepts().count() > 0)
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("group")
+ <<" ref=\""<<makePackageTag(getElementGroupTypeName(c))<<"\"";
+ else
+ XMLschema<<getIndent()<<"<"<<makeSchemaTag("element")
+ <<" name=\""<<getElementName(c)<<"\""
+ <<" type=\""<<makePackageTag(getElementTypeName(c))<<"\"";
+
+ // min/max occurs
+ if (minOccurs != "1")
+ XMLschema<<" minOccurs=\""<<minOccurs<<"\"";
+
+ if (maxOccurs != "1")
+ XMLschema<<" maxOccurs=\""<<maxOccurs<<"\"";
+
+ // tidy up the node
+ XMLschema<<"/>"<<m_endl;
+
+}
+
+// IF the type is "string" we need to declare it as
+// the XMLSchema Object "String" (there is no string primative in XMLSchema).
+// Same thing again for "bool" to "boolean"
+QString XMLSchemaWriter::fixTypeName(const QString& string)
+{
+ // string.replace(QRegExp("^string$"),schemaNamespaceTag+":string");
+ // string.replace(QRegExp("^bool$"),schemaNamespaceTag+":boolean");
+ return schemaNamespaceTag + ':' + string;
+}
+
+QString XMLSchemaWriter::fixInitialStringDeclValue(QString value, const QString &type)
+{
+ // check for strings only
+ if (!value.isEmpty() && type == "xs:string") {
+ if (!value.startsWith("\""))
+ value.remove(0,1);
+ if (!value.endsWith("\""))
+ value.remove(value.length(),1);
+ }
+ return value;
+}
+
+QString XMLSchemaWriter::getElementName(UMLClassifier *c)
+{
+ return cleanName(c->getName());
+}
+
+QString XMLSchemaWriter::getElementTypeName(UMLClassifier *c)
+{
+ QString elementName = getElementName(c);
+ return elementName + "ComplexType";
+}
+
+QString XMLSchemaWriter::getElementGroupTypeName(UMLClassifier *c)
+{
+ QString elementName = getElementName(c);
+ return elementName + "GroupType";
+}
+
+QString XMLSchemaWriter::makePackageTag (QString tagName) {
+ tagName.prepend( packageNamespaceTag + ':');
+ return tagName;
+}
+
+QString XMLSchemaWriter::makeSchemaTag (QString tagName) {
+ tagName.prepend( schemaNamespaceTag + ':');
+ return tagName;
+}
+
+const QStringList XMLSchemaWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if (keywords.isEmpty()) {
+ keywords << "ATTLIST"
+ << "CDATA"
+ << "DOCTYPE"
+ << "ELEMENT"
+ << "ENTITIES"
+ << "ENTITY"
+ << "ID"
+ << "IDREF"
+ << "IDREFS"
+ << "NMTOKEN"
+ << "NMTOKENS"
+ << "NOTATION"
+ << "PUBLIC"
+ << "SHORTREF"
+ << "SYSTEM"
+ << "USEMAP";
+ }
+
+ return keywords;
+}
+
+#include "xmlschemawriter.moc"
diff --git a/umbrello/umbrello/codegenerators/xmlschemawriter.h b/umbrello/umbrello/codegenerators/xmlschemawriter.h
new file mode 100644
index 00000000..caf9f906
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/xmlschemawriter.h
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003 Brian Thomas <brian.thomas@gsfc.nasa.gov> *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef XMLSCHEMAWRITER_H
+#define XMLSCHEMAWRITER_H
+
+#include "../codegenerator.h"
+#include "../attribute.h"
+#include "../association.h"
+#include "../umlclassifierlist.h"
+#include "../umlattributelist.h"
+#include "../umlobjectlist.h"
+#include "../umlassociationlist.h"
+#include "simplecodegenerator.h"
+
+/**
+ * Class XMLSchemaWriter is a code generator for UMLClassifier objects.
+ * Create an instance of this class, and feed it a UMLClassifier when
+ * calling writeClass and it will generate a XMLschema source file for
+ * that concept
+ *
+ * Our basic approach is to map UMLClassifiers (classes/interfaces) into
+ * XML elements (or nodes). We declare these element in the schema either
+ * as complexType or as groups based on whether they are concrete or abstract
+ * in nature. This is not a perfect decision, but thats life with XML Schema...
+ * you cant fully represent Objects in the XML world ..yet. -b.t.
+ */
+
+class XMLSchemaWriter : public SimpleCodeGenerator
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructor, initialises a couple of variables
+ */
+ XMLSchemaWriter();
+
+ /**
+ * Destructor, empty
+ */
+ virtual ~XMLSchemaWriter();
+
+ /**
+ * call this method to generate XMLschema code for a UMLClassifier
+ * @param c the class to generate code for
+ */
+ virtual void writeClass(UMLClassifier *c);
+
+ /**
+ * returns "XMLSchema"
+ */
+ virtual Uml::Programming_Language getLanguage();
+
+ /**
+ * get list of reserved keywords
+ */
+ virtual const QStringList reservedKeywords() const;
+
+private:
+
+ /**
+ * Writes concept's documentation then guts
+ */
+ void writeClassifier(UMLClassifier *c, QTextStream &XMLSchema);
+ void writeAbstractClassifier(UMLClassifier *c, QTextStream &XMLSchema);
+ void writeConcreteClassifier(UMLClassifier *c, QTextStream &XMLSchema);
+
+ /**
+ * write a <complexType> declaration for this classifier
+ */
+ void writeComplexTypeClassifierDecl(UMLClassifier *c,
+ UMLAssociationList associations,
+ UMLAssociationList aggregations,
+ UMLAssociationList compositions,
+ UMLClassifierList superclassifiers,
+ QTextStream &XMLSchema);
+
+ /**
+ * write a <group> declaration for this classifier. Used for interfaces to classes with
+ * inheriting children.
+ */
+ void writeGroupClassifierDecl(UMLClassifier *c,
+ UMLClassifierList superclassifiers,
+ QTextStream &XMLSchema);
+
+ /**
+ * find if the classifier would have any Child elements.
+ */
+ bool determineIfHasChildNodes( UMLClassifier *c);
+
+ /**
+ * write all attributes for a given class
+ * @param c the class for which we are generating code
+ * @param j the stream associated with the output file
+ */
+ void writeAttributes(UMLClassifier *c, QTextStream &j);
+
+ /**
+ * write an element declaration.
+ */
+ void writeElementDecl( const QString &elementName, const QString &elementTypeName, QTextStream &XMLschema);
+
+ /**
+ * writes the Attribute declarations
+ * @param attribs List of attributes
+ * @param XMLschema text stream
+ */
+ void writeAttributeDecls(UMLAttributeList &attribs, QTextStream &XMLschema );
+
+ /**
+ * write an element attribute.
+ */
+ void writeAttributeDecl(UMLAttribute *attrib, QTextStream &XMLschema );
+
+ /**
+ * Find all attributes for this concept.
+ */
+ UMLAttributeList findAttributes (UMLClassifier *c);
+
+ /**
+ * Discover the string name of all the attribute groups (which are child nodes)
+ * of this concept (err.. element)
+ */
+ QStringList findAttributeGroups (UMLClassifier *c);
+
+ /**
+ * Searches a list of associations for appropriate ones to write out as attributes.
+ * This works well for compositions, aggregations and self-associations but will
+ * not work right for plain associations between 2 different classes.
+ */
+ bool writeAssociationDecls(UMLAssociationList associations, bool noRoleOK, bool didOne,
+ Uml::IDType id, QTextStream &XMLschema);
+
+ /**
+ * Find all attributes that belong in group
+ */
+ void writeAttributeGroupDecl(const QString &elementName, UMLAttributeList &attribs, QTextStream &XMLschema );
+
+ /**
+ * Writes out an association as an attribute using Vector
+ */
+ void writeAssociationRoleDecl(UMLClassifier *c, const QString &multi, QTextStream &XMLschema);
+
+ /**
+ * Construct an element tag with the schema namespace
+ */
+ QString makeSchemaTag ( QString tagName );
+
+ /**
+ * Construct an element tag with the package namespace
+ */
+ QString makePackageTag ( QString tagName );
+
+ /**
+ * Writes a comment
+ */
+ void writeComment(const QString &text, QTextStream &XMLschema);
+
+ /**
+ * Find and return a list of child UMLObjects pointed to by the associations
+ * in this UMLClassifier.
+ */
+ UMLObjectList findChildObjsInAssociations (UMLClassifier *c, UMLAssociationList associations);
+
+ /**
+ * Replaces `string' with `String' and `bool' with `boolean'
+ */
+ QString fixTypeName(const QString& string);
+
+ /**
+ * check that initial values of strings DONT have quotes around them
+ * (we get double quoting then!!
+ */
+ QString fixInitialStringDeclValue( QString value, const QString &type);
+
+ /**
+ * Find the element node name for this concept.
+ */
+ QString getElementName(UMLClassifier *c);
+
+ /**
+ * Find the element node "type" name. Used in the "complexType" which
+ * might define that element node.
+ */
+ QString getElementTypeName(UMLClassifier *c);
+
+ /**
+ * Find the group node "type" name. Used for elements which define an interface/are abstract.
+ */
+ QString getElementGroupTypeName(UMLClassifier *c);
+
+ /**
+ * Find all the child objects in this association and make sure they get
+ * written out (if they havent already been)
+ */
+ void writeChildObjsInAssociation (UMLClassifier *c, UMLAssociationList assoc, QTextStream &s);
+
+ /**
+ * Quick check to see if we have written the declaration for this concept yet.
+ */
+ bool hasBeenWritten(UMLClassifier *c);
+
+ /**
+ * mark a concept as written, so it is not repeatedly re-declared in the schema
+ */
+ void markAsWritten(UMLClassifier *c);
+
+ /**
+ * The basic schemaNamespace tag
+ */
+ QString schemaNamespaceTag;
+
+ /**
+ * The basic schemaNamespace tag
+ */
+ QString packageNamespaceTag;
+
+ /*
+ * The basic schemaNamespace URI
+ */
+ QString schemaNamespaceURI;
+
+ /**
+ * The basic schemaNamespace URI
+ */
+ QString packageNamespaceURI;
+
+ /**
+ * A \n, used at the end of each line
+ */
+ QString startline;
+
+ /**
+ * a list of UMLClassifiers we have already written
+ */
+ UMLClassifierList writtenClassifiers;
+};
+
+#endif // XMLSCHEMAWRITER_H
diff --git a/umbrello/umbrello/codegenobjectwithtextblocks.cpp b/umbrello/umbrello/codegenobjectwithtextblocks.cpp
new file mode 100644
index 00000000..383c188f
--- /dev/null
+++ b/umbrello/umbrello/codegenobjectwithtextblocks.cpp
@@ -0,0 +1,517 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Aug 19 2003
+ */
+
+// own header
+#include "codegenobjectwithtextblocks.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "umldoc.h"
+#include "codedocument.h"
+#include "codeoperation.h"
+#include "codegenerators/codegenfactory.h"
+#include "classifiercodedocument.h"
+#include "hierarchicalcodeblock.h"
+#include "uml.h"
+
+// Constructors/Destructors
+//
+
+CodeGenObjectWithTextBlocks::CodeGenObjectWithTextBlocks ( CodeDocument *parent )
+ : m_pCodeDoc(parent)
+{
+ initFields();
+}
+
+CodeGenObjectWithTextBlocks::~CodeGenObjectWithTextBlocks ( ) {
+ resetTextBlocks();
+ // delete all the text blocks we have
+ TextBlock *tb;
+ for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
+ delete tb;
+
+ m_textBlockTagMap.clear();
+ m_textblockVector.clear();
+}
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+/**
+ * Get the list of TextBlock objects held by m_textblockVector
+ * @return QPtrList<TextBlock *> list of TextBlock objects held by
+ * m_textblockVector
+ */
+TextBlockList * CodeGenObjectWithTextBlocks::getTextBlockList ( ) {
+ return &m_textblockVector;
+}
+
+// Other methods
+//
+
+/**
+ * Add a TextBlock object to the m_textblockVector List
+ */
+bool CodeGenObjectWithTextBlocks::addTextBlock(TextBlock* add_object ) {
+
+ QString tag = add_object->getTag();
+
+ // assign a tag if one doesn't already exist
+ if(tag.isEmpty())
+ {
+ tag = getUniqueTag();
+ add_object->setTag(tag);
+ }
+ else
+ {
+
+ // if it has a tag, check to see that its not in some other parent object
+ // IF it is then we will need to remove it FIRST before adding to new parent
+ CodeDocument * parentDoc = add_object->getParentDocument();
+ if(parentDoc) {
+
+ CodeGenObjectWithTextBlocks * oldParent = parentDoc->findParentObjectForTaggedTextBlock (tag);
+ if(oldParent && oldParent != this)
+ oldParent->removeTextBlock(add_object);
+ }
+ }
+
+ if(m_textBlockTagMap.contains(tag))
+ return false; // return false, we already have some object with this tag in the list
+
+ // if we get here, then the object is a "fresh" one, we havent
+ // added before. Add it now and return true.
+ m_textBlockTagMap.insert(tag, add_object);
+ m_textblockVector.append(add_object);
+
+ return true;
+}
+
+/**
+ * Remove a TextBlock object from m_textblockVector List
+ */
+bool CodeGenObjectWithTextBlocks::removeTextBlock ( TextBlock * remove_object ) {
+
+ // check if we can remove it from our local list
+ if(!m_textblockVector.removeRef(remove_object))
+ {
+ // may be hiding in child hierarchical codeblock
+ TextBlock * tb;
+ for(TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
+ {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
+ if(hb && hb->removeTextBlock(remove_object))
+ return true;
+ }
+ }
+
+ // if we get here.. it was in this object so remove from our map
+ QString tag = remove_object->getTag();
+ if(!tag.isEmpty())
+ m_textBlockTagMap.erase(tag);
+
+ return true;
+}
+
+TextBlock * CodeGenObjectWithTextBlocks::findTextBlockByTag( const QString &tag )
+{
+ //if we already know to which file this class was written/should be written, just return it.
+ if(m_textBlockTagMap.contains(tag))
+ return m_textBlockTagMap[tag];
+
+ return (TextBlock*) NULL;
+}
+
+// IMPORTANT: this will only search for a parent from the viewpoint of this object
+// and down into its Hierarchical codeblocks. This means you should start any
+// search from the parent document of the text block. This method NOT meant for
+// casual usage.
+CodeGenObjectWithTextBlocks * CodeGenObjectWithTextBlocks::findParentObjectForTaggedTextBlock (const QString & tag) {
+
+ // what??!? no tag, then CANT be here
+ if(tag.isEmpty())
+ return (CodeGenObjectWithTextBlocks*) NULL;
+
+ if(!findTextBlockByTag(tag))
+ {
+ // may be hiding in child hierarchical codeblock
+ for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next())
+ {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
+ if(hb) {
+ CodeGenObjectWithTextBlocks* cgowtb = dynamic_cast<CodeGenObjectWithTextBlocks*>(hb);
+ CodeGenObjectWithTextBlocks * obj = cgowtb->findParentObjectForTaggedTextBlock(tag);
+ if(obj)
+ return obj;
+ }
+ }
+
+ } else
+ return this;
+
+ // shouldn't happen unless the textblock doesn't exist in this object
+ // or its children at all
+ return (CodeGenObjectWithTextBlocks*) NULL;
+
+}
+
+/**
+ * @return HierarchicalCodeBlock
+ * @param tag
+ * @param comment
+ * @param indentLevel
+ */
+HierarchicalCodeBlock * CodeGenObjectWithTextBlocks::getHierarchicalCodeBlock ( const QString &tag, const QString &comment, int indentLevel ) {
+
+ // now actually declare the fields
+ HierarchicalCodeBlock * codeBlock = dynamic_cast<HierarchicalCodeBlock*>(findTextBlockByTag(tag));
+ if (!codeBlock) {
+ codeBlock = newHierarchicalCodeBlock();
+ codeBlock->setTag(tag);
+ codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc));
+ // don't write empty comments out
+ if(comment.isEmpty())
+ codeBlock->getComment()->setWriteOutText(false);
+
+ if(!addTextBlock(codeBlock))
+ {
+ delete codeBlock;
+ return (HierarchicalCodeBlock*) NULL;
+ }
+ }
+
+ codeBlock->setOverallIndentationLevel (indentLevel);
+ codeBlock->getComment()->setText(comment);
+
+ return codeBlock;
+}
+
+
+/**
+ * @return CodeBlockWithComments
+ * @param tag
+ * @param comment
+ * @param indentLevel
+ */
+CodeBlockWithComments * CodeGenObjectWithTextBlocks::getCodeBlockWithComments ( const QString &tag, const QString &comment, int indentLevel ) {
+
+ // now actually declare the fields
+ CodeBlockWithComments * codeBlock = dynamic_cast<CodeBlockWithComments*>(findTextBlockByTag(tag));
+ if (!codeBlock) {
+ codeBlock = newCodeBlockWithComments();
+ codeBlock->setTag(tag);
+ codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc));
+ // don't write empty comments out
+ if(comment.isEmpty())
+ codeBlock->getComment()->setWriteOutText(false);
+ if(!addTextBlock(codeBlock))
+ return (CodeBlockWithComments*) NULL;
+ }
+ codeBlock->setOverallIndentationLevel (indentLevel);
+ codeBlock->getComment()->setText(comment);
+
+ return codeBlock;
+
+}
+
+
+/**
+ * @return CodeComment
+ * @param tag
+ * @param text
+ * @param indentationLevel
+ */
+CodeComment * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeComment ( const QString &tag, const QString &text, int indentationLevel)
+{
+
+ TextBlock * tBlock = findTextBlockByTag(tag);
+ CodeComment * codeComment = dynamic_cast<CodeComment*>(tBlock);
+ bool createdCodeComment = false;
+
+ if(!codeComment) {
+ createdCodeComment = true;
+ codeComment = CodeGenFactory::newCodeComment(m_pCodeDoc);
+ codeComment->setTag(tag);
+ if(!addTextBlock(codeComment))
+ {
+ delete codeComment;
+ return (CodeComment*) NULL; // hmm. total failure..,was there a preexisting comment with this tag?? lets return null
+ }
+ }
+
+ codeComment->setText(text);
+ if(createdCodeComment)
+ if(!text.isEmpty())
+ codeComment->setWriteOutText(true); // set to visible, if we created
+ else
+ codeComment->setWriteOutText(false); // set to not visible, if we created
+
+ codeComment->setIndentationLevel(indentationLevel);
+
+ return codeComment;
+}
+
+
+/**
+ * @return CodeBlockWithComments
+ * @param tag
+ * @param text
+ * @param comment
+ * @param indentLevel
+ * @param forceUserBlockUpdate
+ */
+CodeBlockWithComments * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeBlockWithComments (const QString &tag, const QString &text, const QString &ctext, int indentLevel, bool forceUserBlockUpdate )
+{
+
+ TextBlock * tBlock = findTextBlockByTag(tag);
+ CodeBlockWithComments * codeBlock = dynamic_cast<CodeBlockWithComments*>(tBlock);
+ bool createdCodeBlock = false;
+
+ if(!codeBlock) {
+ createdCodeBlock = true;
+ codeBlock = newCodeBlockWithComments();
+ codeBlock->setTag(tag);
+ if(!addTextBlock(codeBlock))
+ {
+ delete codeBlock;
+ return (CodeBlockWithComments*) NULL; // hmm. total failure..,was there a preexisting codeblock with this tag?? lets return null
+ }
+ }
+
+ // ONLY update IF we are forcing the update of user blocks OR its an "AutoGenerated" Block
+ if(forceUserBlockUpdate || codeBlock->getContentType() == CodeBlock::AutoGenerated)
+ {
+
+ codeBlock->setText(text);
+ codeBlock->getComment()->setText(ctext);
+
+ // if we created this from scratch, make it write out only when the block isnt empty
+ if (createdCodeBlock)
+ {
+ if(!ctext.isEmpty())
+ codeBlock->getComment()->setWriteOutText(true);
+ else
+ codeBlock->getComment()->setWriteOutText(false);
+
+ if(!text.isEmpty())
+ codeBlock->setWriteOutText(true);
+ else
+ codeBlock->setWriteOutText(false);
+ }
+
+ codeBlock->setOverallIndentationLevel(indentLevel);
+
+ }
+
+ return codeBlock;
+
+}
+
+void CodeGenObjectWithTextBlocks::resetTextBlocks() {
+ TextBlock *tb;
+ for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
+ delete tb;
+ m_textBlockTagMap.clear();
+ m_textblockVector.clear();
+}
+
+
+void CodeGenObjectWithTextBlocks::setAttributesFromObject (CodeGenObjectWithTextBlocks * obj)
+{
+ TextBlockList * list = obj->getTextBlockList();
+ for (TextBlock * tb = list->first(); tb; tb=list->next())
+ {
+ // FIX : we need some functionality like
+ // loadChildTextBlocksFromObject(obj) here
+ }
+}
+
+void CodeGenObjectWithTextBlocks::setAttributesOnNode (QDomDocument & doc, QDomElement & root) {
+
+ // set a section to hold document content
+ QDomElement tblockElement = doc.createElement( "textblocks" );
+
+ // only concrete calls to textblocks are saved
+ TextBlockList * tbList = getTextBlockList();
+ for (TextBlock * block = tbList->first(); block; block= tbList->next())
+ block->saveToXMI(doc, tblockElement);
+
+ root.appendChild( tblockElement);
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeGenObjectWithTextBlocks::setAttributesFromNode ( QDomElement & root)
+{
+
+ // clear existing codeblocks
+ resetTextBlocks();
+
+ // now load em back in
+ loadChildTextBlocksFromNode(root);
+
+}
+
+// load text blocks
+// in this vanilla version, we only load comments and codeblocks
+// as they are the only instanciatable (vanilla) things
+// this method should be overridden if this class is inherited
+// by some other class that is concrete and takes children
+// derived from codeblock/codecomment
+void CodeGenObjectWithTextBlocks::loadChildTextBlocksFromNode ( QDomElement & root)
+{
+
+ QDomNode tnode = root.firstChild();
+ QDomElement telement = tnode.toElement();
+ bool loadCheckForChildrenOK = false;
+ while( !telement.isNull() ) {
+ QString nodeName = telement.tagName();
+
+ if( nodeName == "textblocks" ) {
+
+ QDomNode node = telement.firstChild();
+ QDomElement element = node.toElement();
+
+ // if there is nothing to begin with, then we don't worry about it
+ loadCheckForChildrenOK = element.isNull() ? true : false;
+
+ while( !element.isNull() ) {
+ QString name = element.tagName();
+
+ if( name == "codecomment" ) {
+ CodeComment * block = CodeGenFactory::newCodeComment(m_pCodeDoc);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI: unable to add codeComment to :"<<this<<endl;
+ delete block;
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeaccessormethod" ||
+ name == "ccfdeclarationcodeblock"
+ ) {
+ QString acctag = element.attribute("tag","");
+ // search for our method in the
+ TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
+ if(!tb || !addTextBlock(tb))
+ {
+ kError()<<"loadFromXMI : unable to add code accessor/decl method block (tag:"<<acctag<<") to:"<<this<<endl;
+ // DON'T delete
+
+ } else
+ loadCheckForChildrenOK= true;
+
+ } else
+ if( name == "codeblock" ) {
+ CodeBlock * block = newCodeBlock();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl;
+ delete block;
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeblockwithcomments" ) {
+ CodeBlockWithComments * block = newCodeBlockWithComments();
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl;
+ delete block;
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "header" ) {
+ // do nothing.. this is treated elsewhere
+ } else
+ if( name == "hierarchicalcodeblock" ) {
+ HierarchicalCodeBlock * block = new HierarchicalCodeBlock(m_pCodeDoc);
+ block->loadFromXMI(element);
+ if(!addTextBlock(block))
+ {
+ kError()<<"loadFromXMI : unable to add hierarchicalcodeBlock to:"<<this<<endl;
+ delete block;
+ } else
+ loadCheckForChildrenOK= true;
+ } else
+ if( name == "codeoperation" ) {
+ // find the code operation by id
+ QString id = element.attribute("parent_id","-1");
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+ if(op) {
+ CodeOperation * block = CodeGenFactory::newCodeOperation(dynamic_cast<ClassifierCodeDocument*>(m_pCodeDoc), op);
+ block->loadFromXMI(element);
+ if(addTextBlock(block))
+ loadCheckForChildrenOK= true;
+ else
+ {
+ kError()<<"loadFromXMI : unable to add codeoperation to:"<<this<<endl;
+ delete block;
+ }
+ } else
+ kError()<<"loadFromXMI : unable to create codeoperation for obj id:"<<id<<endl;
+ }
+ /*
+ // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
+ else
+ kWarning()<<" LoadFromXMI: Got strange tag in text block stack:"<<name.latin1()<<", ignorning"<<endl;
+ */
+
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+ break;
+ }
+
+ tnode = telement.nextSibling();
+ telement = tnode.toElement();
+ }
+
+ if(!loadCheckForChildrenOK)
+ {
+ CodeDocument * test = dynamic_cast<CodeDocument*>(this);
+ if(test)
+ {
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
+ } else {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
+ if(hb)
+ kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
+ else
+ kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
+ }
+ }
+
+}
+
+void CodeGenObjectWithTextBlocks::initFields ( ) {
+
+ m_textblockVector.setAutoDelete(false);
+
+}
+
diff --git a/umbrello/umbrello/codegenobjectwithtextblocks.h b/umbrello/umbrello/codegenobjectwithtextblocks.h
new file mode 100644
index 00000000..4e784b07
--- /dev/null
+++ b/umbrello/umbrello/codegenobjectwithtextblocks.h
@@ -0,0 +1,192 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Aug 19 2003
+ */
+
+#ifndef CODEGENOBJECTWITHTEXTBLOCKS_H
+#define CODEGENOBJECTWITHTEXTBLOCKS_H
+
+#include <qmap.h>
+#include "codeaccessormethod.h"
+#include "textblocklist.h"
+
+class CodeBlock;
+class CodeBlockWithComments;
+class CodeClassField;
+class CodeComment;
+class CodeDocument;
+class HierarchicalCodeBlock;
+class TextBlock;
+
+
+/**
+ * class CodeGenObjectWithTextBlocks
+ * This abstract class is for code generator objects which 'own' text blocks.
+ */
+
+class CodeGenObjectWithTextBlocks
+{
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ CodeGenObjectWithTextBlocks ( CodeDocument *parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeGenObjectWithTextBlocks ( );
+
+ /**
+ * Add a TextBlock object to the m_textblockVector List
+ * @return boolean value where false means not added because an TextBlock
+ * object with that tag already exists in this document.
+ */
+ virtual bool addTextBlock ( TextBlock * add_object );
+
+ /**
+ * Remove a TextBlock object from m_textblockVector List
+ */
+ virtual bool removeTextBlock ( TextBlock * remove_object );
+
+ /**
+ * Insert a new text block before/after the existing text block. Returns
+ * false if it cannot insert the textblock.
+ */
+ virtual bool insertTextBlock (TextBlock * newBlock, TextBlock * existingBlock, bool after) = 0;
+
+ /**
+ * Get the list of TextBlock objects held by m_textblockVector
+ * @return TextBlockList list of TextBlock objects held by m_textblockVector
+ */
+ TextBlockList * getTextBlockList ( );
+
+ /**
+ * Will get a hierarchicalcodeblock from the document with given tag. IF the codeblock
+ * doesn't exist, then it will create it at the end of the document textBlock
+ * list and pass back a reference.
+ * @return HierarchicalCodeBlock
+ * @param tag
+ * @param comment
+ * @param indentLevel
+ */
+ virtual HierarchicalCodeBlock * getHierarchicalCodeBlock ( const QString &tag, const QString &comment, int indentLevel );
+
+ /**
+ * Will get a codeblockwithcomments from the document with given tag. IF the codeblock
+ * doesn't exist, then it will create it at the end of the document textBlock
+ * list and pass back a reference.
+ * @return CodeBlockWithComments
+ * @param tag
+ * @param comment
+ * @param indentLevel
+ */
+ virtual CodeBlockWithComments * getCodeBlockWithComments ( const QString &tag, const QString &comment, int indentLevel );
+
+ /** allows the user to add a code comment to the end of the list
+ * of text blocks in this document OR, if a text block already exists
+ * with that tag, it will update it with the passed text as appropriate.
+ * @return codeblock/comment pointer to the object which was created/updated.
+ * @return CodeComment
+ * @param tag
+ * @param text
+ * @param indentationLevel
+ */
+ CodeComment * addOrUpdateTaggedCodeComment (const QString &tag = "", const QString &text = "", int indentationLevel = 0 );
+
+ /** allows the user to either add a code block with comments to the end of the list
+ * of text blocks in this document OR, if a text block already exists
+ * with that tag, it will update it with the passed text as appropriate.
+ * @return codeblock/comment pointer to the object which was created/updated.
+ * @return CodeBlockWithComments
+ * @param tag
+ * @param text
+ * @param comment
+ * @param indentLevel
+ * @param forceUserBlockUpdate
+ */
+ CodeBlockWithComments * addOrUpdateTaggedCodeBlockWithComments (const QString &tag, const QString &text, const QString &comment, int indentLevel, bool forceUserBlockUpdate );
+
+ /**
+ * @return TextBlock
+ * @param tag
+ */
+ virtual TextBlock * findTextBlockByTag ( const QString &tag );
+
+ /**
+ * @return QString
+ * @param prefix
+ */
+ virtual QString getUniqueTag (const QString& prefix = "" ) = 0;
+
+ /** Virtual methods that return a new code document objects.
+ */
+ virtual CodeBlock * newCodeBlock() = 0;
+ virtual CodeBlockWithComments * newCodeBlockWithComments() = 0;
+ virtual HierarchicalCodeBlock * newHierarchicalCodeBlock() = 0;
+
+ /** Find the direct parent for a given textblock. This
+ * may be any object which holds text blocks, e.g. a CodeGenObjectWithTextBlocks.
+ * @return parent object. Could return null if the textblock is missing from the
+ * branch of the document tree being examined.
+ */
+ CodeGenObjectWithTextBlocks * findParentObjectForTaggedTextBlock (const QString & tag);
+
+protected:
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode (QDomDocument & doc, QDomElement & elem );
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ virtual void setAttributesFromObject (CodeGenObjectWithTextBlocks * obj);
+
+ /**
+ * in this vanilla version, we only load comments and codeblocks
+ * as they are the only instanciatable (vanilla) things
+ * this method should be overridden if this class is inherited
+ * by some other class that is concrete and takes children
+ * derived from codeblock/codecomment/hierarchicalcb/ownedhiercodeblock
+ */
+ virtual void loadChildTextBlocksFromNode ( QDomElement & root);
+
+ // reset/clear the inventory text blocks held by this object
+ virtual void resetTextBlocks();
+
+ QMap<QString, TextBlock *> m_textBlockTagMap;
+ TextBlockList m_textblockVector;
+
+ // find specific text block belonging to code classfields.
+ // block may not presently be alocated t othe textblock list.
+ virtual TextBlock * findCodeClassFieldTextBlockByTag( const QString &tag) = 0;
+
+private:
+
+ void initFields ();
+
+ // needed in order to use findTextBlocksByTag
+ CodeDocument *m_pCodeDoc;
+
+};
+
+#endif // CODEGENOBJECTWITHTEXTBLOCKS_H
diff --git a/umbrello/umbrello/codeimport/Makefile.am b/umbrello/umbrello/codeimport/Makefile.am
new file mode 100644
index 00000000..5f821fab
--- /dev/null
+++ b/umbrello/umbrello/codeimport/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I./kdevcppparser $(all_includes)
+
+noinst_LTLIBRARIES = libcodeimport.la
+libcodeimport_la_SOURCES = adaimport.cpp classimport.cpp cppimport.cpp idlimport.cpp import_utils.cpp javaimport.cpp nativeimportbase.cpp pascalimport.cpp pythonimport.cpp
+
+SUBDIRS = kdevcppparser
diff --git a/umbrello/umbrello/codeimport/adaimport.cpp b/umbrello/umbrello/codeimport/adaimport.cpp
new file mode 100644
index 00000000..54ac3907
--- /dev/null
+++ b/umbrello/umbrello/codeimport/adaimport.cpp
@@ -0,0 +1,588 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "adaimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../package.h"
+#include "../folder.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../association.h"
+
+AdaImport::AdaImport() : NativeImportBase("--") {
+ initVars();
+}
+
+AdaImport::~AdaImport() {
+}
+
+void AdaImport::initVars() {
+ m_inGenericFormalPart = false;
+ m_classesDefinedInThisScope.clear();
+ m_renaming.clear();
+}
+
+/// Split the line so that a string is returned as a single element of the list,
+/// when not in a string then split at white space.
+QStringList AdaImport::split(const QString& lin) {
+ QStringList list;
+ QString listElement;
+ bool inString = false;
+ bool seenSpace = false;
+ QString line = lin.stripWhiteSpace();
+ uint len = line.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = line[i];
+ if (inString) {
+ listElement += c;
+ if (c == '"') {
+ if (i < len - 1 && line[i + 1] == '"') {
+ i++; // escaped quotation mark
+ continue;
+ }
+ list.append(listElement);
+ listElement = QString();
+ inString = false;
+ }
+ } else if (c == '"') {
+ inString = true;
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ listElement = QString(c);
+ seenSpace = false;
+ } else if (c == '\'') {
+ if (i < len - 2 && line[i + 2] == '\'') {
+ // character constant
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ listElement = line.mid(i, 3);
+ i += 2;
+ list.append(listElement);
+ listElement = QString();
+ continue;
+ }
+ listElement += c;
+ seenSpace = false;
+ } else if (c.isSpace()) {
+ if (seenSpace)
+ continue;
+ seenSpace = true;
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ listElement = QString();
+ }
+ } else {
+ listElement += c;
+ seenSpace = false;
+ }
+ }
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ return list;
+}
+
+void AdaImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.' || c == '#') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ if (c == ':' && word[i + 1] == '=') {
+ m_source.append(":=");
+ i++;
+ } else {
+ m_source.append(QString(c));
+ }
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+QString AdaImport::expand(const QString& name) {
+ QRegExp pfxRegExp("^(\\w+)\\.");
+ pfxRegExp.setCaseSensitive(false);
+ int pos = pfxRegExp.search(name);
+ if (pos == -1)
+ return name;
+ QString result = name;
+ QString pfx = pfxRegExp.cap(1);
+ if (m_renaming.contains(pfx)) {
+ result.remove(pfxRegExp);
+ result.prepend(m_renaming[pfx] + '.');
+ }
+ return result;
+}
+
+void AdaImport::parseStems(const QStringList& stems) {
+ if (stems.isEmpty())
+ return;
+ QString base = stems.first();
+ uint i = 0;
+ while (1) {
+ QString filename = base + ".ads";
+ if (! m_parsedFiles.contains(filename)) {
+ // Save current m_source and m_srcIndex.
+ QStringList source(m_source);
+ uint srcIndex = m_srcIndex;
+ m_source.clear();
+ parseFile(filename);
+ // Restore m_source and m_srcIndex.
+ m_source = source;
+ m_srcIndex = srcIndex;
+ // Also reset m_currentAccess.
+ // CHECK: need to reset more stuff?
+ m_currentAccess = Uml::Visibility::Public;
+ }
+ if (++i >= stems.count())
+ break;
+ base += '-' + stems[i];
+ }
+}
+
+bool AdaImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ QString keyword = m_source[m_srcIndex];
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "with") {
+ if (m_inGenericFormalPart) {
+ // mapping of generic formal subprograms or packages is not yet implemented
+ return false;
+ }
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ";") {
+ QStringList components = QStringList::split(".", m_source[m_srcIndex].lower());
+ const QString& prefix = components.first();
+ if (prefix == "system" || prefix == "ada" || prefix == "gnat" ||
+ prefix == "interfaces" || prefix == "text_io" ||
+ prefix == "unchecked_conversion" ||
+ prefix == "unchecked_deallocation") {
+ if (advance() != ",")
+ break;
+ continue;
+ }
+ parseStems(components);
+ if (advance() != ",")
+ break;
+ }
+ return true;
+ }
+ if (keyword == "generic") {
+ m_inGenericFormalPart = true;
+ return true;
+ }
+ if (keyword == "package") {
+ const QString& name = advance();
+ QStringList parentPkgs = QStringList::split(".", name.lower());
+ parentPkgs.pop_back(); // exclude the current package
+ parseStems(parentPkgs);
+ UMLObject *ns = NULL;
+ if (advance() == "is") {
+ ns = Import_Utils::createUMLObject(Uml::ot_Package, name,
+ m_scope[m_scopeIndex], m_comment);
+ if (m_source[m_srcIndex + 1] == "new") {
+ m_srcIndex++;
+ QString pkgName = advance();
+ UMLObject *gp = Import_Utils::createUMLObject(Uml::ot_Package, pkgName,
+ m_scope[m_scopeIndex]);
+ gp->setStereotype("generic");
+ // Add binding from instantiator to instantiatee
+ UMLAssociation *assoc = new UMLAssociation(Uml::at_Dependency, ns, gp);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ assoc->setStereotype("bind");
+ // Work around missing display of stereotype in AssociationWidget:
+ assoc->setName(assoc->getStereotype(true));
+ umldoc->addAssociation(assoc);
+ skipStmt();
+ } else {
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ }
+ } else if (m_source[m_srcIndex] == "renames") {
+ m_renaming[name] = advance();
+ } else {
+ kError() << "AdaImport::parseStmt: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt("is");
+ }
+ if (m_inGenericFormalPart) {
+ ns->setStereotype("generic");
+ m_inGenericFormalPart = false;
+ }
+ return true;
+ }
+ if (m_inGenericFormalPart)
+ return false; // skip generic formal parameter (not yet implemented)
+ if (keyword == "subtype") {
+ QString name = advance();
+ advance(); // "is"
+ QString base = expand(advance());
+ base.remove("Standard.", false);
+ UMLObject *type = umldoc->findUMLObject(base, Uml::ot_UMLObject, m_scope[m_scopeIndex]);
+ if (type == NULL) {
+ type = Import_Utils::createUMLObject(Uml::ot_Datatype, base, m_scope[m_scopeIndex]);
+ }
+ UMLObject *subtype = Import_Utils::createUMLObject(type->getBaseType(), name,
+ m_scope[m_scopeIndex], m_comment);
+ UMLAssociation *assoc = new UMLAssociation(Uml::at_Dependency, subtype, type);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ assoc->setStereotype("subtype");
+ // Work around missing display of stereotype in AssociationWidget:
+ assoc->setName(assoc->getStereotype(true));
+ umldoc->addAssociation(assoc);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "type") {
+ QString name = advance();
+ QString next = advance();
+ if (next == "(") {
+ kDebug() << "AdaImport::parseStmt(" << name << "): "
+ << "discriminant handling is not yet implemented" << endl;
+ // @todo Find out how to map discriminated record to UML.
+ // For now, we just create a pro forma empty record.
+ Import_Utils::createUMLObject(Uml::ot_Class, name, m_scope[m_scopeIndex],
+ m_comment, "record");
+ skipStmt("end");
+ if ((next = advance()) == "case")
+ m_srcIndex += 2; // skip "case" ";"
+ skipStmt();
+ return true;
+ }
+ if (next == ";") {
+ // forward declaration
+ Import_Utils::createUMLObject(Uml::ot_Class, name, m_scope[m_scopeIndex],
+ m_comment);
+ return true;
+ }
+ if (next != "is") {
+ kError() << "AdaImport::parseStmt: expecting \"is\"" << endl;
+ return false;
+ }
+ next = advance();
+ if (next == "(") {
+ // enum type
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ while ((next = advance()) != ")") {
+ Import_Utils::addEnumLiteral(enumType, next, m_comment);
+ m_comment = QString();
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ bool isTaggedType = false;
+ if (next == "abstract") {
+ m_isAbstract = true;
+ next = advance();
+ }
+ if (next == "tagged") {
+ isTaggedType = true;
+ next = advance();
+ }
+ if (next == "limited" ||
+ next == "task" ||
+ next == "protected" ||
+ next == "synchronized") {
+ next = advance(); // we can't (yet?) represent that
+ }
+ if (next == "private" ||
+ next == "interface" ||
+ next == "record" ||
+ (next == "null" &&
+ m_source[m_srcIndex+1] == "record")) {
+ Uml::Object_Type t = (next == "interface" ? Uml::ot_Interface : Uml::ot_Class);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ if (t == Uml::ot_Interface) {
+ while ((next = advance()) == "and") {
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ QString base = expand(advance());
+ UMLObject *p = Import_Utils::createUMLObject(Uml::ot_Interface, base, m_scope[m_scopeIndex]);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(p);
+ Import_Utils::createGeneralization(klass, parent);
+ }
+ } else {
+ ns->setAbstract(m_isAbstract);
+ }
+ m_isAbstract = false;
+ if (isTaggedType) {
+ if (! m_classesDefinedInThisScope.contains(ns))
+ m_classesDefinedInThisScope.append(ns);
+ } else {
+ ns->setStereotype("record");
+ }
+ if (next == "record")
+ m_klass = static_cast<UMLClassifier*>(ns);
+ else
+ skipStmt();
+ return true;
+ }
+ if (next == "new") {
+ QString base = expand(advance());
+ QStringList baseInterfaces;
+ while ((next = advance()) == "and") {
+ baseInterfaces.append(expand(advance()));
+ }
+ const bool isExtension = (next == "with");
+ Uml::Object_Type t;
+ if (isExtension || m_isAbstract) {
+ t = Uml::ot_Class;
+ } else {
+ base.remove("Standard.", false);
+ UMLObject *known = umldoc->findUMLObject(base, Uml::ot_UMLObject, m_scope[m_scopeIndex]);
+ t = (known ? known->getBaseType() : Uml::ot_Datatype);
+ }
+ UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(ns);
+ ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ if (isExtension) {
+ next = advance();
+ if (next == "null" || next == "record") {
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ Import_Utils::createGeneralization(klass, parent);
+ if (next == "record") {
+ // Set the m_klass for attributes.
+ m_klass = klass;
+ }
+ if (baseInterfaces.count()) {
+ t = Uml::ot_Interface;
+ QStringList::Iterator end(baseInterfaces.end());
+ for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) {
+ ns = Import_Utils::createUMLObject(t, *bi, m_scope[m_scopeIndex]);
+ parent = static_cast<UMLClassifier*>(ns);
+ Import_Utils::createGeneralization(klass, parent);
+ }
+ }
+ }
+ }
+ skipStmt();
+ return true;
+ }
+ // Datatypes: TO BE DONE
+ return false;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "end") {
+ if (m_klass) {
+ if (advance() != "record") {
+ kError() << "end: expecting \"record\" at "
+ << m_source[m_srcIndex] << endl;
+ }
+ m_klass = NULL;
+ } else if (m_scopeIndex) {
+ if (advance() != ";") {
+ QString scopeName = m_scope[m_scopeIndex]->getFullyQualifiedName();
+ if (scopeName.lower() != m_source[m_srcIndex].lower())
+ kError() << "end: expecting " << scopeName << ", found "
+ << m_source[m_srcIndex] << endl;
+ }
+ m_scopeIndex--;
+ m_currentAccess = Uml::Visibility::Public; // @todo make a stack for this
+ } else {
+ kError() << "importAda: too many \"end\"" << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ // subprogram
+ if (keyword == "not")
+ keyword = advance();
+ if (keyword == "overriding")
+ keyword = advance();
+ if (keyword == "function" || keyword == "procedure") {
+ const QString& name = advance();
+ QString returnType;
+ if (advance() != "(") {
+ // Unlike an Ada package, a UML package does not support
+ // subprograms.
+ // In order to map those, we would need to create a UML
+ // class with stereotype <<utility>> for the Ada package.
+ kDebug() << "ignoring parameterless " << keyword << " " << name << endl;
+ skipStmt();
+ return true;
+ }
+ UMLClassifier *klass = NULL;
+ UMLOperation *op = NULL;
+ const uint MAX_PARNAMES = 16;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString parName[MAX_PARNAMES];
+ uint parNameCount = 0;
+ do {
+ if (parNameCount >= MAX_PARNAMES) {
+ kError() << "MAX_PARNAMES is exceeded at " << name << endl;
+ break;
+ }
+ parName[parNameCount++] = advance();
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ":") {
+ kError() << "importAda: expecting ':'" << endl;
+ skipStmt();
+ break;
+ }
+ const QString &direction = advance();
+ QString typeName;
+ Uml::Parameter_Direction dir = Uml::pd_In;
+ if (direction == "access") {
+ // Oops, we have to improvise here because there
+ // is no such thing as "access" in UML.
+ // So we use the next best thing, "inout".
+ // Better ideas, anyone?
+ dir = Uml::pd_InOut;
+ typeName = advance();
+ } else if (direction == "in") {
+ if (m_source[m_srcIndex + 1] == "out") {
+ dir = Uml::pd_InOut;
+ m_srcIndex++;
+ }
+ typeName = advance();
+ } else if (direction == "out") {
+ dir = Uml::pd_Out;
+ typeName = advance();
+ } else {
+ typeName = direction; // In Ada, the default direction is "in"
+ }
+ typeName.remove("Standard.", false);
+ typeName = expand(typeName);
+ if (op == NULL) {
+ // In Ada, the first parameter indicates the class.
+ UMLObject *type = Import_Utils::createUMLObject(Uml::ot_Class, typeName, m_scope[m_scopeIndex]);
+ Uml::Object_Type t = type->getBaseType();
+ if ((t != Uml::ot_Interface &&
+ (t != Uml::ot_Class || type->getStereotype() == "record")) ||
+ !m_classesDefinedInThisScope.contains(type)) {
+ // Not an instance bound method - we cannot represent it.
+ skipStmt(")");
+ break;
+ }
+ klass = static_cast<UMLClassifier*>(type);
+ op = Import_Utils::makeOperation(klass, name);
+ // The controlling parameter is suppressed.
+ parNameCount--;
+ if (parNameCount) {
+ for (uint i = 0; i < parNameCount; i++)
+ parName[i] = parName[i + 1];
+ }
+ }
+ for (uint i = 0; i < parNameCount; i++) {
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]);
+ att->setParmKind(dir);
+ }
+ if (advance() != ";")
+ break;
+ }
+ if (keyword == "function") {
+ if (advance() != "return") {
+ if (klass)
+ kError() << "importAda: expecting \"return\" at function "
+ << name << endl;
+ return false;
+ }
+ returnType = expand(advance());
+ returnType.remove("Standard.", false);
+ }
+ bool isAbstract = false;
+ if (advance() == "is" && advance() == "abstract")
+ isAbstract = true;
+ if (klass != NULL && op != NULL)
+ Import_Utils::insertMethod(klass, op, m_currentAccess, returnType,
+ false, isAbstract, false, false, m_comment);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "task" || keyword == "protected") {
+ // Can task and protected objects/types be mapped to UML?
+ bool isType = false;
+ QString name = advance();
+ if (name == "type") {
+ isType = true;
+ name = advance();
+ }
+ QString next = advance();
+ if (next == "(") {
+ skipStmt(")"); // skip discriminant
+ next = advance();
+ }
+ if (next == "is")
+ skipStmt("end");
+ skipStmt();
+ return true;
+ }
+ if (keyword == "for") { // rep spec
+ QString typeName = advance();
+ QString next = advance();
+ if (next == "'") {
+ advance(); // skip qualifier
+ next = advance();
+ }
+ if (next == "use") {
+ if (advance() == "record")
+ skipStmt("end");
+ } else {
+ kError() << "importAda: expecting \"use\" at rep spec of "
+ << typeName << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ // At this point we're only interested in attribute declarations.
+ if (m_klass == NULL || keyword == "null") {
+ skipStmt();
+ return true;
+ }
+ const QString& name = keyword;
+ if (advance() != ":") {
+ kError() << "adaImport: expecting \":\" at " << name << " "
+ << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString nextToken = advance();
+ if (nextToken == "aliased")
+ nextToken = advance();
+ QString typeName = expand(nextToken);
+ QString initialValue;
+ if (advance() == ":=") {
+ initialValue = advance();
+ QString token;
+ while ((token = advance()) != ";") {
+ initialValue.append(' ' + token);
+ }
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ attr->setInitialValue(initialValue);
+ skipStmt();
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/adaimport.h b/umbrello/umbrello/codeimport/adaimport.h
new file mode 100644
index 00000000..14e41926
--- /dev/null
+++ b/umbrello/umbrello/codeimport/adaimport.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ADAIMPORT_H
+#define ADAIMPORT_H
+
+#include <qmap.h>
+#include <qstringlist.h>
+
+#include "nativeimportbase.h"
+#include "../umlobjectlist.h"
+
+/**
+ * Ada code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AdaImport : public NativeImportBase {
+public:
+ AdaImport();
+ virtual ~AdaImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Split the line so that a string is returned as a single element of the list.
+ * When not in a string then split at white space.
+ * Reimplementation of method from NativeImportBase is required because of
+ * Ada's tic which is liable to be confused with the beginning of a character
+ * constant.
+ */
+ QStringList split(const QString& line);
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Apply package renamings to the given name.
+ *
+ * @return expanded name
+ */
+ QString expand(const QString& name);
+
+ /**
+ * Parse all files that can be formed by concatenation of the given stems.
+ */
+ void parseStems(const QStringList& stems);
+
+ bool m_inGenericFormalPart; ///< auxiliary variable
+
+ /**
+ * List for keeping track of tagged objects declared in the current scope.
+ * This is required for distinguishing primitive from non primitive
+ * methods.
+ */
+ UMLObjectList m_classesDefinedInThisScope;
+
+ typedef QMap<QString, QString> StringMap;
+
+ /**
+ * Map of package renamings.
+ * Keyed by the renaming. Value returns the expanded name.
+ */
+ StringMap m_renaming;
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/classimport.cpp b/umbrello/umbrello/codeimport/classimport.cpp
new file mode 100644
index 00000000..ed675bda
--- /dev/null
+++ b/umbrello/umbrello/codeimport/classimport.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classimport.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <klocale.h>
+// app includes
+#include "../umldoc.h"
+#include "../uml.h"
+#include "idlimport.h"
+#include "pythonimport.h"
+#include "javaimport.h"
+#include "adaimport.h"
+#include "pascalimport.h"
+#include "cppimport.h"
+
+void ClassImport::importFiles(const QStringList &fileList) {
+ initialize();
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ uint processedFilesCount = 0;
+ for (QStringList::const_iterator fileIT = fileList.begin();
+ fileIT != fileList.end(); ++fileIT) {
+ QString fileName = (*fileIT);
+ umldoc->writeToStatusBar(i18n("Importing file: %1 Progress: %2/%3").
+ arg(fileName).arg(processedFilesCount).arg(fileList.size()));
+ parseFile(fileName);
+ processedFilesCount++;
+ }
+ umldoc->writeToStatusBar(i18n("Ready."));
+}
+
+ClassImport *ClassImport::createImporterByFileExt(const QString &filename) {
+ ClassImport *classImporter;
+ if (filename.endsWith(".idl"))
+ classImporter = new IDLImport();
+ else if (filename.endsWith(".py"))
+ classImporter = new PythonImport();
+ else if (filename.endsWith(".java"))
+ classImporter = new JavaImport();
+ else if (filename.contains( QRegExp("\\.ad[sba]$") ))
+ classImporter = new AdaImport();
+ else if (filename.endsWith(".pas"))
+ classImporter = new PascalImport();
+ else
+ classImporter = new CppImport(); // the default.
+ return classImporter;
+}
+
diff --git a/umbrello/umbrello/codeimport/classimport.h b/umbrello/umbrello/codeimport/classimport.h
new file mode 100644
index 00000000..351ddec5
--- /dev/null
+++ b/umbrello/umbrello/codeimport/classimport.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIMPORT_H
+#define CLASSIMPORT_H
+
+#include <qstringlist.h>
+
+/**
+ * Interfaces classparser library to uml models
+ * Abstract base for programming language specific import classes
+ * @author Mikko Pasanen
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class ClassImport {
+public:
+ ClassImport() {}
+ virtual ~ClassImport() {}
+
+ /**
+ * Import files.
+ *
+ * @param files List of files to import.
+ */
+ void importFiles(const QStringList &files);
+
+ /**
+ * Factory method.
+ */
+ static ClassImport *createImporterByFileExt(const QString &filename);
+
+protected:
+ /**
+ * Initialize the importer.
+ * This is called by importFiles() once, before entering
+ * the loop for importing one or more files.
+ * To be implemented by inheriting classes.
+ */
+ virtual void initialize() = 0;
+
+ /**
+ * Import a single file.
+ * To be implemented by inheriting classes.
+ *
+ * @param filename The file to import.
+ */
+ virtual void parseFile(const QString& filename) = 0;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/cppimport.cpp b/umbrello/umbrello/codeimport/cppimport.cpp
new file mode 100644
index 00000000..4537c038
--- /dev/null
+++ b/umbrello/umbrello/codeimport/cppimport.cpp
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cppimport.h"
+// qt/kde includes
+#include <qmap.h>
+#include <qregexp.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../umlobject.h"
+#include "../docwindow.h"
+#include "../package.h"
+#include "../enum.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../template.h"
+#include "../association.h"
+#include "kdevcppparser/lexer.h"
+#include "kdevcppparser/driver.h"
+#include "kdevcppparser/cpptree2uml.h"
+
+// static members
+CppDriver * CppImport::ms_driver;
+QStringList CppImport::ms_seenFiles;
+
+class CppDriver : public Driver {
+public:
+ void setupLexer(Lexer* lexer) {
+ Driver::setupLexer(lexer);
+ lexer->setRecordComments(true);
+ }
+};
+
+CppImport::CppImport() {
+ ms_driver = new CppDriver();
+}
+
+CppImport::~CppImport() {}
+
+void CppImport::feedTheModel(const QString& fileName) {
+ if (ms_seenFiles.find(fileName) != ms_seenFiles.end())
+ return;
+ ms_seenFiles.append(fileName);
+ QMap<QString, Dependence> deps = ms_driver->dependences(fileName);
+ if (! deps.empty()) {
+ QMap<QString, Dependence>::Iterator it;
+ for (it = deps.begin(); it != deps.end(); ++it) {
+ if (it.data().second == Dep_Global) // don't want these
+ continue;
+ QString includeFile = it.key();
+ if (includeFile.isEmpty()) {
+ kError() << fileName << ": " << it.data().first
+ << " not found" << endl;
+ continue;
+ }
+ kDebug() << fileName << ": " << includeFile << " => " << it.data().first << endl;
+ if (ms_seenFiles.find(includeFile) == ms_seenFiles.end())
+ feedTheModel(includeFile);
+ }
+ }
+ TranslationUnitAST *ast = ms_driver->translationUnit( fileName );
+ if (ast == NULL) {
+ kError() << "CppImport::feedTheModel: " << fileName << " not found" << endl;
+ return;
+ }
+ CppTree2Uml modelFeeder( fileName );
+ modelFeeder.parseTranslationUnit( ast );
+}
+
+void CppImport::initialize() {
+ // Reset the driver
+ ms_driver->reset();
+ // The driver shall attempt to parse included files.
+ ms_driver->setResolveDependencesEnabled( true );
+ // Add some standard include paths
+ ms_driver->addIncludePath( "/usr/include" );
+ ms_driver->addIncludePath( "/usr/include/c++" );
+ ms_driver->addIncludePath( "/usr/include/g++" );
+ ms_driver->addIncludePath( "/usr/local/include" );
+ QStringList incPathList = Import_Utils::includePathList();
+ if (incPathList.count()) {
+ QStringList::Iterator end(incPathList.end());
+ for (QStringList::Iterator i(incPathList.begin()); i != end; ++i) {
+ ms_driver->addIncludePath( *i );
+ }
+
+ }
+ ms_seenFiles.clear();
+}
+
+void CppImport::parseFile(const QString& fileName) {
+ if (ms_seenFiles.find(fileName) != ms_seenFiles.end())
+ return;
+ ms_driver->parseFile( fileName );
+ feedTheModel(fileName);
+}
+
diff --git a/umbrello/umbrello/codeimport/cppimport.h b/umbrello/umbrello/codeimport/cppimport.h
new file mode 100644
index 00000000..3d5d8195
--- /dev/null
+++ b/umbrello/umbrello/codeimport/cppimport.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CPPIMPORT_H
+#define CPPIMPORT_H
+
+#include <qstring.h>
+#include "classimport.h"
+
+class CppDriver;
+
+/**
+ * C++ code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class CppImport : public ClassImport {
+public:
+ CppImport();
+ virtual ~CppImport();
+
+protected:
+ /**
+ * Implement abstract operation from ClassImport for C++.
+ */
+ void initialize();
+
+ /**
+ * Import a single file.
+ *
+ * @param filename The file to import.
+ */
+ void parseFile(const QString& filename);
+
+private:
+ /**
+ * Auxiliary method for recursively traversing the #include dependencies
+ * in order to feed innermost includes to the model before dependent
+ * includes. It is important that includefiles are fed to the model
+ * in proper order so that references between UML objects are created
+ * properly.
+ */
+ void feedTheModel(const QString& fileName);
+
+ static CppDriver * ms_driver;
+ static QStringList ms_seenFiles; ///< auxiliary buffer for feedTheModel()
+
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/idlimport.cpp b/umbrello/umbrello/codeimport/idlimport.cpp
new file mode 100644
index 00000000..6d228baf
--- /dev/null
+++ b/umbrello/umbrello/codeimport/idlimport.cpp
@@ -0,0 +1,356 @@
+/***************************************************************************
+ * *
+ * 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) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "idlimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+// #include <qprocess.h> //should use this instead of popen()
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+IDLImport::IDLImport() : NativeImportBase("//") {
+ m_isOneway = m_isReadonly = m_isAttribute = false;
+ setMultiLineComment("/*", "*/");
+}
+
+IDLImport::~IDLImport() {
+}
+
+/// Check for split type names (e.g. unsigned long long)
+QString IDLImport::joinTypename() {
+ QString typeName = m_source[m_srcIndex];
+ if (m_source[m_srcIndex] == "unsigned")
+ typeName += ' ' + advance();
+ if (m_source[m_srcIndex] == "long" &&
+ (m_source[m_srcIndex + 1] == "long" || m_source[m_srcIndex + 1] == "double"))
+ typeName += ' ' + advance();
+ return typeName;
+}
+
+bool IDLImport::preprocess(QString& line) {
+ // Ignore C preprocessor generated lines.
+ if (line.startsWith("#"))
+ return true; // done
+ return NativeImportBase::preprocess(line);
+}
+
+void IDLImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_') {
+ lexeme += c;
+ } else if (c == ':' && word[i + 1] == ':') {
+ // compress scoped name into lexeme
+ lexeme += "::";
+ i++;
+ } else if (c == '<') {
+ // compress sequence or bounded string into lexeme
+ do {
+ lexeme += word[i];
+ } while (word[i] != '>' && ++i < len);
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+void IDLImport::parseFile(const QString& filename) {
+ if (filename.contains('/')) {
+ QString path = filename;
+ path.remove( QRegExp("/[^/]+$") );
+ kDebug() << "IDLImport::parseFile: adding path " << path << endl;
+ Import_Utils::addIncludePath(path);
+ }
+ QStringList includePaths = Import_Utils::includePathList();
+ //QProcess command("cpp", UMLAp::app());
+ QString command("cpp -C"); // -C means "preserve comments"
+ for (QStringList::Iterator pathIt = includePaths.begin();
+ pathIt != includePaths.end(); ++pathIt) {
+ QString path = (*pathIt);
+ //command.addArgument(" -I" + path);
+ command += " -I" + path;
+ }
+ command += ' ' + filename;
+ kDebug() << "importIDL: " << command << endl;
+ FILE *fp = popen(command.ascii(), "r");
+ if (fp == NULL) {
+ kError() << "IDLImport::parseFile: cannot popen(" << command << ")" << endl;
+ return;
+ }
+ // Scan the input file into the QStringList m_source.
+ m_source.clear();
+ char buf[256];
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ int len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[--len] = '\0';
+ NativeImportBase::scan( QString(buf) );
+ }
+ // Parse the QStringList m_source.
+ m_scopeIndex = 0;
+ m_scope[0] = NULL;
+ const uint srcLength = m_source.count();
+ for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
+ const QString& keyword = m_source[m_srcIndex];
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword.startsWith(m_singleLineCommentIntro)) {
+ m_comment = keyword.mid(m_singleLineCommentIntro.length());
+ continue;
+ }
+ if (! parseStmt())
+ skipStmt();
+ m_currentAccess = Uml::Visibility::Public;
+ m_comment = QString();
+ }
+ pclose(fp);
+}
+
+bool IDLImport::parseStmt() {
+ const QString& keyword = m_source[m_srcIndex];
+ const uint srcLength = m_source.count();
+ if (keyword == "module") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ m_scope[m_scopeIndex]->setStereotype("CORBAModule");
+ if (advance() != "{") {
+ kError() << "importIDL: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "interface") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setStereotype("CORBAInterface");
+ m_klass->setAbstract(m_isAbstract);
+ m_isAbstract = false;
+ m_comment = QString();
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == ":") {
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importIDL: ignoring excess chars at "
+ << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "struct" || keyword == "exception") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ if (keyword == "struct")
+ m_klass->setStereotype("CORBAStruct");
+ else
+ m_klass->setStereotype("CORBAException");
+ if (advance() != "{") {
+ kError() << "importIDL: expecting '{' at " << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "union") {
+ // TBD. <gulp>
+ skipStmt("}");
+ m_srcIndex++; // advance to ';'
+ return true;
+ }
+ if (keyword == "enum") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ m_srcIndex++; // skip name
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "}") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "typedef") {
+ const QString& existingType = advance();
+ const QString& newType = advance();
+ Import_Utils::createUMLObject(Uml::ot_Class, newType, m_scope[m_scopeIndex],
+ m_comment, "CORBATypedef" /* stereotype */);
+ // @todo How do we convey the existingType ?
+ skipStmt();
+ return true;
+ }
+ if (keyword == "const") {
+ skipStmt();
+ return true;
+ }
+ if (keyword == "custom") {
+ return true;
+ }
+ if (keyword == "abstract") {
+ m_isAbstract = true;
+ return true;
+ }
+ if (keyword == "valuetype") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setAbstract(m_isAbstract);
+ m_isAbstract = false;
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == ":") {
+ if (advance() == "truncatable")
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importIDL: ignoring excess chars at "
+ << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "public") {
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "readonly") {
+ m_isReadonly = true;
+ return true;
+ }
+ if (keyword == "attribute") {
+ m_isAttribute = true;
+ return true;
+ }
+ if (keyword == "oneway") {
+ m_isOneway = true;
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importIDL: too many }" << endl;
+ m_srcIndex++; // skip ';'
+ return true;
+ }
+ if (keyword == ";")
+ return true;
+ // At this point, we expect `keyword' to be a type name
+ // (of a member of struct or valuetype, or return type
+ // of an operation.) Up next is the name of the attribute
+ // or operation.
+ if (! keyword.contains( QRegExp("^\\w") )) {
+ kError() << "importIDL: ignoring " << keyword << endl;
+ return false;
+ }
+ QString typeName = joinTypename();
+ QString name = advance();
+ if (name.contains( QRegExp("\\W") )) {
+ kError() << "importIDL: expecting name in " << name << endl;
+ return false;
+ }
+ // At this point we most definitely need a class.
+ if (m_klass == NULL) {
+ kError() << "importIDL: no class set for " << name << endl;
+ return false;
+ }
+ QString nextToken = advance();
+ if (nextToken == "(") {
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ const QString &direction = m_source[m_srcIndex++];
+ QString typeName = joinTypename();
+ const QString &parName = advance();
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName);
+ Uml::Parameter_Direction dir;
+ if (Model_Utils::stringToDirection(direction, dir))
+ att->setParmKind(dir);
+ else
+ kError() << "importIDL: expecting parameter direction at "
+ << direction << endl;
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, typeName,
+ false, false, false, false, m_comment);
+ if (m_isOneway) {
+ op->setStereotype("oneway");
+ m_isOneway = false;
+ }
+ skipStmt(); // skip possible "raises" clause
+ return true;
+ }
+ // At this point we know it's some kind of attribute declaration.
+ while (1) {
+ while (nextToken != "," && nextToken != ";") {
+ name += nextToken; // add possible array dimensions to `name'
+ nextToken = advance();
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ if (m_isReadonly) {
+ attr->setStereotype("readonly");
+ m_isReadonly = false;
+ }
+ if (nextToken != ",")
+ break;
+ name = advance();
+ nextToken = advance();
+ }
+ return true;
+}
+
diff --git a/umbrello/umbrello/codeimport/idlimport.h b/umbrello/umbrello/codeimport/idlimport.h
new file mode 100644
index 00000000..6945364f
--- /dev/null
+++ b/umbrello/umbrello/codeimport/idlimport.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * *
+ * 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) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IDLIMPORT_H
+#define IDLIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * CORBA IDL code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class IDLImport : public NativeImportBase {
+public:
+ IDLImport();
+ virtual ~IDLImport();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Reimplement operation from NativeImportBase.
+ * Need to do this because we use the external C preprocessor.
+ */
+ void parseFile(const QString& file);
+
+ /**
+ * Override operation from NativeImportBase.
+ */
+ bool preprocess(QString& line);
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+protected:
+ QString joinTypename();
+ bool m_isOneway, m_isReadonly, m_isAttribute;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/import_utils.cpp b/umbrello/umbrello/codeimport/import_utils.cpp
new file mode 100644
index 00000000..92a87867
--- /dev/null
+++ b/umbrello/umbrello/codeimport/import_utils.cpp
@@ -0,0 +1,464 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "import_utils.h"
+// qt/kde includes
+#include <qmap.h>
+#include <qregexp.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+// app includes
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umllistview.h"
+#include "../umllistviewitem.h"
+#include "../umlobject.h"
+#include "../package.h"
+#include "../folder.h"
+#include "../enum.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../template.h"
+#include "../association.h"
+#include "../object_factory.h"
+
+#include <stdlib.h>
+
+namespace Import_Utils {
+
+/**
+ * Flag manipulated by createUMLObject().
+ * Global state is generally bad, I know.
+ * It would be cleaner to make this into a return value from
+ * createUMLObject().
+ */
+bool bNewUMLObjectWasCreated = false;
+
+/**
+ * Related classifier for creation of dependencies on template
+ * parameters in createUMLObject().
+ */
+UMLClassifier * gRelatedClassifier = NULL;
+
+/**
+ * On encountering a scoped typename string where the scopes
+ * have not yet been seen, we synthesize UML objects for the
+ * unknown scopes (using a question dialog to the user to decide
+ * whether to treat a scope as a class or as a package.)
+ * However, such an unknown scope is put at the global level.
+ * I.e. before calling createUMLObject() we set this flag to true.
+ */
+bool bPutAtGlobalScope = false;
+
+/**
+ * The include path list (see addIncludePath() and includePathList())
+ */
+QStringList incPathList;
+
+void putAtGlobalScope(bool yesno) {
+ bPutAtGlobalScope = yesno;
+}
+
+void setRelatedClassifier(UMLClassifier *c) {
+ gRelatedClassifier = c;
+}
+
+void assignUniqueIdOnCreation(bool yesno) {
+ Object_Factory::assignUniqueIdOnCreation(yesno);
+}
+
+bool newUMLObjectWasCreated() {
+ return bNewUMLObjectWasCreated;
+}
+
+QString formatComment(const QString &comment) {
+ if (comment.isEmpty())
+ return comment;
+
+ QStringList lines = QStringList::split("\n", comment);
+ QString& first = lines.first();
+ QRegExp wordex("\\w");
+ if (first.startsWith("/*")) {
+ int wordpos = wordex.search(first);
+ if (wordpos != -1)
+ first = first.mid(wordpos); // remove comment start
+ else
+ lines.pop_front(); // nothing interesting on this line
+ }
+ QString& last = lines.last();
+ int endpos = last.find("*/");
+ if (endpos != -1) {
+ if (last.contains(wordex))
+ last = last.mid(0, endpos - 1); // remove comment end
+ else
+ lines.pop_back(); // nothing interesting on this line
+ }
+ if (! lines.count())
+ return "";
+
+ QStringList::Iterator end(lines.end());
+ for (QStringList::Iterator lit(lines.begin()); lit != end; ++lit) {
+ (*lit).remove(QRegExp("^\\s+"));
+ (*lit).remove(QRegExp("^\\*+\\s?"));
+ }
+ return lines.join("\n");
+}
+
+/*
+UMLObject* findUMLObject(QString name,
+ Uml::Object_Type type) {
+ // Why an extra wrapper? See comment at addMethodParameter()
+ UMLObject * o = umldoc->findUMLObject(name, type);
+ return o;
+}
+ */
+
+UMLObject *createUMLObject(Uml::Object_Type type,
+ const QString& inName,
+ UMLPackage *parentPkg,
+ const QString& comment,
+ const QString& stereotype) {
+ QString name = inName;
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
+ const Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (parentPkg == NULL) {
+ // kDebug() << "Import_Utils::createUMLObject(" << name
+ // << "): parentPkg is NULL, assuming Logical View" << endl;
+ parentPkg = logicalView;
+ }
+ UMLObject * o = umldoc->findUMLObject(name, type, parentPkg);
+ bNewUMLObjectWasCreated = false;
+ if (o == NULL) {
+ // Strip possible adornments and look again.
+ int isConst = name.contains(QRegExp("^const "));
+ name.remove(QRegExp("^const\\s+"));
+ QString typeName(name);
+ const int isAdorned = typeName.contains( QRegExp("[^\\w:\\. ]") );
+ const int isPointer = typeName.contains('*');
+ const int isRef = typeName.contains('&');
+ typeName.remove(QRegExp("[^\\w:\\. ].*$"));
+ typeName = typeName.simplifyWhiteSpace();
+ UMLObject *origType = umldoc->findUMLObject(typeName, Uml::ot_UMLObject, parentPkg);
+ if (origType == NULL) {
+ // Still not found. Create the stripped down type.
+ if (bPutAtGlobalScope)
+ parentPkg = logicalView;
+ // Find, or create, the scopes.
+ QStringList components;
+ if (typeName.contains("::")) {
+ components = QStringList::split("::", typeName);
+ } else if (typeName.contains(".")) {
+ components = QStringList::split(".", typeName);
+ }
+ if (components.count() > 1) {
+ typeName = components.back();
+ components.pop_back();
+ while ( components.count() ) {
+ QString scopeName = components.front();
+ components.pop_front();
+ o = umldoc->findUMLObject(scopeName, Uml::ot_UMLObject, parentPkg);
+ if (o) {
+ parentPkg = static_cast<UMLPackage*>(o);
+ continue;
+ }
+ int wantNamespace = KMessageBox::Yes;
+ if (pl == Uml::pl_Cpp) {
+ /* We know std and Qt are namespaces */
+ if (scopeName != "std" && scopeName != "Qt") {
+ wantNamespace = KMessageBox::questionYesNo(NULL,
+ i18n("Is the scope %1 a namespace or a class?").arg(scopeName),
+ i18n("C++ Import Requests Your Help"),
+ i18n("Namespace"), i18n("Class"));
+ }
+ }
+ Uml::Object_Type ot = (wantNamespace == KMessageBox::Yes ? Uml::ot_Package : Uml::ot_Class);
+ o = Object_Factory::createUMLObject(ot, scopeName, parentPkg);
+ parentPkg = static_cast<UMLPackage*>(o);
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *lvitem = listView->findUMLObject(o);
+ listView->setCurrentItem(lvitem);
+ }
+ // All scope qualified datatypes live in the global scope.
+ bPutAtGlobalScope = true;
+ }
+ Uml::Object_Type t = type;
+ if (type == Uml::ot_UMLObject || isAdorned)
+ t = Uml::ot_Class;
+ origType = Object_Factory::createUMLObject(t, typeName, parentPkg, false);
+ bNewUMLObjectWasCreated = true;
+ bPutAtGlobalScope = false;
+ }
+ if (isConst || isAdorned) {
+ // Create the full given type (including adornments.)
+ if (isConst)
+ name.prepend("const ");
+ o = Object_Factory::createUMLObject(Uml::ot_Datatype, name,
+ umldoc->getDatatypeFolder(),
+ false); //solicitNewName
+ UMLClassifier *dt = static_cast<UMLClassifier*>(o);
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(origType);
+ if (c)
+ dt->setOriginType(c);
+ else
+ kError() << "createUMLObject(" << name << "): "
+ << "origType " << typeName << " is not a UMLClassifier"
+ << endl;
+ if (isRef || isPointer)
+ dt->setIsReference();
+ /*
+ if (isPointer) {
+ UMLObject *pointerDecl = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+ UMLClassifier *dt = static_cast<UMLClassifier*>(pointerDecl);
+ dt->setOriginType(classifier);
+ dt->setIsReference();
+ classifier = dt;
+ } */
+ } else {
+ o = origType;
+ }
+ } else if (parentPkg && !bPutAtGlobalScope) {
+ UMLPackage *existingPkg = o->getUMLPackage();
+ if (existingPkg != umldoc->getDatatypeFolder()) {
+ if (existingPkg)
+ existingPkg->removeObject(o);
+ else
+ kError() << "createUMLObject(" << name << "): "
+ << "o->getUMLPackage() was NULL" << endl;
+ o->setUMLPackage(parentPkg);
+ parentPkg->addObject(o);
+ }
+ }
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ o->setDoc(strippedComment);
+ }
+ if (!stereotype.isEmpty()) {
+ o->setStereotype(stereotype);
+ }
+ if (gRelatedClassifier == NULL || gRelatedClassifier == o)
+ return o;
+ QRegExp templateInstantiation("^[\\w:\\.]+\\s*<(.*)>");
+ int pos = templateInstantiation.search(name);
+ if (pos == -1)
+ return o;
+ // Create dependencies on template parameters.
+ QString caption = templateInstantiation.cap(1);
+ QStringList params = QStringList::split(QRegExp("[^\\w:\\.]+"), caption);
+ if (!params.count())
+ return o;
+ QStringList::Iterator end(params.end());
+ for (QStringList::Iterator it(params.begin()); it != end; ++it) {
+ UMLObject *p = umldoc->findUMLObject(*it, Uml::ot_UMLObject, parentPkg);
+ if (p == NULL || p->getBaseType() == Uml::ot_Datatype)
+ continue;
+ const Uml::Association_Type at = Uml::at_Dependency;
+ UMLAssociation *assoc = umldoc->findAssociation(at, gRelatedClassifier, p);
+ if (assoc)
+ continue;
+ assoc = new UMLAssociation(at, gRelatedClassifier, p);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ umldoc->addAssociation(assoc);
+ }
+ return o;
+}
+
+UMLOperation* makeOperation(UMLClassifier *parent, const QString &name) {
+ UMLOperation *op = Object_Factory::createOperation(parent, name);
+ return op;
+}
+
+UMLObject* insertAttribute(UMLClassifier *owner,
+ Uml::Visibility scope,
+ const QString& name,
+ UMLClassifier *attrType,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */) {
+ Uml::Object_Type ot = owner->getBaseType();
+ Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (! (ot == Uml::ot_Class || ot == Uml::ot_Interface && pl == Uml::pl_Java)) {
+ kDebug() << "insertAttribute: Don't know what to do with "
+ << owner->getName() << " (object type " << ot << ")" << endl;
+ return NULL;
+ }
+ UMLObject *o = owner->findChildObject(name, Uml::ot_Attribute);
+ if (o) {
+ return o;
+ }
+
+ UMLAttribute *attr = owner->addAttribute(name, attrType, scope);
+ attr->setStatic(isStatic);
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ attr->setDoc(strippedComment);
+ }
+
+ UMLApp::app()->getDocument()->setModified(true);
+ return attr;
+}
+
+UMLObject* insertAttribute(UMLClassifier *owner, Uml::Visibility scope,
+ const QString& name,
+ const QString& type,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */) {
+ UMLObject *attrType = owner->findTemplate(type);
+ if (attrType == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = owner;
+ attrType = createUMLObject(Uml::ot_UMLObject, type, owner);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ }
+ return insertAttribute (owner, scope, name,
+ static_cast<UMLClassifier*>(attrType),
+ comment, isStatic);
+}
+
+void insertMethod(UMLClassifier *klass, UMLOperation* &op,
+ Uml::Visibility scope, const QString& type,
+ bool isStatic, bool isAbstract,
+ bool isFriend, bool isConstructor,
+ const QString& comment) {
+ op->setVisibility(scope);
+ if (!type.isEmpty() // return type may be missing (constructor/destructor)
+ && type != "void") {
+ if (type == klass->getName()) {
+ op->setType(klass);
+ } else {
+ UMLObject *typeObj = klass->findTemplate(type);
+ if (typeObj == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = klass;
+ typeObj = createUMLObject(Uml::ot_UMLObject, type, klass);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ op->setType(typeObj);
+ }
+ }
+ }
+
+ op->setStatic(isStatic);
+ op->setAbstract(isAbstract);
+
+ // if the operation is friend, add it as a stereotype
+ if (isFriend)
+ op->setStereotype("friend");
+ // if the operation is a constructor, add it as a stereotype
+ if (isConstructor)
+ op->setStereotype("constructor");
+
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ op->setDoc(strippedComment);
+ }
+
+ UMLAttributeList params = op->getParmList();
+ UMLOperation *exist = klass->checkOperationSignature(op->getName(), params);
+ if (exist) {
+ // copy contents to existing operation
+ exist->setVisibility(scope);
+ exist->setStatic(isStatic);
+ exist->setAbstract(isAbstract);
+ if (! strippedComment.isEmpty())
+ exist->setDoc(strippedComment);
+ UMLAttributeList exParams = exist->getParmList();
+ UMLAttribute *param, *exParam = exParams.first();
+ for (UMLAttributeListIt it(params); (param = it.current()) != NULL;
+ ++it, exParam = exParams.next()) {
+ exParam->setName(param->getName());
+ exParam->setVisibility(param->getVisibility());
+ exParam->setStatic(param->getStatic());
+ exParam->setAbstract(param->getAbstract());
+ exParam->setDoc(param->getDoc());
+ exParam->setInitialValue(param->getInitialValue());
+ exParam->setParmKind(param->getParmKind());
+ }
+ // delete incoming UMLOperation and pass out the existing one
+ delete op;
+ op = exist;
+ } else {
+ klass->addOperation(op);
+ }
+}
+
+UMLAttribute* addMethodParameter(UMLOperation *method,
+ const QString& type,
+ const QString& name) {
+ UMLClassifier *owner = static_cast<UMLClassifier*>(method->parent());
+ UMLObject *typeObj = owner->findTemplate(type);
+ if (typeObj == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = owner;
+ typeObj = createUMLObject(Uml::ot_UMLObject, type, owner);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ }
+ UMLAttribute *attr = Object_Factory::createAttribute(method, name, typeObj);
+ method->addParm(attr);
+ return attr;
+}
+
+void addEnumLiteral(UMLEnum *enumType, const QString &literal, const QString &comment) {
+ UMLObject *el = enumType->addEnumLiteral(literal);
+ el->setDoc(comment);
+}
+
+void createGeneralization(UMLClassifier *child, UMLClassifier *parent) {
+ // if the child is an interface, so is the parent.
+ if (child->isInterface())
+ parent->setBaseType(Uml::ot_Interface);
+ Uml::Association_Type association = Uml::at_Generalization;
+
+ if (parent->isInterface() && !child->isInterface()) {
+ // if the parent is an interface, but the child is not, then
+ // this is really realization.
+ //
+ association = Uml::at_Realization;
+ }
+ UMLAssociation *assoc = new UMLAssociation(association, child, parent);
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ umldoc->addAssociation(assoc);
+}
+
+void createGeneralization(UMLClassifier *child, const QString &parentName) {
+ UMLObject *parentObj = createUMLObject( Uml::ot_Class, parentName );
+ UMLClassifier *parent = static_cast<UMLClassifier*>(parentObj);
+ createGeneralization(child, parent);
+}
+
+QStringList includePathList() {
+ QStringList includePathList(incPathList);
+ char *umbrello_incpath = getenv( "UMBRELLO_INCPATH" );
+ if (umbrello_incpath) {
+ includePathList += QStringList::split( ':', umbrello_incpath );
+ }
+ return includePathList;
+}
+
+void addIncludePath(const QString& path) {
+ if (! incPathList.contains(path))
+ incPathList.append(path);
+}
+
+
+bool isDatatype(const QString& name, UMLPackage *parentPkg) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLObject * o = umldoc->findUMLObject(name, Uml::ot_Datatype, parentPkg);
+ return (o!=NULL);
+}
+
+} // end namespace Import_Utils
+
diff --git a/umbrello/umbrello/codeimport/import_utils.h b/umbrello/umbrello/codeimport/import_utils.h
new file mode 100644
index 00000000..7d36bc77
--- /dev/null
+++ b/umbrello/umbrello/codeimport/import_utils.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IMPORT_UTILS_H
+#define IMPORT_UTILS_H
+
+#include <qstringlist.h>
+#include "../umlnamespace.h"
+#include "../umlattributelist.h"
+
+class UMLObject;
+class UMLClassifier;
+class UMLPackage;
+class UMLOperation;
+class UMLEnum;
+
+/**
+ * Utilities for code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+namespace Import_Utils {
+
+ /**
+ * Find or create a document object.
+ */
+ UMLObject* createUMLObject(Uml::Object_Type type,
+ const QString& name,
+ UMLPackage *parentPkg = NULL,
+ const QString& comment = QString::null,
+ const QString& stereotype = QString::null);
+ /**
+ * Control whether an object which is newly created by createUMLObject()
+ * is put at the global scope.
+ *
+ * @param yesno When set to false, the object is created at the scope
+ * given by the parentPkg argument of createUMLObject().
+ */
+ void putAtGlobalScope(bool yesno);
+
+ /**
+ * Set a related classifier for creation of dependencies on template
+ * parameters in createUMLObject().
+ */
+ void setRelatedClassifier(UMLClassifier *c);
+
+ /**
+ * Control whether the creation methods solicit a new unique ID for the
+ * created object.
+ * By default, unique ID generation is turned on.
+ *
+ * @param yesno False turns UID generation off, true turns it on.
+ */
+ void assignUniqueIdOnCreation(bool yesno);
+
+ /**
+ * Create a UMLAttribute and insert it into the document.
+ */
+ UMLObject* insertAttribute(UMLClassifier *klass, Uml::Visibility scope,
+ const QString& name,
+ const QString& type,
+ const QString& comment = QString::null,
+ bool isStatic = false);
+ /**
+ * Create a UMLAttribute and insert it into the document.
+ * Use the specified existing attrType.
+ */
+ UMLObject* insertAttribute(UMLClassifier *klass, Uml::Visibility scope,
+ const QString& name,
+ UMLClassifier *attrType,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */);
+ /**
+ * Create a UMLOperation.
+ * The reason for this method is to not generate any Qt signals.
+ * Instead, these are generated by insertMethod().
+ * (If we generated a creation signal prematurely, i.e. without
+ * the method parameters being known yet, then that would lead to
+ * a conflict with a pre-existing parameterless method of the same
+ * name.)
+ */
+ UMLOperation* makeOperation(UMLClassifier *parent, const QString &name);
+
+ /**
+ * Insert the UMLOperation into the given classifier.
+ *
+ * @param klass The classifier into which the operation shall be added.
+ * @param op Reference to pointer to the temporary UMLOperation
+ * for insertion. The caller relinquishes ownership of the
+ * object pointed to. If an UMLOperation of same signature
+ * already exists at the classifier then the incoming
+ * UMLOperation is deleted and the pointer is set to the
+ * existing UMLOperation.
+ * @param scope The Uml::Visibility of the method
+ * @param type The return type
+ * @param isStatic boolean switch to decide if method is static
+ * @param isAbstract boolean switch to decide if method is abstract
+ * @param isFriend true boolean switch to decide if methods is a friend function
+ * @param isConstructor boolean switch to decide if methods is a constructor
+ * @param comment The Documentation for this method
+ */
+ void insertMethod(UMLClassifier *klass, UMLOperation* &op,
+ Uml::Visibility scope, const QString& type,
+ bool isStatic, bool isAbstract,
+ bool isFriend = false, bool isConstructor = false,
+ const QString& comment = QString::null);
+
+ /**
+ * Add an argument to a UMLOperation.
+ * The parentPkg arg is only used for resolving possible scope
+ * prefixes in the `type'.
+ */
+ UMLAttribute* addMethodParameter(UMLOperation *method,
+ const QString& type,
+ const QString& name);
+
+ /**
+ * Add an enum literal to an UMLEnum.
+ */
+ void addEnumLiteral(UMLEnum *enumType, const QString &literal,
+ const QString &comment = QString());
+
+ /**
+ * Create a generalization from the given child classifier to the given
+ * parent classifier.
+ */
+ void createGeneralization(UMLClassifier *child, UMLClassifier *parent);
+
+ /**
+ * Create a generalization from the existing child UMLObject to the given
+ * parent class name.
+ */
+ void createGeneralization(UMLClassifier *child, const QString &parentName);
+
+ /**
+ * Strip comment lines of leading whitespace and stars.
+ */
+ QString formatComment(const QString &comment);
+
+ /**
+ * Return the list of paths set by previous calls to addIncludePath()
+ * and the environment variable UMBRELLO_INCPATH.
+ * This list can be used for finding #included (or Ada with'ed or...)
+ * files.
+ */
+ QStringList includePathList();
+
+ /**
+ * Add a path to the include path list.
+ */
+ void addIncludePath(const QString& path);
+
+ /**
+ * Returns whether the last createUMLObject() actually created
+ * a new object or just returned an existing one.
+ */
+ bool newUMLObjectWasCreated();
+
+ /**
+ * Returns true if a type is an actual Datatype
+ */
+ bool isDatatype(const QString& name, UMLPackage *parentPkg = NULL);
+
+} // end namespace Import_Utils
+
+#endif
diff --git a/umbrello/umbrello/codeimport/javaimport.cpp b/umbrello/umbrello/codeimport/javaimport.cpp
new file mode 100644
index 00000000..8df6e5e7
--- /dev/null
+++ b/umbrello/umbrello/codeimport/javaimport.cpp
@@ -0,0 +1,549 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "javaimport.h"
+
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+QStringList JavaImport::s_filesAlreadyParsed;
+int JavaImport::s_parseDepth = 0;
+
+JavaImport::JavaImport() : NativeImportBase("//") {
+ setMultiLineComment("/*", "*/");
+ initVars();
+}
+
+JavaImport::~JavaImport() {
+}
+
+void JavaImport::initVars() {
+ m_isStatic = false;
+}
+
+/// Catenate possible template arguments/array dimensions to the end of the type name.
+QString JavaImport::joinTypename(QString typeName) {
+ if (m_source[m_srcIndex + 1] == "<" ||
+ m_source[m_srcIndex + 1] == "[") {
+ uint start = ++m_srcIndex;
+ if (! skipToClosing(m_source[start][0]))
+ return typeName;
+ for (uint i = start; i <= m_srcIndex; i++) {
+ typeName += m_source[i];
+ }
+ }
+ // to handle multidimensional arrays, call recursively
+ if (m_source[m_srcIndex + 1] == "[") {
+ typeName = joinTypename( typeName );
+ }
+ return typeName;
+}
+
+void JavaImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+
+///Spawn off an import of the specified file
+void JavaImport::spawnImport( QString file ) {
+ // if the file is being parsed, don't bother
+ //
+ if (s_filesAlreadyParsed.contains( file ) ) {
+ return;
+ }
+ if (QFile::exists(file)) {
+ JavaImport importer;
+ QStringList fileList;
+ fileList.append( file );
+ s_filesAlreadyParsed.append( file );
+ importer.importFiles( fileList );
+ }
+}
+
+
+///returns the UML Object if found, or null otherwise
+UMLObject* findObject( QString name, UMLPackage *parentPkg ) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLObject * o = umldoc->findUMLObject(name, Uml::ot_UMLObject , parentPkg);
+ return o;
+}
+
+
+///Resolve the specified className
+UMLObject* JavaImport::resolveClass (QString className) {
+ kDebug() << "importJava trying to resolve " << className << endl;
+ // keep track if we are dealing with an array
+ //
+ bool isArray = className.contains('[');
+ // remove any [] so that the class itself can be resolved
+ //
+ QString baseClassName = className;
+ baseClassName.remove('[');
+ baseClassName.remove(']');
+
+ // java has a few implicit imports. Most relevant for this is the
+ // current package, which is in the same directory as the current file
+ // being parsed
+ //
+ QStringList file = QStringList::split( '/', m_currentFileName);
+ // remove the filename. This leaves the full path to the containing
+ // dir which should also include the package hierarchy
+ //
+ file.pop_back();
+
+ // the file we're looking for might be in the same directory as the
+ // current class
+ //
+ QString myDir = file.join( "/" );
+ QString myFile = '/' + myDir + '/' + baseClassName + ".java";
+ if ( QFile::exists(myFile) ) {
+ spawnImport( myFile );
+ if ( isArray ) {
+ // we have imported the type. For arrays we want to return
+ // the array type
+ return Import_Utils::createUMLObject(Uml::ot_Class, className, m_scope[m_scopeIndex]);
+ }
+ return findObject(baseClassName, m_scope[m_scopeIndex]);
+ }
+
+ // the class we want is not in the same package as the one being imported.
+ // use the imports to find the one we want.
+ //
+ QStringList package = QStringList::split( '.', m_currentPackage);
+ int dirsInPackageCount = package.size();
+
+ for (int count=0; count < dirsInPackageCount; count ++ ) {
+ // pop off one by one the directories, until only the source root remains
+ //
+ file.pop_back();
+ }
+ // this is now the root of any further source imports
+ QString sourceRoot = '/' + file.join("/") + '/';
+
+ for (QStringList::Iterator pathIt = m_imports.begin();
+ pathIt != m_imports.end(); ++pathIt) {
+ QString import = (*pathIt);
+ QStringList split = QStringList::split( '.', import );
+ split.pop_back(); // remove the * or the classname
+ if ( import.endsWith( "*" ) || import.endsWith( baseClassName) ) {
+ // check if the file we want is in this imported package
+ // convert the org.test type package into a filename
+ //
+ QString aFile = sourceRoot + split.join("/") + '/' + baseClassName + ".java";
+ if ( QFile::exists(aFile) ) {
+ spawnImport( aFile );
+ // we need to set the package for the class that will be resolved
+ // start at the root package
+ UMLPackage *parent = m_scope[0];
+ UMLPackage *current = NULL;
+
+ for (QStringList::Iterator it = split.begin(); it != split.end(); ++it) {
+ QString name = (*it);
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, parent);
+ current = static_cast<UMLPackage*>(ns);
+ parent = current;
+ } // for
+ if ( isArray ) {
+ // we have imported the type. For arrays we want to return
+ // the array type
+ return Import_Utils::createUMLObject(Uml::ot_Class, className, current);
+ }
+ // now that we have the right package, the class should be findable
+ return findObject(baseClassName, current);
+ } // if file exists
+ } // if import matches
+ } //foreach import
+ return NULL; // no match
+}
+
+
+/// keep track of the current file being parsed and reset the list of imports
+void JavaImport::parseFile(const QString& filename) {
+ m_currentFileName= filename;
+ m_imports.clear();
+ // default visibility is Impl, unless we are an interface, then it is
+ // public for member vars and methods
+ m_defaultCurrentAccess = Uml::Visibility::Implementation;
+ m_currentAccess = m_defaultCurrentAccess;
+ s_parseDepth++;
+ // in the case of self referencing types, we can avoid parsing the
+ // file twice by adding it to the list
+ s_filesAlreadyParsed.append(filename);
+ NativeImportBase::parseFile(filename);
+ s_parseDepth--;
+ if ( s_parseDepth <= 0 ) {
+ // if the user decides to clear things out and reparse, we need
+ // to honor the request, so reset things for next time.
+ s_filesAlreadyParsed.clear();
+ s_parseDepth = 0;
+ }
+}
+
+
+
+
+bool JavaImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ const QString& keyword = m_source[m_srcIndex];
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "package") {
+ m_currentPackage = advance();
+ const QString& qualifiedName = m_currentPackage;
+ QStringList names = QStringList::split(".", qualifiedName);
+ for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
+ QString name = (*it);
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ }
+ if (advance() != ";") {
+ kError() << "importJava: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ }
+ return true;
+ }
+ if (keyword == "class" || keyword == "interface") {
+ const QString& name = advance();
+ const Uml::Object_Type t = (keyword == "class" ? Uml::ot_Class : Uml::ot_Interface);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setAbstract(m_isAbstract);
+ m_klass->setStatic(m_isStatic);
+ m_klass->setVisibility(m_currentAccess);
+ // The UMLObject found by createUMLObject might originally have been created as a
+ // placeholder with a type of class but if is really an interface, then we need to
+ // change it.
+ Uml::Object_Type ot = (keyword == "interface" ? Uml::ot_Interface : Uml::ot_Class);
+ m_klass->setBaseType(ot);
+ m_isAbstract = m_isStatic = false;
+ // if no modifier is specified in an interface, then it means public
+ if ( m_klass->isInterface() ) {
+ m_defaultCurrentAccess = Uml::Visibility::Public;
+ }
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == "<") {
+ // template args - preliminary, rudimentary implementation
+ // @todo implement all template arg syntax
+ uint start = m_srcIndex;
+ if (! skipToClosing('<')) {
+ kError() << "importJava(" << name << "): template syntax error" << endl;
+ return false;
+ }
+ while (1) {
+ const QString arg = m_source[++start];
+ if (! arg.contains( QRegExp("^[A-Za-z_]") )) {
+ kDebug() << "importJava(" << name << "): cannot handle template syntax ("
+ << arg << ")" << endl;
+ break;
+ }
+ /* UMLTemplate *tmpl = */ m_klass->addTemplate(arg);
+ const QString next = m_source[++start];
+ if (next == ">")
+ break;
+ if (next != ",") {
+ kDebug() << "importJava(" << name << "): can't handle template syntax ("
+ << next << ")" << endl;
+ break;
+ }
+ }
+ advance(); // skip over ">"
+ }
+ if (m_source[m_srcIndex] == "extends") {
+ const QString& baseName = advance();
+ // try to resolve the class we are extending, or if impossible
+ // create a placeholder
+ UMLObject *parent = resolveClass( baseName );
+ if ( parent ) {
+ Import_Utils::createGeneralization(m_klass, static_cast<UMLClassifier*>(parent));
+ } else {
+ kDebug() << "importJava parentClass " << baseName
+ << " is not resolveable. Creating placeholder" << endl;
+ Import_Utils::createGeneralization(m_klass, baseName);
+ }
+ advance();
+ }
+ if (m_source[m_srcIndex] == "implements") {
+ while (m_srcIndex < srcLength - 1 && advance() != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ // try to resolve the interface we are implementing, if this fails
+ // create a placeholder
+ UMLObject *interface = resolveClass( baseName );
+ if ( interface ) {
+ Import_Utils::createGeneralization(m_klass, static_cast<UMLClassifier*>(interface));
+ } else {
+ kDebug() << "importJava implementing interface "<< baseName
+ <<" is not resolvable. Creating placeholder" <<endl;
+ Import_Utils::createGeneralization(m_klass, baseName);
+ }
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importJava: ignoring excess chars at " << name
+ << " (" << m_source[m_srcIndex] << ")" << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "enum") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ skipStmt("{");
+ while (m_srcIndex < srcLength - 1 && advance() != "}") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ QString next = advance();
+ if (next == "{" || next == "(") {
+ if (! skipToClosing(next[0]))
+ return false;
+ next = advance();
+ }
+ if (next != ",") {
+ if (next == ";") {
+ // @todo handle methods in enum
+ // For now, we cheat (skip them)
+ m_source[m_srcIndex] = "{";
+ if (! skipToClosing('{'))
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+ if (keyword == "static") {
+ m_isStatic = true;
+ return true;
+ }
+ // if we detected static previously and keyword is { then this is a static block
+ if (m_isStatic && keyword == "{") {
+ // reset static flag and jump to end of static block
+ m_isStatic = false;
+ return skipToClosing('{');
+ }
+ if (keyword == "abstract") {
+ m_isAbstract = true;
+ return true;
+ }
+ if (keyword == "public") {
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "protected") {
+ m_currentAccess = Uml::Visibility::Protected;
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "final" ||
+ keyword == "native" ||
+ keyword == "synchronized" ||
+ keyword == "transient" ||
+ keyword == "volatile") {
+ //@todo anything to do here?
+ return true;
+ }
+ if (keyword == "import") {
+ // keep track of imports so we can resolve classes we are dependent on
+ QString import = advance();
+ if ( import.endsWith(".") ) {
+ //this most likely an import that ends with a *
+ //
+ import = import + advance();
+ }
+ m_imports.append( import );
+
+ // move past ;
+ skipStmt();
+ return true;
+ }
+ if (keyword == "@") { // annotation
+ advance();
+ if (m_source[m_srcIndex + 1] == "(") {
+ advance();
+ skipToClosing('(');
+ }
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importJava: too many }" << endl;
+ return true;
+ }
+ // At this point, we expect `keyword' to be a type name
+ // (of a member of class or interface, or return type
+ // of an operation.) Up next is the name of the attribute
+ // or operation.
+ if (! keyword.contains( QRegExp("^\\w") )) {
+ kError() << "importJava: ignoring " << keyword << endl;
+ return false;
+ }
+ QString typeName = m_source[m_srcIndex];
+ typeName = joinTypename(typeName);
+ // At this point we need a class.
+ if (m_klass == NULL) {
+ kError() << "importJava: no class set for " << typeName << endl;
+ return false;
+ }
+ QString name = advance();
+ QString nextToken;
+ if (typeName == m_klass->getName() && name == "(") {
+ // Constructor.
+ nextToken = name;
+ name = typeName;
+ typeName = QString();
+ } else {
+ nextToken = advance();
+ }
+ if (name.contains( QRegExp("\\W") )) {
+ kError() << "importJava: expecting name in " << name << endl;
+ return false;
+ }
+ if (nextToken == "(") {
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString typeName = m_source[m_srcIndex];
+ if ( typeName == "final" || typeName.startsWith( "//") ) {
+ // ignore the "final" keyword and any comments in method args
+ typeName = advance();
+ }
+ typeName = joinTypename(typeName);
+ QString parName = advance();
+ // the Class might not be resolved yet so resolve it if necessary
+ UMLObject *obj = resolveClass(typeName);
+ if (obj) {
+ // by prepending the package, unwanted placeholder types will not get created
+ typeName = obj->getFullyQualifiedName(".");
+ }
+ /* UMLAttribute *att = */ Import_Utils::addMethodParameter(op, typeName, parName);
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ // before adding the method, try resolving the return type
+ UMLObject *obj = resolveClass(typeName);
+ if (obj) {
+ // using the fully qualified name means that a placeholder type will not be created.
+ typeName = obj->getFullyQualifiedName(".");
+ }
+ Import_Utils::insertMethod(m_klass, op, m_currentAccess, typeName,
+ m_isStatic, m_isAbstract, false /*isFriend*/,
+ false /*isConstructor*/, m_comment);
+ m_isAbstract = m_isStatic = false;
+ // reset the default visibility
+ m_currentAccess = m_defaultCurrentAccess;
+ // At this point we do not know whether the method has a body or not.
+ do {
+ nextToken = advance();
+ } while (nextToken != "{" && nextToken != ";");
+ if (nextToken == ";") {
+ // No body (interface or abstract)
+ return true;
+ } else {
+ return skipToClosing('{');
+ }
+ }
+ // At this point we know it's some kind of attribute declaration.
+ while (1) {
+ while (nextToken != "," && nextToken != ";") {
+ if (nextToken == "=") {
+ if ((nextToken = advance()) == "new") {
+ advance();
+ if ((nextToken = advance()) == "(") {
+ skipToClosing('(');
+ if ((nextToken = advance()) == "{") {
+ skipToClosing('{');
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ name += nextToken; // add possible array dimensions to `name'
+ }
+ nextToken = advance();
+ }
+ // try to resolve the class type, or create a placeholder if that fails
+ UMLObject *type = resolveClass( typeName );
+ UMLObject *o;
+ if (type) {
+ o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ static_cast<UMLClassifier*>(type), m_comment, m_isStatic);
+ } else {
+ o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment, m_isStatic);
+ }
+ // UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ if (nextToken != ",") {
+ // reset the modifiers
+ m_isStatic = m_isAbstract = false;
+ break;
+ }
+ name = advance();
+ nextToken = advance();
+ }
+ // reset visibility to default
+ m_currentAccess = m_defaultCurrentAccess;
+ if (m_source[m_srcIndex] != ";") {
+ kError() << "importJava: ignoring trailing items at " << name << endl;
+ skipStmt();
+ }
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/javaimport.h b/umbrello/umbrello/codeimport/javaimport.h
new file mode 100644
index 00000000..30fa2395
--- /dev/null
+++ b/umbrello/umbrello/codeimport/javaimport.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef JAVAIMPORT_H
+#define JAVAIMPORT_H
+
+#include "nativeimportbase.h"
+#include "../umlobject.h"
+
+/**
+ * Java code import
+ * @author Oliver Kellogg
+ * @author JP Fournier
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class JavaImport : public NativeImportBase {
+public:
+ JavaImport();
+ virtual ~JavaImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Keep track of the filename currently being parsed
+ */
+ void parseFile(const QString& filename);
+
+ /**
+ * Try to resolve the specified class the current class depends on
+ */
+ UMLObject* resolveClass (QString className);
+
+ /**
+ * spawn off an import of the specified file
+ */
+ void spawnImport(QString file);
+
+ /**
+ * figure out if the type is really an array or template of the given typeName
+ */
+ QString joinTypename(QString typeName);
+
+ /**
+ * true if the member var or method is declared static
+ */
+ bool m_isStatic;
+
+ /**
+ * The current filename being parsed
+ */
+ QString m_currentFileName;
+
+ /**
+ * the current package of the file being parsed
+ */
+ QString m_currentPackage;
+
+ /**
+ * the imports included in the current file
+ */
+ QStringList m_imports;
+
+ /**
+ * Keep track of the files we have already parsed so we don't
+ * reparse the same ones over and over again.
+ */
+ static QStringList s_filesAlreadyParsed;
+
+ /**
+ * Keep track of the parses so that the filesAlreadyParsed
+ * can be reset when we're done.
+ */
+ static int s_parseDepth;
+
+ /**
+ * The current visibility for when the visibility is absent
+ */
+ Uml::Visibility m_defaultCurrentAccess;
+
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
new file mode 100644
index 00000000..b8325478
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libkdevcppparser.la
+libkdevcppparser_la_SOURCES = ast.cpp driver.cpp errors.cpp lexer.cpp lookup.cpp parser.cpp tree_parser.cpp urlutil.cpp ast_utils.cpp cpptree2uml.cpp
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/README b/umbrello/umbrello/codeimport/kdevcppparser/README
new file mode 100644
index 00000000..3ed39eba
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/README
@@ -0,0 +1,56 @@
+This directory contains the C++ parser from Kdevelop-3.0.
+
+Following files are copies from the directory kdevelop/lib/cppparser:
+ ast.{h,cpp} driver.{h,cpp} errors.{h,cpp} keywords.lut.h lexer.{h,cpp}
+ lookup.{h,cpp} parser.{h,cpp} tree_parser.{h,cpp}
+
+Following files are copies from the directory kdevelop/languages/cpp:
+ ast_utils.{h,cpp}
+
+Following files are copies from the directory kdevelop/lib/util:
+ urlutil.{h,cpp}
+
+The source files cpptree2uml.{h,cpp} are based on kdevelop/languages/cpp/
+store_walker.{h,cpp}. The class CppTree2Uml inherits from class TreeParser
+and overrides certain methods from that class.
+
+CppTree2Uml visits the nodes of the abstract syntax tree constructed by the
+CppParser, and constructs UML objects on the way.
+
+The import_utils.h (in the parent directory) is the interface between the
+CppTree2Uml and Umbrello.
+import_utils implements the construction of the UML objects. CppTree2Uml calls
+the create/insert methods in the import_utils while traversing the syntax
+tree.
+
+The one and only method that Umbrello uses for accessing the C++ parser,
+and any other parser for that matter, is ClassImport::importFiles().
+The class CppImport (in the parent directory) implements that operation.
+Thus we have these classes:
+
+ +-------------------+
+ | <<interface>> |
+ | ClassImport |
+ +===================+
+Umbrello ------>| importFiles() = 0 |
+ +-------------------+
+ A
+ | <<realize>>
+ |
+ +-------------------+ +-------------------+
+ | CppImport | | CppTree2Uml |
+ +===================+ <<invoke>> +===================+
+ | importFiles() |-------------->| |
+ +-------------------+ | |
+ +-------------------+
+ |
+ +-------------------+ |
+ | <<utility>> | |
+ | Import_Utils | |
+ +===================+ |
+ | createUMLObject() | <<invoke>> |
+ | insertMethod() |<-----------------------+
+ | insertAttribute() |
+ +-------------------+
+ |
+Umbrello <--------------+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
new file mode 100644
index 00000000..6baca685
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
@@ -0,0 +1,1183 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "ast.h"
+#include <qstringlist.h>
+#include <kdebug.h>
+
+QString nodeTypeToString( int type )
+{
+ switch( type )
+ {
+ case NodeType_Generic:
+ return "Generic";
+ case NodeType_TemplateArgumentList:
+ return "TemplateArgumentList";
+ case NodeType_ClassOrNamespaceName:
+ return "ClassOrNamespaceName";
+ case NodeType_Name:
+ return "Name";
+ case NodeType_Declaration:
+ return "Declaration";
+ case NodeType_TypeSpecifier:
+ return "TypeSpecifier";
+ case NodeType_BaseSpecifier:
+ return "BaseSpecifier";
+ case NodeType_BaseClause:
+ return "BaseClause";
+ case NodeType_ClassSpecifier:
+ return "ClassSpecifier";
+ case NodeType_Enumerator:
+ return "Enumerator";
+ case NodeType_EnumSpecifier:
+ return "EnumSpecifier";
+ case NodeType_ElaboratedTypeSpecifier:
+ return "ElaboratedTypeSpecifier";
+ case NodeType_LinkageBody:
+ return "LinkageBody";
+ case NodeType_LinkageSpecification:
+ return "LinkageSpecification";
+ case NodeType_Namespace:
+ return "Namespace";
+ case NodeType_NamespaceAlias:
+ return "NamespaceAlias";
+ case NodeType_Using:
+ return "Using";
+ case NodeType_UsingDirective:
+ return "UsingDirective";
+ case NodeType_InitDeclaratorList:
+ return "InitDeclaratorList";
+ case NodeType_Typedef:
+ return "Typedef";
+ case NodeType_Declarator:
+ return "Declarator";
+ case NodeType_InitDeclarator:
+ return "InitDeclarator";
+ case NodeType_TemplateDeclaration:
+ return "TemplateDeclaration";
+ case NodeType_SimpleDeclaration:
+ return "SimpleDeclaration";
+ case NodeType_Statement:
+ return "Statement";
+ case NodeType_IfStatement:
+ return "IfStatement";
+ case NodeType_WhileStatement:
+ return "WhileStatement";
+ case NodeType_DoStatement:
+ return "DoStatement";
+ case NodeType_ForStatement:
+ return "ForStatement";
+ case NodeType_SwitchStatement:
+ return "SwitchStatement";
+ case NodeType_DeclarationStatement:
+ return "DeclarationStatement";
+ case NodeType_StatementList:
+ return "StatementList";
+ case NodeType_TranslationUnit:
+ return "TranslationUnit";
+ case NodeType_FunctionDefinition:
+ return "FunctionDefinition";
+ case NodeType_ExpressionStatement:
+ return "ExpressionStatement";
+ case NodeType_ParameterDeclaration:
+ return "ParameterDeclaration";
+ case NodeType_ParameterDeclarationList:
+ return "ParameterDeclarationList";
+ case NodeType_ParameterDeclarationClause:
+ return "ParameterDeclarationClause";
+ case NodeType_Group:
+ return "Group";
+ case NodeType_AccessDeclaration:
+ return "AccessDeclaration";
+ case NodeType_TypeParameter:
+ return "TypeParameter";
+ case NodeType_TemplateParameter:
+ return "TemplateParameter";
+ case NodeType_TemplateParameterList:
+ return "TemplateParameterList";
+ case NodeType_Condition:
+ return "Condition";
+ case NodeType_Custom:
+ return "Custom";
+ }
+
+ return QString::null;
+}
+
+
+// ------------------------------------------------------------------------
+AST::AST()
+ : m_nodeType( NodeType_Generic ), m_parent( 0 ),
+ m_startLine( 0 ), m_startColumn( 0 ),
+ m_endLine( 0 ), m_endColumn( 0 )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ m_children.setAutoDelete( false );
+#endif
+}
+
+AST::~AST()
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+}
+
+void AST::setStartPosition( int line, int col )
+{
+ m_startLine = line;
+ m_startColumn = col;
+}
+
+void AST::getStartPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_startLine;
+
+ if( col )
+ * col = m_startColumn;
+}
+
+void AST::setEndPosition( int line, int col )
+{
+ m_endLine = line;
+ m_endColumn = col;
+}
+
+void AST::getEndPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_endLine;
+
+ if( col )
+ * col = m_endColumn;
+}
+
+void AST::setParent( AST* parent )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+
+ m_parent = parent;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->appendChild( this );
+#endif
+}
+
+#ifndef CPPPARSER_NO_CHILDREN
+void AST::appendChild( AST* child )
+{
+ m_children.append( child );
+}
+
+void AST::removeChild( AST* child )
+{
+ m_children.remove( child );
+}
+#endif
+
+// ------------------------------------------------------------------------
+NameAST::NameAST()
+ : m_global( false )
+{
+ m_classOrNamespaceNameList.setAutoDelete( true );
+}
+
+void NameAST::setGlobal( bool b )
+{
+ m_global = b;
+}
+
+void NameAST::setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName )
+{
+ m_unqualifiedName = unqualifiedName;
+ if( m_unqualifiedName.get() ) m_unqualifiedName->setParent( this );
+}
+
+void NameAST::addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName )
+{
+ if( !classOrNamespaceName.get() )
+ return;
+
+ classOrNamespaceName->setParent( this );
+ m_classOrNamespaceNameList.append( classOrNamespaceName.release() );
+}
+
+QString NameAST::text() const
+{
+ if( !m_unqualifiedName.get() )
+ return QString::null;
+
+ QString str;
+
+ if( m_global )
+ str += "::";
+
+ QStringList l;
+ QPtrListIterator<ClassOrNamespaceNameAST> it( m_classOrNamespaceNameList );
+ while( it.current() ){
+ str += it.current()->text() + "::";
+ ++it;
+ }
+
+ if( m_unqualifiedName.get() )
+ str += m_unqualifiedName->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+DeclarationAST::DeclarationAST()
+{
+}
+
+// ------------------------------------------------------------------------
+LinkageBodyAST::LinkageBodyAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void LinkageBodyAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+LinkageSpecificationAST::LinkageSpecificationAST()
+{
+}
+
+void LinkageSpecificationAST::setExternType( AST::Node& externType )
+{
+ m_externType = externType;
+ if( m_externType.get() ) m_externType->setParent( this );
+}
+
+void LinkageSpecificationAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+void LinkageSpecificationAST::setDeclaration( DeclarationAST::Node& decl )
+{
+ m_declaration = decl;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TranslationUnitAST::TranslationUnitAST()
+{
+ //kdDebug(9007) << "++ TranslationUnitAST::TranslationUnitAST()" << endl;
+ m_declarationList.setAutoDelete( true );
+}
+
+void TranslationUnitAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+NamespaceAST::NamespaceAST()
+{
+}
+
+void NamespaceAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+NamespaceAliasAST::NamespaceAliasAST()
+{
+}
+
+void NamespaceAliasAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAliasAST::setAliasName( NameAST::Node& name )
+{
+ m_aliasName = name;
+ if( m_aliasName.get() ) m_aliasName->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingAST::UsingAST()
+{
+}
+
+void UsingAST::setTypeName( AST::Node& typeName )
+{
+ m_typeName = typeName;
+ if( m_typeName.get() ) m_typeName->setParent( this );
+}
+
+void UsingAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingDirectiveAST::UsingDirectiveAST()
+{
+}
+
+void UsingDirectiveAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+TypedefAST::TypedefAST()
+{
+}
+
+void TypeSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypedefAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void TypedefAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TemplateArgumentListAST::TemplateArgumentListAST()
+{
+ m_argumentList.setAutoDelete( true );
+}
+
+void TemplateArgumentListAST::addArgument( AST::Node& arg )
+{
+ if( !arg.get() )
+ return;
+
+ arg->setParent( this );
+ m_argumentList.append( arg.release() );
+}
+
+QString TemplateArgumentListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_argumentList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+// ------------------------------------------------------------------------
+TemplateDeclarationAST::TemplateDeclarationAST()
+{
+}
+
+void TemplateDeclarationAST::setExported( AST::Node& exported )
+{
+ m_exported = exported;
+ if( m_exported.get() ) m_exported->setParent( this );
+}
+
+void TemplateDeclarationAST::setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TemplateDeclarationAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+ClassOrNamespaceNameAST::ClassOrNamespaceNameAST()
+{
+}
+
+void ClassOrNamespaceNameAST::setName( AST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void ClassOrNamespaceNameAST::setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList )
+{
+ m_templateArgumentList = templateArgumentList;
+ if( m_templateArgumentList.get() ) m_templateArgumentList->setParent( this );
+}
+
+QString ClassOrNamespaceNameAST::text() const
+{
+ if( !m_name.get() )
+ return QString::null;
+
+ QString str = m_name->text();
+ if( m_templateArgumentList.get() )
+ str += QString::fromLatin1("< ") + m_templateArgumentList->text() + QString::fromLatin1(" >");
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+TypeSpecifierAST::TypeSpecifierAST()
+{
+}
+
+void TypeSpecifierAST::setCvQualify( GroupAST::Node& cvQualify )
+{
+ m_cvQualify = cvQualify;
+ if( m_cvQualify.get() ) m_cvQualify->setParent( this );
+}
+
+void TypeSpecifierAST::setCv2Qualify( GroupAST::Node& cv2Qualify )
+{
+ m_cv2Qualify = cv2Qualify;
+ if( m_cv2Qualify.get() ) m_cv2Qualify->setParent( this );
+}
+
+QString TypeSpecifierAST::text() const
+{
+ QString str;
+
+ if( m_cvQualify.get() )
+ str += m_cvQualify->text() + ' ';
+
+ if( m_name.get() )
+ str += m_name->text();
+
+ if( m_cv2Qualify.get() )
+ str += QString(" ") + m_cv2Qualify->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+ClassSpecifierAST::ClassSpecifierAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void ClassSpecifierAST::setClassKey( AST::Node& classKey )
+{
+ m_classKey = classKey;
+ if( m_classKey.get() ) m_classKey->setParent( this );
+}
+
+void ClassSpecifierAST::addDeclaration( DeclarationAST::Node& declaration )
+{
+ if( !declaration.get() )
+ return;
+
+ declaration->setParent( this );
+ m_declarationList.append( declaration.release() );
+}
+
+void ClassSpecifierAST::setBaseClause( BaseClauseAST::Node& baseClause )
+{
+ m_baseClause = baseClause;
+ if( m_baseClause.get() ) m_baseClause->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+EnumSpecifierAST::EnumSpecifierAST()
+{
+ m_enumeratorList.setAutoDelete( true );
+}
+
+void EnumSpecifierAST::addEnumerator( EnumeratorAST::Node& enumerator )
+{
+ if( !enumerator.get() )
+ return;
+
+ enumerator->setParent( this );
+ m_enumeratorList.append( enumerator.release() );
+}
+
+
+// ------------------------------------------------------------------------
+ElaboratedTypeSpecifierAST::ElaboratedTypeSpecifierAST()
+{
+}
+
+void ElaboratedTypeSpecifierAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+QString ElaboratedTypeSpecifierAST::text() const
+{
+ if( m_kind.get() )
+ return m_kind->text() + ' ' + TypeSpecifierAST::text();
+
+ return TypeSpecifierAST::text();
+}
+
+// ------------------------------------------------------------------------
+StatementAST::StatementAST()
+{
+}
+
+// ------------------------------------------------------------------------
+EnumeratorAST::EnumeratorAST()
+{
+}
+
+void EnumeratorAST::setId( AST::Node& id )
+{
+ m_id = id;
+ if( m_id.get() ) m_id->setParent( this );
+}
+
+void EnumeratorAST::setExpr( AST::Node& expr )
+{
+ m_expr = expr;
+ if( m_expr.get() ) m_expr->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+BaseClauseAST::BaseClauseAST()
+{
+ m_baseSpecifierList.setAutoDelete( true );
+}
+
+void BaseClauseAST::addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier )
+{
+ if( !baseSpecifier.get() )
+ return;
+
+ baseSpecifier->setParent( this );
+ m_baseSpecifierList.append( baseSpecifier.release() );
+}
+
+// ------------------------------------------------------------------------
+BaseSpecifierAST::BaseSpecifierAST()
+{
+}
+
+void BaseSpecifierAST::setIsVirtual( AST::Node& isVirtual )
+{
+ m_isVirtual = isVirtual;
+ if( m_isVirtual.get() ) m_isVirtual->setParent( this );
+}
+
+void BaseSpecifierAST::setAccess( AST::Node& access )
+{
+ m_access = access;
+ if( m_access.get() ) m_access->setParent( this );
+}
+
+void BaseSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+SimpleDeclarationAST::SimpleDeclarationAST()
+{
+}
+
+void SimpleDeclarationAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void SimpleDeclarationAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+void SimpleDeclarationAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+InitDeclaratorListAST::InitDeclaratorListAST()
+{
+ m_initDeclaratorList.setAutoDelete( true );
+}
+
+void InitDeclaratorListAST::addInitDeclarator( InitDeclaratorAST::Node& decl )
+{
+ if( !decl.get() )
+ return;
+
+ decl->setParent( this );
+ m_initDeclaratorList.append( decl.release() );
+}
+
+// ------------------------------------------------------------------------
+DeclaratorAST::DeclaratorAST()
+{
+ m_ptrOpList.setAutoDelete( true );
+ m_arrayDimensionList.setAutoDelete( true );
+}
+
+void DeclaratorAST::setSubDeclarator( DeclaratorAST::Node& subDeclarator )
+{
+ m_subDeclarator = subDeclarator;
+ if( m_subDeclarator.get() ) m_subDeclarator->setParent( this );
+}
+
+void DeclaratorAST::setDeclaratorId( NameAST::Node& declaratorId )
+{
+ m_declaratorId = declaratorId;
+ if( m_declaratorId.get() ) m_declaratorId->setParent( this );
+}
+
+void DeclaratorAST::setBitfieldInitialization( AST::Node& bitfieldInitialization )
+{
+ m_bitfieldInitialization = bitfieldInitialization;
+ if( m_bitfieldInitialization.get() ) m_bitfieldInitialization->setParent( this );
+}
+
+void DeclaratorAST::addArrayDimension( AST::Node& arrayDimension )
+{
+ if( !arrayDimension.get() )
+ return;
+
+ arrayDimension->setParent( this );
+ m_arrayDimensionList.append( arrayDimension.release() );
+}
+
+void DeclaratorAST::setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause )
+{
+ m_parameterDeclarationClause = parameterDeclarationClause;
+ if( m_parameterDeclarationClause.get() ) m_parameterDeclarationClause->setParent( this );
+}
+
+void DeclaratorAST::setConstant( AST::Node& constant )
+{
+ m_constant = constant;
+ if( m_constant.get() ) m_constant->setParent( this );
+}
+
+void DeclaratorAST::setExceptionSpecification( GroupAST::Node& exceptionSpecification )
+{
+ m_exceptionSpecification = exceptionSpecification;
+ if( m_exceptionSpecification.get() ) m_exceptionSpecification->setParent( this );
+}
+
+void DeclaratorAST::addPtrOp( AST::Node& ptrOp )
+{
+ if( !ptrOp.get() )
+ return;
+
+ ptrOp->setParent( this );
+ m_ptrOpList.append( ptrOp.release() );
+}
+
+// --------------------------------------------------------------------------
+InitDeclaratorAST::InitDeclaratorAST()
+{
+}
+
+void InitDeclaratorAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void InitDeclaratorAST::setInitializer( AST::Node& initializer )
+{
+ m_initializer = initializer;
+ if( m_initializer.get() ) m_initializer->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+FunctionDefinitionAST::FunctionDefinitionAST()
+{
+}
+
+void FunctionDefinitionAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void FunctionDefinitionAST::setInitDeclarator( InitDeclaratorAST::Node& initDeclarator )
+{
+ m_initDeclarator = initDeclarator;
+ if( m_initDeclarator.get() ) m_initDeclarator->setParent( this );
+}
+
+void FunctionDefinitionAST::setFunctionBody( StatementListAST::Node& functionBody )
+{
+ m_functionBody = functionBody;
+ if( m_functionBody.get() ) m_functionBody->setParent( this );
+}
+
+void FunctionDefinitionAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+StatementListAST::StatementListAST()
+{
+ m_statementList.setAutoDelete( true );
+}
+
+void StatementListAST::addStatement( StatementAST::Node& statement )
+{
+ if( !statement.get() )
+ return;
+
+ statement->setParent( this );
+ m_statementList.append( statement.release() );
+}
+
+// --------------------------------------------------------------------------
+IfStatementAST::IfStatementAST()
+{
+}
+
+void IfStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void IfStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void IfStatementAST::setElseStatement( StatementAST::Node& elseStatement )
+{
+ m_elseStatement = elseStatement;
+ if( m_elseStatement.get() ) m_elseStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+WhileStatementAST::WhileStatementAST()
+{
+}
+
+void WhileStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void WhileStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DoStatementAST::DoStatementAST()
+{
+}
+
+void DoStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void DoStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ForStatementAST::ForStatementAST()
+{
+}
+
+void ForStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void ForStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ForStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void ForStatementAST::setInitStatement( StatementAST::Node& initStatement )
+{
+ m_initStatement = initStatement;
+ if( m_initStatement.get() ) m_initStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+SwitchStatementAST::SwitchStatementAST()
+{
+}
+
+void SwitchStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void SwitchStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DeclarationStatementAST::DeclarationStatementAST()
+{
+}
+
+void DeclarationStatementAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ExpressionStatementAST::ExpressionStatementAST()
+{
+}
+
+void ExpressionStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationAST::ParameterDeclarationAST()
+{
+}
+
+void ParameterDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ParameterDeclarationAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ParameterDeclarationAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+QString ParameterDeclarationAST::text() const
+{
+ QString str;
+ if( m_typeSpec.get() )
+ str += m_typeSpec->text() + ' ';
+
+ if( m_declarator.get() )
+ str += m_declarator->text();
+
+ if( m_expression.get() )
+ str += QString( " = " ) + m_expression->text();
+
+ return str;
+}
+
+// --------------------------------------------------------------------------
+ParameterDeclarationListAST::ParameterDeclarationListAST()
+{
+ m_parameterList.setAutoDelete( true );
+}
+
+void ParameterDeclarationListAST::addParameter( ParameterDeclarationAST::Node& parameter )
+{
+ if( !parameter.get() )
+ return;
+
+ parameter->setParent( this );
+ m_parameterList.append( parameter.release() );
+}
+
+QString ParameterDeclarationListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<ParameterDeclarationAST> it( m_parameterList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationClauseAST::ParameterDeclarationClauseAST()
+{
+}
+
+void ParameterDeclarationClauseAST::setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList )
+{
+ m_parameterDeclarationList = parameterDeclarationList;
+ if( m_parameterDeclarationList.get() ) m_parameterDeclarationList->setParent( this );
+}
+
+void ParameterDeclarationClauseAST::setEllipsis( AST::Node& ellipsis )
+{
+ m_ellipsis = ellipsis;
+ if( m_ellipsis.get() ) m_ellipsis->setParent( this );
+}
+
+QString ParameterDeclarationClauseAST::text() const
+{
+ QString str;
+
+ if( m_parameterDeclarationList.get() )
+ str += m_parameterDeclarationList->text();
+
+ if( m_ellipsis.get() )
+ str += " ...";
+
+ return str;
+}
+
+
+// --------------------------------------------------------------------------
+GroupAST::GroupAST()
+{
+ m_nodeList.setAutoDelete( true );
+}
+
+void GroupAST::addNode( AST::Node& node )
+{
+ if( !node.get() )
+ return;
+
+ node->setParent( this );
+ m_nodeList.append( node.release() );
+}
+
+QString GroupAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_nodeList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+AccessDeclarationAST::AccessDeclarationAST()
+{
+ m_accessList.setAutoDelete( true );
+}
+
+void AccessDeclarationAST::addAccess( AST::Node& access )
+{
+ if( !access.get() )
+ return;
+
+ access->setParent( this );
+ m_accessList.append( access.release() );
+}
+
+QString AccessDeclarationAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_accessList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+TypeParameterAST::TypeParameterAST()
+{
+}
+
+void TypeParameterAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+void TypeParameterAST::setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TypeParameterAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypeParameterAST::setTypeId( AST::Node& typeId )
+{
+ m_typeId = typeId;
+ if( m_typeId.get() ) m_typeId->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterAST::TemplateParameterAST()
+{
+}
+
+void TemplateParameterAST::setTypeParameter( TypeParameterAST::Node& typeParameter )
+{
+ m_typeParameter = typeParameter;
+ if( m_typeParameter.get() ) m_typeParameter->setParent( this );
+}
+
+void TemplateParameterAST::setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter )
+{
+ m_typeValueParameter = typeValueParameter;
+ if( m_typeValueParameter.get() ) m_typeValueParameter->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterListAST::TemplateParameterListAST()
+{
+ m_templateParameterList.setAutoDelete( true );
+}
+
+void TemplateParameterListAST::addTemplateParameter( TemplateParameterAST::Node& templateParameter )
+{
+ if( !templateParameter.get() )
+ return;
+
+ templateParameter->setParent( this );
+ m_templateParameterList.append( templateParameter.release() );
+}
+
+// --------------------------------------------------------------------------
+ConditionAST::ConditionAST()
+{
+}
+
+void ConditionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ConditionAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ConditionAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ClassSpecifierAST::setWinDeclSpec( GroupAST::Node & winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.h b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
new file mode 100644
index 00000000..9b7b5aac
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
@@ -0,0 +1,1449 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __ast_h
+#define __ast_h
+
+#include <memory>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#if defined( Q_OS_WIN32 ) || defined( Q_CC_SUN )
+
+#ifndef _THROW0
+# define _THROW0()
+#endif
+
+template <class _Tp> class AUTO_PTR {
+private:
+ _Tp* _M_ptr;
+
+public:
+ typedef _Tp element_type;
+
+ explicit AUTO_PTR(_Tp* __p = 0) _THROW0() : _M_ptr(__p) {}
+
+ template <class _Tp1> AUTO_PTR(AUTO_PTR<_Tp1>& __a) _THROW0()
+ : _M_ptr(__a.release()) {}
+
+ AUTO_PTR(AUTO_PTR& __a) _THROW0() : _M_ptr(__a.release()) {}
+
+
+
+ template <class _Tp1>
+ AUTO_PTR& operator=(AUTO_PTR<_Tp1>& __a) _THROW0() {
+ if (__a.get() != this->get()) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ AUTO_PTR& operator=(AUTO_PTR& __a) _THROW0() {
+ if (&__a != this) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ ~AUTO_PTR() _THROW0() { delete _M_ptr; }
+
+ _Tp& operator*() const _THROW0() {
+ return *_M_ptr;
+ }
+ _Tp* operator->() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* get() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* release() _THROW0() {
+ _Tp* __tmp = _M_ptr;
+ _M_ptr = 0;
+ return __tmp;
+ }
+ void reset(_Tp* __p = 0) _THROW0() {
+ delete _M_ptr;
+ _M_ptr = __p;
+ }
+
+ // According to the C++ standard, these conversions are required. Most
+ // present-day compilers, however, do not enforce that requirement---and,
+ // in fact, most present-day compilers do not support the language
+ // features that these conversions rely on.
+
+
+private:
+ template<class _Tp1> struct AUTO_PTR_ref {
+ _Tp1* _M_ptr;
+ AUTO_PTR_ref(_Tp1* __p) : _M_ptr(__p) {}
+ };
+
+public:
+ AUTO_PTR(AUTO_PTR_ref<_Tp> __ref) _THROW0()
+ : _M_ptr(__ref._M_ptr) {}
+ template <class _Tp1> operator AUTO_PTR_ref<_Tp1>() _THROW0()
+ { return AUTO_PTR_ref<_Tp>(this->release()); }
+ template <class _Tp1> operator AUTO_PTR<_Tp1>() _THROW0()
+ { return AUTO_PTR<_Tp1>(this->release()) }
+
+};
+
+#else
+#define AUTO_PTR std::auto_ptr
+#endif
+
+template <class T> typename T::Node CreateNode()
+{
+ typename T::Node node( new T );
+ node->setNodeType( T::Type );
+ return node;
+}
+
+template <class T> typename T::Node NullNode()
+{
+ typename T::Node node;
+ return node;
+}
+
+enum NodeType
+{
+ NodeType_Generic = 0,
+
+ NodeType_TemplateArgumentList = 1000,
+ NodeType_ClassOrNamespaceName,
+ NodeType_Name,
+ NodeType_Declaration,
+ NodeType_TypeSpecifier,
+ NodeType_BaseSpecifier,
+ NodeType_BaseClause,
+ NodeType_ClassSpecifier,
+ NodeType_Enumerator,
+ NodeType_EnumSpecifier,
+ NodeType_ElaboratedTypeSpecifier,
+ NodeType_LinkageBody,
+ NodeType_LinkageSpecification,
+ NodeType_Namespace,
+ NodeType_NamespaceAlias,
+ NodeType_Using,
+ NodeType_UsingDirective,
+ NodeType_InitDeclaratorList,
+ NodeType_Typedef,
+ NodeType_Declarator,
+ NodeType_InitDeclarator,
+ NodeType_TemplateDeclaration,
+ NodeType_SimpleDeclaration,
+ NodeType_Statement,
+ NodeType_StatementList,
+ NodeType_IfStatement,
+ NodeType_WhileStatement,
+ NodeType_DoStatement,
+ NodeType_ForStatement,
+ NodeType_SwitchStatement,
+ NodeType_DeclarationStatement,
+ NodeType_TranslationUnit,
+ NodeType_FunctionDefinition,
+ NodeType_ExpressionStatement,
+ NodeType_ParameterDeclaration,
+ NodeType_ParameterDeclarationList,
+ NodeType_ParameterDeclarationClause,
+ NodeType_Group,
+ NodeType_AccessDeclaration,
+ NodeType_TypeParameter,
+ NodeType_TemplateParameter,
+ NodeType_TemplateParameterList,
+ NodeType_Condition,
+
+ NodeType_Custom = 2000
+};
+
+QString nodeTypeToString( int type );
+
+
+#if defined(CPPPARSER_QUICK_ALLOCATOR)
+
+#include <quick_allocator.h>
+
+#define DECLARE_ALLOC(tp) \
+ void * operator new(std::size_t) \
+ { \
+ return quick_allocator< tp >::alloc(); \
+ } \
+ \
+ void operator delete(void * p) \
+ { \
+ quick_allocator< tp >::dealloc(p); \
+ }
+#else
+
+#define DECLARE_ALLOC(tp)
+
+#endif
+
+struct Slice
+{
+ QString source;
+ int position;
+ int length;
+
+ inline Slice()
+ : position(0), length(0) {}
+};
+
+class AST
+{
+public:
+ typedef AUTO_PTR<AST> Node;
+ enum { Type=NodeType_Generic };
+
+ DECLARE_ALLOC( AST )
+
+public:
+ AST();
+ virtual ~AST();
+
+ int nodeType() const { return m_nodeType; }
+ void setNodeType( int nodeType ) { m_nodeType = nodeType; }
+
+ AST* parent() { return m_parent; }
+ void setParent( AST* parent );
+
+ void setStartPosition( int line, int col );
+ void getStartPosition( int* line, int* col ) const;
+
+ void setEndPosition( int line, int col );
+ void getEndPosition( int* line, int* col ) const;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> children() { return m_children; }
+ void appendChild( AST* child );
+ void removeChild( AST* child );
+#endif
+
+ virtual inline QString text() const
+ { return m_slice.source.mid(m_slice.position, m_slice.length); }
+
+ QString comment() const
+ { return m_comment; }
+
+ inline void setSlice( const Slice& slice )
+ { m_slice = slice; }
+
+ inline void setSlice( const QString &text, int position, int length )
+ {
+ m_slice.source = text;
+ m_slice.position = position;
+ m_slice.length = length;
+ }
+
+ inline void setText(const QString &text)
+ { setSlice(text, 0, text.length()); }
+
+ void setComment( const QString &comment )
+ { m_comment = comment; }
+
+private:
+ int m_nodeType;
+ AST* m_parent;
+ int m_startLine, m_startColumn;
+ int m_endLine, m_endColumn;
+ Slice m_slice;
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> m_children;
+#endif
+ QString m_comment;
+
+private:
+ AST( const AST& source );
+ void operator = ( const AST& source );
+};
+
+class GroupAST: public AST
+{
+public:
+ typedef AUTO_PTR<GroupAST> Node;
+ enum { Type = NodeType_Group };
+
+ DECLARE_ALLOC( GroupAST )
+
+public:
+ GroupAST();
+
+ QPtrList<AST> nodeList() { return m_nodeList; }
+ void addNode( AST::Node& node );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_nodeList;
+
+private:
+ GroupAST( const GroupAST& source );
+ void operator = ( const GroupAST& source );
+};
+
+
+class TemplateArgumentListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateArgumentListAST> Node;
+ enum { Type = NodeType_TemplateArgumentList };
+
+ DECLARE_ALLOC( TemplateArgumentListAST )
+
+public:
+ TemplateArgumentListAST();
+
+ void addArgument( AST::Node& arg );
+ QPtrList<AST> argumentList() { return m_argumentList; }
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_argumentList;
+
+private:
+ TemplateArgumentListAST( const TemplateArgumentListAST& source );
+ void operator = ( const TemplateArgumentListAST& source );
+};
+
+class ClassOrNamespaceNameAST: public AST
+{
+public:
+ typedef AUTO_PTR<ClassOrNamespaceNameAST> Node;
+ enum { Type = NodeType_ClassOrNamespaceName };
+
+ DECLARE_ALLOC( ClassOrNamespaceNameAST )
+
+public:
+ ClassOrNamespaceNameAST();
+
+ AST* name() { return m_name.get(); }
+ void setName( AST::Node& name );
+
+ TemplateArgumentListAST* templateArgumentList() { return m_templateArgumentList.get(); }
+ void setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_name;
+ TemplateArgumentListAST::Node m_templateArgumentList;
+
+private:
+ ClassOrNamespaceNameAST( const ClassOrNamespaceNameAST& source );
+ void operator = ( const ClassOrNamespaceNameAST& source );
+};
+
+class NameAST: public AST
+{
+public:
+ typedef AUTO_PTR<NameAST> Node;
+ enum { Type = NodeType_Name };
+
+ DECLARE_ALLOC( NameAST )
+
+public:
+ NameAST();
+
+ bool isGlobal() const { return m_global; }
+ void setGlobal( bool b );
+
+ void addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName );
+ QPtrList<ClassOrNamespaceNameAST> classOrNamespaceNameList() { return m_classOrNamespaceNameList; }
+
+ ClassOrNamespaceNameAST* unqualifiedName() { return m_unqualifiedName.get(); }
+ void setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName );
+
+ virtual QString text() const;
+
+private:
+ bool m_global;
+ ClassOrNamespaceNameAST::Node m_unqualifiedName;
+ QPtrList<ClassOrNamespaceNameAST> m_classOrNamespaceNameList;
+
+private:
+ NameAST( const NameAST& source );
+ void operator = ( const NameAST& source );
+};
+
+class TypeParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeParameterAST> Node;
+ enum { Type = NodeType_TypeParameter };
+
+ DECLARE_ALLOC( TypeParameterAST )
+
+public:
+ TypeParameterAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ class TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+ AST* typeId() { return m_typeId.get(); }
+ void setTypeId( AST::Node& typeId );
+
+private:
+ AST::Node m_kind;
+ AUTO_PTR<class TemplateParameterListAST> m_templateParameterList;
+ NameAST::Node m_name;
+ AST::Node m_typeId;
+
+private:
+ TypeParameterAST( const TypeParameterAST& source );
+ void operator = ( const TypeParameterAST& source );
+};
+
+class DeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclarationAST> Node;
+ enum { Type = NodeType_Declaration };
+
+ DECLARE_ALLOC( DeclarationAST )
+
+public:
+ DeclarationAST();
+
+private:
+ DeclarationAST( const DeclarationAST& source );
+ void operator = ( const DeclarationAST& source );
+};
+
+class AccessDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<AccessDeclarationAST> Node;
+ enum { Type = NodeType_AccessDeclaration };
+
+ DECLARE_ALLOC( AccessDeclarationAST )
+
+public:
+ AccessDeclarationAST();
+
+ QPtrList<AST> accessList() { return m_accessList; }
+ void addAccess( AST::Node& access );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_accessList;
+
+private:
+ AccessDeclarationAST( const AccessDeclarationAST& source );
+ void operator = ( const AccessDeclarationAST& source );
+};
+
+class TypeSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeSpecifierAST> Node;
+ enum { Type = NodeType_TypeSpecifier };
+
+ DECLARE_ALLOC( TypeSpecifierAST )
+
+public:
+ TypeSpecifierAST();
+
+ virtual NameAST* name() { return m_name.get(); }
+ virtual void setName( NameAST::Node& name );
+
+ GroupAST* cvQualify() { return m_cvQualify.get(); }
+ void setCvQualify( GroupAST::Node& cvQualify );
+
+ GroupAST* cv2Qualify() { return m_cv2Qualify.get(); }
+ void setCv2Qualify( GroupAST::Node& cv2Qualify );
+
+ virtual QString text() const;
+
+private:
+ NameAST::Node m_name;
+ GroupAST::Node m_cvQualify;
+ GroupAST::Node m_cv2Qualify;
+
+private:
+ TypeSpecifierAST( const TypeSpecifierAST& source );
+ void operator = ( const TypeSpecifierAST& source );
+};
+
+class BaseSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseSpecifierAST> Node;
+ enum { Type = NodeType_BaseSpecifier };
+
+ DECLARE_ALLOC( BaseSpecifierAST )
+
+public:
+ BaseSpecifierAST();
+
+ AST* isVirtual() { return m_isVirtual.get(); }
+ void setIsVirtual( AST::Node& isVirtual );
+
+ AST* access() { return m_access.get(); }
+ void setAccess( AST::Node& access );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_isVirtual;
+ AST::Node m_access;
+ NameAST::Node m_name;
+
+private:
+ BaseSpecifierAST( const BaseSpecifierAST& source );
+ void operator = ( const BaseSpecifierAST& source );
+};
+
+class BaseClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseClauseAST> Node;
+ enum { Type = NodeType_BaseClause };
+
+ DECLARE_ALLOC( BaseClauseAST )
+
+public:
+ BaseClauseAST();
+
+ void addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier );
+ QPtrList<BaseSpecifierAST> baseSpecifierList() { return m_baseSpecifierList; }
+
+private:
+ QPtrList<BaseSpecifierAST> m_baseSpecifierList;
+
+private:
+ BaseClauseAST( const BaseClauseAST& source );
+ void operator = ( const BaseClauseAST& source );
+};
+
+class ClassSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ClassSpecifierAST> Node;
+ enum { Type = NodeType_ClassSpecifier };
+
+ DECLARE_ALLOC( ClassSpecifierAST )
+
+public:
+ ClassSpecifierAST();
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+ AST* classKey() { return m_classKey.get(); }
+ void setClassKey( AST::Node& classKey );
+
+ BaseClauseAST* baseClause() { return m_baseClause.get(); }
+ void setBaseClause( BaseClauseAST::Node& baseClause );
+
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+ void addDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ GroupAST::Node m_winDeclSpec;
+ AST::Node m_classKey;
+ BaseClauseAST::Node m_baseClause;
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ ClassSpecifierAST( const ClassSpecifierAST& source );
+ void operator = ( const ClassSpecifierAST& source );
+};
+
+class EnumeratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<EnumeratorAST> Node;
+ enum { Type = NodeType_Enumerator };
+
+ DECLARE_ALLOC( EnumeratorAST )
+
+public:
+ EnumeratorAST();
+
+ AST* id() { return m_id.get(); }
+ void setId( AST::Node& id );
+
+ AST* expr() { return m_expr.get(); }
+ void setExpr( AST::Node& expr );
+
+private:
+ AST::Node m_id;
+ AST::Node m_expr;
+
+private:
+ EnumeratorAST( const EnumeratorAST& source );
+ void operator = ( const EnumeratorAST& source );
+};
+
+class EnumSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<EnumSpecifierAST> Node;
+ enum { Type = NodeType_EnumSpecifier };
+
+ DECLARE_ALLOC( EnumSpecifierAST )
+
+public:
+ EnumSpecifierAST();
+
+ void addEnumerator( EnumeratorAST::Node& enumerator );
+ QPtrList<EnumeratorAST> enumeratorList() { return m_enumeratorList; }
+
+private:
+ QPtrList<EnumeratorAST> m_enumeratorList;
+
+private:
+ EnumSpecifierAST( const EnumSpecifierAST& source );
+ void operator = ( const EnumSpecifierAST& source );
+};
+
+class ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ElaboratedTypeSpecifierAST> Node;
+ enum { Type = NodeType_ElaboratedTypeSpecifier };
+
+ DECLARE_ALLOC( ElaboratedTypeSpecifierAST )
+
+public:
+ ElaboratedTypeSpecifierAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_kind;
+
+private:
+ ElaboratedTypeSpecifierAST( const ElaboratedTypeSpecifierAST& source );
+ void operator = ( const ElaboratedTypeSpecifierAST& source );
+};
+
+
+class LinkageBodyAST: public AST
+{
+public:
+ typedef AUTO_PTR<LinkageBodyAST> Node;
+ enum { Type = NodeType_LinkageBody };
+
+ DECLARE_ALLOC( LinkageBodyAST )
+
+public:
+ LinkageBodyAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ LinkageBodyAST( const LinkageBodyAST& source );
+ void operator = ( const LinkageBodyAST& source );
+};
+
+class LinkageSpecificationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<LinkageSpecificationAST> Node;
+ enum { Type = NodeType_LinkageSpecification };
+
+ DECLARE_ALLOC( LinkageSpecificationAST )
+
+public:
+ LinkageSpecificationAST();
+
+ AST* externType() { return m_externType.get(); }
+ void setExternType( AST::Node& externType );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& decl );
+
+private:
+ AST::Node m_externType;
+ LinkageBodyAST::Node m_linkageBody;
+ DeclarationAST::Node m_declaration;
+
+private:
+ LinkageSpecificationAST( const LinkageSpecificationAST& source );
+ void operator = ( const LinkageSpecificationAST& source );
+};
+
+class NamespaceAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAST> Node;
+ enum { Type = NodeType_Namespace };
+
+ DECLARE_ALLOC( NamespaceAST )
+
+public:
+ NamespaceAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& namespaceName );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+private:
+ AST::Node m_namespaceName;
+ LinkageBodyAST::Node m_linkageBody;
+
+private:
+ NamespaceAST( const NamespaceAST& source );
+ void operator = ( const NamespaceAST& source );
+};
+
+class NamespaceAliasAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAliasAST> Node;
+ enum { Type = NodeType_NamespaceAlias };
+
+ DECLARE_ALLOC( NamespaceAliasAST )
+
+public:
+ NamespaceAliasAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& name );
+
+ NameAST* aliasName() { return m_aliasName.get(); }
+ void setAliasName( NameAST::Node& name );
+
+private:
+ AST::Node m_namespaceName;
+ NameAST::Node m_aliasName;
+
+private:
+ NamespaceAliasAST( const NamespaceAliasAST& source );
+ void operator = ( const NamespaceAliasAST& source );
+};
+
+class UsingAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingAST> Node;
+ enum { Type = NodeType_Using };
+
+ DECLARE_ALLOC( UsingAST )
+
+public:
+ UsingAST();
+
+ AST* typeName() { return m_typeName.get(); }
+ void setTypeName( AST::Node& typeName );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_typeName;
+ NameAST::Node m_name;
+
+private:
+ UsingAST( const UsingAST& source );
+ void operator = ( const UsingAST& source );
+};
+
+class UsingDirectiveAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingDirectiveAST> Node;
+ enum { Type = NodeType_UsingDirective };
+
+ DECLARE_ALLOC( UsingDirectiveAST )
+
+public:
+ UsingDirectiveAST();
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ NameAST::Node m_name;
+
+private:
+ UsingDirectiveAST( const UsingDirectiveAST& source );
+ void operator = ( const UsingDirectiveAST& source );
+};
+
+class DeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclaratorAST> Node;
+ enum { Type = NodeType_Declarator };
+
+ DECLARE_ALLOC( DeclaratorAST )
+
+public:
+ DeclaratorAST();
+
+ QPtrList<AST> ptrOpList() { return m_ptrOpList; }
+ void addPtrOp( AST::Node& ptrOp );
+
+ DeclaratorAST* subDeclarator() { return m_subDeclarator.get(); }
+ void setSubDeclarator( Node& subDeclarator );
+
+ NameAST* declaratorId() { return m_declaratorId.get(); }
+ void setDeclaratorId( NameAST::Node& declaratorId );
+
+ AST* bitfieldInitialization() { return m_bitfieldInitialization.get(); }
+ void setBitfieldInitialization( AST::Node& bitfieldInitialization );
+
+ QPtrList<AST> arrayDimensionList() { return m_arrayDimensionList; }
+ void addArrayDimension( AST::Node& arrayDimension );
+
+ class ParameterDeclarationClauseAST* parameterDeclarationClause() { return m_parameterDeclarationClause.get(); }
+ void setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause );
+
+ // ### replace 'constant' with cvQualify
+ AST* constant() { return m_constant.get(); }
+ void setConstant( AST::Node& constant );
+
+ GroupAST* exceptionSpecification() { return m_exceptionSpecification.get(); }
+ void setExceptionSpecification( GroupAST::Node& exceptionSpecification );
+
+private:
+ QPtrList<AST> m_ptrOpList;
+ Node m_subDeclarator;
+ NameAST::Node m_declaratorId;
+ AST::Node m_bitfieldInitialization;
+ QPtrList<AST> m_arrayDimensionList;
+ AUTO_PTR<class ParameterDeclarationClauseAST> m_parameterDeclarationClause;
+ AST::Node m_constant;
+ GroupAST::Node m_exceptionSpecification;
+
+private:
+ DeclaratorAST( const DeclaratorAST& source );
+ void operator = ( const DeclaratorAST& source );
+};
+
+class ParameterDeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationAST> Node;
+ enum { Type = NodeType_ParameterDeclaration };
+
+ DECLARE_ALLOC( ParameterDeclarationAST )
+
+public:
+ ParameterDeclarationAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ virtual QString text() const;
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ParameterDeclarationAST( const ParameterDeclarationAST& source );
+ void operator = ( const ParameterDeclarationAST& source );
+};
+
+class ParameterDeclarationListAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationListAST> Node;
+ enum { Type = NodeType_ParameterDeclarationList };
+
+ DECLARE_ALLOC( ParameterDeclarationListAST )
+
+public:
+ ParameterDeclarationListAST();
+
+ QPtrList<ParameterDeclarationAST> parameterList() { return m_parameterList; }
+ void addParameter( ParameterDeclarationAST::Node& parameter );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<ParameterDeclarationAST> m_parameterList;
+
+private:
+ ParameterDeclarationListAST( const ParameterDeclarationListAST& source );
+ void operator = ( const ParameterDeclarationListAST& source );
+};
+
+class ParameterDeclarationClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationClauseAST> Node;
+ enum { Type = NodeType_ParameterDeclarationClause };
+
+ DECLARE_ALLOC( ParameterDeclarationClauseAST )
+
+public:
+ ParameterDeclarationClauseAST();
+
+ ParameterDeclarationListAST* parameterDeclarationList() { return m_parameterDeclarationList.get(); }
+ void setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList );
+
+ AST* ellipsis() { return m_ellipsis.get(); }
+ void setEllipsis( AST::Node& ellipsis );
+
+ virtual QString text() const;
+
+private:
+ ParameterDeclarationListAST::Node m_parameterDeclarationList;
+ AST::Node m_ellipsis;
+
+private:
+ ParameterDeclarationClauseAST( const ParameterDeclarationClauseAST& source );
+ void operator = ( const ParameterDeclarationClauseAST& source );
+};
+
+
+class InitDeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorAST> Node;
+ enum { Type = NodeType_InitDeclarator };
+
+ DECLARE_ALLOC( InitDeclaratorAST )
+
+public:
+ InitDeclaratorAST();
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* initializer() { return m_initializer.get(); }
+ void setInitializer( AST::Node& initializer );
+
+private:
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_initializer;
+
+private:
+ InitDeclaratorAST( const InitDeclaratorAST& source );
+ void operator = ( const InitDeclaratorAST& source );
+};
+
+class InitDeclaratorListAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorListAST> Node;
+ enum { Type = NodeType_InitDeclaratorList };
+
+ DECLARE_ALLOC( InitDeclaratorListAST )
+
+public:
+ InitDeclaratorListAST();
+
+ QPtrList<InitDeclaratorAST> initDeclaratorList() { return m_initDeclaratorList; }
+ void addInitDeclarator( InitDeclaratorAST::Node& decl );
+
+private:
+ QPtrList<InitDeclaratorAST> m_initDeclaratorList;
+
+private:
+ InitDeclaratorListAST( const InitDeclaratorListAST& source );
+ void operator = ( const InitDeclaratorListAST& source );
+};
+
+class TypedefAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TypedefAST> Node;
+ enum { Type = NodeType_Typedef };
+
+ DECLARE_ALLOC( TypedefAST )
+
+public:
+ TypedefAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+
+private:
+ TypedefAST( const TypedefAST& source );
+ void operator = ( const TypedefAST& source );
+};
+
+class TemplateParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterAST> Node;
+ enum { Type = NodeType_TemplateParameter };
+
+ DECLARE_ALLOC( TemplateParameterAST )
+
+public:
+ TemplateParameterAST();
+
+ TypeParameterAST* typeParameter() { return m_typeParameter.get(); }
+ void setTypeParameter( TypeParameterAST::Node& typeParameter );
+
+ ParameterDeclarationAST* typeValueParameter() { return m_typeValueParameter.get(); }
+ void setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter );
+
+private:
+ TypeParameterAST::Node m_typeParameter;
+ ParameterDeclarationAST::Node m_typeValueParameter;
+
+private:
+ TemplateParameterAST( const TemplateParameterAST& source );
+ void operator = ( const TemplateParameterAST& source );
+};
+
+class TemplateParameterListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterListAST> Node;
+ enum { Type = NodeType_TemplateParameterList };
+
+ DECLARE_ALLOC( TemplateParameterListAST )
+
+public:
+ TemplateParameterListAST();
+
+ QPtrList<TemplateParameterAST> templateParameterList() { return m_templateParameterList; }
+ void addTemplateParameter( TemplateParameterAST::Node& templateParameter );
+
+private:
+ QPtrList<TemplateParameterAST> m_templateParameterList;
+
+private:
+ TemplateParameterListAST( const TemplateParameterListAST& source );
+ void operator = ( const TemplateParameterListAST& source );
+};
+
+class TemplateDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TemplateDeclarationAST> Node;
+ enum { Type = NodeType_TemplateDeclaration };
+
+ DECLARE_ALLOC( TemplateDeclarationAST )
+
+public:
+ TemplateDeclarationAST();
+
+ AST* exported() { return m_exported.get(); }
+ void setExported( AST::Node& exported );
+
+ TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ AST::Node m_exported;
+ TemplateParameterListAST::Node m_templateParameterList;
+ DeclarationAST::Node m_declaration;
+
+private:
+ TemplateDeclarationAST( const TemplateDeclarationAST& source );
+ void operator = ( const TemplateDeclarationAST& source );
+};
+
+class SimpleDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<SimpleDeclarationAST> Node;
+ enum { Type = NodeType_SimpleDeclaration };
+
+ DECLARE_ALLOC( SimpleDeclarationAST )
+
+public:
+ SimpleDeclarationAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ SimpleDeclarationAST( const SimpleDeclarationAST& source );
+ void operator = ( const SimpleDeclarationAST& source );
+};
+
+class StatementAST: public AST
+{
+public:
+ typedef AUTO_PTR<StatementAST> Node;
+ enum { Type = NodeType_Statement };
+
+ DECLARE_ALLOC( StatementAST )
+
+public:
+ StatementAST();
+
+private:
+ StatementAST( const StatementAST& source );
+ void operator = ( const StatementAST& source );
+};
+
+class ExpressionStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ExpressionStatementAST> Node;
+ enum { Type = NodeType_ExpressionStatement };
+
+ DECLARE_ALLOC( ExpressionStatementAST )
+
+public:
+ ExpressionStatementAST();
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ AST::Node m_expression;
+
+private:
+ ExpressionStatementAST( const ExpressionStatementAST& source );
+ void operator = ( const ExpressionStatementAST& source );
+};
+
+class ConditionAST: public AST
+{
+public:
+ typedef AUTO_PTR<ConditionAST> Node;
+ enum { Type = NodeType_Condition };
+
+ DECLARE_ALLOC( ConditionAST )
+
+public:
+ ConditionAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ConditionAST( const ConditionAST& source );
+ void operator = ( const ConditionAST& source );
+};
+
+class IfStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<IfStatementAST> Node;
+ enum { Type = NodeType_IfStatement };
+
+ DECLARE_ALLOC( IfStatementAST )
+
+public:
+ IfStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+ StatementAST* elseStatement() { return m_elseStatement.get(); }
+ void setElseStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+ StatementAST::Node m_elseStatement;
+
+private:
+ IfStatementAST( const IfStatementAST& source );
+ void operator = ( const IfStatementAST& source );
+};
+
+class WhileStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<WhileStatementAST> Node;
+ enum { Type = NodeType_WhileStatement };
+
+ DECLARE_ALLOC( WhileStatementAST )
+
+public:
+ WhileStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ WhileStatementAST( const WhileStatementAST& source );
+ void operator = ( const WhileStatementAST& source );
+};
+
+class DoStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DoStatementAST> Node;
+ enum { Type = NodeType_DoStatement };
+
+ DECLARE_ALLOC( DoStatementAST )
+
+public:
+ DoStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ DoStatementAST( const DoStatementAST& source );
+ void operator = ( const DoStatementAST& source );
+};
+
+class ForStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ForStatementAST> Node;
+ enum { Type = NodeType_ForStatement };
+
+ DECLARE_ALLOC( ForStatementAST )
+
+public:
+ ForStatementAST();
+
+ StatementAST* initStatement() { return m_initStatement.get(); }
+ void setInitStatement( StatementAST::Node& statement );
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ AST* expression() const { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_initStatement;
+ StatementAST::Node m_statement;
+ AST::Node m_expression;
+
+private:
+ ForStatementAST( const ForStatementAST& source );
+ void operator = ( const ForStatementAST& source );
+};
+
+class SwitchStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<SwitchStatementAST> Node;
+ enum { Type = NodeType_SwitchStatement };
+
+ DECLARE_ALLOC( SwitchStatementAST )
+
+public:
+ SwitchStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ SwitchStatementAST( const SwitchStatementAST& source );
+ void operator = ( const SwitchStatementAST& source );
+};
+
+class StatementListAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<StatementListAST> Node;
+ enum { Type = NodeType_StatementList };
+
+ DECLARE_ALLOC( StatementListAST )
+
+public:
+ StatementListAST();
+
+ QPtrList<StatementAST> statementList() { return m_statementList; }
+ void addStatement( StatementAST::Node& statement );
+
+private:
+ QPtrList<StatementAST> m_statementList;
+
+private:
+ StatementListAST( const StatementListAST& source );
+ void operator = ( const StatementListAST& source );
+};
+
+class DeclarationStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DeclarationStatementAST> Node;
+ enum { Type = NodeType_DeclarationStatement };
+
+ DECLARE_ALLOC( DeclarationStatementAST )
+
+public:
+ DeclarationStatementAST();
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ DeclarationAST::Node m_declaration;
+
+private:
+ DeclarationStatementAST( const DeclarationStatementAST& source );
+ void operator = ( const DeclarationStatementAST& source );
+};
+
+class FunctionDefinitionAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<FunctionDefinitionAST> Node;
+ enum { Type = NodeType_FunctionDefinition };
+
+ DECLARE_ALLOC( FunctionDefinitionAST )
+
+public:
+ FunctionDefinitionAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorAST* initDeclarator() { return m_initDeclarator.get(); }
+ void setInitDeclarator( InitDeclaratorAST::Node& initDeclarator );
+
+ StatementListAST* functionBody() { return m_functionBody.get(); }
+ void setFunctionBody( StatementListAST::Node& functionBody );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorAST::Node m_initDeclarator;
+ StatementListAST::Node m_functionBody;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ FunctionDefinitionAST( const FunctionDefinitionAST& source );
+ void operator = ( const FunctionDefinitionAST& source );
+};
+
+
+class TranslationUnitAST: public AST
+{
+public:
+ typedef AUTO_PTR<TranslationUnitAST> Node;
+ enum { Type = NodeType_TranslationUnit };
+
+ DECLARE_ALLOC( TranslationUnitAST )
+
+public:
+ TranslationUnitAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ TranslationUnitAST( const TranslationUnitAST& source );
+ void operator = ( const TranslationUnitAST& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
new file mode 100644
index 00000000..e30f0c1e
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "ast_utils.h"
+#include "ast.h"
+
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+AST* findNodeAt( AST* node, int line, int column )
+{
+ // kdDebug(9007) << "findNodeAt(" << node << ")" << endl;
+
+ if( !node )
+ return 0;
+
+ int startLine, startColumn;
+ int endLine, endColumn;
+
+ node->getStartPosition( &startLine, &startColumn );
+ node->getEndPosition( &endLine, &endColumn );
+
+ if( (line > startLine || (line == startLine && column >= startColumn)) &&
+ (line < endLine || (line == endLine && column < endColumn)) ){
+
+ QPtrList<AST> children = node->children();
+ QPtrListIterator<AST> it( children );
+ while( it.current() ){
+ AST* a = it.current();
+ ++it;
+
+ AST* r = findNodeAt( a, line, column );
+ if( r )
+ return r;
+ }
+
+ return node;
+ }
+
+ return 0;
+}
+
+void scopeOfNode( AST* ast, QStringList& scope )
+{
+ if( !ast )
+ return;
+
+ if( ast->parent() )
+ scopeOfNode( ast->parent(), scope );
+
+ QString s;
+ switch( ast->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ if( ((ClassSpecifierAST*)ast)->name() ){
+ s = ((ClassSpecifierAST*)ast)->name()->text();
+ s = s.isEmpty() ? QString::fromLatin1("<unnamed>") : s;
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_Namespace:
+ {
+ AST* namespaceName = ((NamespaceAST*)ast)->namespaceName();
+ s = namespaceName ? namespaceName->text() : QString::fromLatin1("<unnamed>");
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_FunctionDefinition:
+ {
+ FunctionDefinitionAST* funDef = static_cast<FunctionDefinitionAST*>( ast );
+ DeclaratorAST* d = funDef->initDeclarator()->declarator();
+
+ // hotfix for bug #68726
+ if ( !d->declaratorId() )
+ break;
+
+ QPtrList<ClassOrNamespaceNameAST> l = d->declaratorId()->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> nameIt( l );
+ while( nameIt.current() ){
+ AST* name = nameIt.current()->name();
+ scope.push_back( name->text() );
+
+ ++nameIt;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+QString typeSpecToString( TypeSpecifierAST* typeSpec ) /// @todo remove
+{
+ if( !typeSpec )
+ return QString::null;
+
+ return typeSpec->text().replace( QRegExp(" :: "), "::" );
+}
+
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope, bool skipPtrOp )
+{
+ if( !declarator )
+ return QString::null;
+
+ QString text;
+
+ if( !skipPtrOp ){
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+ text += ' ';
+ }
+
+ text += scope;
+
+ if( declarator->subDeclarator() )
+ text += QString::fromLatin1("(") + declaratorToString(declarator->subDeclarator()) + QString::fromLatin1(")");
+
+ if( declarator->declaratorId() )
+ text += declarator->declaratorId()->text();
+
+ QPtrList<AST> arrays = declarator->arrayDimensionList();
+ QPtrListIterator<AST> it( arrays );
+ while( it.current() ){
+ text += "[]";
+ ++it;
+ }
+
+ if( declarator->parameterDeclarationClause() ){
+ text += "( ";
+
+ ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
+ if( l != 0 ){
+ QPtrList<ParameterDeclarationAST> params = l->parameterList();
+ QPtrListIterator<ParameterDeclarationAST> it( params );
+
+ while( it.current() ){
+ QString type = typeSpecToString( it.current()->typeSpec() );
+ text += type;
+ if( !type.isEmpty() )
+ text += ' ';
+ text += declaratorToString( it.current()->declarator() );
+
+ ++it;
+
+ if( it.current() )
+ text += ", ";
+ }
+ }
+
+ text += " )";
+
+ if( declarator->constant() != 0 )
+ text += " const";
+ }
+
+ return text.replace( QRegExp(" :: "), "::" ).simplifyWhiteSpace();
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
new file mode 100644
index 00000000..187647b7
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef __ast_utils_h
+#define __ast_utils_h
+
+#include <qstring.h>
+
+class AST;
+class DeclaratorAST;
+class TypeSpecifierAST;
+class QStringList;
+
+namespace KTextEditor{ class EditInterface; }
+
+AST* findNodeAt( AST* unit, int line, int column );
+void scopeOfNode( AST* ast, QStringList& );
+QString typeSpecToString( TypeSpecifierAST* typeSpec );
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope = QString::null, bool skipPtrOp=false );
+
+#endif // __ast_utils_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
new file mode 100644
index 00000000..e7d0b848
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
@@ -0,0 +1,640 @@
+/***************************************************************************
+ * Based on kdevelop-3.0 languages/cpp/store_walker.cpp by Roberto Raggi *
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cpptree2uml.h"
+// qt/kde includes
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "ast_utils.h"
+#include "urlutil.h"
+#include "../import_utils.h"
+// FIXME: The sole reason for the next 2 includes is parseTypedef().
+// Make capsule methods in ClassImport, and remove these includes.
+#include "../../classifier.h"
+// FIXME The next include is motivated by template params
+#include "../../template.h"
+
+CppTree2Uml::CppTree2Uml( const QString& fileName)
+ : m_anon( 0 ), m_nsCnt( 0 ), m_clsCnt( 0 )
+{
+ m_fileName = URLUtil::canonicalPath(fileName);
+}
+
+CppTree2Uml::~CppTree2Uml()
+{
+}
+
+void CppTree2Uml::parseTranslationUnit( TranslationUnitAST* ast )
+{
+ m_currentScope.clear();
+ m_currentNamespace[0] = NULL; // index 0 is reserved (always NULL)
+ m_currentClass[0] = NULL; // index 0 is reserved (always NULL)
+ m_nsCnt = 0;
+ m_clsCnt = 0;
+
+ m_currentAccess = Uml::Visibility::Public;
+ m_inSlots = false;
+ m_inSignals = false;
+ m_inStorageSpec = false;
+ m_inTypedef = false;
+ m_currentDeclarator = 0;
+ m_anon = 0;
+
+ TreeParser::parseTranslationUnit( ast );
+}
+
+void CppTree2Uml::parseNamespace( NamespaceAST* ast )
+{
+ if (m_clsCnt > 0) {
+ kDebug() << "CppTree2Uml::parseNamespace: error - cannot nest namespace inside class"
+ << endl;
+ return;
+ }
+
+ QString nsName;
+ if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+
+ nsName.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ nsName = ast->namespaceName()->text();
+ }
+
+#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseNamespace: " << nsName << endl;
+#endif
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Package, nsName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment());
+ UMLPackage *ns = (UMLPackage *)o;
+ m_currentScope.push_back( nsName );
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = ns;
+
+ TreeParser::parseNamespace( ast );
+
+ --m_nsCnt;
+ m_currentScope.pop_back();
+}
+
+void CppTree2Uml::parseTypedef( TypedefAST* ast )
+{
+#if 0
+ DeclaratorAST* oldDeclarator = m_currentDeclarator;
+
+ if( ast && ast->initDeclaratorList() && ast->initDeclaratorList()->initDeclaratorList().count() > 0 ) {
+ QPtrList<InitDeclaratorAST> lst( ast->initDeclaratorList()->initDeclaratorList() );
+ m_currentDeclarator = lst.at( 0 )->declarator();
+ }
+
+ m_inTypedef = true;
+
+ TreeParser::parseTypedef( ast );
+
+ m_inTypedef = false;
+ m_currentDeclarator = oldDeclarator;
+#else
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ if( typeSpec && declarators ){
+ QString typeId;
+
+ if( typeSpec->name() )
+ typeId = typeSpec->name()->text();
+
+ QPtrList<InitDeclaratorAST> l( declarators->initDeclaratorList() );
+ QPtrListIterator<InitDeclaratorAST> it( l );
+
+ InitDeclaratorAST* initDecl = 0;
+ while( 0 != (initDecl = it.current()) ){
+
+ QString type, id;
+ if( initDecl->declarator() ){
+ type = typeOfDeclaration( typeSpec, initDecl->declarator() );
+
+ DeclaratorAST* d = initDecl->declarator();
+ while( d->subDeclarator() ){
+ d = d->subDeclarator();
+ }
+
+ if( d->declaratorId() )
+ id = d->declaratorId()->text();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseTypedef: name=" << id << ", type=" << type << endl;
+//#endif
+ /* @todo Trace typedefs back to their root type for deciding
+ whether to build a Datatype (for pointers.) */
+ /* check out if the ID type is a Datatype
+ ex: typedef unsigned int uint;
+ where unsigned int is a known datatype
+ I'm not sure if setIsReference() should be run
+ */
+ bool isDatatype = Import_Utils::isDatatype(typeId, m_currentNamespace[m_nsCnt]);
+
+ if (type.contains('*') || isDatatype) {
+ UMLObject *inner =
+ Import_Utils::createUMLObject( Uml::ot_Class, typeId,
+ m_currentNamespace[m_nsCnt] );
+ UMLObject *typedefObj =
+ Import_Utils::createUMLObject( Uml::ot_Datatype, id,
+ m_currentNamespace[m_nsCnt] );
+ UMLClassifier *dt = static_cast<UMLClassifier*>(typedefObj);
+ dt->setIsReference();
+ dt->setOriginType(static_cast<UMLClassifier*>(inner));
+ } else {
+ Import_Utils::createUMLObject( Uml::ot_Class, id,
+ m_currentNamespace[m_nsCnt],
+ "" /* doc */,
+ "typedef" /* stereotype */);
+ }
+ ++it;
+ }
+
+ }
+#endif
+}
+
+void CppTree2Uml::parseTemplateDeclaration( TemplateDeclarationAST* ast )
+{
+ TemplateParameterListAST* parmListAST = ast->templateParameterList();
+ if (parmListAST == NULL)
+ return;
+ QPtrList<TemplateParameterAST> parmList = parmListAST->templateParameterList();
+ for (QPtrListIterator<TemplateParameterAST> it(parmList); it.current(); ++it) {
+ // The template is either a typeParameter or a typeValueParameter.
+
+ TemplateParameterAST* tmplParmNode = it.current();
+ TypeParameterAST* typeParmNode = tmplParmNode->typeParameter();
+ if (typeParmNode) {
+ NameAST* nameNode = typeParmNode->name();
+ if (nameNode) {
+ QString typeName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(typeName, NULL);
+ m_templateParams.append(nt);
+ } else {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(type):"
+ << " nameNode is NULL" << endl;
+ }
+ }
+
+ ParameterDeclarationAST* valueNode = tmplParmNode->typeValueParameter();
+ if (valueNode) {
+ TypeSpecifierAST* typeSpec = valueNode->typeSpec();
+ if (typeSpec == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " typeSpec is NULL" << endl;
+ continue;
+ }
+ QString typeName = typeSpec->name()->text();
+ UMLObject *t = Import_Utils::createUMLObject( Uml::ot_UMLObject, typeName,
+ m_currentNamespace[m_nsCnt] );
+ DeclaratorAST* declNode = valueNode->declarator();
+ NameAST* nameNode = declNode->declaratorId();
+ if (nameNode == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " nameNode is NULL" << endl;
+ continue;
+ }
+ QString paramName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(paramName, t);
+ m_templateParams.append(nt);
+ }
+ }
+
+ if( ast->declaration() )
+ TreeParser::parseDeclaration( ast->declaration() );
+}
+
+void CppTree2Uml::parseSimpleDeclaration( SimpleDeclarationAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ m_comment = ast->comment();
+
+ if( typeSpec )
+ parseTypeSpecifier( typeSpec );
+
+ if( declarators ){
+ QPtrList<InitDeclaratorAST> l = declarators->initDeclaratorList();
+
+ QPtrListIterator<InitDeclaratorAST> it( l );
+ while( it.current() ){
+ parseDeclaration( ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() );
+ ++it;
+ }
+ }
+}
+
+void CppTree2Uml::parseFunctionDefinition( FunctionDefinitionAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ GroupAST* funSpec = ast->functionSpecifier();
+ GroupAST* storageSpec = ast->storageSpecifier();
+
+ if( !ast->initDeclarator() )
+ return;
+
+ DeclaratorAST* d = ast->initDeclarator()->declarator();
+
+ if( !d->declaratorId() )
+ return;
+
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ QString id = d->declaratorId()->unqualifiedName()->text().stripWhiteSpace();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDefinition (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, false /*isAbstract*/, isFriend, isConstructor, m_comment);
+ m_comment = "";
+
+/* For reference, Kdevelop does some more:
+ method->setFileName( m_fileName );
+ if( m_inSignals )
+ method->setSignal( true );
+ if( m_inSlots )
+ method->setSlot( true );
+ */
+}
+
+void CppTree2Uml::parseClassSpecifier( ClassSpecifierAST* ast )
+{
+ Uml::Visibility oldAccess = m_currentAccess;
+ bool oldInSlots = m_inSlots;
+ bool oldInSignals = m_inSignals;
+
+ QString kind = ast->classKey()->text();
+ m_currentAccess=Uml::Visibility::fromString(kind);
+ m_inSlots = false;
+ m_inSignals = false;
+
+ QString className;
+ if( !ast->name() && m_currentDeclarator && m_currentDeclarator->declaratorId() ) {
+ className = m_currentDeclarator->declaratorId()->text().stripWhiteSpace();
+ } else if( !ast->name() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+ className.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ className = ast->name()->unqualifiedName()->text().stripWhiteSpace();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseClassSpecifier: name=" << className << endl;
+//#endif
+ if( !scopeOfName( ast->name(), QStringList() ).isEmpty() ){
+ kDebug() << "skip private class declarations" << endl;
+ return;
+ }
+
+ if (className.isEmpty()) {
+ className = "anon_" + QString::number(m_anon);
+ m_anon++;
+ }
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Class, className,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+ UMLClassifier *klass = static_cast<UMLClassifier*>(o);
+ flushTemplateParams(klass);
+ if ( ast->baseClause() )
+ parseBaseClause( ast->baseClause(), klass );
+
+ m_currentScope.push_back( className );
+ if (++m_clsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive class nesting" << endl;
+ m_clsCnt = STACKSIZE;
+ }
+ m_currentClass[m_clsCnt] = klass;
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = (UMLPackage*)klass;
+
+ TreeParser::parseClassSpecifier( ast );
+
+ --m_nsCnt;
+ --m_clsCnt;
+
+ m_currentScope.pop_back();
+
+ m_currentAccess = oldAccess;
+ m_inSlots = oldInSlots;
+ m_inSignals = oldInSignals;
+}
+
+void CppTree2Uml::parseEnumSpecifier( EnumSpecifierAST* ast )
+{
+ NameAST *nameNode = ast->name();
+ if (nameNode == NULL)
+ return; // skip constants
+ QString typeName = nameNode->unqualifiedName()->text().stripWhiteSpace();
+ if (typeName.isEmpty())
+ return; // skip constants
+ UMLObject *o = Import_Utils::createUMLObject( Uml::ot_Enum, typeName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+
+ QPtrList<EnumeratorAST> l = ast->enumeratorList();
+ QPtrListIterator<EnumeratorAST> it( l );
+ while ( it.current() ) {
+ QString enumLiteral = it.current()->id()->text();
+ Import_Utils::addEnumLiteral( (UMLEnum*)o, enumLiteral );
+ ++it;
+ }
+}
+
+void CppTree2Uml::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ // This is invoked for forward declarations.
+ /// @todo Refine - Currently only handles class forward declarations.
+ /// - Using typeSpec->text() is probably not good, decode
+ /// the kind() instead.
+ QString text = typeSpec->text();
+ kDebug() << "CppTree2Uml::parseElaboratedTypeSpecifier: text is " << text << endl;
+ text.remove(QRegExp("^class\\s+"));
+ UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Class, text, m_currentNamespace[m_nsCnt]);
+ flushTemplateParams( static_cast<UMLClassifier*>(o) );
+}
+
+void CppTree2Uml::parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl )
+{
+ if( m_inStorageSpec )
+ return;
+
+ DeclaratorAST* d = decl->declarator();
+
+ if( !d )
+ return;
+
+ if( !d->subDeclarator() && d->parameterDeclarationClause() )
+ return parseFunctionDeclaration( funSpec, storageSpec, typeSpec, decl );
+
+ DeclaratorAST* t = d;
+ while( t && t->subDeclarator() )
+ t = t->subDeclarator();
+
+ QString id;
+ if( t && t->declaratorId() && t->declaratorId()->unqualifiedName() )
+ id = t->declaratorId()->unqualifiedName()->text();
+
+ if( !scopeOfDeclarator(d, QStringList()).isEmpty() ){
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id << "): skipping."
+ << endl;
+ return;
+ }
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString typeName = typeOfDeclaration( typeSpec, d );
+ bool isFriend = false;
+ bool isStatic = false;
+ //bool isInitialized = decl->initializer() != 0;
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ Import_Utils::insertAttribute( c, m_currentAccess, id, typeName,
+ m_comment, isStatic);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseAccessDeclaration( AccessDeclarationAST * access )
+{
+ QPtrList<AST> l = access->accessList();
+
+ QString accessStr = l.at( 0 )->text();
+
+ m_currentAccess=Uml::Visibility::fromString(accessStr);
+
+ m_inSlots = l.count() > 1 ? l.at( 1 )->text() == "slots" : false;
+ m_inSignals = l.count() >= 1 ? l.at( 0 )->text() == "signals" : false;
+}
+
+void CppTree2Uml::parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl )
+{
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isPure = decl->initializer() != 0;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ DeclaratorAST* d = decl->declarator();
+ QString id = d->declaratorId()->unqualifiedName()->text();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, isPure, isFriend, isConstructor, m_comment);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseFunctionArguments(DeclaratorAST* declarator,
+ UMLOperation* method)
+{
+ ParameterDeclarationClauseAST* clause = declarator->parameterDeclarationClause();
+
+ if( clause && clause->parameterDeclarationList() ){
+ ParameterDeclarationListAST* params = clause->parameterDeclarationList();
+ QPtrList<ParameterDeclarationAST> l( params->parameterList() );
+ QPtrListIterator<ParameterDeclarationAST> it( l );
+ while( it.current() ){
+ ParameterDeclarationAST* param = it.current();
+ ++it;
+
+ QString name;
+ if (param->declarator())
+ name = declaratorToString(param->declarator(), QString::null, true );
+
+ QString tp = typeOfDeclaration( param->typeSpec(), param->declarator() );
+
+ if (tp != "void")
+ Import_Utils::addMethodParameter( method, tp, name );
+ }
+ }
+}
+
+QString CppTree2Uml::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator )
+{
+ if( !typeSpec || !declarator )
+ return QString::null;
+
+ QString text;
+
+ text += typeSpec->text();
+
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+
+ return text;
+}
+
+void CppTree2Uml::parseBaseClause( BaseClauseAST * baseClause, UMLClassifier* klass )
+{
+ QPtrList<BaseSpecifierAST> l = baseClause->baseSpecifierList();
+ QPtrListIterator<BaseSpecifierAST> it( l );
+ while( it.current() ){
+ BaseSpecifierAST* baseSpecifier = it.current();
+ ++it;
+
+ if (baseSpecifier->name() == NULL) {
+ kDebug() << "CppTree2Uml::parseBaseClause: baseSpecifier->name() is NULL"
+ << endl;
+ continue;
+ }
+
+ QString baseName = baseSpecifier->name()->text();
+ Import_Utils::createGeneralization( klass, baseName );
+ }
+}
+
+QStringList CppTree2Uml::scopeOfName( NameAST* id, const QStringList& startScope )
+{
+ QStringList scope = startScope;
+ if( id && id->classOrNamespaceNameList().count() ){
+ if( id->isGlobal() )
+ scope.clear();
+ QPtrList<ClassOrNamespaceNameAST> l = id->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> it( l );
+ while( it.current() ){
+ if( it.current()->name() ){
+ scope << it.current()->name()->text();
+ }
+ ++it;
+ }
+ }
+
+ return scope;
+}
+
+QStringList CppTree2Uml::scopeOfDeclarator( DeclaratorAST* d, const QStringList& startScope )
+{
+ return scopeOfName( d->declaratorId(), startScope );
+}
+
+void CppTree2Uml::flushTemplateParams(UMLClassifier *klass) {
+ if (m_templateParams.count()) {
+ Model_Utils::NameAndType_ListIt it;
+ for (it = m_templateParams.begin(); it != m_templateParams.end(); ++it) {
+ const Model_Utils::NameAndType &nt = *it;
+ kDebug() << "CppTree2Uml::parseClassSpecifier: adding template param: "
+ << nt.m_name << endl;
+ UMLTemplate *tmpl = klass->addTemplate(nt.m_name);
+ tmpl->setType(nt.m_type);
+ }
+ m_templateParams.clear();
+ }
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
new file mode 100644
index 00000000..b9791372
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CPPTREE2UML_H
+#define CPPTREE2UML_H
+
+#include "tree_parser.h"
+#include <qstringlist.h>
+#include "../../model_utils.h"
+
+// fwd decls
+class UMLClassifier;
+class UMLOperation;
+class UMLPackage;
+
+class CppTree2Uml: public TreeParser
+{
+public:
+ CppTree2Uml( const QString& fileName);
+ virtual ~CppTree2Uml();
+
+ //FileDom file() { return m_file; }
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ //virtual void parseDeclaration( DeclarationAST* ); // use parent method
+ //virtual void parseLinkageSpecification( LinkageSpecificationAST* ); // use parent method
+ virtual void parseNamespace( NamespaceAST* );
+ //virtual void parseNamespaceAlias( NamespaceAliasAST* ); // use parent method
+ //virtual void parseUsing( UsingAST* ); // use parent method
+ //virtual void parseUsingDirective( UsingDirectiveAST* ); // use parent method
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ //virtual void parseLinkageBody( LinkageBodyAST* ); // use parent method
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ //virtual void parseTypeSpecifier( TypeSpecifierAST* ); // use parent method
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+ // non-overriding (locally added) methods
+
+ virtual void parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ virtual void parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ void parseFunctionArguments( DeclaratorAST* declarator, UMLOperation* method);
+ virtual void parseBaseClause( BaseClauseAST* baseClause, UMLClassifier* klass );
+
+private:
+ //NamespaceDom findOrInsertNamespace( NamespaceAST* ast, const QString& name );
+
+ QString typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator );
+ QStringList scopeOfName( NameAST* id, const QStringList& scope );
+ QStringList scopeOfDeclarator( DeclaratorAST* d, const QStringList& scope );
+ /**
+ * Flush template parameters pending in m_templateParams to the klass.
+ */
+ void flushTemplateParams(UMLClassifier *klass);
+
+private:
+ //FileDom m_file;
+ QString m_fileName;
+ QStringList m_currentScope;
+ Uml::Visibility m_currentAccess;
+ bool m_inSlots;
+ bool m_inSignals;
+ int m_anon;
+ bool m_inStorageSpec;
+ bool m_inTypedef;
+ QString m_comment;
+ Model_Utils::NameAndType_List m_templateParams;
+
+ DeclaratorAST* m_currentDeclarator;
+# define STACKSIZE 30
+ UMLPackage* m_currentNamespace[STACKSIZE+1]; ///< stack
+ UMLClassifier* m_currentClass[STACKSIZE+1]; ///< stack
+ int m_nsCnt; ///< stack top for m_currentNamespace
+ int m_clsCnt; ///< stack top for m_currentClass
+
+private:
+ CppTree2Uml( const CppTree2Uml& source );
+ void operator = ( const CppTree2Uml& source );
+};
+
+#endif // CPPTREE2UML
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
new file mode 100644
index 00000000..84941025
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
@@ -0,0 +1,435 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "driver.h"
+#include "lexer.h"
+#include "parser.h"
+#include <kdebug.h>
+#include <stdlib.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+class DefaultSourceProvider: public SourceProvider
+{
+public:
+ DefaultSourceProvider() {}
+
+ virtual QString contents( const QString& fileName )
+ {
+ QString source;
+
+ QFile f( fileName );
+ if( f.open(IO_ReadOnly) ){
+ QTextStream s( &f );
+ source = s.read();
+ f.close();
+ }
+ return source;
+ }
+
+ virtual bool isModified( const QString& fileName )
+ {
+ Q_UNUSED( fileName );
+ return true;
+ }
+
+private:
+ DefaultSourceProvider( const DefaultSourceProvider& source );
+ void operator = ( const DefaultSourceProvider& source );
+};
+
+
+Driver::Driver()
+ : depresolv( false ), lexer( 0 )
+{
+ m_sourceProvider = new DefaultSourceProvider();
+}
+
+Driver::~Driver()
+{
+ reset();
+ delete( m_sourceProvider );
+}
+
+SourceProvider* Driver::sourceProvider()
+{
+ return m_sourceProvider;
+}
+
+void Driver::setSourceProvider( SourceProvider* sourceProvider )
+{
+ if( m_sourceProvider )
+ delete( m_sourceProvider );
+ m_sourceProvider = sourceProvider;
+}
+
+void Driver::reset( )
+{
+ m_dependences.clear();
+ m_macros.clear();
+ m_problems.clear();
+ m_includePaths.clear();
+
+ while( m_parsedUnits.size() ){
+ TranslationUnitAST* unit = *m_parsedUnits.begin();
+ m_parsedUnits.remove( m_parsedUnits.begin() );
+ delete( unit );
+ }
+}
+
+void Driver::remove( const QString & fileName )
+{
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+ removeAllMacrosInFile( fileName );
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ if( it != m_parsedUnits.end() ){
+ TranslationUnitAST* unit = *it;
+ m_parsedUnits.remove( it );
+ delete( unit );
+ }
+}
+
+void Driver::removeAllMacrosInFile( const QString& fileName )
+{
+ QMap<QString, Macro>::Iterator it = m_macros.begin();
+ while( it != m_macros.end() ){
+ Macro m = *it++;
+ if( m.fileName() == fileName )
+ removeMacro( m.name() );
+ }
+}
+
+TranslationUnitAST::Node Driver::takeTranslationUnit( const QString& fileName )
+{
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ TranslationUnitAST::Node unit( *it );
+ //m_parsedUnits.remove( it );
+ m_parsedUnits[ fileName] = 0;
+ return unit;
+}
+
+TranslationUnitAST* Driver::translationUnit( const QString& fileName ) const
+{
+ QMap<QString, TranslationUnitAST*>::ConstIterator it = m_parsedUnits.find( fileName );
+ return it != m_parsedUnits.end() ? *it : 0;
+}
+
+void Driver::addDependence( const QString & fileName, const Dependence & dep )
+{
+ QFileInfo fileInfo( dep.first );
+ QString fn = fileInfo.absFilePath();
+
+ if ( !depresolv ){
+ findOrInsertDependenceList( fileName ).insert( fn, dep );
+ return;
+ }
+
+ QString file = findIncludeFile( dep );
+ findOrInsertDependenceList( fileName ).insert( file, dep );
+
+ if ( m_parsedUnits.find(file) != m_parsedUnits.end() )
+ return;
+
+ if ( !QFile::exists( file ) ) {
+ Problem p( "Couldn't find include file " + dep.first,
+ lexer ? lexer->currentLine() : -1,
+ lexer ? lexer->currentColumn() : -1 );
+ addProblem( fileName, p );
+ return;
+ }
+
+ QString cfn = m_currentFileName;
+ Lexer *l = lexer;
+ parseFile( file );
+ m_currentFileName = cfn;
+ lexer = l;
+}
+
+void Driver::addMacro( const Macro & macro )
+{
+ m_macros.insert( macro.name(), macro );
+}
+
+void Driver::addProblem( const QString & fileName, const Problem & problem )
+{
+ findOrInsertProblemList( fileName ).append( problem );
+}
+
+QMap< QString, Dependence >& Driver::findOrInsertDependenceList( const QString & fileName )
+{
+ QMap<QString, QMap<QString, Dependence> >::Iterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+
+ QMap<QString, Dependence> l;
+ m_dependences.insert( fileName, l );
+ return m_dependences[ fileName ];
+}
+
+QValueList < Problem >& Driver::findOrInsertProblemList( const QString & fileName )
+{
+ QMap<QString, QValueList<Problem> >::Iterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+
+ QValueList<Problem> l;
+ m_problems.insert( fileName, l );
+ return m_problems[ fileName ];
+}
+
+QMap< QString, Dependence > Driver::dependences( const QString & fileName ) const
+{
+ QMap<QString, QMap<QString, Dependence> >::ConstIterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+ return QMap<QString, Dependence>();
+}
+
+QMap< QString, Macro > Driver::macros() const
+{
+ return m_macros;
+}
+
+QValueList < Problem > Driver::problems( const QString & fileName ) const
+{
+ QMap<QString, QValueList<Problem> >::ConstIterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+ return QValueList<Problem>();
+}
+
+void Driver::parseFile( const QString& fileName, bool onlyPreProcess, bool force )
+{
+ QFileInfo fileInfo( fileName );
+ QString absFilePath = fileInfo.absFilePath();
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( absFilePath );
+
+ if( force && it != m_parsedUnits.end() ){
+ takeTranslationUnit( absFilePath );
+ } else if( it != m_parsedUnits.end() && *it != 0 ){
+ // file already processed
+ return;
+ }
+
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+
+ m_currentFileName = fileName;
+
+ Lexer lex( this );
+ lexer = &lex;
+ setupLexer( &lex );
+
+ lex.setSource( sourceProvider()->contents(fileName) );
+
+ if( !onlyPreProcess ){
+ Parser parser( this, &lex );
+ setupParser( &parser );
+
+ TranslationUnitAST :: Node translationUnit;
+ parser.parseTranslationUnit( translationUnit );
+ m_parsedUnits.insert( fileName, translationUnit.release() );
+ fileParsed( fileName );
+ }
+
+ m_currentFileName = QString::null;
+ lexer = 0;
+}
+
+void Driver::setupLexer( Lexer * lexer )
+{
+ // stl
+ lexer->addSkipWord( "__STL_BEGIN_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_NAMESPACE" );
+ lexer->addSkipWord( "__STL_BEGIN_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_TEMPLATE_NULL" );
+ lexer->addSkipWord( "__STL_TRY" );
+ lexer->addSkipWord( "__STL_UNWIND" );
+ lexer->addSkipWord( "__STL_NOTHROW" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+ lexer->addSkipWord( "__STL_UNWIND", SkipWordAndArguments );
+ lexer->addSkipWord( "__GC_CONST" );
+ lexer->addSkipWord( "__HASH_ALLOC_INIT", SkipWordAndArguments );
+ lexer->addSkipWord( "__STL_DEFAULT_ALLOCATOR", SkipWordAndArguments, "T" );
+ lexer->addSkipWord( "__STL_MUTEX_INITIALIZER" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+
+ // antlr
+ lexer->addSkipWord( "ANTLR_BEGIN_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USE_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USING_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_END_NAMESPACE" );
+ lexer->addSkipWord( "ANTLR_C_USING", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_API" );
+
+ // gnu
+ lexer->addSkipWord( "__extension__", SkipWordAndArguments );
+ lexer->addSkipWord( "__attribute__", SkipWordAndArguments );
+ lexer->addSkipWord( "__BEGIN_DECLS" );
+ lexer->addSkipWord( "__END_DECLS" );
+ lexer->addSkipWord( "__THROW" );
+ lexer->addSkipWord( "__restrict" );
+ lexer->addSkipWord( "__restrict__" );
+ lexer->addSkipWord( "__attribute_pure__" );
+ lexer->addSkipWord( "__attribute_malloc__" );
+ lexer->addSkipWord( "__attribute_format_strfmon__" );
+ lexer->addSkipWord( "__asm__", SkipWordAndArguments );
+ lexer->addSkipWord( "__devinit" );
+ lexer->addSkipWord( "__devinit__" );
+ lexer->addSkipWord( "__init" );
+ lexer->addSkipWord( "__init__" );
+ lexer->addSkipWord( "__signed" );
+ lexer->addSkipWord( "__signed__" );
+ lexer->addSkipWord( "__unsigned" );
+ lexer->addSkipWord( "__unsigned__" );
+ lexer->addSkipWord( "asmlinkage" );
+ lexer->addSkipWord( "____cacheline_aligned" );
+ lexer->addSkipWord( "__glibcpp_class_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class2_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class4_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_function_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "restrict" );
+
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_STD" );
+ lexer->addSkipWord( "__END_NAMESPACE_STD" );
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_C99" );
+ lexer->addSkipWord( "__END_NAMESPACE_C99" );
+ lexer->addSkipWord( "__USING_NAMESPACE_STD", SkipWordAndArguments );
+
+ // kde
+ lexer->addSkipWord( "K_SYCOCATYPE", SkipWordAndArguments );
+ lexer->addSkipWord( "EXPORT_DOCKCLASS" );
+ lexer->addSkipWord( "K_EXPORT_COMPONENT_FACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "K_SYCOCAFACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "KDE_DEPRECATED" );
+
+ // qt
+ lexer->addSkipWord( "Q_OVERRIDE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_ENUMS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_PROPERTY", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CLASSINFO", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_SETS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_UNUSED", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CREATE_INSTANCE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_DUMMY_COMPARISON_OPERATOR", SkipWordAndArguments );
+ lexer->addSkipWord( "ACTIVATE_SIGNAL_WITH_PARAM", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_INLINE_TEMPLATES" );
+ lexer->addSkipWord( "Q_TEMPLATE_EXTERN" );
+ lexer->addSkipWord( "Q_TYPENAME" );
+ lexer->addSkipWord( "Q_REFCOUNT" );
+ lexer->addSkipWord( "Q_EXPLICIT" );
+ lexer->addSkipWord( "QMAC_PASCAL" );
+ lexer->addSkipWord( "QT_STATIC_CONST" );
+ lexer->addSkipWord( "QT_STATIC_CONST_IMPL" );
+ lexer->addSkipWord( "QT_WIN_PAINTER_MEMBERS" );
+ lexer->addSkipWord( "QT_NC_MSGBOX" );
+ lexer->addSkipWord( "Q_VARIANT_AS", SkipWordAndArguments );
+ lexer->addSkipWord( "CALLBACK_CALL_TYPE" );
+
+ // flex
+ lexer->addSkipWord( "yyconst" );
+ lexer->addSkipWord( "YY_RULE_SETUP" );
+ lexer->addSkipWord( "YY_BREAK" );
+ lexer->addSkipWord( "YY_RESTORE_YY_MORE_OFFSET" );
+
+ // gtk
+ lexer->addSkipWord( "G_BEGIN_DECLS" );
+ lexer->addSkipWord( "G_END_DECLS" );
+ lexer->addSkipWord( "G_GNUC_CONST" );
+ lexer->addSkipWord( "G_CONST_RETURN" );
+ lexer->addSkipWord( "GTKMAIN_C_VAR" );
+ lexer->addSkipWord( "GTKVAR" );
+ lexer->addSkipWord( "GDKVAR" );
+ lexer->addSkipWord( "G_GNUC_PRINTF", SkipWordAndArguments );
+
+ // windows
+ lexer->addSkipWord( "WINAPI" );
+ lexer->addSkipWord( "__stdcall" );
+ lexer->addSkipWord( "__cdecl" );
+ lexer->addSkipWord( "_cdecl" );
+ lexer->addSkipWord( "CALLBACK" );
+
+ // gcc extensions
+ addMacro( Macro("__asm__", "asm") );
+ addMacro( Macro("__inline", "inline") );
+ addMacro( Macro("__inline__", "inline") );
+ addMacro( Macro("__const", "const") );
+ addMacro( Macro("__const__", "const") );
+ addMacro( Macro("__volatile__", "volatile") );
+ addMacro( Macro("__complex__", "") );
+}
+
+void Driver::setupParser( Parser * parser )
+{
+ Q_UNUSED( parser );
+}
+
+void Driver::removeMacro( const QString& macroName )
+{
+ m_macros.remove( macroName );
+}
+
+void Driver::addIncludePath( const QString &path )
+{
+ if( !path.stripWhiteSpace().isEmpty() )
+ m_includePaths << path;
+}
+
+QString Driver::findIncludeFile( const Dependence& dep ) const
+{
+ QString fileName = dep.first;
+
+ if( dep.second == Dep_Local ){
+ QString path = QFileInfo( currentFileName() ).dirPath( true );
+ QFileInfo fileInfo( QFileInfo(path, fileName) );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+
+ }
+
+ QStringList::ConstIterator end(m_includePaths.end());
+ for ( QStringList::ConstIterator it(m_includePaths.begin()); it != end; ++it ) {
+ QFileInfo fileInfo( *it, fileName );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+ }
+
+ return QString::null;
+}
+
+void Driver::setResolveDependencesEnabled( bool enabled )
+{
+ depresolv = enabled;
+ if ( depresolv )
+ setupPreProcessor();
+}
+
+void Driver::setupPreProcessor()
+{
+}
+
+void Driver::fileParsed( const QString & fileName )
+{
+ Q_UNUSED( fileName );
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.h b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
new file mode 100644
index 00000000..ecb603ab
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
@@ -0,0 +1,230 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include "ast.h"
+
+#include <qpair.h>
+#include <qvaluestack.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+class Lexer;
+class Parser;
+
+class Problem
+{
+public:
+ enum
+ {
+ Level_Error = 0,
+ Level_Warning,
+ Level_Todo,
+ Level_Fixme
+ };
+
+public:
+ Problem() {}
+ Problem( const Problem& source )
+ : m_text( source.m_text ), m_line( source.m_line ),
+ m_column( source.m_column ), m_level( source.m_level ) {}
+ Problem( const QString& text, int line, int column, int level=Level_Error )
+ : m_text( text ), m_line( line ), m_column( column ), m_level(level) {}
+
+ Problem& operator = ( const Problem& source )
+ {
+ m_text = source.m_text;
+ m_line = source.m_line;
+ m_column = source.m_column;
+ m_level = source.m_level;
+ return( *this );
+ }
+
+ bool operator == ( const Problem& p ) const
+ {
+ return m_text == p.m_text && m_line == p.m_line && m_column == p.m_column && m_level == p.m_level;
+ }
+
+ QString text() const { return m_text; }
+ int line() const { return m_line; }
+ int column() const { return m_column; }
+ int level() const { return m_level; }
+
+private:
+ QString m_text;
+ int m_line;
+ int m_column;
+ int m_level;
+};
+
+enum
+{
+ Dep_Global,
+ Dep_Local
+};
+
+typedef QPair<QString, int> Dependence;
+
+class Macro
+{
+public:
+ typedef QString Argument;
+
+public:
+ Macro( bool hasArguments = false ): m_hasArguments( hasArguments ) {}
+ Macro( const QString &n, const QString &b ) : m_name( n ), m_body( b ), m_hasArguments( false ) {}
+
+ Macro( const Macro& source )
+ : m_name( source.m_name),
+ m_fileName( source.m_fileName ),
+ m_body( source.m_body ),
+ m_hasArguments( source.m_hasArguments ),
+ m_argumentList( source.m_argumentList ) {}
+
+ Macro& operator = ( const Macro& source )
+ {
+ m_name = source.m_name;
+ m_body = source.m_body;
+ m_fileName = source.m_fileName;
+ m_hasArguments = source.m_hasArguments;
+ m_argumentList = source.m_argumentList;
+ return *this;
+ }
+
+ bool operator == ( const Macro& source ) const
+ {
+ return
+ m_name == source.m_name &&
+ m_fileName == source.m_fileName &&
+ m_body == source.m_body &&
+ m_hasArguments == source.m_hasArguments &&
+ m_argumentList == source.m_argumentList;
+ }
+
+ QString name() const { return m_name; }
+ void setName( const QString& name ) { m_name = name; }
+
+ QString fileName() const { return m_fileName; }
+ void setFileName( const QString& fileName ) { m_fileName = fileName; }
+
+ QString body() const { return m_body; }
+ void setBody( const QString& body ) { m_body = body; }
+
+ bool hasArguments() const { return m_hasArguments; }
+ void setHasArguments( bool hasArguments ) { m_hasArguments = hasArguments; }
+ QValueList<Argument> argumentList() const { return m_argumentList; }
+
+ void clearArgumentList() { m_argumentList.clear(); m_hasArguments = false; }
+ void addArgument( const Argument& argument ) { m_argumentList << argument; }
+ void addArgumentList( const QValueList<Argument>& arguments ) { m_argumentList += arguments; }
+
+private:
+ QString m_name;
+ QString m_fileName;
+ QString m_body;
+ bool m_hasArguments;
+ QValueList<Argument> m_argumentList;
+};
+
+class SourceProvider
+{
+public:
+ SourceProvider() {}
+ virtual ~SourceProvider() {}
+
+ virtual QString contents( const QString& fileName ) = 0;
+ virtual bool isModified( const QString& fileName ) = 0;
+
+private:
+ SourceProvider( const SourceProvider& source );
+ void operator = ( const SourceProvider& source );
+};
+
+class Driver
+{
+public:
+ Driver();
+ virtual ~Driver();
+
+ SourceProvider* sourceProvider();
+ void setSourceProvider( SourceProvider* sourceProvider );
+
+ virtual void reset();
+
+ virtual void parseFile( const QString& fileName, bool onlyPreProcesss=false, bool force=false );
+ virtual void fileParsed( const QString& fileName );
+ virtual void remove( const QString& fileName );
+
+ virtual void addDependence( const QString& fileName, const Dependence& dep );
+ virtual void addMacro( const Macro& macro );
+ virtual void addProblem( const QString& fileName, const Problem& problem );
+
+
+ QString currentFileName() const { return m_currentFileName; }
+ TranslationUnitAST::Node takeTranslationUnit( const QString& fileName );
+ TranslationUnitAST* translationUnit( const QString& fileName ) const;
+ QMap<QString, Dependence> dependences( const QString& fileName ) const;
+ QMap<QString, Macro> macros() const;
+ QValueList<Problem> problems( const QString& fileName ) const;
+
+ bool hasMacro( const QString& name ) const { return m_macros.contains( name ); }
+ const Macro& macro( const QString& name ) const { return m_macros[ name ]; }
+ Macro& macro( const QString& name ) { return m_macros[ name ]; }
+
+ virtual void removeMacro( const QString& macroName );
+ virtual void removeAllMacrosInFile( const QString& fileName );
+
+ QStringList includePaths() const { return m_includePaths; }
+ virtual void addIncludePath( const QString &path );
+
+ /// @todo remove
+ const QMap<QString, TranslationUnitAST*> &parsedUnits() const { return m_parsedUnits; }
+
+ virtual void setResolveDependencesEnabled( bool enabled );
+ bool isResolveDependencesEnabled() const { return depresolv; }
+
+protected:
+ virtual void setupLexer( Lexer* lexer );
+ virtual void setupParser( Parser* parser );
+ virtual void setupPreProcessor();
+
+private:
+ QMap<QString, Dependence>& findOrInsertDependenceList( const QString& fileName );
+ QValueList<Problem>& findOrInsertProblemList( const QString& fileName );
+ QString findIncludeFile( const Dependence& dep ) const;
+
+private:
+ QString m_currentFileName;
+ QMap< QString, QMap<QString, Dependence> > m_dependences;
+ QMap<QString, Macro> m_macros;
+ QMap< QString, QValueList<Problem> > m_problems;
+ QMap<QString, TranslationUnitAST*> m_parsedUnits;
+ QStringList m_includePaths;
+ uint depresolv : 1;
+ Lexer *lexer;
+ SourceProvider* m_sourceProvider;
+
+private:
+ Driver( const Driver& source );
+ void operator = ( const Driver& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
new file mode 100644
index 00000000..154301c6
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
@@ -0,0 +1,25 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "errors.h"
+#include <klocale.h>
+
+QT_STATIC_CONST_IMPL Error& Errors::InternalError = Error( 1, -1, i18n("Internal Error") );
+QT_STATIC_CONST_IMPL Error& Errors::SyntaxError = Error( 2, -1, i18n("Syntax Error before '%1'") );
+QT_STATIC_CONST_IMPL Error& Errors::ParseError = Error( 3, -1, i18n("Parse Error before '%1'") );
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.h b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
new file mode 100644
index 00000000..f846533d
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
@@ -0,0 +1,45 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include <qstring.h>
+
+
+struct Error{
+ int code;
+ int level;
+ QString text;
+
+ Error( int c, int l, const QString& s )
+ : code( c ), level( l ), text( s )
+ {}
+};
+
+class Errors{
+public:
+ QT_STATIC_CONST Error& InternalError;
+ QT_STATIC_CONST Error& SyntaxError;
+ QT_STATIC_CONST Error& ParseError;
+};
+
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
new file mode 100644
index 00000000..5c276953
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
@@ -0,0 +1,123 @@
+/* Automatically generated from keywords.table using /home/roberto/src/kdelibs/kjs/create_hash_table. DO NOT EDIT ! */
+
+
+static const struct HashEntry keywordEntries[] = {
+ { "template", Token_template, 0, 0, 0 },
+ { "emit", Token_emit, 0, 0, &keywordEntries[88] },
+ { "long", Token_long, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "void", Token_void, 0, 0, &keywordEntries[113] },
+ { 0, 0, 0, 0, 0 },
+ { "explicit", Token_explicit, 0, 0, &keywordEntries[100] },
+ { "enum", Token_enum, 0, 0, &keywordEntries[105] },
+ { 0, 0, 0, 0, 0 },
+ { "continue", Token_continue, 0, 0, &keywordEntries[99] },
+ { "k_dcop_signals", Token_k_dcop_signals, 0, 0, &keywordEntries[104] },
+ { "auto", Token_auto, 0, 0, &keywordEntries[91] },
+ { 0, 0, 0, 0, 0 },
+ { "Q_OBJECT", Token_Q_OBJECT, 0, 0, &keywordEntries[86] },
+ { "and_eq", Token_and_eq, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "operator", Token_operator, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "class", Token_class, 0, 0, &keywordEntries[90] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "while", Token_while, 0, 0, 0 },
+ { "k_dcop", Token_k_dcop, 0, 0, 0 },
+ { "compl", Token_compl, 0, 0, 0 },
+ { "bitand", Token_bitand, 0, 0, &keywordEntries[97] },
+ { "__int64", Token_int, 0, 0, &keywordEntries[89] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bitor", Token_bitor, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "friend", Token_friend, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signed", Token_signed, 0, 0, 0 },
+ { "double", Token_double, 0, 0, 0 },
+ { "K_DCOP", Token_K_DCOP, 0, 0, &keywordEntries[111] },
+ { "const", Token_const, 0, 0, &keywordEntries[92] },
+ { 0, 0, 0, 0, 0 },
+ { "inline", Token_inline, 0, 0, &keywordEntries[98] },
+ { 0, 0, 0, 0, 0 },
+ { "do", Token_do, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "const_cast", Token_const_cast, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not_eq", Token_not_eq, 0, 0, &keywordEntries[102] },
+ { 0, 0, 0, 0, 0 },
+ { "static", Token_static, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "throw", Token_throw, 0, 0, 0 },
+ { "slots", Token_slots, 0, 0, &keywordEntries[87] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "static_cast", Token_static_cast, 0, 0, &keywordEntries[115] },
+ { "default", Token_default, 0, 0, &keywordEntries[95] },
+ { "sizeof", Token_sizeof, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "switch", Token_switch, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "mutable", Token_mutable, 0, 0, 0 },
+ { "dynamic_cast", Token_dynamic_cast, 0, 0, 0 },
+ { "extern", Token_extern, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "asm", Token_asm, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signals", Token_signals, 0, 0, &keywordEntries[106] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "case", Token_case, 0, 0, 0 },
+ { "for", Token_for, 0, 0, 0 },
+ { "char", Token_char, 0, 0, &keywordEntries[101] },
+ { 0, 0, 0, 0, 0 },
+ { "export", Token_export, 0, 0, &keywordEntries[94] },
+ { "int", Token_int, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "private", Token_private, 0, 0, &keywordEntries[103] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not", Token_not, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "else", Token_else, 0, 0, &keywordEntries[93] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bool", Token_bool, 0, 0, 0 },
+ { "catch", Token_catch, 0, 0, 0 },
+ { "__asm__", Token_asm, 0, 0, 0 },
+ { "and", Token_and, 0, 0, 0 },
+ { "break", Token_break, 0, 0, &keywordEntries[110] },
+ { "delete", Token_delete, 0, 0, 0 },
+ { "float", Token_float, 0, 0, &keywordEntries[96] },
+ { "goto", Token_goto, 0, 0, 0 },
+ { "if", Token_if, 0, 0, 0 },
+ { "namespace", Token_namespace, 0, 0, 0 },
+ { "new", Token_new, 0, 0, 0 },
+ { "or", Token_or, 0, 0, &keywordEntries[107] },
+ { "or_eq", Token_or_eq, 0, 0, 0 },
+ { "protected", Token_protected, 0, 0, 0 },
+ { "public", Token_public, 0, 0, &keywordEntries[109] },
+ { "register", Token_register, 0, 0, 0 },
+ { "reinterpret_cast", Token_reinterpret_cast, 0, 0, 0 },
+ { "return", Token_return, 0, 0, 0 },
+ { "short", Token_short, 0, 0, 0 },
+ { "struct", Token_struct, 0, 0, 0 },
+ { "this", Token_this, 0, 0, 0 },
+ { "try", Token_try, 0, 0, &keywordEntries[108] },
+ { "typedef", Token_typedef, 0, 0, 0 },
+ { "typeid", Token_typeid, 0, 0, 0 },
+ { "typename", Token_typename, 0, 0, 0 },
+ { "union", Token_union, 0, 0, 0 },
+ { "unsigned", Token_unsigned, 0, 0, &keywordEntries[112] },
+ { "using", Token_using, 0, 0, 0 },
+ { "virtual", Token_virtual, 0, 0, &keywordEntries[114] },
+ { "volatile", Token_volatile, 0, 0, 0 },
+ { "xor", Token_xor, 0, 0, 0 },
+ { "xor_eq", Token_xor_eq, 0, 0, 0 }
+};
+
+static const struct HashTable keyword = { 2, 116, keywordEntries, 86 };
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
new file mode 100644
index 00000000..2748688f
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
@@ -0,0 +1,1002 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "lexer.h"
+#include "lookup.h"
+#include "keywords.lut.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qregexp.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+
+#if defined( KDEVELOP_BGPARSER )
+#include <qthread.h>
+
+class KDevTread: public QThread
+{
+public:
+ static void yield()
+ {
+ msleep( 0 );
+ }
+};
+
+inline void qthread_yield()
+{
+ KDevTread::yield();
+}
+
+#endif
+
+#define CREATE_TOKEN(type, start, len) Token( (type), (start), (len), m_source )
+#define ADD_TOKEN(tk) m_tokens.insert( m_size++, new Token(tk) );
+
+using namespace std;
+
+struct LexerData
+{
+ typedef QMap<QString, QString> Scope;
+ typedef QValueList<Scope> StaticChain;
+
+ StaticChain staticChain;
+
+ void beginScope()
+ {
+ Scope scope;
+ staticChain.push_front( scope );
+ }
+
+ void endScope()
+ {
+ staticChain.pop_front();
+ }
+
+ void bind( const QString& name, const QString& value )
+ {
+ Q_ASSERT( staticChain.size() > 0 );
+ staticChain.front().insert( name, value );
+ }
+
+ bool hasBind( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return true;
+ }
+
+ return false;
+ }
+
+ QString apply( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return scope[ name ];
+ }
+
+ return QString::null;
+ }
+
+};
+
+Lexer::Lexer( Driver* driver )
+ : d( new LexerData),
+ m_driver( driver ),
+ m_recordComments( false ),
+ m_recordWhiteSpaces( false ),
+ m_skipWordsEnabled( true ),
+ m_preprocessorEnabled( true ),
+ m_reportWarnings( false ),
+ m_reportMessages( false )
+{
+ m_tokens.setAutoDelete( true );
+ reset();
+ d->beginScope();
+}
+
+Lexer::~Lexer()
+{
+ d->endScope();
+ delete( d );
+}
+
+void Lexer::setSource( const QString& source )
+{
+ reset();
+ m_source = source;
+ m_ptr = 0;
+ m_endPtr = m_source.length();
+ m_inPreproc = false;
+
+ tokenize();
+}
+
+void Lexer::reset()
+{
+ m_index = 0;
+ m_size = 0;
+ m_tokens.clear();
+ m_source = QString::null;
+ m_ptr = 0;
+ m_endPtr = 0;
+ m_startLine = false;
+ m_ifLevel = 0;
+ m_skipping.resize( 200 );
+ m_skipping.fill( 0 );
+ m_trueTest.resize( 200 );
+ m_trueTest.fill( 0 );
+
+ m_currentLine = 0;
+ m_currentColumn = 0;
+}
+
+// ### should all be done with a "long" type IMO
+int Lexer::toInt( const Token& token )
+{
+ QString s = token.text();
+ if( token.type() == Token_number_literal ){
+ // hex literal ?
+ if( s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ return s.mid( 2 ).toInt( 0, 16 );
+ QString n;
+ int i = 0;
+ while( i < int(s.length()) && s[i].isDigit() )
+ n += s[i++];
+ // ### respect more prefixes and suffixes ?
+ return n.toInt();
+ } else if( token.type() == Token_char_literal ){
+ int i = s[0] == 'L' ? 2 : 1; // wide char ?
+ if( s[i] == '\\' ){
+ // escaped char
+ int c = s[i+1].unicode();
+ switch( c ) {
+ case '0':
+ return 0;
+ case 'n':
+ return '\n';
+ // ### more
+ default:
+ return c;
+ }
+ } else {
+ return s[i].unicode();
+ }
+ } else {
+ return 0;
+ }
+}
+
+void Lexer::getTokenPosition( const Token& token, int* line, int* col )
+{
+ token.getStartPosition( line, col );
+}
+
+void Lexer::nextToken( Token& tk, bool stopOnNewline )
+{
+ int op = 0;
+
+ if( m_size == (int)m_tokens.size() ){
+ m_tokens.resize( m_tokens.size() + 5000 );
+ }
+
+ readWhiteSpaces( !stopOnNewline );
+
+ int startLine = m_currentLine;
+ int startColumn = m_currentColumn;
+
+ QChar ch = currentChar();
+ QChar ch1 = peekChar();
+
+ if( ch.isNull() || ch.isSpace() ){
+ /* skip */
+ } else if( m_startLine && ch == '#' ){
+
+ nextChar(); // skip #
+ readWhiteSpaces( false ); // skip white spaces
+ m_startLine = false;
+
+ int start = currentPosition();
+ readIdentifier(); // read the directive
+ QString directive = m_source.mid( start, currentPosition() - start );
+
+ handleDirective( directive );
+ } else if( m_startLine && m_skipping[ m_ifLevel ] ){
+ // skip line and continue
+ m_startLine = false;
+ int ppe = preprocessorEnabled();
+ setPreprocessorEnabled( false );
+ while( currentChar() && currentChar() != '\n' ){
+ Token tok;
+ nextToken( tok, true );
+ }
+ m_startLine = true;
+ setPreprocessorEnabled( ppe );
+ return;
+ } else if( ch == '/' && ch1 == '/' ){
+ int start = currentPosition();
+ readLineComment();
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '/' && ch1 == '*' ){
+ int start = currentPosition();
+ nextChar( 2 );
+ readMultiLineComment();
+
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '\'' || (ch == 'L' && ch1 == '\'') ){
+ int start = currentPosition();
+ readCharLiteral();
+ tk = CREATE_TOKEN( Token_char_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch == '"' ){
+ int start = currentPosition();
+ readStringLiteral();
+ tk = CREATE_TOKEN( Token_string_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch.isLetter() || ch == '_' ){
+ int start = currentPosition();
+ readIdentifier();
+ QString ide = m_source.mid( start, currentPosition() - start );
+ int k = Lookup::find( &keyword, ide );
+ if( m_preprocessorEnabled && m_driver->hasMacro(ide) &&
+ (k == -1 || !m_driver->macro(ide).body().isEmpty()) ){
+
+
+ bool preproc = m_preprocessorEnabled;
+ m_preprocessorEnabled = false;
+
+ d->beginScope();
+
+ int svLine = currentLine();
+ int svColumn = currentColumn();
+
+// Macro& m = m_driver->macro( ide );
+ Macro m = m_driver->macro( ide );
+ //m_driver->removeMacro( m.name() );
+
+ QString ellipsisArg;
+
+ if( m.hasArguments() ){
+ int endIde = currentPosition();
+
+ readWhiteSpaces();
+ if( currentChar() == '(' ){
+ nextChar();
+ int argIdx = 0;
+ int argCount = m.argumentList().size();
+ while( currentChar() && argIdx<argCount ){
+ readWhiteSpaces();
+
+ QString argName = m.argumentList()[ argIdx ];
+
+ bool ellipsis = argName == "...";
+
+ QString arg = readArgument();
+
+ if( !ellipsis )
+ d->bind( argName, arg );
+ else
+ ellipsisArg += arg;
+
+ if( currentChar() == ',' ){
+ nextChar();
+ if( !ellipsis ){
+ ++argIdx;
+ } else {
+ ellipsisArg += ", ";
+ }
+ } else if( currentChar() == ')' ){
+ break;
+ }
+ }
+ if( currentChar() == ')' ){
+ // valid macro
+ nextChar();
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, endIde - start );
+ tk.setStartPosition( svLine, svColumn );
+ tk.setEndPosition( svLine, svColumn + (endIde - start) );
+
+ m_startLine = false;
+
+ d->endScope(); // OPS!!
+ m_preprocessorEnabled = preproc;
+ return;
+ }
+ }
+
+ int argsEndAtLine = currentLine();
+ int argsEndAtColumn = currentColumn();
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), m.body() );
+
+ // tokenize the macro body
+
+ QString textToInsert;
+
+ m_endPtr = currentPosition() + m.body().length();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+
+ Token tok;
+ nextToken( tok );
+
+ bool stringify = !m_inPreproc && tok == '#';
+ bool merge = !m_inPreproc && tok == Token_concat;
+
+ if( stringify || merge )
+ nextToken( tok );
+
+ if( tok == Token_eof )
+ break;
+
+ QString tokText = tok.text();
+ QString str = (tok == Token_identifier && d->hasBind(tokText)) ? d->apply( tokText ) : tokText;
+ if( str == ide ){
+ //Problem p( i18n("unsafe use of macro '%1'").arg(ide), m_currentLine, m_currentColumn );
+ //m_driver->addProblem( m_driver->currentFileName(), p );
+ m_driver->removeMacro( ide );
+ // str = QString::null;
+ }
+
+ if( stringify ) {
+ textToInsert.append( QString::fromLatin1("\"") + str + QString::fromLatin1("\" ") );
+ } else if( merge ){
+ textToInsert.truncate( textToInsert.length() - 1 );
+ textToInsert.append( str );
+ } else if( tok == Token_ellipsis && d->hasBind("...") ){
+ textToInsert.append( ellipsisArg );
+ } else {
+ textToInsert.append( str + QString::fromLatin1(" ") );
+ }
+ }
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), textToInsert );
+
+ d->endScope();
+ m_preprocessorEnabled = preproc;
+ //m_driver->addMacro( m );
+ m_currentLine = argsEndAtLine;
+ m_currentColumn = argsEndAtColumn;
+ m_endPtr = m_source.length();
+ } else if( k != -1 ){
+ tk = CREATE_TOKEN( k, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( m_skipWordsEnabled ){
+ QMap< QString, QPair<SkipType, QString> >::Iterator pos = m_words.find( ide );
+ if( pos != m_words.end() ){
+ if( (*pos).first == SkipWordAndArguments ){
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ }
+ if( !(*pos).second.isEmpty() ){
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), QString(" ") + (*pos).second + QString(" ") );
+ m_endPtr = m_source.length();
+ }
+ } else if( /*qt_rx.exactMatch(ide) ||*/
+ ide.endsWith("EXPORT") ||
+ (ide.startsWith("Q_EXPORT") && ide != "Q_EXPORT_INTERFACE") ||
+ ide.startsWith("QM_EXPORT") ||
+ ide.startsWith("QM_TEMPLATE")){
+
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else if( ide.startsWith("K_TYPELIST_") || ide.startsWith("TYPELIST_") ){
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else{
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch.isNumber() ){
+ int start = currentPosition();
+ readNumberLiteral();
+ tk = CREATE_TOKEN( Token_number_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator3()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 3 );
+ nextChar( 3 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator2()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 2 );
+ nextChar( 2 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else {
+ tk = CREATE_TOKEN( ch.unicode(), currentPosition(), 1 );
+ nextChar();
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+
+ m_startLine = false;
+}
+
+
+void Lexer::tokenize()
+{
+ m_startLine = true;
+ m_size = 0;
+
+ for( ;; ) {
+ Token tk;
+ nextToken( tk );
+
+ if( tk.type() != -1 )
+ ADD_TOKEN( tk );
+
+ if( currentChar().isNull() )
+ break;
+ }
+
+ Token tk = CREATE_TOKEN( Token_eof, currentPosition(), 0 );
+ tk.setStartPosition( m_currentLine, m_currentColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ ADD_TOKEN( tk );
+}
+
+void Lexer::resetSkipWords()
+{
+ m_words.clear();
+}
+
+void Lexer::addSkipWord( const QString& word, SkipType skipType, const QString& str )
+{
+ m_words[ word ] = qMakePair( skipType, str );
+}
+
+void Lexer::skip( int l, int r )
+{
+ int svCurrentLine = m_currentLine;
+ int svCurrentColumn = m_currentColumn;
+
+ int count = 0;
+
+ while( !eof() ){
+ Token tk;
+ nextToken( tk );
+
+ if( (int)tk == l )
+ ++count;
+ else if( (int)tk == r )
+ --count;
+
+ if( count == 0 )
+ break;
+ }
+
+ m_currentLine = svCurrentLine;
+ m_currentColumn = svCurrentColumn;
+}
+
+QString Lexer::readArgument()
+{
+ int count = 0;
+
+ QString arg;
+
+ readWhiteSpaces();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+ QChar ch = currentChar();
+
+ if( ch.isNull() || (!count && (ch == ',' || ch == ')')) )
+ break;
+
+ Token tk;
+ nextToken( tk );
+
+ if( tk == '(' ){
+ ++count;
+ } else if( tk == ')' ){
+ --count;
+ }
+
+ if( tk != -1 )
+ arg += tk.text() + ' ';
+ }
+
+ return arg.stripWhiteSpace();
+}
+
+void Lexer::handleDirective( const QString& directive )
+{
+ m_inPreproc = true;
+
+ bool skip = skipWordsEnabled();
+ bool preproc = preprocessorEnabled();
+
+ setSkipWordsEnabled( false );
+ setPreprocessorEnabled( false );
+
+ if( directive == "define" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ Macro m;
+ processDefine( m );
+ }
+ } else if( directive == "else" ){
+ processElse();
+ } else if( directive == "elif" ){
+ processElif();
+ } else if( directive == "endif" ){
+ processEndif();
+ } else if( directive == "if" ){
+ processIf();
+ } else if( directive == "ifdef" ){
+ processIfdef();
+ } else if( directive == "ifndef" ){
+ processIfndef();
+ } else if( directive == "include" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processInclude();
+ }
+ } else if( directive == "undef" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processUndef();
+ }
+ }
+
+ // skip line
+ while( currentChar() && currentChar() != '\n' ){
+ Token tk;
+ nextToken( tk, true );
+ }
+
+ setSkipWordsEnabled( skip );
+ setPreprocessorEnabled( preproc );
+
+ m_inPreproc = false;
+}
+
+int Lexer::testIfLevel()
+{
+ int rtn = !m_skipping[ m_ifLevel++ ];
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ return rtn;
+}
+
+int Lexer::macroDefined()
+{
+ readWhiteSpaces( false );
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ bool r = m_driver->hasMacro( word );
+
+ return r;
+}
+
+void Lexer::processDefine( Macro& m )
+{
+ m.setFileName( m_driver->currentFileName() );
+ readWhiteSpaces( false );
+
+ int startMacroName = currentPosition();
+ readIdentifier();
+ QString macroName = m_source.mid( startMacroName, int(currentPosition()-startMacroName) );
+ m_driver->removeMacro( macroName );
+ m.setName( macroName );
+
+ if( currentChar() == '(' ){
+ m.setHasArguments( true );
+ nextChar();
+
+ readWhiteSpaces( false );
+
+ while( currentChar() && currentChar() != ')' ){
+ readWhiteSpaces( false );
+
+ int startArg = currentPosition();
+
+ if( currentChar() == '.' && peekChar() == '.' && peekChar(2) == '.' )
+ nextChar( 3 );
+ else
+ readIdentifier();
+
+ QString arg = m_source.mid( startArg, int(currentPosition()-startArg) );
+
+ m.addArgument( Macro::Argument(arg) );
+
+ readWhiteSpaces( false );
+ if( currentChar() != ',' )
+ break;
+
+ nextChar(); // skip ','
+ }
+
+ if( currentChar() == ')' )
+ nextChar(); // skip ')'
+ }
+
+ setPreprocessorEnabled( true );
+
+ QString body;
+ while( currentChar() && currentChar() != '\n' ){
+
+ if( currentChar().isSpace() ){
+ readWhiteSpaces( false );
+ body += ' ';
+ } else {
+
+ Token tk;
+ nextToken( tk, true );
+
+ if( tk.type() != -1 ){
+ QString s = tk.text();
+ body += s;
+ }
+ }
+ }
+
+ m.setBody( body );
+ m_driver->addMacro( m );
+}
+
+void Lexer::processElse()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( m_ifLevel > 0 && m_skipping[m_ifLevel-1] )
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ else
+ m_skipping[ m_ifLevel ] = m_trueTest[ m_ifLevel ];
+}
+
+void Lexer::processElif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( !m_trueTest[m_ifLevel] ){
+ /// @todo implement the correct semantic for elif!!
+ bool inSkip = m_ifLevel > 0 && m_skipping[ m_ifLevel-1 ];
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+ else
+ m_skipping[ m_ifLevel ] = true;
+}
+
+void Lexer::processEndif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ m_skipping[ m_ifLevel ] = 0;
+ m_trueTest[ m_ifLevel-- ] = 0;
+}
+
+void Lexer::processIf()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ) {
+#if 0
+ int n;
+ if( (n = testDefined()) != 0 ) {
+ int isdef = macroDefined();
+ m_trueTest[ m_ifLevel ] = (n == 1 && isdef) || (n == -1 && !isdef);
+ } else
+#endif
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfdef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfndef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = !macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processInclude()
+{
+ if( m_skipping[m_ifLevel] )
+ return;
+
+ readWhiteSpaces( false );
+ if( currentChar() ){
+ QChar ch = currentChar();
+ if( ch == '"' || ch == '<' ){
+ nextChar();
+ QChar ch2 = ch == QChar('"') ? QChar('"') : QChar('>');
+
+ int startWord = currentPosition();
+ while( currentChar() && currentChar() != ch2 )
+ nextChar();
+ if( currentChar() ){
+ QString word = m_source.mid( startWord, int(currentPosition()-startWord) );
+ m_driver->addDependence( m_driver->currentFileName(),
+ Dependence(word, ch == '"' ? Dep_Local : Dep_Global) );
+ nextChar();
+ }
+ }
+ }
+}
+
+void Lexer::processUndef()
+{
+ readWhiteSpaces();
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ m_driver->removeMacro( word );
+}
+
+int Lexer::macroPrimary()
+{
+ readWhiteSpaces( false );
+ int result = 0;
+ switch( currentChar().unicode() ) {
+ case '(':
+ nextChar();
+ result = macroExpression();
+ if( currentChar() != ')' ){
+ /// @todo report error
+ return 0;
+ }
+ nextChar();
+ return result;
+
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ QChar tk = currentChar();
+ nextChar();
+ int result = macroPrimary();
+ if( tk == '-' ) return -result;
+ else if( tk == '!' ) return !result;
+ else if( tk == '~' ) return ~result;
+ }
+ break;
+
+ default:
+ {
+ Token tk;
+ nextToken( tk, false );
+ switch( tk.type() ){
+ case Token_identifier:
+ if( tk.text() == "defined" ){
+ return macroPrimary();
+ }
+ /// @todo implement
+ return m_driver->hasMacro( tk.text() );
+ case Token_number_literal:
+ case Token_char_literal:
+ return toInt( tk );
+ default:
+ break;
+ } // end switch
+
+ } // end default
+
+ } // end switch
+
+ return 0;
+}
+
+int Lexer::macroMultiplyDivide()
+{
+ int result = macroPrimary();
+ int iresult, op;
+ for (;;) {
+ readWhiteSpaces( false );
+ if( currentChar() == '*' )
+ op = 0;
+ else if( currentChar() == '/' && !(peekChar() == '*' || peekChar() == '/') )
+ op = 1;
+ else if( currentChar() == '%' )
+ op = 2;
+ else
+ break;
+ nextChar();
+ iresult = macroPrimary();
+ result = op == 0 ? (result * iresult) :
+ op == 1 ? (iresult == 0 ? 0 : (result / iresult)) :
+ (iresult == 0 ? 0 : (result % iresult)) ;
+ }
+ return result;
+}
+
+int Lexer::macroAddSubtract()
+{
+ int result = macroMultiplyDivide();
+ int iresult, ad;
+ readWhiteSpaces( false );
+ while( currentChar() == '+' || currentChar() == '-') {
+ ad = currentChar() == '+';
+ nextChar();
+ iresult = macroMultiplyDivide();
+ result = ad ? (result+iresult) : (result-iresult);
+ }
+ return result;
+}
+
+int Lexer::macroRelational()
+{
+ int result = macroAddSubtract();
+ int iresult;
+ readWhiteSpaces( false );
+ while( currentChar() == '<' || currentChar() == '>') {
+ int lt = currentChar() == '<';
+ nextChar();
+ if( currentChar() == '=') {
+ nextChar();
+
+ iresult = macroAddSubtract();
+ result = lt ? (result <= iresult) : (result >= iresult);
+ }
+ else {
+ iresult = macroAddSubtract();
+ result = lt ? (result < iresult) : (result > iresult);
+ }
+ }
+
+ return result;
+}
+
+int Lexer::macroEquality()
+{
+ int result = macroRelational();
+ int iresult, eq;
+ readWhiteSpaces( false );
+ while ((currentChar() == '=' || currentChar() == '!') && peekChar() == '=') {
+ eq = currentChar() == '=';
+ nextChar( 2 );
+ iresult = macroRelational();
+ result = eq ? (result==iresult) : (result!=iresult);
+ }
+ return result;
+}
+
+int Lexer::macroBoolAnd()
+{
+ int result = macroEquality();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() != '&') {
+ nextChar();
+ result &= macroEquality();
+ }
+ return result;
+}
+
+int Lexer::macroBoolXor()
+{
+ int result = macroBoolAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '^') {
+ nextChar();
+ result ^= macroBoolAnd();
+ }
+ return result;
+}
+
+int Lexer::macroBoolOr()
+{
+ int result = macroBoolXor();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() != '|') {
+ nextChar();
+ result |= macroBoolXor();
+ }
+ return result;
+}
+
+int Lexer::macroLogicalAnd()
+{
+ int result = macroBoolOr();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() == '&') {
+ nextChar( 2 );
+ int start = currentPosition();
+ result = macroBoolOr() && result;
+ QString s = m_source.mid( start, currentPosition() - start );
+ }
+ return result;
+}
+
+int Lexer::macroLogicalOr()
+{
+ int result = macroLogicalAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() == '|') {
+ nextChar( 2 );
+ result = macroLogicalAnd() || result;
+ }
+ return result;
+}
+
+int Lexer::macroExpression()
+{
+ readWhiteSpaces( false );
+ return macroLogicalOr();
+}
+
+// *IMPORTANT*
+// please, don't include lexer.moc here, because Lexer isn't a QObject class!!
+// if you have problem while recompiling try to remove cppsupport/.deps,
+// cppsupport/Makefile.in and rerun automake/autoconf
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.h b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
new file mode 100644
index 00000000..cce951d4
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
@@ -0,0 +1,791 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include "driver.h"
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qvaluestack.h>
+#include <qpair.h>
+#include <qptrvector.h>
+
+enum Type {
+ Token_eof = 0,
+ Token_identifier = 1000,
+ Token_number_literal,
+ Token_char_literal,
+ Token_string_literal,
+ Token_whitespaces,
+ Token_comment,
+ Token_preproc,
+
+ Token_assign = 2000,
+ Token_ptrmem,
+ Token_ellipsis,
+ Token_scope,
+ Token_shift,
+ Token_eq,
+ Token_leq,
+ Token_geq,
+ Token_incr,
+ Token_decr,
+ Token_arrow,
+
+ Token_concat,
+
+ Token_K_DCOP,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+
+ Token_Q_OBJECT,
+ Token_signals,
+ Token_slots,
+ Token_emit,
+
+ Token_and,
+ Token_and_eq,
+ Token_asm,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_class,
+ Token_compl,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_else,
+ Token_enum,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_goto,
+ Token_if,
+ Token_inline,
+ Token_int,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_not,
+ Token_not_eq,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_private,
+ Token_protected,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_short,
+ Token_signed,
+ Token_sizeof,
+ Token_static,
+ Token_static_cast,
+ Token_struct,
+ Token_switch,
+ Token_template,
+ Token_this,
+ Token_throw,
+ Token_true,
+ Token_try,
+ Token_typedef,
+ Token_typeid,
+ Token_typename,
+ Token_union,
+ Token_unsigned,
+ Token_using,
+ Token_virtual,
+ Token_void,
+ Token_volatile,
+ Token_wchar_t,
+ Token_while,
+ Token_xor,
+ Token_xor_eq
+};
+
+enum SkipType {
+ SkipWord,
+ SkipWordAndArguments
+};
+
+struct LexerData;
+
+class Token
+{
+public:
+ Token();
+ Token( int type, int position, int length, const QString& text );
+ Token( const Token& source );
+
+ Token& operator = ( const Token& source );
+ bool operator == ( const Token& token ) const;
+ operator int () const;
+
+ bool isNull() const;
+
+ int type() const;
+ void setType( int type );
+
+ void getStartPosition( int* line, int* column ) const;
+ void setStartPosition( int line, int column );
+ void getEndPosition( int* line, int* column ) const;
+ void setEndPosition( int line, int column );
+
+ unsigned int length() const;
+ void setLength( unsigned int length );
+
+ int position() const;
+ void setPosition( int position );
+
+ QString text() const;
+
+private:
+ int m_type;
+ int m_position;
+ int m_length;
+ int m_startLine;
+ int m_startColumn;
+ int m_endLine;
+ int m_endColumn;
+ QString m_text;
+
+ friend class Lexer;
+ friend class Parser;
+}; // class Token
+
+class Lexer
+{
+public:
+ Lexer( Driver* driver );
+ ~Lexer();
+
+ bool recordComments() const;
+ void setRecordComments( bool record );
+
+ bool recordWhiteSpaces() const;
+ void setRecordWhiteSpaces( bool record );
+
+ bool reportWarnings() const;
+ void setReportWarnings( bool enable );
+
+ bool reportMessages() const;
+ void setReportMessages( bool enable );
+
+ bool skipWordsEnabled() const;
+ void setSkipWordsEnabled( bool enabled );
+
+ bool preprocessorEnabled() const;
+ void setPreprocessorEnabled( bool enabled );
+
+ void resetSkipWords();
+ void addSkipWord( const QString& word, SkipType skipType=SkipWord, const QString& str = QString::null );
+
+ QString source() const;
+ void setSource( const QString& source );
+
+ int index() const;
+ void setIndex( int index );
+
+ void reset();
+
+ const Token& tokenAt( int position ) const;
+ const Token& nextToken();
+ const Token& lookAhead( int n ) const;
+
+ static int toInt( const Token& token );
+
+ int tokenPosition( const Token& token ) const;
+ void getTokenPosition( const Token& token, int* line, int* col );
+
+ int currentLine() const { return m_currentLine; }
+ int currentColumn() const { return m_currentColumn; }
+
+private:
+ QChar currentChar() const;
+ QChar peekChar( int n=1 ) const;
+ int currentPosition() const;
+
+ void tokenize();
+ void nextToken( Token& token, bool stopOnNewline=false );
+ void nextChar();
+ void nextChar( int n );
+ void skip( int l, int r );
+ void readIdentifier();
+ void readWhiteSpaces( bool skipNewLine=true );
+ void readLineComment();
+ void readMultiLineComment();
+ void readCharLiteral();
+ void readStringLiteral();
+ void readNumberLiteral();
+
+ int findOperator3() const;
+ int findOperator2() const;
+ bool eof() const;
+
+ // preprocessor (based on an article of Al Stevens on Dr.Dobb's journal)
+ int testIfLevel();
+ int macroDefined();
+ QString readArgument();
+
+ int macroPrimary();
+ int macroMultiplyDivide();
+ int macroAddSubtract();
+ int macroRelational();
+ int macroEquality();
+ int macroBoolAnd();
+ int macroBoolXor();
+ int macroBoolOr();
+ int macroLogicalAnd();
+ int macroLogicalOr();
+ int macroExpression();
+
+ void handleDirective( const QString& directive );
+ void processDefine( Macro& macro );
+ void processElse();
+ void processElif();
+ void processEndif();
+ void processIf();
+ void processIfdef();
+ void processIfndef();
+ void processInclude();
+ void processUndef();
+
+private:
+ LexerData* d;
+ Driver* m_driver;
+ QPtrVector< Token > m_tokens;
+ int m_size;
+ int m_index;
+ QString m_source;
+ int m_ptr;
+ int m_endPtr;
+ bool m_recordComments;
+ bool m_recordWhiteSpaces;
+ bool m_startLine;
+ QMap< QString, QPair<SkipType, QString> > m_words;
+
+ int m_currentLine;
+ int m_currentColumn;
+ bool m_skipWordsEnabled;
+
+ // preprocessor
+ QMemArray<bool> m_skipping;
+ QMemArray<bool> m_trueTest;
+ int m_ifLevel;
+ bool m_preprocessorEnabled;
+ bool m_inPreproc;
+
+ bool m_reportWarnings;
+ bool m_reportMessages;
+
+private:
+ Lexer( const Lexer& source );
+ void operator = ( const Lexer& source );
+};
+
+
+inline Token::Token()
+ : m_type( -1 ),
+ m_position( 0 ),
+ m_length( 0 ),
+ m_text( 0 )
+{
+}
+
+inline Token::Token( int type, int position, int length, const QString& text )
+ : m_type( type ),
+ m_position( position ),
+ m_length( length ),
+ m_text( text )
+{
+}
+
+inline Token::Token( const Token& source )
+ : m_type( source.m_type ),
+ m_position( source.m_position ),
+ m_length( source.m_length ),
+ m_startLine( source.m_startLine ),
+ m_startColumn( source.m_startColumn ),
+ m_endLine( source.m_endLine ),
+ m_endColumn( source.m_endColumn ),
+ m_text( source.m_text )
+{
+}
+
+inline Token& Token::operator = ( const Token& source )
+{
+ m_type = source.m_type;
+ m_position = source.m_position;
+ m_length = source.m_length;
+ m_startLine = source.m_startLine;
+ m_startColumn = source.m_startColumn;
+ m_endLine = source.m_endLine;
+ m_endColumn = source.m_endColumn;
+ m_text = source.m_text;
+ return( *this );
+}
+
+inline Token::operator int () const
+{
+ return m_type;
+}
+
+inline bool Token::operator == ( const Token& token ) const
+{
+ return m_type == token.m_type &&
+ m_position == token.m_position &&
+ m_length == token.m_length &&
+ m_startLine == token.m_startLine &&
+ m_startColumn == token.m_startColumn &&
+ m_endLine == token.m_endLine &&
+ m_endColumn == token.m_endColumn &&
+ m_text == token.m_text;
+}
+
+inline bool Token::isNull() const
+{
+ return m_type == Token_eof || m_length == 0;
+}
+
+inline int Token::type() const
+{
+ return m_type;
+}
+
+inline void Token::setType( int type )
+{
+ m_type = type;
+}
+
+inline int Token::position() const
+{
+ return m_position;
+}
+
+inline QString Token::text() const
+{
+ return m_text.mid(m_position, m_length);
+}
+
+inline void Token::setStartPosition( int line, int column )
+{
+ m_startLine = line;
+ m_startColumn = column;
+}
+
+inline void Token::setEndPosition( int line, int column )
+{
+ m_endLine = line;
+ m_endColumn = column;
+}
+
+inline void Token::getStartPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_startLine;
+ if( column ) *column = m_startColumn;
+}
+
+inline void Token::getEndPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_endLine;
+ if( column ) *column = m_endColumn;
+}
+
+inline void Token::setPosition( int position )
+{
+ m_position = position;
+}
+
+inline unsigned int Token::length() const
+{
+ return m_length;
+}
+
+inline void Token::setLength( unsigned int length )
+{
+ m_length = length;
+}
+
+inline bool Lexer::recordComments() const
+{
+ return m_recordComments;
+}
+
+inline void Lexer::setRecordComments( bool record )
+{
+ m_recordComments = record;
+}
+
+inline bool Lexer::recordWhiteSpaces() const
+{
+ return m_recordWhiteSpaces;
+}
+
+inline void Lexer::setRecordWhiteSpaces( bool record )
+{
+ m_recordWhiteSpaces = record;
+}
+
+inline QString Lexer::source() const
+{
+ return m_source;
+}
+
+inline int Lexer::index() const
+{
+ return m_index;
+}
+
+inline void Lexer::setIndex( int index )
+{
+ m_index = index;
+}
+
+inline const Token& Lexer::nextToken()
+{
+ if( m_index < m_size )
+ return *m_tokens[ m_index++ ];
+
+ return *m_tokens[ m_index ];
+}
+
+inline const Token& Lexer::tokenAt( int n ) const
+{
+ return *m_tokens[ QMIN(n, m_size-1) ];
+}
+
+inline const Token& Lexer::lookAhead( int n ) const
+{
+ return *m_tokens[ QMIN(m_index + n, m_size-1) ];
+}
+
+inline int Lexer::tokenPosition( const Token& token ) const
+{
+ return token.position();
+}
+
+inline void Lexer::nextChar()
+{
+ if(m_source[m_ptr++] == '\n') {
+ ++m_currentLine;
+ m_currentColumn = 0;
+ m_startLine = true;
+ } else {
+ ++m_currentColumn;
+ }
+}
+
+inline void Lexer::nextChar( int n )
+{
+ m_currentColumn += n;
+ m_ptr += n;
+}
+
+inline void Lexer::readIdentifier()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '_' )
+ nextChar();
+}
+
+inline void Lexer::readWhiteSpaces( bool skipNewLine )
+{
+ while( !currentChar().isNull() ){
+ QChar ch = currentChar();
+
+ if( ch == '\n' && !skipNewLine ){
+ break;
+ } else if( ch.isSpace() ){
+ nextChar();
+ } else if( m_inPreproc && currentChar() == '\\' ){
+ nextChar();
+ readWhiteSpaces( true );
+ } else {
+ break;
+ }
+ }
+}
+
+inline void Lexer::readLineComment()
+{
+ while( !currentChar().isNull() && currentChar() != '\n' ){
+ if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readMultiLineComment()
+{
+ while( !currentChar().isNull() ){
+ if( currentChar() == '*' && peekChar() == '/' ){
+ nextChar( 2 );
+ return;
+ } else if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readCharLiteral()
+{
+ if( currentChar() == '\'' )
+ nextChar(); // skip '
+ else if( currentChar() == 'L' && peekChar() == '\'' )
+ nextChar( 2 ); // slip L'
+ else
+ return;
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - currentPosition();
+
+ if( len>=2 && (currentChar() == '\\' && peekChar() == '\'') ){
+ nextChar( 2 );
+ } else if( len>=2 && (currentChar() == '\\' && peekChar() == '\\') ){
+ nextChar( 2 );
+ } else if( currentChar() == '\'' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readStringLiteral()
+{
+ if( currentChar() != '"' )
+ return;
+
+ nextChar(); // skip "
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - m_ptr;
+
+ if( len>=2 && currentChar() == '\\' && peekChar() == '"' ){
+ nextChar( 2 );
+ } else if( len>=2 && currentChar() == '\\' && peekChar() == '\\' ){
+ nextChar( 2 );
+ } else if( currentChar() == '"' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readNumberLiteral()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '.' )
+ nextChar();
+}
+
+inline int Lexer::findOperator3() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n >= 3){
+ QChar ch = currentChar(), ch1=peekChar(), ch2=peekChar(2);
+
+ if( ch == '<' && ch1 == '<' && ch2 == '=' ) return Token_assign;
+ else if( ch == '>' && ch1 == '>' && ch2 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '>' && ch2 == '*' ) return Token_ptrmem;
+ else if( ch == '.' && ch1 == '.' && ch2 == '.' ) return Token_ellipsis;
+ }
+
+ return -1;
+}
+
+inline int Lexer::findOperator2() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n>=2 ){
+ QChar ch = currentChar(), ch1=peekChar();
+
+ if( ch == ':' && ch1 == ':' ) return Token_scope;
+ else if( ch == '.' && ch1 == '*' ) return Token_ptrmem;
+ else if( ch == '+' && ch1 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '=' ) return Token_assign;
+ else if( ch == '*' && ch1 == '=' ) return Token_assign;
+ else if( ch == '/' && ch1 == '=' ) return Token_assign;
+ else if( ch == '%' && ch1 == '=' ) return Token_assign;
+ else if( ch == '^' && ch1 == '=' ) return Token_assign;
+ else if( ch == '&' && ch1 == '=' ) return Token_assign;
+ else if( ch == '|' && ch1 == '=' ) return Token_assign;
+ else if( ch == '<' && ch1 == '<' ) return Token_shift;
+ else if( ch == '>' && ch1 == '>' ) return Token_shift;
+ else if( ch == '=' && ch1 == '=' ) return Token_eq;
+ else if( ch == '!' && ch1 == '=' ) return Token_eq;
+ else if( ch == '<' && ch1 == '=' ) return Token_leq;
+ else if( ch == '>' && ch1 == '=' ) return Token_geq;
+ else if( ch == '&' && ch1 == '&' ) return Token_and;
+ else if( ch == '|' && ch1 == '|' ) return Token_or;
+ else if( ch == '+' && ch1 == '+' ) return Token_incr;
+ else if( ch == '-' && ch1 == '-' ) return Token_decr;
+ else if( ch == '-' && ch1 == '>' ) return Token_arrow;
+ else if( ch == '#' && ch1 == '#' ) return Token_concat;
+ }
+
+ return -1;
+}
+
+inline bool Lexer::skipWordsEnabled() const
+{
+ return m_skipWordsEnabled;
+}
+
+inline void Lexer::setSkipWordsEnabled( bool enabled )
+{
+ m_skipWordsEnabled = enabled;
+}
+
+inline bool Lexer::preprocessorEnabled() const
+{
+ return m_preprocessorEnabled;
+}
+
+inline void Lexer::setPreprocessorEnabled( bool enabled )
+{
+ m_preprocessorEnabled = enabled;
+}
+
+inline int Lexer::currentPosition() const
+{
+ return m_ptr;
+}
+
+inline QChar Lexer::currentChar() const
+{
+ return m_ptr < m_endPtr ? m_source[m_ptr] : QChar::null;
+}
+
+inline QChar Lexer::peekChar( int n ) const
+{
+ return m_ptr+n < m_endPtr ? m_source[m_ptr + n] : QChar::null;
+}
+
+inline bool Lexer::eof() const
+{
+ return m_ptr >= m_endPtr;
+}
+
+inline bool Lexer::reportWarnings() const
+{
+ return m_reportWarnings;
+}
+
+inline void Lexer::setReportWarnings( bool enable )
+{
+ m_reportWarnings = enable;
+}
+
+inline bool Lexer::reportMessages() const
+{
+ return m_reportMessages;
+}
+
+inline void Lexer::setReportMessages( bool enable )
+{
+ m_reportMessages = enable;
+}
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
new file mode 100644
index 00000000..86299304
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
@@ -0,0 +1,113 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#include "lookup.h"
+
+#include <kdebug.h>
+
+#include <stdio.h>
+#include <string.h>
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QChar *c, unsigned int len )
+{
+ if (table->type != 2) {
+ kdDebug() << "KJS: Unknown hash table version" << endl;
+ return 0;
+ }
+ char *ascii = new char[len+1];
+ unsigned int i;
+ for(i = 0; i < len; i++, c++) {
+ if (!c->row())
+ ascii[i] = c->cell();
+ else
+ break;
+ }
+ ascii[i] = '\0';
+
+ int h = hash(ascii) % table->hashSize;
+ const HashEntry *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->s) {
+ delete [] ascii;
+ return 0;
+ }
+
+ do {
+ // compare strings
+ if (strcmp(ascii, e->s) == 0) {
+ delete [] ascii;
+ return e;
+ }
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ delete [] ascii;
+ return 0;
+}
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QString &s )
+{
+ return findEntry( table, s.unicode(), s.length() );
+}
+
+int Lookup::find(const struct HashTable *table,
+ const QChar *c, unsigned int len)
+{
+ const HashEntry *entry = findEntry( table, c, len );
+ if (entry)
+ return entry->value;
+ return -1;
+}
+
+int Lookup::find(const struct HashTable *table, const QString &s)
+{
+ return find(table, s.unicode(), s.length());
+}
+
+unsigned int Lookup::hash(const QChar *c, unsigned int len)
+{
+ unsigned int val = 0;
+ // ignoring rower byte
+ for (unsigned int i = 0; i < len; i++, c++)
+ val += c->cell();
+
+ return val;
+}
+
+unsigned int Lookup::hash(const QString &key)
+{
+ return hash(key.unicode(), key.length());
+}
+
+unsigned int Lookup::hash(const char *s)
+{
+ unsigned int val = 0;
+ while (*s)
+ val += *s++;
+
+ return val;
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.h b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
new file mode 100644
index 00000000..3e9c713c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
@@ -0,0 +1,119 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#ifndef _KJSLOOKUP_H_
+#define _KJSLOOKUP_H_
+
+#include <qstring.h>
+#include <stdio.h>
+
+ /**
+ * An entry in a hash table.
+ */
+ struct HashEntry {
+ /**
+ * s is the key (e.g. a property name)
+ */
+ const char *s;
+ /**
+ * value is the result value (usually an enum value)
+ */
+ int value;
+ /**
+ * attr is a set for flags (e.g. the property flags, see object.h)
+ */
+ short int attr;
+ /**
+ * params is another number. For property hashtables, it is used to
+ * denote the number of argument of the function
+ */
+ short int params;
+ /**
+ * next is the pointer to the next entry for the same hash value
+ */
+ const HashEntry *next;
+ };
+
+ /**
+ * A hash table
+ * Usually the hashtable is generated by the create_hash_table script, from a .table file.
+ *
+ * The implementation uses an array of entries, "size" is the total size of that array.
+ * The entries between 0 and hashSize-1 are the entry points
+ * for each hash value, and the entries between hashSize and size-1
+ * are the overflow entries for the hash values that need one.
+ * The "next" pointer of the entry links entry points to overflow entries,
+ * and links overflow entries between them.
+ */
+ struct HashTable {
+ /**
+ * type is a version number. Currently always 2
+ */
+ int type;
+ /**
+ * size is the total number of entries in the hashtable, including the null entries,
+ * i.e. the size of the "entries" array.
+ * Used to iterate over all entries in the table
+ */
+ int size;
+ /**
+ * pointer to the array of entries
+ * Mind that some entries in the array are null (0,0,0,0).
+ */
+ const HashEntry *entries;
+ /**
+ * the maximum value for the hash. Always smaller than size.
+ */
+ int hashSize;
+ };
+
+ /**
+ * @short Fast keyword lookup.
+ */
+ class Lookup {
+ public:
+ /**
+ * Find an entry in the table, and return its value (i.e. the value field of HashEntry)
+ */
+ static int find(const struct HashTable *table, const QString& s);
+ static int find(const struct HashTable *table, const QChar *c, unsigned int len);
+
+ /**
+ * Find an entry in the table, and return the entry
+ * This variant gives access to the other attributes of the entry,
+ * especially the attr field.
+ */
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QString &s);
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QChar *c, unsigned int len);
+
+ /**
+ * Calculate the hash value for a given key
+ */
+ static unsigned int hash(const QString &key);
+ static unsigned int hash(const QChar *c, unsigned int len);
+ static unsigned int hash(const char *s);
+ };
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
new file mode 100644
index 00000000..0314a60c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
@@ -0,0 +1,4238 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// c++ support
+#include "parser.h"
+#include "driver.h"
+#include "lexer.h"
+#include "errors.h"
+
+// qt
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qasciidict.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace std;
+
+#define ADVANCE(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ } \
+ else \
+ lex->nextToken(); \
+}
+
+#define CHECK(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define MATCH(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( Errors::SyntaxError ); \
+ return false; \
+ } \
+}
+
+#define UPDATE_POS(node, start, end) \
+{ \
+ int line, col; \
+ const Token &a = lex->tokenAt(start); \
+ const Token &b = lex->tokenAt( end!=start ? end-1 : end ); \
+ a.getStartPosition( &line, &col ); \
+ (node)->setStartPosition( line, col ); \
+ b.getEndPosition( &line, &col ); \
+ (node)->setEndPosition( line, col ); \
+ if( (node)->nodeType() == NodeType_Generic ) { \
+ if ((start) == (end) || (end) == (start)+1) \
+ (node)->setSlice(lex->source(), a.position(), a.length()); \
+ else \
+ (node)->setText( toString((start),(end)) ); \
+ } \
+}
+
+#define AST_FROM_TOKEN(node, tk) \
+ AST::Node node = CreateNode<AST>(); \
+ UPDATE_POS( node, (tk), (tk)+1 );
+
+
+//@todo remove me
+enum
+{
+ OBJC_CLASS,
+ OBJC_PROTOCOL,
+ OBJC_ALIAS
+};
+
+struct ParserPrivateData
+{
+ ParserPrivateData()
+ {}
+};
+
+Parser::Parser( Driver* driver, Lexer* lexer )
+ : m_driver( driver ),
+ lex( lexer )
+{
+ d = new ParserPrivateData();
+
+ m_maxProblems = 5;
+ objcp = false;
+}
+
+Parser::~Parser()
+{
+ delete d;
+ d = 0;
+}
+
+bool Parser::reportError( const Error& err )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ QString s = lex->lookAhead(0).text();
+ s = s.left( 30 ).stripWhiteSpace();
+ if( s.isEmpty() )
+ s = i18n( "<eof>" );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(err.text.arg(s), line, col) );
+ }
+
+ return true;
+}
+
+bool Parser::reportError( const QString& msg )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col) );
+ }
+
+ return true;
+}
+
+void Parser::syntaxError()
+{
+ (void) reportError( Errors::SyntaxError );
+}
+
+bool Parser::skipUntil( int token )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntil()" << endl;
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == token )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilDeclaration()" << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+
+ switch( lex->lookAhead(0) ){
+ case ';':
+ case '~':
+ case Token_scope:
+ case Token_identifier:
+ case Token_operator:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_extern:
+ case Token_namespace:
+ case Token_using:
+ case Token_typedef:
+ case Token_asm:
+ case Token_template:
+ case Token_export:
+
+ case Token_const: // cv
+ case Token_volatile: // cv
+
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ case Token_signals: // Qt
+ case Token_slots: // Qt
+ return true;
+
+ case '}':
+ return false;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilStatement() -- token = " << lex->lookAhead(0).text() << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+ switch( lex->lookAhead(0) ){
+ case ';':
+ case '{':
+ case '}':
+ case Token_const:
+ case Token_volatile:
+ case Token_identifier:
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_switch:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ case Token_try:
+ case Token_catch:
+ case Token_throw:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_class:
+ case Token_struct:
+ case Token_union:
+ case Token_enum:
+ case Token_scope:
+ case Token_template:
+ case Token_using:
+ return true;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip( int l, int r )
+{
+ int count = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == l )
+ ++count;
+ else if( tk == r )
+ --count;
+ else if( l != '{' && (tk == '{' || tk == '}' || tk == ';') )
+ return false;
+
+ if( count == 0 )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipCommaExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !skipExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !skipExpression(expr) ){
+ reportError( i18n("expression expected") );
+ return false;
+ }
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::skipExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpression()" << endl;
+
+ int start = lex->index();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ switch( tk ){
+ case '(':
+ skip( '(', ')' );
+ lex->nextToken();
+ break;
+
+ case '[':
+ skip( '[', ']' );
+ lex->nextToken();
+ break;
+
+#if 0
+ case Token_identifier:
+ lex->nextToken();
+ if( lex->lookAhead( 0 ) == Token_identifier )
+ return true;
+ break;
+#endif
+
+ case ';':
+ case ',':
+ case ']':
+ case ')':
+ case '{':
+ case '}':
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ {
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ }
+ return true;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseName( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseName()" << endl;
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ int start = lex->index();
+
+ NameAST::Node ast = CreateNode<NameAST>();
+
+ if( lex->lookAhead(0) == Token_scope ){
+ ast->setGlobal( true );
+ lex->nextToken();
+ }
+
+ int idx = lex->index();
+
+ while( true ){
+ ClassOrNamespaceNameAST::Node n;
+ if( !parseUnqualifiedName(n) ) {
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ ast->addClassOrNamespaceName( n );
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken(); /// skip optional template #### @todo CHECK
+ } else {
+ ast->setUnqualifiedName( n );
+ break;
+ }
+ }
+
+ if( idx == lex->index() )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit( TranslationUnitAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTranslationUnit()" << endl;
+
+ int start = lex->index();
+
+ m_problems = 0;
+ TranslationUnitAST::Node tun = CreateNode<TranslationUnitAST>();
+ node = tun;
+ while( !lex->lookAhead(0).isNull() ){
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( !parseDeclaration(def) ){
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ node->addDeclaration( def );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ // force (0,0) as start position
+ node->setStartPosition( 0, 0 );
+
+ return m_problems == 0;
+}
+
+bool Parser::parseDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaration()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+ bool success = false;
+
+ switch( lex->lookAhead(0) ){
+
+ case ';':
+ lex->nextToken();
+ return true;
+
+ case Token_extern:
+ success = parseLinkageSpecification( node );
+ break;
+
+ case Token_namespace:
+ success = parseNamespace( node );
+ break;
+
+ case Token_using:
+ success = parseUsing( node );
+ break;
+
+ case Token_typedef:
+ success = parseTypedef( node );
+ break;
+
+ case Token_asm:
+ success = parseAsmDefinition( node );
+ break;
+
+ case Token_template:
+ case Token_export:
+ success = parseTemplateDeclaration( node );
+ break;
+
+ default:
+ {
+ // lex->setIndex( start );
+
+ if( objcp && parseObjcDef(node) )
+ return true;
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ AST::Node declarator;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList(declarators);
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+ success = parseDeclarationInternal( node, comment );
+ }
+
+ } // end switch
+
+ if( success && !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(): comment is " << comment << endl;
+ node->setComment( comment );
+ }
+ return success;
+}
+
+bool Parser::parseLinkageSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageSpecification()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_extern ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageSpecificationAST::Node ast = CreateNode<LinkageSpecificationAST>();
+
+ int startExternType = lex->index();
+ if( lex->lookAhead(0) == Token_string_literal ){
+ lex->nextToken();
+ AST::Node externType = CreateNode<AST>();
+ UPDATE_POS( externType, startExternType, lex->index() );
+
+ ast->setExternType( externType );
+ }
+
+ if( lex->lookAhead(0) == '{' ){
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+ ast->setLinkageBody( linkageBody );
+ } else {
+ DeclarationAST::Node decl;
+ if( !parseDeclaration(decl) ){
+ reportError( i18n("Declaration syntax error") );
+ }
+ ast->setDeclaration( decl );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody( LinkageBodyAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageBody()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageBodyAST::Node lba = CreateNode<LinkageBodyAST>();
+ node = lba;
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == '}' )
+ break;
+
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( parseDeclaration(def) ){
+ node->addDeclaration( def );
+ } else {
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseNamespace( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNamespace()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ int startNamespaceName = lex->index();
+ if( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+ }
+ AST::Node namespaceName = CreateNode<AST>();
+ UPDATE_POS( namespaceName, startNamespaceName, lex->index() );
+
+ if ( lex->lookAhead(0) == '=' ) {
+ // namespace alias
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( parseName(name) ){
+ ADVANCE( ';', ";" );
+
+ NamespaceAliasAST::Node ast = CreateNode<NamespaceAliasAST>();
+ ast->setNamespaceName( namespaceName );
+ ast->setAliasName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else {
+ reportError( i18n("namespace expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) != '{' ){
+ reportError( i18n("{ expected") );
+ return false;
+ }
+
+ NamespaceAST::Node ast = CreateNode<NamespaceAST>();
+ ast->setNamespaceName( namespaceName );
+
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+
+ ast->setLinkageBody( linkageBody );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsing()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_using ){
+ return false;
+ }
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_namespace ){
+ if( !parseUsingDirective(node) ){
+ return false;
+ }
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ UsingAST::Node ast = CreateNode<UsingAST>();
+
+ int startTypeName = lex->index();
+ if( lex->lookAhead(0) == Token_typename ){
+ lex->nextToken();
+ AST::Node tn = CreateNode<AST>();
+ UPDATE_POS( tn, startTypeName, lex->index() );
+ ast->setTypeName( tn );
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) )
+ return false;
+
+ ast->setName( name );
+
+ ADVANCE( ';', ";" );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsingDirective()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ UsingDirectiveAST::Node ast = CreateNode<UsingDirectiveAST>();
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperatorFunctionId()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_operator ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node op;
+ if( parseOperator(op) ){
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ } else {
+ // parse cast operator
+ GroupAST::Node cv;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST::Node spec;
+ if( !parseSimpleTypeSpecifier(spec) ){
+ syntaxError();
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify( cv2 );
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) )
+ ;
+
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+}
+
+bool Parser::parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgumentList()" << endl;
+
+ int start = lex->index();
+
+ TemplateArgumentListAST::Node ast = CreateNode<TemplateArgumentListAST>();
+
+ AST::Node templArg;
+ if( !parseTemplateArgument(templArg) )
+ return false;
+ ast->addArgument( templArg );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateArgument(templArg) ){
+ if( reportError ){
+ syntaxError();
+ break;
+ } else
+ return false;
+ }
+ if (!comment.isEmpty())
+ templArg->setComment(comment);
+ ast->addArgument( templArg );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypedef( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypedef()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_typedef ){
+ return false;
+ }
+ lex->nextToken();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifierOrClassSpec(spec) ){
+ reportError( i18n("Need a type specifier to declare") );
+ return false;
+ }
+
+ InitDeclaratorListAST::Node declarators;
+ if( !parseInitDeclaratorList(declarators) ){
+ //reportError( i18n("Need an identifier to declare") );
+ //return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ TypedefAST::Node ast = CreateNode<TypedefAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition( DeclarationAST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAsmDefinition()" << endl;
+
+ ADVANCE( Token_asm, "asm" );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ skip( '(', ')' );
+ ADVANCE( ')', ")" );
+ ADVANCE( ';', ';' );
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateDeclaration()" << endl;
+
+ int start = lex->index();
+
+ AST::Node exp;
+
+ int startExport = lex->index();
+ if( lex->lookAhead(0) == Token_export ){
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startExport, lex->index() );
+ exp = n;
+ }
+
+ if( lex->lookAhead(0) != Token_template ){
+ return false;
+ }
+ lex->nextToken();
+
+ TemplateParameterListAST::Node params;
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+ if (lex->lookAhead(0) != '>')
+ parseTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+ }
+
+ DeclarationAST::Node def;
+ if( !parseDeclaration(def) ){
+ reportError( i18n("expected a declaration") );
+ }
+
+ TemplateDeclarationAST::Node ast = CreateNode<TemplateDeclarationAST>();
+ ast->setExported( exp );
+ ast->setTemplateParameterList( params );
+ ast->setDeclaration( def );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperator()" << endl;
+ QString text = lex->lookAhead(0).text();
+
+ switch( lex->lookAhead(0) ){
+ case Token_new:
+ case Token_delete:
+ lex->nextToken();
+ if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ text += "[]";
+ }
+ return true;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '~':
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ case ',':
+ case Token_assign:
+ case Token_shift:
+ case Token_eq:
+ case Token_not_eq:
+ case Token_leq:
+ case Token_geq:
+ case Token_and:
+ case Token_or:
+ case Token_incr:
+ case Token_decr:
+ case Token_ptrmem:
+ case Token_arrow:
+ lex->nextToken();
+ return true;
+
+ default:
+ if( lex->lookAhead(0) == '(' && lex->lookAhead(1) == ')' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseCvQualify( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCvQualify()" << endl;
+
+ int start = lex->index();
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ int n = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_const || tk == Token_volatile ){
+ ++n;
+ int startWord = lex->index();
+ lex->nextToken();
+ AST::Node word = CreateNode<AST>();
+ UPDATE_POS( word, startWord, lex->index() );
+ ast->addNode( word );
+ } else
+ break;
+ }
+
+ if( n == 0 )
+ return false;
+
+
+ //kdDebug(9007)<< "-----------------> token = " << lex->lookAhead(0).text() << endl;
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ int start = lex->index();
+ bool isIntegral = false;
+ bool done = false;
+
+ while( !done ){
+
+ switch( lex->lookAhead(0) ){
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ isIntegral = true;
+ lex->nextToken();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ TypeSpecifierAST::Node ast = CreateNode<TypeSpecifierAST>();
+ if( isIntegral ){
+ ClassOrNamespaceNameAST::Node cl = CreateNode<ClassOrNamespaceNameAST>();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ cl->setName( n );
+ UPDATE_POS( cl, start, lex->index() );
+
+ NameAST::Node name = CreateNode<NameAST>();
+ name->setUnqualifiedName( cl );
+ UPDATE_POS( name, start, lex->index() );
+ ast->setName( name );
+
+ } else {
+ NameAST::Node name;
+ if( !parseName(name) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->setName( name );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parsePtrOperator( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrOperator()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == '*' ){
+ lex->nextToken();
+ } else {
+ int index = lex->index();
+ AST::Node memPtr;
+ if( !parsePtrToMember(memPtr) ){
+ lex->setIndex( index );
+ return false;
+ }
+ }
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseTemplateArgument( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgument()" << endl;
+
+ int start = lex->index();
+ if( parseTypeId(node) ){
+ if( lex->lookAhead(0) == ',' || lex->lookAhead(0) == '>' )
+ return true;
+ }
+
+ lex->setIndex( start );
+ if( !parseLogicalOrExpression(node, true) ){
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier( TypeSpecifierAST::Node& spec )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeSpecifier()" << endl;
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ if( parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ } else {
+
+ if( lex->lookAhead(0) == ':' ){
+ // unnamed bitfield
+ } else if( parseDeclaratorId(declId) ){
+ ast->setDeclaratorId( declId );
+ } else {
+ lex->setIndex( start );
+ return false;
+ }
+
+ if( lex->lookAhead(0) == ':' ){
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = true;
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ if( ast->subDeclarator() && (!isVector || lex->lookAhead(0) != '(') ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ //kdDebug(9007)<< "----------------------> not a parameter declaration, maybe an initializer!?" << endl;
+ lex->setIndex( index );
+ goto update_pos;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto update_pos;
+ }
+
+ lex->nextToken(); // skip ')'
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+update_pos:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseAbstractDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ }
+
+ {
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ } else
+ lex->nextToken();
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+UPDATE_POS:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseEnumSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumSpecifier()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_enum ){
+ return false;
+ }
+
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ EnumSpecifierAST::Node ast = CreateNode<EnumSpecifierAST>();
+ ast->setName( name );
+
+ EnumeratorAST::Node enumerator;
+ if( parseEnumerator(enumerator) ){
+ ast->addEnumerator( enumerator );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() ){
+ EnumeratorAST *lastLit = ast->enumeratorList().last();
+ if( lastLit )
+ lastLit->setComment( comment );
+ }
+
+ if( !parseEnumerator(enumerator) ){
+ //reportError( i18n("Enumerator expected") );
+ break;
+ }
+
+ ast->addEnumerator( enumerator );
+ }
+ }
+
+ if( lex->lookAhead(0) == Token_comment )
+ lex->nextToken();
+ if( lex->lookAhead(0) != '}' )
+ reportError( i18n("} missing") );
+ else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList( TemplateParameterListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameterList()" << endl;
+
+ int start = lex->index();
+
+ TemplateParameterListAST::Node ast = CreateNode<TemplateParameterListAST>();
+
+ TemplateParameterAST::Node param;
+ if( !parseTemplateParameter(param) ){
+ return false;
+ }
+ ast->addTemplateParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateParameter(param) ){
+ syntaxError();
+ break;
+ } else {
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addTemplateParameter( param );
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter( TemplateParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameter()" << endl;
+
+ int start = lex->index();
+ TemplateParameterAST::Node ast = CreateNode<TemplateParameterAST>();
+
+ TypeParameterAST::Node typeParameter;
+ ParameterDeclarationAST::Node param;
+
+ int tk = lex->lookAhead( 0 );
+
+ if( (tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter) ){
+ ast->setTypeParameter( typeParameter );
+ goto ok;
+ }
+
+ if( !parseParameterDeclaration(param) )
+ return false;
+ ast->setTypeValueParameter( param );
+
+ok:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter( TypeParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeParameter()" << endl;
+
+ int start = lex->index();
+ TypeParameterAST::Node ast = CreateNode<TypeParameterAST>();
+
+ AST_FROM_TOKEN( kind, lex->index() );
+ ast->setKind( kind );
+
+ switch( lex->lookAhead(0) ){
+
+ case Token_class:
+ case Token_typename:
+ {
+ lex->nextToken(); // skip class
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+ }
+ break;
+
+ case Token_template:
+ {
+ lex->nextToken(); // skip template
+ ADVANCE( '<', '<' );
+
+ TemplateParameterListAST::Node params;
+ if( !parseTemplateParameterList(params) ){
+ return false;
+ }
+ ast->setTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+
+ if( lex->lookAhead(0) == Token_class )
+ lex->nextToken();
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ NameAST::Node templ_name;
+ parseName( templ_name );
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStorageClassSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static ||
+ tk == Token_extern || tk == Token_mutable ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else
+ break;
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseFunctionSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_inline || tk == Token_virtual || tk == Token_explicit ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else {
+ break;
+ }
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTypeId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeId()" << endl;
+
+ /// @todo implement the AST for typeId
+ int start = lex->index();
+ AST::Node ast = CreateNode<AST>();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ return false;
+ }
+
+ DeclaratorAST::Node decl;
+ parseAbstractDeclarator( decl );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList( InitDeclaratorListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList()" << endl;
+
+ int start = lex->index();
+
+ InitDeclaratorListAST::Node ast = CreateNode<InitDeclaratorListAST>();
+ InitDeclaratorAST::Node decl;
+
+ if( !parseInitDeclarator(decl) ){
+ return false;
+ }
+ ast->addInitDeclarator( decl );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseInitDeclarator(decl) ){
+ syntaxError();
+ break;
+ }
+ if ( !comment.isEmpty() )
+ decl->setComment( comment );
+ ast->addInitDeclarator( decl );
+ }
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList() -- end" << endl;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationClause()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationClauseAST::Node ast = CreateNode<ParameterDeclarationClauseAST>();
+
+ ParameterDeclarationListAST::Node params;
+ if( !parseParameterDeclarationList(params) ){
+
+ if ( lex->lookAhead(0) == ')' )
+ goto good;
+
+ if( lex->lookAhead(0) == Token_ellipsis && lex->lookAhead(1) == ')' ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ goto good;
+ }
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ }
+
+good:
+ ast->setParameterDeclarationList( params );
+
+ /// @todo add ellipsis
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList( ParameterDeclarationListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationList()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationListAST::Node ast = CreateNode<ParameterDeclarationListAST>();
+
+ ParameterDeclarationAST::Node param;
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->addParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( lex->lookAhead(0) == Token_ellipsis )
+ break;
+
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addParameter( param );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration( ParameterDeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclaration()" << endl;
+
+ int start = lex->index();
+
+ // parse decl spec
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+
+ DeclaratorAST::Node decl;
+ if( !parseDeclarator(decl) ){
+ lex->setIndex( index );
+
+ // try with abstract declarator
+ if( !parseAbstractDeclarator(decl) )
+ return false;
+ }
+
+ AST::Node expr;
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+ if( !parseLogicalOrExpression(expr,true) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ ParameterDeclarationAST::Node ast = CreateNode<ParameterDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseClassSpecifier()" << endl;
+
+ int start = lex->index();
+
+ AST::Node classKey;
+ int classKeyStart = lex->index();
+
+ int kind = lex->lookAhead( 0 );
+ if( kind == Token_class || kind == Token_struct || kind == Token_union ){
+ AST::Node asn = CreateNode<AST>();
+ classKey = asn;
+ lex->nextToken();
+ UPDATE_POS( classKey, classKeyStart, lex->index() );
+ } else {
+ return false;
+ }
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ while( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == Token_identifier )
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ BaseClauseAST::Node bases;
+ if( lex->lookAhead(0) == ':' ){
+ if( !parseBaseClause(bases) ){
+ skipUntil( '{' );
+ }
+ }
+
+ QString comment;
+ while (lex->lookAhead(0) == Token_comment) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ ADVANCE( '{', '{' );
+
+ ClassSpecifierAST::Node ast = CreateNode<ClassSpecifierAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setClassKey( classKey );
+ ast->setName( name );
+ ast->setBaseClause( bases );
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ DeclarationAST::Node memSpec = CreateNode<DeclarationAST>();
+ int startDecl = lex->index();
+ if( !parseMemberSpecification(memSpec) ){
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->addDeclaration( memSpec );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAccessSpecifier()" << endl;
+
+ int start = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case Token_public:
+ case Token_protected:
+ case Token_private: {
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ lex->nextToken();
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Parser::advanceAndCheckTrailingComment(QString& comment)
+{
+ Token t = lex->tokenAt( lex->index() );
+ int previousTokenEndLine = 0;
+ t.getEndPosition( &previousTokenEndLine, 0 );
+ lex->nextToken();
+ if( lex->lookAhead(0) != Token_comment )
+ return;
+ t = lex->tokenAt( lex->index() );
+ int commentStartLine = 0;
+ t.getStartPosition( &commentStartLine, 0 );
+ if( commentStartLine != previousTokenEndLine )
+ return;
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+}
+
+bool Parser::parseMemberSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemberSpecification()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ AST::Node access;
+
+ if( lex->lookAhead(0) == ';' ){
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() )
+ node->setComment( comment );
+ return true;
+ } else if( lex->lookAhead(0) == Token_Q_OBJECT || lex->lookAhead(0) == Token_K_DCOP ){
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == Token_signals || lex->lookAhead(0) == Token_k_dcop || lex->lookAhead(0) == Token_k_dcop_signals ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ ast->addAccess( n );
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else if( parseTypedef(node) ){
+ return true;
+ } else if( parseUsing(node) ){
+ return true;
+ } else if( parseTemplateDeclaration(node) ){
+ return true;
+ } else if( parseAccessSpecifier(access) ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ ast->addAccess( access );
+
+ int startSlot = lex->index();
+ if( lex->lookAhead(0) == Token_slots ){
+ lex->nextToken();
+ AST::Node sl = CreateNode<AST>();
+ UPDATE_POS( sl, startSlot, lex->index() );
+ ast->addAccess( sl );
+ }
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseMemberSpecification(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ bool success = parseDeclarationInternal(node, comment);
+ if( success && !comment.isEmpty() ) {
+ node->setComment( comment );
+ //kdDebug(9007) << "Parser::parseMemberSpecification(): comment is " << comment << endl;
+ }
+ return success;
+}
+
+bool Parser::parseCtorInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCtorInitializer()" << endl;
+
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node inits;
+ if( !parseMemInitializerList(inits) ){
+ reportError( i18n("Member initializers expected") );
+ }
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseElaboratedTypeSpecifier()" << endl;
+
+ int start = lex->index();
+
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_class ||
+ tk == Token_struct ||
+ tk == Token_union ||
+ tk == Token_enum ||
+ tk == Token_typename )
+ {
+ AST::Node kind = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( kind, start, lex->index() );
+
+ NameAST::Node name;
+
+ if( parseName(name) ){
+ ElaboratedTypeSpecifierAST::Node ast = CreateNode<ElaboratedTypeSpecifierAST>();
+ ast->setKind( kind );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+
+ lex->setIndex( start );
+ return false;
+}
+
+bool Parser::parseDeclaratorId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaratorId()" << endl;
+ return parseName( node );
+}
+
+bool Parser::parseExceptionSpecification( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExceptionSpecification()" << endl;
+
+ if( lex->lookAhead(0) != Token_throw ){
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( '(', "(" );
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ // extension found in MSVC++ 7.x headers
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->addNode( ellipsis );
+ lex->nextToken();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ } else {
+ parseTypeIdList( node );
+ }
+ ADVANCE( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseEnumerator( EnumeratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumerator()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier ){
+ return false;
+ }
+ lex->nextToken();
+
+ EnumeratorAST::Node ena = CreateNode<EnumeratorAST>();
+ node = ena;
+
+ AST::Node id = CreateNode<AST>();
+ UPDATE_POS( id, start, lex->index() );
+ node->setId( id );
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ node->setExpr( expr );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator( InitDeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node decl;
+ AST::Node init;
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+
+ parseInitializer( init );
+
+ InitDeclaratorAST::Node ast = CreateNode<InitDeclaratorAST>();
+ ast->setDeclarator( decl );
+ ast->setInitializer( init );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+
+bool Parser::parseBaseClause( BaseClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseClause()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ BaseClauseAST::Node bca = CreateNode<BaseClauseAST>();
+
+ BaseSpecifierAST::Node baseSpec;
+ if( parseBaseSpecifier(baseSpec) ){
+ bca->addBaseSpecifier( baseSpec );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseBaseSpecifier(baseSpec) ){
+ reportError( i18n("Base class specifier expected") );
+ return false;
+ }
+ if (!comment.isEmpty())
+ baseSpec->setComment(comment);
+ bca->addBaseSpecifier( baseSpec );
+ }
+ } else
+ return false;
+
+ UPDATE_POS( bca, start, lex->index() );
+ node = bca;
+
+ return true;
+}
+
+bool Parser::parseInitializer( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializer()" << endl;
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node init;
+ if( !parseInitializerClause(node) ){
+ reportError( i18n("Initializer clause expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ')', ")" );
+ }
+
+ return false;
+}
+
+bool Parser::parseMemInitializerList( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerList()" << endl;
+
+ AST::Node init;
+ if( !parseMemInitializer(init) ){
+ return false;
+ }
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( parseMemInitializer(init) ){
+ } else {
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializer()" << endl;
+
+ NameAST::Node initId;
+ if( !parseMemInitializerId(initId) ){
+ reportError( i18n("Identifier expected") );
+ return false;
+ }
+ ADVANCE( '(', '(' );
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ')' );
+
+ return true;
+}
+
+bool Parser::parseTypeIdList( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeIdList()" << endl;
+
+ int start = lex->index();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ return false;
+ }
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ ast->addNode( typeId );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( parseTypeId(typeId) ){
+ if (!comment.isEmpty())
+ typeId->setComment(comment);
+ ast->addNode( typeId );
+ } else {
+ reportError( i18n("Type id expected") );
+ break;
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseBaseSpecifier( BaseSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseSpecifier()" << endl;
+
+ int start = lex->index();
+ BaseSpecifierAST::Node ast = CreateNode<BaseSpecifierAST>();
+
+ AST::Node access;
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+
+ lex->nextToken();
+
+ parseAccessSpecifier( access );
+ } else {
+ parseAccessSpecifier( access );
+
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+ lex->nextToken();
+ }
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Class name expected") );
+ }
+
+ ast->setAccess( access );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseInitializerClause( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializerClause()" << endl;
+
+ if( lex->lookAhead(0) == '{' ){
+ if( !skip('{','}') ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+ } else {
+ if( !parseAssignmentExpression(node) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializerId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerId()" << endl;
+
+ return parseName( node );
+}
+
+bool Parser::parsePtrToMember( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrToMember()" << endl;
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ }
+
+ while( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == '*' ){
+ lex->nextToken(); // skip ::
+ lex->nextToken(); // skip *
+ return true;
+ } else
+ break;
+ }
+
+ return false;
+}
+
+bool Parser::parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnqualifiedName()" << endl;
+
+ int start = lex->index();
+ bool isDestructor = false;
+
+ ClassOrNamespaceNameAST::Node ast = CreateNode<ClassOrNamespaceNameAST>();
+
+ if( lex->lookAhead(0) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ } else if( lex->lookAhead(0) == '~' && lex->lookAhead(1) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken(); // skip ~
+ lex->nextToken(); // skip classname
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ isDestructor = true;
+ } else if( lex->lookAhead(0) == Token_operator ){
+ AST::Node n;
+ if( !parseOperatorFunctionId(n) )
+ return false;
+ ast->setName( n );
+ } else {
+ return false;
+ }
+
+ if( !isDestructor ){
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+
+ // optional template arguments
+ TemplateArgumentListAST::Node args;
+ parseTemplateArgumentList( args );
+
+ if( lex->lookAhead(0) != '>' ){
+ lex->setIndex( index );
+ } else {
+ lex->nextToken();
+ ast->setTemplateArgumentList( args );
+ }
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral( AST::Node& /*node*/ )
+{
+ while( !lex->lookAhead(0).isNull() ) {
+ if( lex->lookAhead(0) == Token_identifier &&
+ lex->lookAhead(0).text() == "L" && lex->lookAhead(1) == Token_string_literal ) {
+
+ lex->nextToken();
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == Token_string_literal ) {
+ lex->nextToken();
+ } else
+ return false;
+ }
+ return true;
+}
+
+bool Parser::skipExpressionStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpressionStatement()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ';', ";" );
+
+ ExpressionStatementAST::Node ast = CreateNode<ExpressionStatementAST>();
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement( StatementAST::Node& node ) // thanks to fiore@8080.it ;)
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+
+ case Token_while:
+ return parseWhileStatement( node );
+
+ case Token_do:
+ return parseDoStatement( node );
+
+ case Token_for:
+ return parseForStatement( node );
+
+ case Token_if:
+ return parseIfStatement( node );
+
+ case Token_switch:
+ return parseSwitchStatement( node );
+
+ case Token_try:
+ return parseTryBlockStatement( node );
+
+ case Token_case:
+ case Token_default:
+ return parseLabeledStatement( node );
+
+ case Token_break:
+ case Token_continue:
+ lex->nextToken();
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_goto:
+ lex->nextToken();
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_return:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ';', ";" );
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement( node );
+
+ case Token_identifier:
+ if( parseLabeledStatement(node) )
+ return true;
+ break;
+ }
+
+ //kdDebug(9007)<< "------------> try with declaration statement" << endl;
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCondition( ConditionAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCondition()" << endl;
+
+ int start = lex->index();
+
+ ConditionAST::Node ast = CreateNode<ConditionAST>();
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ DeclaratorAST::Node decl;
+ if( parseDeclarator(decl) && lex->lookAhead(0) == '=' ) {
+ lex->nextToken();
+
+ AST::Node expr;
+ if( skipExpression(expr) ){
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( start );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) )
+ return false;
+
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+
+bool Parser::parseWhileStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseWhileStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_while, "while" );
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ WhileStatementAST::Node ast = CreateNode<WhileStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDoStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_do, "do" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( Token_while, "while" );
+ ADVANCE_NR( '(' , "(" );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) ){
+ reportError( i18n("expression expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( ')', ")" );
+ ADVANCE_NR( ';', ";" );
+
+ DoStatementAST::Node ast = CreateNode<DoStatementAST>();
+ ast->setStatement( body );
+ //ast->setCondition( condition );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_for, "for" );
+ ADVANCE( '(', "(" );
+
+ StatementAST::Node init;
+ if( !parseForInitStatement(init) ){
+ reportError( i18n("for initialization expected") );
+ return false;
+ }
+
+ ConditionAST::Node cond;
+ parseCondition( cond );
+ ADVANCE( ';', ";" );
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) )
+ return false;
+
+ ForStatementAST::Node ast = CreateNode<ForStatementAST>();
+ ast->setInitStatement( init );
+ ast->setCondition( cond );
+ // ast->setExpression( expression );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForInitStatement()" << endl;
+
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCompoundStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCompoundStatement()" << endl;
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else {
+ ast->addStatement( stmt );
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else {
+ lex->nextToken();
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseIfStatement()" << endl;
+
+ int start = lex->index();
+
+ ADVANCE( Token_if, "if" );
+
+ ADVANCE( '(' , "(" );
+
+ IfStatementAST::Node ast = CreateNode<IfStatementAST>();
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseStatement(stmt) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+
+ if( lex->lookAhead(0) == Token_else ){
+ lex->nextToken();
+ StatementAST::Node elseStmt;
+ if( !parseStatement(elseStmt) ) {
+ reportError( i18n("statement expected") );
+ return false;
+ }
+ ast->setElseStatement( elseStmt );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseSwitchStatement()" << endl;
+ int start = lex->index();
+ ADVANCE( Token_switch, "switch" );
+
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST::Node ast = CreateNode<SwitchStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLabeledStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+ case Token_identifier:
+ case Token_default:
+ if( lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ case Token_case:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("expression expected") );
+ } else if( lex->lookAhead(0) == Token_ellipsis ){
+ lex->nextToken();
+
+ AST::Node expr2;
+ if( !parseConstantExpression(expr2) ){
+ reportError( i18n("expression expected") );
+ }
+ }
+ ADVANCE( ':', ":" );
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ }
+
+ return false;
+}
+
+bool Parser::parseBlockDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBlockDeclaration()" << endl;
+ switch( lex->lookAhead(0) ) {
+ case Token_typedef:
+ return parseTypedef( node );
+ case Token_using:
+ return parseUsing( node );
+ case Token_asm:
+ return parseAsmDefinition( node );
+ case Token_namespace:
+ return parseNamespaceAliasDefinition( node );
+ }
+
+ int start = lex->index();
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if ( !parseTypeSpecifierOrClassSpec(spec) ) { // replace with simpleTypeSpecifier?!?!
+ lex->setIndex( start );
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+
+ if( lex->lookAhead(0) != ';' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition( DeclarationAST::Node& /*node*/ )
+{
+ if ( lex->lookAhead(0) != Token_namespace ) {
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( '=', "=" );
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ }
+
+ ADVANCE( ';', ";" );
+
+ return true;
+
+}
+
+bool Parser::parseDeclarationStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationStatement()" << endl;
+
+ int start = lex->index();
+
+ DeclarationAST::Node decl;
+ if ( !parseBlockDeclaration(decl) ){
+ return false;
+ }
+
+ DeclarationStatementAST::Node ast = CreateNode<DeclarationStatementAST>();
+ ast->setDeclaration( decl );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ //kdDebug(9007)<< "---------------------> found a block declaration" << endl;
+ return true;
+}
+
+bool Parser::parseDeclarationInternal( DeclarationAST::Node& node, QString& comment )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationInternal()" << endl;
+
+ int start = lex->index();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ GroupAST::Node funSpec;
+ bool hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ GroupAST::Node storageSpec;
+ bool hasStorageSpec = parseStorageClassSpecifier( storageSpec );
+
+ if( hasStorageSpec && !hasFunSpec )
+ hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ GroupAST::Node winDeclSpec2;
+ parseWinDeclSpec( winDeclSpec2 );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ int index = lex->index();
+ NameAST::Node name;
+ if( parseName(name) && lex->lookAhead(0) == '(' ){
+ // no type specifier, maybe a constructor or a cast operator??
+
+ lex->setIndex( index );
+
+ InitDeclaratorAST::Node declarator;
+ if( parseInitDeclarator(declarator) ){
+ int endSignature = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ lex->nextToken();
+
+ InitDeclaratorListAST::Node declarators = CreateNode<InitDeclaratorListAST>();
+
+ // update declarators position
+ int startLine, startColumn, endLine, endColumn;
+ if( declarator.get() ){
+ declarator->getStartPosition( &startLine, &startColumn );
+ declarator->getEndPosition( &endLine, &endColumn );
+ declarators->setStartPosition( startLine, startColumn );
+ declarators->setEndPosition( endLine, endColumn );
+ }
+ declarators->addInitDeclarator( declarator );
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setInitDeclaratorList( declarators );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+
+ }
+ break;
+
+ case ':':
+ {
+ AST::Node ctorInit;
+ StatementListAST::Node funBody;
+ if( parseCtorInitializer(ctorInit) && parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setFunctionBody( funBody );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ StatementListAST::Node funBody;
+ if( parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setText( toString(start, endSignature) );
+ ast->setFunctionBody( funBody );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+
+ syntaxError();
+ return false;
+ }
+
+start_decl:
+ lex->setIndex( index );
+
+ if( lex->lookAhead(0) == Token_const && lex->lookAhead(1) == Token_identifier && lex->lookAhead(2) == '=' ){
+ // constant definition
+ lex->nextToken();
+ InitDeclaratorListAST::Node declarators;
+ if( parseInitDeclaratorList(declarators) ){
+ ADVANCE( ';', ";" );
+ DeclarationAST::Node ast = CreateNode<DeclarationAST>();
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ syntaxError();
+ return false;
+ }
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ if ( !hasFunSpec )
+ parseFunctionSpecifier( funSpec ); // e.g. "void inline"
+ spec->setCvQualify( cv );
+
+ InitDeclaratorListAST::Node declarators;
+
+ InitDeclaratorAST::Node decl;
+ int startDeclarator = lex->index();
+ bool maybeFunctionDefinition = false;
+
+ if( lex->lookAhead(0) != ';' ){
+ if( parseInitDeclarator(decl) && lex->lookAhead(0) == '{' ){
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ lex->setIndex( startDeclarator );
+ if( !parseInitDeclaratorList(declarators) ){
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ int endSignature = lex->index();
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ advanceAndCheckTrailingComment( comment );
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setInitDeclaratorList( declarators );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ }
+ return true;
+
+ case '{':
+ {
+ if( !maybeFunctionDefinition ){
+ syntaxError();
+ return false;
+ }
+ StatementListAST::Node funBody;
+ if ( parseFunctionBody(funBody) ) {
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setFunctionBody( funBody );
+ ast->setInitDeclarator( decl );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ }
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::parseFunctionBody( StatementListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionBody()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else
+ ast->addStatement( stmt );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+QString Parser::toString( int start, int end, const QString& sep ) const
+{
+ QStringList l;
+
+ for( int i=start; i<end; ++i ){
+ l << lex->tokenAt(i).text();
+ }
+
+ return l.join( sep ).stripWhiteSpace();
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node )
+{
+ if( parseClassSpecifier(node) )
+ return true;
+ else if( parseEnumSpecifier(node) )
+ return true;
+ else if( parseTypeSpecifier(node) )
+ return true;
+
+ return false;
+}
+
+bool Parser::parseTryBlockStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTryBlockStatement()" << endl;
+
+ if( lex->lookAhead(0) != Token_try ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ if( lex->lookAhead(0) != Token_catch ){
+ reportError( i18n("catch expected") );
+ return false;
+ }
+
+ while( lex->lookAhead(0) == Token_catch ){
+ lex->nextToken();
+ ADVANCE( '(', "(" );
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseCompoundStatement(body) ){
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePrimarExpression()" << endl;
+
+
+ switch( lex->lookAhead(0) ){
+ case Token_string_literal:
+ {
+ AST::Node lit;
+ parseStringLiteral( lit );
+ }
+ return true;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ lex->nextToken();
+ return true;
+
+ case Token_this:
+ lex->nextToken();
+ return true;
+
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast:
+ {
+ lex->nextToken();
+
+ CHECK( '<', "<" );
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( '>', ">" );
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case Token_typeid:
+ {
+ lex->nextToken();
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case '(':
+ {
+ lex->nextToken();
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "token = " << lex->lookAhead(0).text() << endl;
+ AST::Node expr;
+ if( !parseExpression(expr) ){
+ return false;
+ }
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ {
+ int start = lex->index();
+ TypeSpecifierAST::Node typeSpec;
+ if( parseSimpleTypeSpecifier(typeSpec) && lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ return true;
+ }
+
+ lex->setIndex( start );
+ NameAST::Node name;
+ if( parseName(name) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parsePostfixExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePostfixExpression()" << endl;
+
+ AST::Node expr;
+ if( !parsePrimaryExpression(expr) )
+ return false;
+
+ while( true ){
+ switch(lex->lookAhead(0))
+ {
+ case '[':
+ {
+ lex->nextToken();
+ AST::Node e;
+ parseCommaExpression( e );
+ CHECK( ']', "]" );
+ }
+ break;
+
+ case '(':
+ {
+ lex->nextToken();
+ AST::Node funArgs;
+ parseCommaExpression( funArgs );
+ CHECK( ')', ")" );
+ }
+ break;
+
+ case Token_incr:
+ case Token_decr:
+ lex->nextToken();
+ break;
+
+ case '.':
+ case Token_arrow:
+ {
+ lex->nextToken();
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+ }
+ break;
+
+ case Token_typename:
+ {
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression(expr);
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ return true;
+
+ } // end switch
+
+ } // end while
+
+ return true;
+}
+
+bool Parser::parseUnaryExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnaryExpression()" << endl;
+
+ switch( lex->lookAhead(0) ){
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ lex->nextToken();
+ AST::Node expr;
+ return parseCastExpression( expr );
+ }
+
+ case Token_sizeof:
+ {
+ lex->nextToken();
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if( parseTypeId(typeId) && lex->lookAhead(0) == ')' ){
+ lex->nextToken();
+ return true;
+ }
+ lex->setIndex( index );
+ }
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+ }
+
+ case Token_new:
+ return parseNewExpression( node );
+
+ case Token_delete:
+ return parseDeleteExpression( node );
+ }
+
+ return parsePostfixExpression( node );
+}
+
+bool Parser::parseNewExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_new )
+ lex->nextToken();
+
+ CHECK( Token_new, "new");
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( ')', ")" );
+ } else {
+ AST::Node typeId;
+ parseNewTypeId( typeId );
+ }
+
+ AST::Node init;
+ parseNewInitializer( init );
+ return true;
+}
+
+bool Parser::parseNewTypeId( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewTypeId()" << endl;
+ TypeSpecifierAST::Node typeSpec;
+ if( parseTypeSpecifier(typeSpec) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewDeclarator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewDeclarator()" << endl;
+ AST::Node ptrOp;
+ if( parsePtrOperator(ptrOp) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ if( lex->lookAhead(0) == '[' ){
+ while( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseExpression( expr );
+ ADVANCE( ']', "]" );
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewInitializer()" << endl;
+ if( lex->lookAhead(0) != '(' )
+ return false;
+
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseDeleteExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeleteExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_delete )
+ lex->nextToken();
+
+ CHECK( Token_delete, "delete" );
+
+ if( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ CHECK( ']', "]" );
+ }
+
+ AST::Node expr;
+ return parseCastExpression( expr );
+}
+
+bool Parser::parseCastExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCastExpression()" << endl;
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if ( parseTypeId(typeId) ) {
+ if ( lex->lookAhead(0) == ')' ) {
+ lex->nextToken();
+ AST::Node expr;
+ if( parseCastExpression(expr) )
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( index );
+
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+}
+
+bool Parser::parsePmExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser:parsePmExpression()" << endl;
+ AST::Node expr;
+ if( !parseCastExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_ptrmem ){
+ lex->nextToken();
+
+ if( !parseCastExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMultiplicativeExpression()" << endl;
+ AST::Node expr;
+ if( !parsePmExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '*' || lex->lookAhead(0) == '/' || lex->lookAhead(0) == '%' ){
+ lex->nextToken();
+
+ if( !parsePmExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAdditiveExpression()" << endl;
+ AST::Node expr;
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '+' || lex->lookAhead(0) == '-' ){
+ lex->nextToken();
+
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseShiftExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseShiftExpression()" << endl;
+ AST::Node expr;
+ if( !parseAdditiveExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_shift ){
+ lex->nextToken();
+
+ if( !parseAdditiveExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseRelationalExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseRelationalExpression()" << endl;
+ AST::Node expr;
+ if( !parseShiftExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '<' || (lex->lookAhead(0) == '>' && !templArgs) ||
+ lex->lookAhead(0) == Token_leq || lex->lookAhead(0) == Token_geq ){
+ lex->nextToken();
+
+ if( !parseShiftExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseEqualityExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEqualityExpression()" << endl;
+ AST::Node expr;
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_eq || lex->lookAhead(0) == Token_not_eq ){
+ lex->nextToken();
+
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAndExpression()" << endl;
+ AST::Node expr;
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '^' ){
+ lex->nextToken();
+
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '|' ){
+ lex->nextToken();
+
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalAndExpression()" << endl;
+
+ AST::Node expr;
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_and ){
+ lex->nextToken();
+
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression( AST::Node& node, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalOrExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_or ){
+ lex->nextToken();
+
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConditionalExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConditionalExpression()" << endl;
+ AST::Node expr;
+ if( !parseLogicalOrExpression(expr) )
+ return false;
+
+ if( lex->lookAhead(0) == '?' ){
+ lex->nextToken();
+
+ if( !parseExpression(expr) )
+ return false;
+
+ CHECK( ':', ":" );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAssignmentExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAssignmentExpression()" << endl;
+ int start = lex->index();
+ AST::Node expr;
+ if( lex->lookAhead(0) == Token_throw && !parseThrowExpression(expr) )
+ return false;
+ else if( !parseConditionalExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_assign || lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ if( !parseConditionalExpression(expr) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConstantExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConstantExpression()" << endl;
+ int start = lex->index();
+ if( parseConditionalExpression(node) ){
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExpression()" << endl;
+
+ int start = lex->index();
+
+ if( !parseCommaExpression(node) )
+ return false;
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCommaExpression()" << endl;
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ if (!comment.isEmpty())
+ expr->setComment(comment);
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseThrowExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseThrowExpression()" << endl;
+ if( lex->lookAhead(0) != Token_throw )
+ return false;
+
+ CHECK( Token_throw, "throw" );
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ return true;
+}
+
+bool Parser::parseIvarDeclList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecls( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvars( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDeclarator( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMethodDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseUnarySelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReceiver( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMessageExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMessageArgs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArgList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReservedWord( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParms( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParm( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseOptParmList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcSelectorExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelectorArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordNameList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordName( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcEncodeExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcString( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseProtocolRefs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIdentifierList( GroupAST::Node & node )
+{
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier )
+ return false;
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( lex->lookAhead(0) == Token_identifier ){
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+ }
+ ADVANCE( Token_identifier, "identifier" );
+ }
+
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseIdentifierColon( AST::Node & node )
+{
+ Q_UNUSED( node );
+
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } // ### else if PTYPENAME -> return true ;
+
+ return false;
+}
+
+bool Parser::parseObjcProtocolExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcOpenBracketExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcCloseBracket( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_CLASS, "@class" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_PROTOCOL, "@protocol" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcAliasDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_ALIAS, "@alias" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMethodDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseWinDeclSpec( GroupAST::Node & node )
+{
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(0).text() == "__declspec" && lex->lookAhead(1) == '(' ){
+ int start = lex->index();
+ lex->nextToken();
+ lex->nextToken(); // skip '('
+
+ parseIdentifierList( node );
+ ADVANCE( ')', ")" );
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.h b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
new file mode 100644
index 00000000..611ceb14
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
@@ -0,0 +1,221 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+
+struct ParserPrivateData;
+
+class Driver;
+class Lexer;
+class Token;
+struct Error;
+
+class Parser
+{
+public:
+ Parser( Driver* driver, Lexer* lexer );
+ virtual ~Parser();
+
+private:
+ virtual bool reportError( const Error& err );
+ /** @todo remove*/ virtual bool reportError( const QString& msg );
+ /** @todo remove*/ virtual void syntaxError();
+
+public: /*rules*/
+
+ bool parseTranslationUnit( TranslationUnitAST::Node& node );
+
+ bool parseDeclaration( DeclarationAST::Node& node );
+ bool parseBlockDeclaration( DeclarationAST::Node& node );
+ bool parseLinkageSpecification( DeclarationAST::Node& node );
+ bool parseLinkageBody( LinkageBodyAST::Node& node );
+ bool parseNamespace( DeclarationAST::Node& node );
+ bool parseNamespaceAliasDefinition( DeclarationAST::Node& node );
+ bool parseUsing( DeclarationAST::Node& node );
+ bool parseUsingDirective( DeclarationAST::Node& node );
+ bool parseTypedef( DeclarationAST::Node& node );
+ bool parseAsmDefinition( DeclarationAST::Node& node );
+ bool parseTemplateDeclaration( DeclarationAST::Node& node );
+ bool parseDeclarationInternal( DeclarationAST::Node& node, QString& comment );
+
+ bool parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node );
+ bool parseStringLiteral( AST::Node& node );
+ bool parseName( NameAST::Node& node );
+ bool parseOperatorFunctionId( AST::Node& node );
+ bool parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError=true );
+ bool parseOperator( AST::Node& node );
+ bool parseCvQualify( GroupAST::Node& node );
+ bool parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parsePtrOperator( AST::Node& node );
+ bool parseTemplateArgument( AST::Node& node );
+ bool parseTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node );
+ bool parseDeclarator( DeclaratorAST::Node& node );
+ bool parseTemplateParameterList( TemplateParameterListAST::Node& node );
+ bool parseTemplateParameter( TemplateParameterAST::Node& node );
+ bool parseStorageClassSpecifier( GroupAST::Node& node );
+ bool parseFunctionSpecifier( GroupAST::Node& node );
+ bool parseInitDeclaratorList( InitDeclaratorListAST::Node& node );
+ bool parseInitDeclarator( InitDeclaratorAST::Node& node );
+ bool parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node );
+ bool parseCtorInitializer( AST::Node& node );
+ bool parsePtrToMember( AST::Node& node );
+ bool parseEnumSpecifier( TypeSpecifierAST::Node& node );
+ bool parseClassSpecifier( TypeSpecifierAST::Node& node );
+ bool parseWinDeclSpec( GroupAST::Node& node );
+ bool parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseDeclaratorId( NameAST::Node& node );
+ bool parseExceptionSpecification( GroupAST::Node& node );
+ bool parseEnumerator( EnumeratorAST::Node& node );
+ bool parseTypeParameter( TypeParameterAST::Node& node );
+ bool parseParameterDeclaration( ParameterDeclarationAST::Node& node );
+ bool parseTypeId( AST::Node& node );
+ bool parseAbstractDeclarator( DeclaratorAST::Node& node );
+ bool parseParameterDeclarationList( ParameterDeclarationListAST::Node& node );
+ bool parseMemberSpecification( DeclarationAST::Node& node );
+ bool parseAccessSpecifier( AST::Node& node );
+ bool parseTypeIdList( GroupAST::Node& node );
+ bool parseMemInitializerList( AST::Node& node );
+ bool parseMemInitializer( AST::Node& node );
+ bool parseInitializer( AST::Node& node );
+ bool parseBaseClause( BaseClauseAST::Node& node );
+ bool parseBaseSpecifier( BaseSpecifierAST::Node& node );
+ bool parseInitializerClause( AST::Node& node );
+ bool parseMemInitializerId( NameAST::Node& node );
+ bool parseFunctionBody( StatementListAST::Node& node );
+
+ // expression
+ bool skipExpression( AST::Node& node );
+ bool skipCommaExpression( AST::Node& node );
+ bool skipExpressionStatement( StatementAST::Node& node );
+
+ bool parseExpression( AST::Node& node );
+ bool parsePrimaryExpression( AST::Node& node );
+ bool parsePostfixExpression( AST::Node& node );
+ bool parseUnaryExpression( AST::Node& node );
+ bool parseNewExpression( AST::Node& node );
+ bool parseNewTypeId( AST::Node& node );
+ bool parseNewDeclarator( AST::Node& node );
+ bool parseNewInitializer( AST::Node& node );
+ bool parseDeleteExpression( AST::Node& node );
+ bool parseCastExpression( AST::Node& node );
+ bool parsePmExpression( AST::Node& node );
+ bool parseMultiplicativeExpression( AST::Node& node );
+ bool parseAdditiveExpression( AST::Node& node );
+ bool parseShiftExpression( AST::Node& node );
+ bool parseRelationalExpression( AST::Node& node, bool templArgs=false );
+ bool parseEqualityExpression( AST::Node& node, bool templArgs=false );
+ bool parseAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseExclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseInclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseConditionalExpression( AST::Node& node );
+ bool parseAssignmentExpression( AST::Node& node );
+ bool parseConstantExpression( AST::Node& node );
+ bool parseCommaExpression( AST::Node& node );
+ bool parseThrowExpression( AST::Node& node );
+
+ // statement
+ bool parseCondition( ConditionAST::Node& node );
+ bool parseStatement( StatementAST::Node& node );
+ bool parseWhileStatement( StatementAST::Node& node );
+ bool parseDoStatement( StatementAST::Node& node );
+ bool parseForStatement( StatementAST::Node& node );
+ bool parseCompoundStatement( StatementAST::Node& node );
+ bool parseForInitStatement( StatementAST::Node& node );
+ bool parseIfStatement( StatementAST::Node& node );
+ bool parseSwitchStatement( StatementAST::Node& node );
+ bool parseLabeledStatement( StatementAST::Node& node );
+ bool parseDeclarationStatement( StatementAST::Node& node );
+ bool parseTryBlockStatement( StatementAST::Node& node );
+
+ // objective c
+ bool parseObjcDef( DeclarationAST::Node& node );
+ bool parseObjcClassDef( DeclarationAST::Node& node );
+ bool parseObjcClassDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDecl( DeclarationAST::Node& node );
+ bool parseObjcAliasDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDef( DeclarationAST::Node& node );
+ bool parseObjcMethodDef( DeclarationAST::Node& node );
+
+ bool parseIvarDeclList( AST::Node& node );
+ bool parseIvarDecls( AST::Node& node );
+ bool parseIvarDecl( AST::Node& node );
+ bool parseIvars( AST::Node& node );
+ bool parseIvarDeclarator( AST::Node& node );
+ bool parseMethodDecl( AST::Node& node );
+ bool parseUnarySelector( AST::Node& node );
+ bool parseKeywordSelector( AST::Node& node );
+ bool parseSelector( AST::Node& node );
+ bool parseKeywordDecl( AST::Node& node );
+ bool parseReceiver( AST::Node& node );
+ bool parseObjcMessageExpr( AST::Node& node );
+ bool parseMessageArgs( AST::Node& node );
+ bool parseKeywordExpr( AST::Node& node );
+ bool parseKeywordArgList( AST::Node& node );
+ bool parseKeywordArg( AST::Node& node );
+ bool parseReservedWord( AST::Node& node );
+ bool parseMyParms( AST::Node& node );
+ bool parseMyParm( AST::Node& node );
+ bool parseOptParmList( AST::Node& node );
+ bool parseObjcSelectorExpr( AST::Node& node );
+ bool parseSelectorArg( AST::Node& node );
+ bool parseKeywordNameList( AST::Node& node );
+ bool parseKeywordName( AST::Node& node );
+ bool parseObjcEncodeExpr( AST::Node& node );
+ bool parseObjcString( AST::Node& node );
+ bool parseProtocolRefs( AST::Node& node );
+ bool parseIdentifierList( GroupAST::Node& node );
+ bool parseIdentifierColon( AST::Node& node );
+ bool parseObjcProtocolExpr( AST::Node& node );
+ bool parseObjcOpenBracketExpr( AST::Node& node );
+ bool parseObjcCloseBracket( AST::Node& node );
+
+ void advanceAndCheckTrailingComment(QString& comment);
+
+ bool skipUntil( int token );
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip( int l, int r );
+ QString toString( int start, int end, const QString& sep=" " ) const;
+
+private:
+ ParserPrivateData* d;
+ Driver* m_driver;
+ Lexer* lex;
+ int m_problems;
+ int m_maxProblems;
+ bool objcp;
+
+private:
+ Parser( const Parser& source );
+ void operator = ( const Parser& source );
+};
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
new file mode 100644
index 00000000..7f9210e2
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
@@ -0,0 +1,207 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "tree_parser.h"
+#include <kdebug.h>
+
+TreeParser::TreeParser()
+{
+}
+
+TreeParser::~TreeParser()
+{
+}
+
+void TreeParser::parseTranslationUnit( TranslationUnitAST* translationUnit )
+{
+ //kdDebug(9007) << "TreeParser::parseTranslationUnit()" << endl;
+
+ QPtrList<DeclarationAST> declarations = translationUnit->declarationList();
+ QPtrListIterator<DeclarationAST> it( declarations );
+ while( it.current() ){
+ parseDeclaration( it.current() );
+ ++it;
+ }
+}
+
+void TreeParser::parseDeclaration( DeclarationAST* declaration )
+{
+ //kdDebug(9007) << "TreeParser::parseDeclaration()" << endl;
+
+ if( !declaration )
+ return;
+
+ switch( declaration->nodeType() )
+ {
+ case NodeType_LinkageSpecification:
+ parseLinkageSpecification( static_cast<LinkageSpecificationAST*>(declaration) );
+ break;
+
+ case NodeType_Namespace:
+ parseNamespace( static_cast<NamespaceAST*>(declaration) );
+ break;
+
+ case NodeType_NamespaceAlias:
+ parseNamespaceAlias( static_cast<NamespaceAliasAST*>(declaration) );
+ break;
+
+ case NodeType_Using:
+ parseUsing( static_cast<UsingAST*>(declaration) );
+ break;
+
+ case NodeType_UsingDirective:
+ parseUsingDirective( static_cast<UsingDirectiveAST*>(declaration) );
+ break;
+
+ case NodeType_Typedef:
+ parseTypedef( static_cast<TypedefAST*>(declaration) );
+ break;
+
+ case NodeType_TemplateDeclaration:
+ parseTemplateDeclaration( static_cast<TemplateDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_SimpleDeclaration:
+ parseSimpleDeclaration( static_cast<SimpleDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_FunctionDefinition:
+ parseFunctionDefinition( static_cast<FunctionDefinitionAST*>(declaration) );
+ break;
+
+ case NodeType_AccessDeclaration:
+ parseAccessDeclaration( static_cast<AccessDeclarationAST*>(declaration) );
+ break;
+ }
+}
+
+void TreeParser::parseLinkageSpecification( LinkageSpecificationAST* ast )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageSpecification()" << endl;
+ if( ast->linkageBody() )
+ parseLinkageBody( ast->linkageBody() );
+ else if( ast->declaration() )
+ parseDeclaration( ast->declaration() );
+}
+
+void TreeParser::parseNamespace( NamespaceAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespace()" << endl;
+ if( decl->linkageBody() )
+ parseLinkageBody( decl->linkageBody() );
+}
+
+void TreeParser::parseNamespaceAlias( NamespaceAliasAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespaceAlias()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsing( UsingAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsing()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsingDirective( UsingDirectiveAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsingDirective()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseTypedef( TypedefAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTypedef()" << endl;
+ if( decl->typeSpec() )
+ parseTypeSpecifier( decl->typeSpec() );
+}
+
+void TreeParser::parseTemplateDeclaration( TemplateDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTemplateDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseSimpleDeclaration( SimpleDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseSimpleDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseFunctionDefinition( FunctionDefinitionAST* def )
+{
+ //kdDebug(9007) << "TreeParser::parseFunctionDefinition()" << endl;
+ Q_UNUSED( def );
+}
+
+void TreeParser::parseLinkageBody( LinkageBodyAST* linkageBody )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageBody()" << endl;
+ QPtrList<DeclarationAST> declarations = linkageBody->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseTypeSpecifier( TypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseTypeSpecifier()" << endl;
+ switch( typeSpec->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ parseClassSpecifier( static_cast<ClassSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_EnumSpecifier:
+ parseEnumSpecifier( static_cast<EnumSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_ElaboratedTypeSpecifier:
+ parseElaboratedTypeSpecifier( static_cast<ElaboratedTypeSpecifierAST*>(typeSpec) );
+ break;
+ }
+}
+
+void TreeParser::parseClassSpecifier( ClassSpecifierAST* classSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseClassSpecifier()" << endl;
+ QPtrList<DeclarationAST> declarations = classSpec->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseEnumSpecifier( EnumSpecifierAST* enumSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseEnumSpecifier()" << endl;
+ Q_UNUSED( enumSpec );
+}
+
+void TreeParser::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseElaboratedTypeSpecifier()" << endl;
+ Q_UNUSED( typeSpec );
+}
+
+void TreeParser::parseAccessDeclaration ( AccessDeclarationAST * access )
+{
+ //kdDebug(9007) << "TreeParser::parseAccessDeclaration()" << endl;
+ Q_UNUSED( access );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
new file mode 100644
index 00000000..42059408
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
@@ -0,0 +1,59 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __tree_parser_h
+#define __tree_parser_h
+
+#include "ast.h"
+
+class TreeParser
+{
+public:
+ TreeParser();
+ virtual ~TreeParser();
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ virtual void parseDeclaration( DeclarationAST* );
+ virtual void parseLinkageSpecification( LinkageSpecificationAST* );
+ virtual void parseNamespace( NamespaceAST* );
+ virtual void parseNamespaceAlias( NamespaceAliasAST* );
+ virtual void parseUsing( UsingAST* );
+ virtual void parseUsingDirective( UsingDirectiveAST* );
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ virtual void parseLinkageBody( LinkageBodyAST* );
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ virtual void parseTypeSpecifier( TypeSpecifierAST* );
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+private:
+ TreeParser( const TreeParser& source );
+ void operator = ( const TreeParser& source );
+};
+
+#endif // __tree_parser_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
new file mode 100644
index 00000000..a2fd29dd
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
@@ -0,0 +1,310 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "urlutil.h"
+
+#include <qstringlist.h>
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <kdebug.h>
+
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <kdeversion.h>
+#if (KDE_VERSION_MINOR==0) && (KDE_VERSION_MAJOR==3)
+#include <kdevkurl.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Namespace URLUtil
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::filename(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? name : name.mid(slashPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::directory(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? QString("") : name.left(slashPos);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const KURL & parent, const KURL & child, uint slashPolicy) {
+ bool slashPrefix = slashPolicy & SLASH_PREFIX;
+ bool slashSuffix = slashPolicy & SLASH_SUFFIX;
+ if (parent == child)
+ return slashPrefix ? QString("/") : QString("");
+
+ if (!parent.isParentOf(child)) return QString();
+ int a=slashPrefix ? -1 : 1;
+ int b=slashSuffix ? 1 : -1;
+ return child.path(b).mid(parent.path(a).length());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const QString & parent, const QString & child, uint slashPolicy) {
+ return relativePath(KURL(parent), KURL(child), slashPolicy);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::upDir(const QString & path, bool slashSuffix) {
+ int slashPos = path.findRev("/");
+ if (slashPos<1) return QString::null;
+ return path.mid(0,slashPos+ (slashSuffix ? 1 : 0) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+KURL URLUtil::mergeURL(const KURL & source, const KURL & dest, const KURL & child) {
+
+ // if already a child of source, then fine
+ if (source.isParentOf(child) || source == child) return child;
+
+ // if not a child of dest, return blank URL (error)
+ if (!dest.isParentOf(child) && dest != child) return KURL();
+
+ // if child is same as dest, return source
+ if (dest == child) return source;
+
+ // calculate
+ QString childUrlStr = child.url(-1);
+ QString destStemStr = dest.url(1);
+ QString sourceStemStr = source.url(1);
+ return KURL(sourceStemStr.append( childUrlStr.mid( destStemStr.length() ) ) );
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::getExtension(const QString & path) {
+ int dotPos = path.findRev('.');
+ if (dotPos<0) return QString("");
+ return path.mid(dotPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const KURL &baseDirUrl, const KURL &url )
+{
+ QString absBase = extractPathNameAbsolute( baseDirUrl ),
+ absRef = extractPathNameAbsolute( url );
+ int i = absRef.find( absBase, 0, true );
+
+ if (i == -1)
+ return QString();
+
+ if (absRef == absBase)
+ return QString( "." );
+ else
+ return absRef.replace( 0, absBase.length(), QString() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const KURL &url )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, url );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const QString &absFilePath )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath ),
+ fileUrl = KURL::fromPathOrURL( absFilePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath ),
+ fileUrl = KdevKURL::fromPathOrURL( absFilePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, fileUrl );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameAbsolute( const KURL &url )
+{
+ if (isDirectory( url ))
+ return url.path( +1 ); // with trailing "/" if none is present
+ else
+ {
+ // Ok, this is an over-tight pre-condition on "url" since I hope nobody will never
+ // stress this function with absurd cases ... but who knows?
+ /*
+ QString path = url.path();
+ QFileInfo fi( path ); // Argh: QFileInfo is back ;))
+ return ( fi.exists()? path : QString() );
+ */
+ return url.path();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const KURL &url )
+{
+ return isDirectory( url.path() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const QString &absFilePath )
+{
+ return QDir( absFilePath ).exists();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void URLUtil::dump( const KURL::List &urls, const QString &aMessage )
+{
+ if (!aMessage.isNull())
+ {
+ kdDebug(9000) << aMessage << endl;
+ }
+ kdDebug(9000) << " List has " << urls.count() << " elements." << endl;
+
+ for (size_t i = 0; i<urls.count(); ++i)
+ {
+ KURL url = urls[ i ];
+// kdDebug(9000) << " * Element = " << url.path() << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QStringList URLUtil::toRelativePaths( const QString &baseDir, const KURL::List &urls)
+{
+ QStringList paths;
+
+ for (size_t i=0; i<urls.count(); ++i)
+ {
+ paths << extractPathNameRelative( baseDir, urls[i] );
+ }
+
+ return paths;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePathToFile( const QString & dirUrl, const QString & fileUrl )
+{
+ if (dirUrl.isEmpty() || (dirUrl == "/"))
+ return fileUrl;
+
+ QStringList dir = QStringList::split("/", dirUrl, false);
+ QStringList file = QStringList::split("/", fileUrl, false);
+
+ QString resFileName = file.last();
+ file.remove(file.last());
+
+ uint i = 0;
+ while ( (i < dir.count()) && (i < (file.count())) && (dir[i] == file[i]) )
+ i++;
+
+ QString result_up;
+ QString result_down;
+ QString currDir;
+ QString currFile;
+ do
+ {
+ i >= dir.count() ? currDir = "" : currDir = dir[i];
+ i >= file.count() ? currFile = "" : currFile = file[i];
+ qWarning("i = %d, currDir = %s, currFile = %s", i, currDir.latin1(), currFile.latin1());
+ if (currDir.isEmpty() && currFile.isEmpty())
+ break;
+ else if (currDir.isEmpty())
+ result_down += file[i] + '/';
+ else if (currFile.isEmpty())
+ result_up += "../";
+ else
+ {
+ result_down += file[i] + '/';
+ result_up += "../";
+ }
+ i++;
+ }
+ while ( (!currDir.isEmpty()) || (!currFile.isEmpty()) );
+
+ return result_up + result_down + resFileName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// code from qt-3.1.2 version of QDir::canonicalPath()
+QString URLUtil::canonicalPath( const QString & path )
+{
+ QString r;
+ char cur[PATH_MAX+1];
+ if ( ::getcwd( cur, PATH_MAX ) )
+ {
+ char tmp[PATH_MAX+1];
+ if( ::realpath( QFile::encodeName( path ), tmp ) )
+ {
+ r = QFile::decodeName( tmp );
+ }
+ //always make sure we go back to the current dir
+ ::chdir( cur );
+ }
+ return r;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//written by "Dawit A." <adawit@kde.org>
+//borrowed from his patch to KShell
+QString URLUtil::envExpand ( const QString& str )
+{
+ uint len = str.length();
+
+ if (len > 1 && str[0] == '$')
+ {
+ int pos = str.find ('/');
+
+ if (pos < 0)
+ pos = len;
+
+ char* ret = getenv( QConstString(str.unicode()+1, pos-1).string().local8Bit().data() );
+
+ if (ret)
+ {
+ QString expandedStr ( QFile::decodeName( ret ) );
+ if (pos < (int)len)
+ expandedStr += str.mid(pos);
+ return expandedStr;
+ }
+ }
+
+ return str;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
new file mode 100644
index 00000000..3460d28b
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
@@ -0,0 +1,132 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _URLUTIL_H_
+#define _URLUTIL_H_
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <kurl.h>
+
+namespace URLUtil
+{
+ enum SlashesPosition { SLASH_PREFIX = 1, SLASH_SUFFIX = 2 };
+
+ /**
+ * Returns the filename part of a pathname (i.e. everything past the last slash)
+ */
+ QString filename(const QString & pathName);
+ /**
+ * Returns the directory part of a path (i.e. everything up to but not including the last slash)
+ */
+ QString directory(const QString & pathName);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const KURL & parent, const KURL & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const QString & parent, const QString & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a directory and file. Should never return empty path.
+ * Example:
+ * dirUrl: /home/test/src
+ * fileUrl: /home/test/lib/mylib.cpp
+ * returns: ../lib/mylib.cpp
+ */
+ QString relativePathToFile( const QString & dirUrl, const QString & fileUrl );
+ /**
+ *Returns the path 'up one level' - the opposite of what filename returns
+ */
+ QString upDir(const QString & path, bool slashSuffix = false);
+ /**
+ * 'Merges' URLs - changes a URL that starts with dest to start with source instead
+ * Example:
+ * source is /home/me/
+ * dest is /home/you/
+ * child is /home/you/dir1/file1
+ * returns /home/me/dir1/fil1
+ */
+ KURL mergeURL(const KURL & source, const KURL & dest, const KURL & child);
+ /**
+ * Returns the file extension for a filename or path
+ */
+ QString getExtension(const QString & path);
+
+ /**
+ * Given a base directory url in @p baseDirUrl and the url referring to a date sub-directory or file,
+ * it will return the path relative to @p baseDirUrl.
+ * If baseDirUrl == url.path() then it will return ".".
+ * <code>
+ * KURL baseUrl, dirUrl;
+ * baseUrl.setPath( "/home/mario/src/kdevelop/" );
+ * dirUrl.setPath( "/home/mario/src/kdevelop/parts/cvs/" );
+ * QString relPathName = extractDirPathRelative( baseUrl, url ); // == "parts/cvs/"
+ * QString absPathName = extractDirPathAbsolute( url ); // == "/home/mario/src/kdevelop/parts/cvs/"
+ * </code>
+ * Note that if you pass a file name in @p url (instead of a directory) or the @p baseUrl is not contained
+ * in @p url then the function will return "" (void string).
+ */
+ QString extractPathNameRelative(const KURL &baseDirUrl, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const QString &absFilePath );
+
+ /**
+ * Will return the absolute path name referred in @p url.
+ * Look at above for an example.
+ */
+ QString extractPathNameAbsolute( const KURL &url );
+
+ /**
+ * Returns a QStringList of relative (to @p baseDir) paths from a list of KURLs in @p urls
+ */
+ QStringList toRelativePaths( const QString &baseDir, const KURL::List &urls);
+
+ /**
+ * If @p url is a directory will return true, false otherwise.
+ */
+ bool isDirectory( const KURL &url );
+ bool isDirectory( const QString &absFilePath );
+
+ /**
+ * Will dump the list of KURL @p urls on standard output, eventually printing @ aMessage if it
+ * is not null.
+ */
+ void dump( const KURL::List &urls, const QString &aMessage = QString::null );
+
+ /**
+ * Same as QDir::canonicalPath in later versions of QT. Earlier versions of QT
+ * had this broken, so it's reproduced here.
+ */
+ QString canonicalPath( const QString & path );
+
+ /**
+ * Performs environment variable expansion on @p variable.
+ *
+ * @param variable the string with the environment variable to expand.
+ * @return the expanded environment variable value. if the variable
+ * cannot be expanded, @p variable itself is returned.
+ */
+ QString envExpand ( const QString &variable );
+
+}
+
+#endif
diff --git a/umbrello/umbrello/codeimport/nativeimportbase.cpp b/umbrello/umbrello/codeimport/nativeimportbase.cpp
new file mode 100644
index 00000000..058b4d19
--- /dev/null
+++ b/umbrello/umbrello/codeimport/nativeimportbase.cpp
@@ -0,0 +1,340 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "nativeimportbase.h"
+
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <klocale.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+
+NativeImportBase::NativeImportBase(const QString &singleLineCommentIntro) {
+ m_singleLineCommentIntro = singleLineCommentIntro;
+ m_srcIndex = 0;
+ m_scopeIndex = 0; // index 0 is reserved for global scope
+ m_klass = NULL;
+ m_currentAccess = Uml::Visibility::Public;
+ m_isAbstract = false;
+ m_inComment = false;
+}
+
+NativeImportBase::~NativeImportBase() {
+}
+
+void NativeImportBase::setMultiLineComment(const QString &intro, const QString &end) {
+ m_multiLineCommentIntro = intro;
+ m_multiLineCommentEnd = end;
+}
+
+void NativeImportBase::setMultiLineAltComment(const QString &intro, const QString &end) {
+ m_multiLineAltCommentIntro = intro;
+ m_multiLineAltCommentEnd = end;
+}
+
+void NativeImportBase::skipStmt(QString until /* = ";" */) {
+ const uint srcLength = m_source.count();
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != until)
+ m_srcIndex++;
+}
+
+bool NativeImportBase::skipToClosing(QChar opener) {
+ QString closing;
+ switch (opener) {
+ case '{':
+ closing = "}";
+ break;
+ case '[':
+ closing = "]";
+ break;
+ case '(':
+ closing = ")";
+ break;
+ case '<':
+ closing = ">";
+ break;
+ default:
+ kError() << "NativeImportBase::skipToClosing(" << opener
+ << "): " << "illegal input character" << endl;
+ return false;
+ }
+ const QString opening(opener);
+ skipStmt(opening);
+ const uint srcLength = m_source.count();
+ int nesting = 0;
+ while (m_srcIndex < srcLength) {
+ QString nextToken = advance();
+ if (nextToken.isEmpty())
+ break;
+ if (nextToken == closing) {
+ if (nesting <= 0)
+ break;
+ nesting--;
+ } else if (nextToken == opening) {
+ nesting++;
+ }
+ }
+ if (m_srcIndex == srcLength)
+ return false;
+ return true;
+}
+
+QString NativeImportBase::advance() {
+ while (m_srcIndex < m_source.count() - 1) {
+ if (m_source[++m_srcIndex].startsWith(m_singleLineCommentIntro))
+ m_comment += m_source[m_srcIndex];
+ else
+ break;
+ }
+ if (m_srcIndex >= m_source.count() - 1 ||
+ // if last item in m_source is a comment then it is dropped too
+ (m_srcIndex == m_source.count() - 1 &&
+ m_source[m_srcIndex].startsWith(m_singleLineCommentIntro))) {
+ return QString();
+ }
+ return m_source[m_srcIndex];
+}
+
+bool NativeImportBase::preprocess(QString& line) {
+ if (m_multiLineCommentIntro.isEmpty())
+ return false;
+ // Check for end of multi line comment.
+ if (m_inComment) {
+ int delimiterLen = 0;
+ int pos = line.find(m_multiLineCommentEnd);
+ if (pos == -1) {
+ if (! m_multiLineAltCommentEnd.isEmpty())
+ pos = line.find(m_multiLineAltCommentEnd);
+ if (pos == -1) {
+ m_comment += line + "\n";
+ return true; // done
+ }
+ delimiterLen = m_multiLineAltCommentEnd.length();
+ } else {
+ delimiterLen = m_multiLineCommentEnd.length();
+ }
+ if (pos > 0) {
+ QString text = line.mid(0, pos - 1);
+ m_comment += text.stripWhiteSpace();
+ }
+ m_source.append(m_singleLineCommentIntro + m_comment); // denotes comments in `m_source'
+ m_srcIndex++;
+ m_comment = "";
+ m_inComment = false;
+ pos += delimiterLen; // pos now points behind the closed comment
+ if (pos == (int)line.length())
+ return true; // done
+ line = line.mid(pos);
+ }
+ // If we get here then m_inComment is false.
+ // Check for start of multi line comment.
+ int delimIntroLen = 0;
+ int delimEndLen = 0;
+ int pos = line.find(m_multiLineCommentIntro);
+ if (pos != -1) {
+ delimIntroLen = m_multiLineCommentIntro.length();
+ } else if (!m_multiLineAltCommentIntro.isEmpty()) {
+ pos = line.find(m_multiLineAltCommentIntro);
+ if (pos != -1)
+ delimIntroLen = m_multiLineAltCommentIntro.length();
+ }
+ if (pos != -1) {
+ int endpos = line.find(m_multiLineCommentEnd);
+ if (endpos != -1) {
+ delimEndLen = m_multiLineCommentEnd.length();
+ } else if (!m_multiLineAltCommentEnd.isEmpty()) {
+ endpos = line.find(m_multiLineAltCommentEnd);
+ if (endpos != -1)
+ delimEndLen = m_multiLineAltCommentEnd.length();
+ }
+ if (endpos == -1) {
+ m_inComment = true;
+ if (pos + delimIntroLen < (int)line.length()) {
+ QString cmnt = line.mid(pos + delimIntroLen);
+ m_comment += cmnt.stripWhiteSpace() + "\n";
+ }
+ if (pos == 0)
+ return true; // done
+ line = line.left(pos);
+ } else { // It's a multiline comment on a single line.
+ if (endpos > pos + delimIntroLen) {
+ QString cmnt = line.mid(pos + delimIntroLen, endpos - pos - delimIntroLen);
+ cmnt = cmnt.stripWhiteSpace();
+ if (!cmnt.isEmpty())
+ m_source.append(m_singleLineCommentIntro + cmnt);
+ }
+ endpos++; // endpos now points at the slash of "*/"
+ QString pre;
+ if (pos > 0)
+ pre = line.left(pos);
+ QString post;
+ if (endpos + delimEndLen < (int)line.length())
+ post = line.mid(endpos + 1);
+ line = pre + post;
+ }
+ }
+ return false; // The input was not completely consumed by preprocessing.
+}
+
+/// Split the line so that a string is returned as a single element of the list,
+/// when not in a string then split at white space.
+QStringList NativeImportBase::split(const QString& lin) {
+ QStringList list;
+ QString listElement;
+ QChar stringIntro = 0; // buffers the string introducer character
+ bool seenSpace = false;
+ QString line = lin.stripWhiteSpace();
+ for (uint i = 0; i < line.length(); i++) {
+ const QChar& c = line[i];
+ if (stringIntro) { // we are in a string
+ listElement += c;
+ if (c == stringIntro) {
+ if (line[i - 1] != '\\') {
+ list.append(listElement);
+ listElement = QString();
+ stringIntro = 0; // we are no longer in a string
+ }
+ }
+ } else if (c == '"' || c == '\'') {
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ }
+ listElement = stringIntro = c;
+ seenSpace = false;
+ } else if (c == ' ' || c == '\t') {
+ if (seenSpace)
+ continue;
+ seenSpace = true;
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ listElement = QString();
+ }
+ } else {
+ listElement += c;
+ seenSpace = false;
+ }
+ }
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ return list;
+}
+
+/// The lexer. Tokenizes the given string and fills `m_source'.
+/// Stores possible comments in `m_comment'.
+void NativeImportBase::scan(QString line) {
+ if (preprocess(line))
+ return;
+ // Check for single line comment.
+ int pos = line.find(m_singleLineCommentIntro);
+ if (pos != -1) {
+ QString cmnt = line.mid(pos);
+ m_source.append(cmnt);
+ if (pos == 0)
+ return;
+ line = line.left(pos);
+ }
+ if (line.contains(QRegExp("^\\s*$")))
+ return;
+ QStringList words = split(line);
+ for (QStringList::Iterator it = words.begin(); it != words.end(); ++it) {
+ QString word = *it;
+ if (word[0] == '"' || word[0] == '\'')
+ m_source.append(word); // string constants are handled by split()
+ else
+ fillSource(word);
+ }
+}
+
+void NativeImportBase::initVars() {
+}
+
+void NativeImportBase::parseFile(const QString& filename) {
+ QString nameWithoutPath = filename;
+ nameWithoutPath.remove(QRegExp("^.*/"));
+ if (m_parsedFiles.contains(nameWithoutPath))
+ return;
+ m_parsedFiles.append(nameWithoutPath);
+ QString fname = filename;
+ const QString msgPrefix = "NativeImportBase::parseFile(" + filename + "): ";
+ if (filename.contains('/')) {
+ QString path = filename;
+ path.remove( QRegExp("/[^/]+$") );
+ kDebug() << msgPrefix << "adding path " << path << endl;
+ Import_Utils::addIncludePath(path);
+ }
+ if (! QFile::exists(filename)) {
+ if (filename.startsWith("/")) {
+ kError() << msgPrefix << "cannot find file" << endl;
+ return;
+ }
+ bool found = false;
+ QStringList includePaths = Import_Utils::includePathList();
+ for (QStringList::Iterator pathIt = includePaths.begin();
+ pathIt != includePaths.end(); ++pathIt) {
+ QString path = (*pathIt);
+ if (! path.endsWith("/")) {
+ path.append("/");
+ }
+ if (QFile::exists(path + filename)) {
+ fname.prepend(path);
+ found = true;
+ break;
+ }
+ }
+ if (! found) {
+ kError() << msgPrefix << "cannot find file" << endl;
+ return;
+ }
+ }
+ QFile file(fname);
+ if (! file.open(IO_ReadOnly)) {
+ kError() << msgPrefix << "cannot open file" << endl;
+ return;
+ }
+ kDebug() << msgPrefix << "parsing." << endl;
+ // Scan the input file into the QStringList m_source.
+ m_source.clear();
+ m_srcIndex = 0;
+ initVars();
+ QTextStream stream(&file);
+ while (! stream.atEnd()) {
+ QString line = stream.readLine();
+ scan(line);
+ }
+ file.close();
+ // Parse the QStringList m_source.
+ m_klass = NULL;
+ m_currentAccess = Uml::Visibility::Public;
+ m_scopeIndex = 0;
+ m_scope[0] = NULL; // index 0 is reserved for global scope
+ const uint srcLength = m_source.count();
+ for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
+ const QString& firstToken = m_source[m_srcIndex];
+ //kDebug() << '"' << firstToken << '"' << endl;
+ if (firstToken.startsWith(m_singleLineCommentIntro)) {
+ m_comment = firstToken.mid(m_singleLineCommentIntro.length());
+ continue;
+ }
+ if (! parseStmt())
+ skipStmt();
+ m_comment = QString();
+ }
+ kDebug() << msgPrefix << "end of parse." << endl;
+}
+
+void NativeImportBase::initialize() {
+ m_parsedFiles.clear();
+}
+
diff --git a/umbrello/umbrello/codeimport/nativeimportbase.h b/umbrello/umbrello/codeimport/nativeimportbase.h
new file mode 100644
index 00000000..cc82fd91
--- /dev/null
+++ b/umbrello/umbrello/codeimport/nativeimportbase.h
@@ -0,0 +1,227 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NATIVEIMPORTBASE_H
+#define NATIVEIMPORTBASE_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include "classimport.h"
+#include "../umlnamespace.h"
+
+class UMLPackage;
+class UMLClassifier;
+
+/**
+ * Intermediate base class for native Umbrello implementations of
+ * programming language import
+ *
+ * The default call sequence is as follows (RealizedLanguageImport
+ * is used as a placeholder name for the concrete language importer.)
+ * NativeImportBase RealizedLanguageImport
+ * --> importFiles()
+ * parseFile()
+ * -----------------------------------> initVars()
+ * scan()
+ * preprocess() (may be reimplemented)
+ * ---------------------------------> fillSource()
+ * -----------------------------------> parseStmt()
+ * This sequence may be changed by overriding default implementations
+ * of virtual methods in NativeImportBase.
+ *
+ * @short Base class for native implementations of language import
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class NativeImportBase : public ClassImport {
+public:
+ /**
+ * Constructor
+ * @param singleLineCommentIntro "//" for IDL and Java, "--" for Ada
+ */
+ NativeImportBase(const QString &singleLineCommentIntro);
+ virtual ~NativeImportBase();
+
+protected:
+ /**
+ * Implement abstract operation from ClassImport.
+ */
+ void initialize();
+
+ /**
+ * Set the delimiter strings for a multi line comment.
+ *
+ * @param intro In languages with a C style multiline comment
+ * this is slash-star.
+ * @param end In languages with a C style multiline comment
+ * this is star-slash.
+ */
+ void setMultiLineComment(const QString &intro, const QString &end);
+ /**
+ * Set the delimiter strings for an alternative form of
+ * multi line comment. See setMultiLineComment().
+ */
+ void setMultiLineAltComment(const QString &intro, const QString &end);
+
+ /**
+ * Import a single file.
+ * The default implementation should be feasible for languages that
+ * don't depend on an external preprocessor.
+ *
+ * @param filename The file to import.
+ */
+ virtual void parseFile(const QString& filename);
+
+ /**
+ * Initialize auxiliary variables.
+ * This is called by the default implementation of parseFile()
+ * after scanning (before parsing the QStringList m_source.)
+ * The default implementation is empty.
+ */
+ virtual void initVars();
+
+ /**
+ * Scan a single line.
+ * parseFile() calls this for each line read from the input file.
+ * This in turn calls other methods such as preprocess() and fillSource().
+ *
+ * @param line The line to scan.
+ */
+ void scan(QString line);
+
+ /**
+ * Preprocess a line.
+ * May modify the given line to remove items consumed by the
+ * preprocessing such as comments or preprocessor directives.
+ * The default implementation handles multi-line comments.
+ *
+ * @param line The line to preprocess.
+ * @return True if the line was completely consumed,
+ * false if there are still items left in the line
+ * for further analysis.
+ */
+ virtual bool preprocess(QString& line);
+
+ /**
+ * Split the line so that a string is returned as a single element of the list.
+ * When not in a string then split at white space.
+ * The default implementation is suitable for C style strings and char constants.
+ */
+ virtual QStringList split(const QString& line);
+
+ /**
+ * Analyze the given word and fill `m_source'.
+ * A "word" is a whitespace delimited item from the input line.
+ * To be provided by the specific importer class.
+ */
+ virtual void fillSource(const QString& word) = 0;
+
+ /**
+ * Parse the statement which starts at m_source[m_srcIndex]
+ * leaving m_srcIndex pointing to the end of the recognized
+ * statement.
+ * To be provided by the concrete importer.
+ *
+ * @return True if the statement was recognized.
+ */
+ virtual bool parseStmt() = 0;
+
+ /**
+ * Advance m_srcIndex until m_source[m_srcIndex] contains the lexeme
+ * given by `until'.
+ */
+ void skipStmt(QString until = ";");
+
+ /**
+ * Advance m_srcIndex to the index of the corresponding closing character
+ * of the given opening. Nested opening/closing pairs are respected.
+ * Valid openers are: '{' '[' '(' '<'
+ *
+ * @return True for success, false for misuse (invalid opener) or
+ * if no matching closing character is found in m_source.
+ */
+ bool skipToClosing(QChar opener);
+
+ /**
+ * Advance m_srcIndex until m_source[m_srcIndex] contains a non-comment.
+ * Comments encountered during advancement are accumulated in `m_comment'.
+ * If m_srcIndex hits the end of m_source then QString::null is returned.
+ */
+ QString advance();
+
+ /**
+ * How to start a single line comment in this programming language.
+ */
+ QString m_singleLineCommentIntro;
+
+ /**
+ * The scanned lexemes.
+ */
+ QStringList m_source;
+ /**
+ * Used for indexing m_source.
+ */
+ uint m_srcIndex;
+
+ /**
+ * Stack of scopes for use by the specific importer.
+ */
+ UMLPackage *m_scope[32];
+ /**
+ * Indexes m_scope. Index 0 is reserved for global scope.
+ */
+ uint m_scopeIndex;
+
+ /**
+ * The class currently being processed.
+ */
+ UMLClassifier *m_klass;
+ /**
+ * The current access (public/protected/private)
+ */
+ Uml::Visibility m_currentAccess;
+ /**
+ * Intermediate accumulator for comment text.
+ */
+ QString m_comment;
+ /**
+ * True if we are currently in a multi-line comment.
+ * Only applies to languages with multi-line comments.
+ */
+ bool m_inComment;
+ /**
+ * Accumulator for abstractness
+ */
+ bool m_isAbstract;
+
+ /**
+ * List of parsed files. Contains file names without paths.
+ * Before actually parsing a given file, NativeImportBase checks
+ * whether the name is already present in this list in order to
+ * avoid parsing the same file multiple times.
+ */
+ QStringList m_parsedFiles;
+
+ /**
+ * Multi line comment delimiters
+ */
+ QString m_multiLineCommentIntro;
+ QString m_multiLineCommentEnd;
+ /**
+ * Some languages support an alternative set of multi line
+ * comment delimiters.
+ */
+ QString m_multiLineAltCommentIntro;
+ QString m_multiLineAltCommentEnd;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/pascalimport.cpp b/umbrello/umbrello/codeimport/pascalimport.cpp
new file mode 100644
index 00000000..ffe291ff
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pascalimport.cpp
@@ -0,0 +1,413 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "pascalimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+PascalImport::PascalImport() : NativeImportBase("//") {
+ setMultiLineComment("(*", "*)");
+ setMultiLineAltComment("{", "}");
+ initVars();
+}
+
+PascalImport::~PascalImport() {
+}
+
+void PascalImport::initVars() {
+ m_inInterface = false;
+ m_section = sect_NONE;
+ NativeImportBase::m_currentAccess = Uml::Visibility::Public;
+}
+
+void PascalImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.' || c == '#') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ if (c == ':' && word[i + 1] == '=') {
+ m_source.append(":=");
+ i++;
+ } else {
+ m_source.append(QString(c));
+ }
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+void PascalImport::checkModifiers(bool& isVirtual, bool& isAbstract) {
+ const uint srcLength = m_source.count();
+ while (m_srcIndex < srcLength - 1) {
+ QString lookAhead = m_source[m_srcIndex + 1].lower();
+ if (lookAhead != "virtual" && lookAhead != "abstract" &&
+ lookAhead != "override" &&
+ lookAhead != "register" && lookAhead != "cdecl" &&
+ lookAhead != "pascal" && lookAhead != "stdcall" &&
+ lookAhead != "safecall" && lookAhead != "saveregisters" &&
+ lookAhead != "popstack")
+ break;
+ if (lookAhead == "abstract")
+ isAbstract = true;
+ else if (lookAhead == "virtual")
+ isVirtual = true;
+ advance();
+ skipStmt();
+ }
+}
+
+bool PascalImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ QString keyword = m_source[m_srcIndex].lower();
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "uses") {
+ while (m_srcIndex < srcLength - 1) {
+ QString unit = advance();
+ const QString& prefix = unit.lower();
+ if (prefix == "sysutils" || prefix == "types" || prefix == "classes" ||
+ prefix == "graphics" || prefix == "controls" || prefix == "strings" ||
+ prefix == "forms" || prefix == "windows" || prefix == "messages" ||
+ prefix == "variants" || prefix == "stdctrls" || prefix == "extctrls" ||
+ prefix == "activex" || prefix == "comobj" || prefix == "registry" ||
+ prefix == "classes" || prefix == "dialogs") {
+ if (advance() != ",")
+ break;
+ continue;
+ }
+ QString filename = unit + ".pas";
+ if (! m_parsedFiles.contains(unit)) {
+ // Save current m_source and m_srcIndex.
+ QStringList source(m_source);
+ uint srcIndex = m_srcIndex;
+ m_source.clear();
+ parseFile(filename);
+ // Restore m_source and m_srcIndex.
+ m_source = source;
+ m_srcIndex = srcIndex;
+ // Also reset m_currentAccess.
+ // CHECK: need to reset more stuff?
+ m_currentAccess = Uml::Visibility::Public;
+ }
+ if (advance() != ",")
+ break;
+ }
+ return true;
+ }
+ if (keyword == "unit") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package, name,
+ m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "interface") {
+ m_inInterface = true;
+ return true;
+ }
+ if (keyword == "initialization" || keyword == "implementation") {
+ m_inInterface = false;
+ return true;
+ }
+ if (! m_inInterface) {
+ // @todo parseStmt() should support a notion for "quit parsing, close file immediately"
+ return false;
+ }
+ if (keyword == "label") {
+ m_section = sect_LABEL;
+ return true;
+ }
+ if (keyword == "const") {
+ m_section = sect_CONST;
+ return true;
+ }
+ if (keyword == "resourcestring") {
+ m_section = sect_RESOURCESTRING;
+ return true;
+ }
+ if (keyword == "type") {
+ m_section = sect_TYPE;
+ return true;
+ }
+ if (keyword == "var") {
+ m_section = sect_VAR;
+ return true;
+ }
+ if (keyword == "threadvar") {
+ m_section = sect_THREADVAR;
+ return true;
+ }
+ if (keyword == "automated" || keyword == "published" // no concept in UML
+ || keyword == "public") {
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "protected") {
+ m_currentAccess = Uml::Visibility::Protected;
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "packed") {
+ return true; // TBC: perhaps this could be stored in a TaggedValue
+ }
+ if (keyword == "[") {
+ skipStmt("]");
+ return true;
+ }
+ if (keyword == "end") {
+ if (m_klass) {
+ m_klass = NULL;
+ } else if (m_scopeIndex) {
+ m_scopeIndex--;
+ m_currentAccess = Uml::Visibility::Public;
+ } else {
+ kError() << "importPascal: too many \"end\"" << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "function" || keyword == "procedure" ||
+ keyword == "constructor" || keyword == "destructor") {
+ if (m_klass == NULL) {
+ // Unlike a Pascal unit, a UML package does not support subprograms.
+ // In order to map those, we would need to create a UML class with
+ // stereotype <<utility>> for the unit, http://bugs.kde.org/89167
+ bool dummyVirtual = false;
+ bool dummyAbstract = false;
+ checkModifiers(dummyVirtual, dummyAbstract);
+ return true;
+ }
+ const QString& name = advance();
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ if (m_source[m_srcIndex + 1] == "(") {
+ advance();
+ const uint MAX_PARNAMES = 16;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString nextToken = m_source[m_srcIndex + 1].lower();
+ Uml::Parameter_Direction dir = Uml::pd_In;
+ if (nextToken == "var") {
+ dir = Uml::pd_InOut;
+ advance();
+ } else if (nextToken == "const") {
+ advance();
+ } else if (nextToken == "out") {
+ dir = Uml::pd_Out;
+ advance();
+ }
+ QString parName[MAX_PARNAMES];
+ uint parNameCount = 0;
+ do {
+ if (parNameCount >= MAX_PARNAMES) {
+ kError() << "MAX_PARNAMES is exceeded at " << name << endl;
+ break;
+ }
+ parName[parNameCount++] = advance();
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ":") {
+ kError() << "importPascal: expecting ':' at " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ break;
+ }
+ nextToken = advance();
+ if (nextToken.lower() == "array") {
+ nextToken = advance().lower();
+ if (nextToken != "of") {
+ kError() << "importPascal(" << name << "): expecting 'array OF' at "
+ << nextToken << endl;
+ skipStmt();
+ return false;
+ }
+ nextToken = advance();
+ }
+ for (uint i = 0; i < parNameCount; i++) {
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, nextToken, parName[i]);
+ att->setParmKind(dir);
+ }
+ if (advance() != ";")
+ break;
+ }
+ }
+ QString returnType;
+ if (keyword == "function") {
+ if (advance() != ":") {
+ kError() << "importPascal: expecting \":\" at function "
+ << name << endl;
+ return false;
+ }
+ returnType = advance();
+ } else if (keyword == "constructor" || keyword == "destructor") {
+ op->setStereotype(keyword);
+ }
+ skipStmt();
+ bool isVirtual = false;
+ bool isAbstract = false;
+ checkModifiers(isVirtual, isAbstract);
+ Import_Utils::insertMethod(m_klass, op, m_currentAccess, returnType,
+ !isVirtual, isAbstract, false, false, m_comment);
+ return true;
+ }
+ if (m_section != sect_TYPE) {
+ skipStmt();
+ return true;
+ }
+ if (m_klass == NULL) {
+ const QString& name = m_source[m_srcIndex];
+ QString nextToken = advance();
+ if (nextToken != "=") {
+ kDebug() << "PascalImport::parseStmt(" << name << "): "
+ << "expecting '=' at " << nextToken << endl;
+ return false;
+ }
+ keyword = advance().lower();
+ if (keyword == "(") {
+ // enum type
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "set") { // @todo implement Pascal set types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "array") { // @todo implement Pascal array types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "file") { // @todo implement Pascal file types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "^") { // @todo implement Pascal pointer types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "class" || keyword == "interface") {
+ Uml::Object_Type t = (keyword == "class" ? Uml::ot_Class : Uml::ot_Interface);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name,
+ m_scope[m_scopeIndex], m_comment);
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ QString lookAhead = m_source[m_srcIndex + 1];
+ if (lookAhead == "(") {
+ advance();
+ do {
+ QString base = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class, base, NULL);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ Import_Utils::createGeneralization(klass, parent);
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ")") {
+ kError() << "PascalImport: expecting \")\" at "
+ << m_source[m_srcIndex] << endl;
+ return false;
+ }
+ lookAhead = m_source[m_srcIndex + 1];
+ }
+ if (lookAhead == ";") {
+ skipStmt();
+ return true;
+ }
+ if (lookAhead == "of") {
+ // @todo implement class-reference type
+ return false;
+ }
+ m_klass = klass;
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "record") {
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class, name,
+ m_scope[m_scopeIndex], m_comment);
+ ns->setStereotype("record");
+ m_klass = static_cast<UMLClassifier*>(ns);
+ return true;
+ }
+ if (keyword == "function" || keyword == "procedure") {
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Datatype, name,
+ m_scope[m_scopeIndex], m_comment);
+ if (m_source[m_srcIndex + 1] == "(")
+ skipToClosing('(');
+ skipStmt();
+ return true;
+ }
+ // Datatypes: TO BE DONE
+ return false;
+ }
+ // At this point we need a class because we're expecting its member attributes.
+ if (m_klass == NULL) {
+ kDebug() << "importPascal: skipping " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString name, stereotype;
+ if (keyword == "property") {
+ stereotype = keyword;
+ name = advance();
+ } else {
+ name = m_source[m_srcIndex];
+ }
+ if (advance() != ":") {
+ kError() << "PascalImport: expecting \":\" at " << name << " "
+ << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString typeName = advance();
+ QString initialValue;
+ if (advance() == "=") {
+ initialValue = advance();
+ QString token;
+ while ((token = advance()) != ";") {
+ initialValue.append(' ' + token);
+ }
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ attr->setStereotype(stereotype);
+ attr->setInitialValue(initialValue);
+ skipStmt();
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/pascalimport.h b/umbrello/umbrello/codeimport/pascalimport.h
new file mode 100644
index 00000000..975dc423
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pascalimport.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PASCALIMPORT_H
+#define PASCALIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * Pascal code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PascalImport : public NativeImportBase {
+public:
+ PascalImport();
+ virtual ~PascalImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Check for, and skip over, all modifiers following a method.
+ * Set the output arguments on encountering abstract and/or virtual.
+ *
+ * @param isVirtual return value, set to true when "virtual" seen
+ * @param isAbstract return value, set to true when "abstract" seen
+ */
+ void checkModifiers(bool& isVirtual, bool& isAbstract);
+
+ /**
+ * Auxiliary variable, becomes true when keyword "interface" is seen
+ */
+ bool m_inInterface;
+
+ enum Section_Type { sect_NONE, sect_LABEL, sect_CONST, sect_RESOURCESTRING,
+ sect_TYPE, sect_VAR, sect_THREADVAR };
+ /**
+ * Auxiliary variable, contains the current section
+ */
+ Section_Type m_section;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/pythonimport.cpp b/umbrello/umbrello/codeimport/pythonimport.cpp
new file mode 100644
index 00000000..af59cf8a
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pythonimport.cpp
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "pythonimport.h"
+
+// qt/kde includes
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+PythonImport::PythonImport() : NativeImportBase("#") {
+ setMultiLineComment("\"\"\"", "\"\"\"");
+ initVars();
+}
+
+PythonImport::~PythonImport() {
+}
+
+void PythonImport::initVars() {
+ m_srcIndentIndex = 0;
+ m_srcIndent[m_srcIndentIndex] = 0;
+ m_braceWasOpened = false;
+}
+
+bool PythonImport::preprocess(QString& line) {
+ if (NativeImportBase::preprocess(line))
+ return true;
+ // Handle single line comment
+ int pos = line.find(m_singleLineCommentIntro);
+ if (pos != -1) {
+ QString cmnt = line.mid(pos);
+ m_source.append(cmnt);
+ m_srcIndex++;
+ if (pos == 0)
+ return true;
+ line = line.left(pos);
+ line.remove( QRegExp("\\s+$") );
+ }
+ // Transform changes in indentation into braces a la C++/Java/Perl/...
+ pos = line.find( QRegExp("\\S") );
+ if (pos == -1)
+ return true;
+ bool isContinuation = false;
+ int leadingWhite = line.left(pos).contains( QRegExp("\\s") );
+ if (leadingWhite > m_srcIndent[m_srcIndentIndex]) {
+ if (m_srcIndex == 0) {
+ kError() << "PythonImport::preprocess(): internal error 1" << endl;
+ return true;
+ }
+ if (m_braceWasOpened) {
+ m_srcIndent[++m_srcIndentIndex] = leadingWhite;
+ m_braceWasOpened = false;
+ } else {
+ isContinuation = true;
+ }
+ } else {
+ while (m_srcIndentIndex > 0 && leadingWhite < m_srcIndent[m_srcIndentIndex]) {
+ m_srcIndentIndex--;
+ m_source.append("}");
+ m_srcIndex++;
+ }
+ }
+ if (line.endsWith(":")) {
+ line.replace( QRegExp(":$"), "{" );
+ m_braceWasOpened = true;
+ } else {
+ m_braceWasOpened = false;
+ }
+ if (!isContinuation && !m_braceWasOpened)
+ line += ';';
+ return false; // The input was not completely consumed by preprocessing.
+}
+
+void PythonImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ m_srcIndex++;
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ m_srcIndex++;
+ }
+ }
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ m_srcIndex++;
+ }
+}
+
+void PythonImport::skipBody() {
+ if (m_source[m_srcIndex] != "{")
+ skipStmt("{");
+ int braceNesting = 0;
+ QString token;
+ while (!(token = advance()).isNull()) {
+ if (token == "}") {
+ if (braceNesting <= 0)
+ break;
+ braceNesting--;
+ } else if (token == "{") {
+ braceNesting++;
+ }
+ }
+}
+
+bool PythonImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ const QString& keyword = m_source[m_srcIndex];
+ if (keyword == "class") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ if (advance() == "(") {
+ while (m_srcIndex < srcLength - 1 && advance() != ")") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "def") {
+ if (m_klass == NULL) {
+ // skip functions outside of a class
+ skipBody();
+ return true;
+ }
+ const QString& name = advance();
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ if (advance() != "(") {
+ kError() << "importPython def " << name << ": expecting \"(\"" << endl;
+ skipBody();
+ return true;
+ }
+ while (m_srcIndex < srcLength && advance() != ")") {
+ const QString& parName = m_source[m_srcIndex];
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, "string", parName);
+ if (advance() != ",")
+ break;
+ }
+ Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, "string",
+ false /*isStatic*/, false /*isAbstract*/, false /*isFriend*/,
+ false /*isConstructor*/, m_comment);
+ skipBody();
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importPython: too many }" << endl;
+ return true;
+ }
+ return false; // @todo parsing of attributes
+}
+
+
diff --git a/umbrello/umbrello/codeimport/pythonimport.h b/umbrello/umbrello/codeimport/pythonimport.h
new file mode 100644
index 00000000..41fea0d4
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pythonimport.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PYTHONIMPORT_H
+#define PYTHONIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * Python code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PythonImport : public NativeImportBase {
+public:
+ PythonImport();
+ virtual ~PythonImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& line);
+
+ /**
+ * Reimplement operation from NativeImportBase.
+ * In addition to handling multiline comments, this method transforms
+ * changes in leading indentation into braces (opening brace for increase
+ * in indentation, closing brace for decrease in indentation) in m_source.
+ * Removal of Python's indentation sensitivity simplifies subsequent
+ * processing using Umbrello's native import framework.
+ */
+ bool preprocess(QString& line);
+
+ /**
+ * Skip ahead to outermost closing brace
+ */
+ void skipBody();
+
+ /**
+ * Buffer for number of indentation characters (whitespace,
+ * i.e. tabs or spaces) at beginning of input line.
+ */
+ int m_srcIndent[100];
+
+ /**
+ * Index for m_srcIndent[]. Index 0 is reserved and contains 0.
+ */
+ int m_srcIndentIndex;
+
+ /**
+ * Auxiliary flag denoting the opening of a block
+ */
+ bool m_braceWasOpened;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codemethodblock.cpp b/umbrello/umbrello/codemethodblock.cpp
new file mode 100644
index 00000000..4a6e1f6a
--- /dev/null
+++ b/umbrello/umbrello/codemethodblock.cpp
@@ -0,0 +1,191 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+#include "codemethodblock.h"
+#include "codeclassfield.h"
+#include "classifiercodedocument.h"
+#include "codegenerationpolicy.h"
+#include "uml.h"
+
+// Constructors/Destructors
+//
+
+CodeMethodBlock::CodeMethodBlock ( ClassifierCodeDocument * doc, UMLObject * parentObj, const QString & body, const QString & comment)
+ : CodeBlockWithComments ((CodeDocument*)doc, body, comment), OwnedCodeBlock (parentObj)
+{
+ initFields();
+}
+
+CodeMethodBlock::~CodeMethodBlock ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// we can just call the superclass
+CodeDocument * CodeMethodBlock::getParentDocument() {
+ return TextBlock::getParentDocument();
+}
+
+/**
+ * Get the starting text that begins this method before the body is printed.
+ */
+QString CodeMethodBlock::getStartMethodText() const {
+ return m_startMethod;
+}
+
+/**
+ * Get the ending text that finishes this method after the body is printed.
+ */
+QString CodeMethodBlock::getEndMethodText() const {
+ return m_endMethod;
+}
+
+/**
+ * Set the starting text that begins this method before the body is printed.
+ */
+void CodeMethodBlock::setStartMethodText (const QString &value) {
+ m_startMethod = value;
+}
+
+/**
+ * Set the ending text that finishes this method after the body is printed.
+ */
+void CodeMethodBlock::setEndMethodText (const QString &value) {
+ m_endMethod = value;
+}
+
+// Other methods
+//
+
+void CodeMethodBlock::release () {
+ // just call super-class versions
+ OwnedCodeBlock::release();
+ TextBlock::release();
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void CodeMethodBlock::setAttributesOnNode ( QDomDocument & doc, QDomElement & elem) {
+
+ // set super-class attributes
+ CodeBlockWithComments::setAttributesOnNode(doc, elem);
+ OwnedCodeBlock::setAttributesOnNode(doc, elem);
+
+ // set local class attributes
+ if(getContentType() != AutoGenerated)
+ {
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ elem.setAttribute("startMethodText",encodeText(getStartMethodText(),endLine));
+ elem.setAttribute("endMethodText",encodeText(getEndMethodText(),endLine));
+ }
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeMethodBlock::setAttributesFromNode ( QDomElement & elem) {
+
+ // set attributes from the XMI
+ CodeBlockWithComments::setAttributesFromNode(elem); // superclass load
+ OwnedCodeBlock::setAttributesFromNode(elem); // superclass load
+
+ // now load local attributes
+ if(getContentType() != AutoGenerated)
+ {
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ setStartMethodText(decodeText(elem.attribute("startMethodText",""),endLine));
+ setEndMethodText(decodeText(elem.attribute("endMethodText",""),endLine));
+ }
+
+}
+
+void CodeMethodBlock::setAttributesFromObject(TextBlock * obj)
+{
+
+ CodeBlockWithComments::setAttributesFromObject(obj);
+
+ CodeMethodBlock * mb = dynamic_cast<CodeMethodBlock*>(obj);
+ if(mb)
+ {
+ setStartMethodText(mb->getStartMethodText());
+ setEndMethodText(mb->getEndMethodText());
+ }
+
+}
+
+/**
+ * @return QString
+ */
+QString CodeMethodBlock::toString ( ) {
+
+ QString string = QString("");
+
+ if(getWriteOutText()) {
+
+ QString indent = getIndentationString();
+ QString bodyIndent = getIndentationString(getIndentationLevel()+1);
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ QString startMethod = formatMultiLineText ( getStartMethodText(), indent, endLine);
+ QString body = formatMultiLineText (getText(), bodyIndent, endLine);
+ QString endMethod = formatMultiLineText( getEndMethodText(), indent, endLine);
+
+ QString comment = getComment()->toString();
+ if(!comment.isEmpty() && getComment()->getWriteOutText())
+ string.append(comment);
+
+ if(!startMethod.isEmpty())
+ string.append(startMethod);
+
+ if(!body.isEmpty())
+ string.append(body);
+
+ if(!endMethod.isEmpty())
+ string.append(endMethod);
+
+ }
+
+ return string;
+
+}
+
+void CodeMethodBlock::initFields ( ) {
+
+ m_startMethod = QString("");
+ m_endMethod = QString("");
+}
+
+void CodeMethodBlock::syncToParent ( )
+{
+
+ getComment()->setText(getParentObject()->getDoc());
+
+ updateMethodDeclaration();
+
+ // only update IF we are NOT AutoGenerated
+ if(getContentType() != AutoGenerated)
+ return;
+
+ updateContent();
+}
+
+#include "codemethodblock.moc"
diff --git a/umbrello/umbrello/codemethodblock.h b/umbrello/umbrello/codemethodblock.h
new file mode 100644
index 00000000..65cbe2e8
--- /dev/null
+++ b/umbrello/umbrello/codemethodblock.h
@@ -0,0 +1,133 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+
+
+#ifndef CODEMETHODBLOCK_H
+#define CODEMETHODBLOCK_H
+
+#include <qstring.h>
+
+#include "ownedcodeblock.h"
+#include "codeblockwithcomments.h"
+#include "umlnamespace.h"
+
+class ClassifierCodeDocument;
+
+/**
+ * class CodeMethodBlock
+ * A common type of "code block" that occurs in OO code.
+ */
+
+class CodeMethodBlock : public CodeBlockWithComments, public OwnedCodeBlock
+{
+ friend class CodeGenObjectWithTextBlocks;
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+
+ /**
+ * Constructors
+ */
+ CodeMethodBlock ( ClassifierCodeDocument * doc, UMLObject * parentObj,
+ const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeMethodBlock ( );
+
+ // Public attributes
+ //
+
+ /**
+ * @return QString
+ */
+ virtual QString toString ( );
+
+ /**
+ * Get the starting text that begins this method before the body is printed.
+ */
+ QString getStartMethodText () const;
+
+ /**
+ * Get the ending text that finishes this method after the body is printed.
+ */
+ QString getEndMethodText () const;
+
+ // get the parent code document
+ CodeDocument * getParentDocument();
+
+protected:
+
+
+ /** causes the text block to release all of its connections
+ * and any other text blocks that it 'owns'.
+ * needed to be called prior to deletion of the textblock.
+ */
+ virtual void release ();
+
+ /**
+ * Set the starting text that begins this method before the body is printed.
+ */
+ void setStartMethodText (const QString &value);
+
+ /**
+ * Set the ending text that finishes this method after the body is printed.
+ */
+ void setEndMethodText (const QString &value);
+
+ /** this is the method called from within syncToparent().
+ * to update the start and end Method text. It is called
+ * whether or not the method is Auto or User generated.
+ */
+ virtual void updateMethodDeclaration ( ) = 0;
+
+ /** this is the method called from within syncToparent().
+ * to update the *body* of the method
+ * It is only called if the method is Auto-generated.
+ */
+ virtual void updateContent ( ) = 0;
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+private:
+
+ QString m_startMethod;
+ QString m_endMethod;
+
+ void initFields ( );
+
+public slots:
+
+ virtual void syncToParent();
+};
+
+#endif // CODEMETHODBLOCK_H
diff --git a/umbrello/umbrello/codeoperation.cpp b/umbrello/umbrello/codeoperation.cpp
new file mode 100644
index 00000000..3e98af8f
--- /dev/null
+++ b/umbrello/umbrello/codeoperation.cpp
@@ -0,0 +1,177 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+// own header
+#include "codeoperation.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "codedocument.h"
+#include "codegenerator.h"
+#include "classifiercodedocument.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+
+
+// Constructors/Destructors
+//
+
+CodeOperation::CodeOperation ( ClassifierCodeDocument * doc , UMLOperation * parentOp, const QString & body, const QString & comment)
+ : CodeMethodBlock ( doc, parentOp, body, comment)
+{
+ init(parentOp);
+}
+
+CodeOperation::~CodeOperation ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+/**
+ * Add a Parameter object to the m_parameterVector List
+ */
+/*
+void CodeOperation::addParameter ( CodeParameter * add_object ) {
+ m_parameterVector.append(add_object);
+}
+*/
+
+/**
+ * Remove a Parameter object from m_parameterVector List
+ */
+/*
+void CodeOperation::removeParameter ( CodeParameter * remove_object ) {
+ m_parameterVector.remove(remove_object);
+}
+*/
+
+/**
+ * Get the list of Parameter objects held by m_parameterVector
+ * @return QPtrList<CodeParameter *> list of Parameter objects held by
+ * m_parameterVector
+ */
+/*
+QPtrList<CodeParameter> CodeOperation::getParameterList ( ) {
+ return m_parameterVector;
+}
+*/
+
+/**
+ * Get the parent UMLOperation of this codeoperation.
+ */
+UMLOperation * CodeOperation::getParentOperation( ) {
+ return dynamic_cast<UMLOperation*>(getParentObject());
+}
+
+// Other methods
+//
+
+/** Save the XMI representation of this object
+ */
+void CodeOperation::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "codeoperation" );
+
+ // set attributes
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void CodeOperation::loadFromXMI ( QDomElement & root )
+{
+ setAttributesFromNode(root);
+}
+
+QString CodeOperation::findTag (UMLOperation * op) {
+ return QString("operation_" + ID2STR(op->getID()));
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void CodeOperation::setAttributesOnNode ( QDomDocument & doc, QDomElement & elem)
+{
+
+ CodeMethodBlock::setAttributesOnNode(doc,elem); // superclass
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeOperation::setAttributesFromNode ( QDomElement & element)
+{
+
+ CodeMethodBlock::setAttributesFromNode(element); // superclass
+
+ // now set local attributes
+
+ // oops..this is done in the parent class "ownedcodeblock".
+ // we simply need to record the parent operation here
+ // m_parentOperation->disconnect(this); // always disconnect from current parent
+
+ QString idStr = element.attribute("parent_id","-1");
+ Uml::IDType id = STR2ID(idStr);
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(id);
+ UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
+
+ if(op)
+ init(op);
+ else
+ kError()<<"ERROR: could'nt load code operation because of missing UMLoperation, corrupt savefile?"<<endl;
+
+}
+
+void CodeOperation::setAttributesFromObject(TextBlock * obj)
+{
+
+ CodeMethodBlock::setAttributesFromObject(obj);
+
+ CodeOperation * op = dynamic_cast<CodeOperation*>(obj);
+ if(op)
+ init((UMLOperation*) op->getParentObject());
+
+}
+
+void CodeOperation::init (UMLOperation * parentOp)
+{
+
+ m_canDelete = false; // we cant delete these with the codeeditor, delete the UML operation instead.
+ setTag(CodeOperation::findTag(parentOp));
+
+ // not needed.. done by parent "ownedcodeblock" class
+ // connect(parentOp,SIGNAL(modified()),this,SLOT(syncToParent()));
+
+}
+
+void CodeOperation::updateContent() {
+ kDebug() << "CodeOperation::updateContent is called!" << endl;
+ // Empty. Unlike codeaccessor methods for most (all?) languages
+ // we don't auto-generate content for operations
+}
+
+
+#include "codeoperation.moc"
diff --git a/umbrello/umbrello/codeoperation.h b/umbrello/umbrello/codeoperation.h
new file mode 100644
index 00000000..abe97e75
--- /dev/null
+++ b/umbrello/umbrello/codeoperation.h
@@ -0,0 +1,94 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+
+#ifndef CODEOPERATION_H
+#define CODEOPERATION_H
+
+#include <qstring.h>
+
+#include "codemethodblock.h"
+#include "operation.h"
+
+// class CodeParameter;
+
+class CodeOperation : public CodeMethodBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ CodeOperation ( ClassifierCodeDocument * doc , UMLOperation * parent,
+ const QString & body = "", const QString & comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeOperation ( );
+
+ /**
+ * Get the parent UMLOperation of this codeoperation.
+ */
+ UMLOperation * getParentOperation( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /** Find the value of the tag that this operation would have.
+ */
+ static QString findTag (UMLOperation * op) ;
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+protected:
+
+ // list of parameters used by this code operation.
+ // QPtrList<CodeParameter> m_parameterVector;
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ virtual void updateMethodDeclaration() = 0;
+ virtual void updateContent();
+
+private:
+
+ UMLOperation * m_parentOperation;
+ void init (UMLOperation * parentOp);
+
+};
+
+#endif // CODEOPERATION_H
diff --git a/umbrello/umbrello/codeparameter.cpp b/umbrello/umbrello/codeparameter.cpp
new file mode 100644
index 00000000..f2f429fa
--- /dev/null
+++ b/umbrello/umbrello/codeparameter.cpp
@@ -0,0 +1,287 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+// own header
+#include "codeparameter.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "association.h"
+#include "attribute.h"
+#include "classifiercodedocument.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlrole.h"
+#include "uml.h"
+#include "codegenerators/codegenfactory.h"
+
+// Constructors/Destructors
+//
+
+CodeParameter::CodeParameter ( ClassifierCodeDocument * parentDoc, UMLObject * parentObject )
+ : QObject ( (QObject*) parentObject, "ACodeParam")
+{
+ initFields( parentDoc, parentObject );
+}
+
+CodeParameter::~CodeParameter ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+/**
+ * Utility method to get the value of parent object abstract value
+ * @return the value of parent object abstrtact
+ */
+bool CodeParameter::getAbstract ( ) {
+ return m_parentObject->getAbstract();
+}
+
+/**
+ * Utility method to get the value of parent object static
+ * Whether or not this is static.
+ * @return the value of static
+ */
+bool CodeParameter::getStatic ( ) {
+ return m_parentObject->getStatic();
+}
+
+/**
+ * Utility method to get the value of parent object name
+ * The name of this code parameter.
+ * @return the value
+ */
+QString CodeParameter::getName ( ) const {
+ return m_parentObject->getName();
+}
+
+/**
+ * Utility method to get the value of parent object type.
+ * the typeName of this parameters (e.g. boolean, int, etc or perhaps Class name of
+ * an object)
+ * @return the value of type
+ */
+QString CodeParameter::getTypeName ( ) {
+ UMLAttribute * at = (UMLAttribute*) m_parentObject;
+ return at->getTypeName();
+}
+
+/**
+ * Utility method to get the value of parent object scope.
+ * The visibility of this code parameter.
+ * @return the value of parent object scope
+ */
+Uml::Visibility CodeParameter::getVisibility ( ) const {
+ return m_parentObject->getVisibility();
+}
+
+/**
+ * Set the value of m_initialValue
+ * The initial value of this code parameter
+ * @param new_var the new value of m_initialValue
+ */
+void CodeParameter::setInitialValue ( const QString &new_var ) {
+ m_initialValue = new_var;
+}
+
+/**
+ * Get the value of m_initialValue
+ * The initial value of this code parameter
+ * @return the value of m_initialValue
+ */
+QString CodeParameter::getInitialValue ( ) {
+ return m_initialValue;
+}
+
+/**
+ * Set a Comment object.
+ */
+void CodeParameter::setComment ( CodeComment * object ) {
+ m_comment = object;
+}
+
+/**
+ * Get the Comment on this object.
+ */
+CodeComment * CodeParameter::getComment ( ) {
+ return m_comment;
+}
+
+
+ClassifierCodeDocument * CodeParameter::getParentDocument ( ) {
+ return m_parentDocument;
+}
+
+/**
+ * Get the ParentObject object
+ */
+UMLObject * CodeParameter::getParentObject ( ) {
+ return m_parentObject;
+}
+
+// need to get the ID of the parent object
+// this is kind of broken for UMLRoles.
+QString CodeParameter::getID () {
+ UMLRole * role = dynamic_cast<UMLRole*>(m_parentObject);
+ if(role)
+ {
+ // cant use Role "ID" as that is used to distinquish if its
+ // role "A" or "B"
+ UMLAssociation *assoc = role->getParentAssociation();
+ return ID2STR(assoc->getID());
+ } else
+ return ID2STR(m_parentObject->getID());
+
+}
+
+// Other methods
+//
+
+void CodeParameter::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement)
+{
+
+
+ // set local attributes
+ blockElement.setAttribute("parent_id",getID());
+
+ // setting ID's takes special treatment
+ // as UMLRoles arent properly stored in the XMI right now.
+ // (change would break the XMI format..save for big version change )
+ UMLRole * role = dynamic_cast<UMLRole*>(m_parentObject);
+ if(role)
+ blockElement.setAttribute("role_id", role->getRole());
+ else
+ blockElement.setAttribute("role_id","-1");
+
+ blockElement.setAttribute("initialValue",getInitialValue());
+
+ // a comment which we will store in its own separate child node block
+ QDomElement commElement = doc.createElement( "header" );
+ getComment()->saveToXMI(doc, commElement); // comment
+ blockElement.appendChild( commElement);
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void CodeParameter::setAttributesFromNode ( QDomElement & root) {
+
+ // set local attributes, parent object first
+ QString idStr = root.attribute("parent_id","-1");
+ Uml::IDType id = STR2ID(idStr);
+
+ // always disconnect
+ m_parentObject->disconnect(this);
+
+ // now, what is the new object we want to set?
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(id);
+ if(obj)
+ {
+
+ // FIX..one day.
+ // Ugh. This is UGLY, but we have to do it this way because UMLRoles
+ // don't go into the document list of UMLobjects, and have the same
+ // ID as their parent UMLAssociations. So..the drill is then special
+ // for Associations..in that case we need to find out which role will
+ // serve as the parameter here. The REAL fix, of course, would be to
+ // treat UMLRoles on a more even footing, but im not sure how that change
+ // might ripple throughout the code and cause problems. Thus, since the
+ // change appears to be needed for only this part, I'll do this crappy
+ // change instead. -b.t.
+ UMLAssociation * assoc = dynamic_cast<UMLAssociation*>(obj);
+ if(assoc) {
+ // In this case we init with indicated role child obj.
+ UMLRole * role = 0;
+ int role_id = root.attribute("role_id","-1").toInt();
+ if(role_id == 1)
+ role = assoc->getUMLRole(Uml::A);
+ else if(role_id == 0)
+ role = assoc->getUMLRole(Uml::B);
+ else
+ kError() << "corrupt save file? "
+ << "cant get proper UMLRole for codeparameter uml id:"
+ << ID2STR(id) << " w/role_id:" << role_id << endl;
+
+ // init using UMLRole obj
+ initFields ( m_parentDocument, role);
+
+ } else
+ initFields ( m_parentDocument, obj); // just the regular approach
+
+ } else
+ kError() << "Cant load CodeParam: parentUMLObject w/id:"
+ << ID2STR(id) << " not found, corrupt save file?" << endl;
+
+ // other attribs now
+ setInitialValue(root.attribute("initialValue",""));
+
+ // load comment now
+ // by looking for our particular child element
+ QDomNode node = root.firstChild();
+ QDomElement element = node.toElement();
+ bool gotComment = false;
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if( tag == "header" ) {
+ QDomNode cnode = element.firstChild();
+ QDomElement celem = cnode.toElement();
+ getComment()->loadFromXMI(celem);
+ gotComment = true;
+ break;
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ if(!gotComment)
+ kWarning()<<" loadFromXMI : Warning: unable to initialize CodeComment in codeparam:"<<this<<endl;
+
+
+}
+
+/**
+ * create the string representation of this code parameter.
+ * @return QString
+ */
+void CodeParameter::syncToParent( ) {
+
+ getComment()->setText(getParentObject()->getDoc());
+
+ updateContent();
+}
+
+void CodeParameter::initFields ( ClassifierCodeDocument * doc, UMLObject * obj) {
+
+ m_parentObject = obj;
+
+ m_parentDocument = doc;
+ m_initialValue = QString("");
+
+ m_comment = CodeGenFactory::newCodeComment(m_parentDocument);
+ m_comment->setText(getParentObject()->getDoc());
+
+ connect(m_parentObject,SIGNAL(modified()),this,SLOT(syncToParent()));
+}
+
+#include "codeparameter.moc"
diff --git a/umbrello/umbrello/codeparameter.h b/umbrello/umbrello/codeparameter.h
new file mode 100644
index 00000000..8ee4dc45
--- /dev/null
+++ b/umbrello/umbrello/codeparameter.h
@@ -0,0 +1,160 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Jun 20 2003
+ */
+
+
+
+#ifndef CODEPARAMETER_H
+#define CODEPARAMETER_H
+
+
+#include "umlnamespace.h"
+#include "codecomment.h"
+
+/**
+ * class CodeParameter
+ * A parameter on some type of code.
+ */
+
+class ClassifierCodeDocument;
+class UMLObject;
+
+class CodeParameter : public QObject
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Empty Constructor
+ */
+ CodeParameter ( ClassifierCodeDocument * doc, UMLObject * parentObj );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~CodeParameter ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Get the parent Code Document
+ */
+ ClassifierCodeDocument * getParentDocument ( );
+
+ /**
+ * Get the parent UMLObject
+ */
+ UMLObject * getParentObject ( );
+
+ /**
+ * Utility method. Get the value of parent abstract value.
+ * @return the value
+ */
+ bool getAbstract ( );
+
+ /**
+ * Utility method. Get the value of parent Static
+ * Whether or not this is static.
+ * @return the value
+ */
+ bool getStatic ( );
+
+ /**
+ * The name of this code parameter.
+ * @return the value of parameter name
+ */
+ QString getName ( ) const;
+
+ /**
+ * Get the value of m_typeName
+ * the typeName of this parameters (e.g. boolean, int, etc or perhaps Class name of
+ * an object)
+ * @return the value of m_typeName
+ */
+ virtual QString getTypeName ( );
+
+ /**
+ * Get the value of m_visibility
+ * The visibility of this code parameter.
+ * @return the value of m_visibility
+ */
+ Uml::Visibility getVisibility ( ) const;
+
+ /**
+ * Set the value of m_initialValue
+ * The initial value of this code parameter
+ * @param new_var the new value of m_initialValue
+ */
+ virtual void setInitialValue ( const QString &new_var );
+
+ /**
+ * Get the value of m_initialValue
+ * The initial value of this code parameter
+ * @return the value of m_initialValue
+ */
+ virtual QString getInitialValue ( );
+
+ /**
+ * Set a Comment
+ */
+ void setComment ( CodeComment * comment );
+
+ /**
+ * get any Comment object on this
+ */
+ CodeComment * getComment ( );
+
+ // the id of this parameter is the same as the parent UMLObject id.
+ QString getID ();
+
+protected:
+
+ virtual void updateContent() = 0;
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+private:
+
+ ClassifierCodeDocument * m_parentDocument;
+ UMLObject * m_parentObject;
+ CodeComment * m_comment;
+
+ // The initial value of this code parameter
+ QString m_initialValue;
+
+ void initFields ( ClassifierCodeDocument * doc, UMLObject * obj);
+
+public slots:
+
+ void syncToParent ();
+
+};
+
+#endif // CODEPARAMETER_H
diff --git a/umbrello/umbrello/codeviewerstate.h b/umbrello/umbrello/codeviewerstate.h
new file mode 100644
index 00000000..0a45fce9
--- /dev/null
+++ b/umbrello/umbrello/codeviewerstate.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEVIEWERSTATE_H
+#define CODEVIEWERSTATE_H
+
+#include <qcolor.h>
+#include <qfont.h>
+
+namespace Settings {
+
+/// configurable params for the code viewer tool
+struct CodeViewerState {
+ int height;
+ int width;
+ bool showHiddenBlocks;
+ bool blocksAreHighlighted;
+ QFont font;
+ QColor paperColor;
+ QColor fontColor;
+ QColor selectedColor;
+ QColor editBlockColor;
+ QColor nonEditBlockColor;
+ QColor umlObjectColor;
+ QColor hiddenColor;
+};
+
+}
+
+#endif // CODEVIEWERSTATE_H
diff --git a/umbrello/umbrello/component.cpp b/umbrello/umbrello/component.cpp
new file mode 100644
index 00000000..6c8f674b
--- /dev/null
+++ b/umbrello/umbrello/component.cpp
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "component.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+// app includes
+#include "association.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "clipboard/idchangelog.h"
+
+UMLComponent::UMLComponent(const QString & name, Uml::IDType id)
+ : UMLPackage(name, id) {
+ init();
+}
+
+UMLComponent::~UMLComponent() {
+}
+
+void UMLComponent::init() {
+ m_BaseType = Uml::ot_Component;
+ m_executable = false;
+}
+
+UMLObject* UMLComponent::clone() const {
+ UMLComponent *clone = new UMLComponent();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLComponent::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement componentElement = UMLObject::save("UML:Component", qDoc);
+ componentElement.setAttribute("executable", m_executable);
+ // Save contained components if any.
+ if (m_objects.count()) {
+ QDomElement ownedElement = qDoc.createElement( "UML:Namespace.ownedElement" );
+ for (UMLObject *obj = m_objects.first(); obj; obj = m_objects.next())
+ obj->saveToXMI (qDoc, ownedElement);
+ componentElement.appendChild(ownedElement);
+ }
+ qElement.appendChild(componentElement);
+}
+
+bool UMLComponent::load(QDomElement& element) {
+ QString executable = element.attribute("executable", "0");
+ m_executable = (bool)executable.toInt();
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (Uml::tagEq(type, "Namespace.ownedElement") ||
+ Uml::tagEq(type, "Namespace.contents")) {
+ //CHECK: Umbrello currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement))
+ return false;
+ continue;
+ }
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+ if( !pObject ) {
+ kWarning() << "UMLComponent::load: "
+ << "Unknown type of umlobject to create: "
+ << type << endl;
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (pObject->loadFromXMI(tempElement)) {
+ addObject(pObject);
+ } else {
+ delete pObject;
+ }
+ }
+ return true;
+}
+
+void UMLComponent::setExecutable(bool executable) {
+ m_executable = executable;
+}
+
+bool UMLComponent::getExecutable() {
+ return m_executable;
+}
+
+#include "component.moc"
diff --git a/umbrello/umbrello/component.h b/umbrello/umbrello/component.h
new file mode 100644
index 00000000..014cf39e
--- /dev/null
+++ b/umbrello/umbrello/component.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef COMPONENT_H
+#define COMPONENT_H
+
+#include "package.h"
+
+
+/**
+ * This class contains the non-graphical information required for a
+ * UML Component.
+ * This class inherits from @ref UMLPackage which contains most
+ * of the information.
+ *
+ * @short Non-graphical information for a Component.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLComponent : public UMLPackage {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a Component.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLComponent(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Empty deconstructor.
+ */
+ virtual ~UMLComponent();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates the UML:Component element including its operations,
+ * attributes and templates
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * sets m_executable
+ */
+ void setExecutable(bool executable);
+
+ /**
+ * returns the value of m_executable
+ */
+ bool getExecutable();
+
+protected:
+ /**
+ * Loads the UML:Component element including its operations,
+ * attributes and templates
+ */
+ bool load( QDomElement & element );
+
+private:
+ /**
+ * holds whether this is an executable component or not
+ */
+ bool m_executable;
+};
+
+#endif
diff --git a/umbrello/umbrello/componentwidget.cpp b/umbrello/umbrello/componentwidget.cpp
new file mode 100644
index 00000000..f4c38270
--- /dev/null
+++ b/umbrello/umbrello/componentwidget.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "componentwidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+
+// app includes
+#include <kdebug.h>
+#include "component.h"
+#include "umlview.h"
+
+
+ComponentWidget::ComponentWidget(UMLView * view, UMLComponent *c)
+ : UMLWidget(view, c) {
+ init();
+}
+
+void ComponentWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Component);
+ setSize(100, 30);
+ m_pMenu = 0;
+ //set defaults from m_pView
+ if (m_pView) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ m_bShowStereotype = ops.classState.showStereoType;
+ }
+ //maybe loading and this may not be set.
+ if (m_pObject) {
+ updateComponentSize();
+ update();
+ }
+}
+
+ComponentWidget::~ComponentWidget() {}
+
+void ComponentWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLComponent *umlcomp = static_cast<UMLComponent*>(m_pObject);
+ if (umlcomp == NULL)
+ return;
+ UMLWidget::setPen(p);
+ if ( umlcomp->getExecutable() ) {
+ QPen thickerPen = p.pen();
+ thickerPen.setWidth(2);
+ p.setPen(thickerPen);
+ }
+ if ( UMLWidget::getUseFillColour() ) {
+ p.setBrush( UMLWidget::getFillColour() );
+ } else {
+ p.setBrush( m_pView->viewport()->backgroundColor() );
+ }
+
+ const int w = width();
+ const int h = height();
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString name = getName();
+ const QString stereotype = m_pObject->getStereotype();
+
+ p.drawRect(offsetX + 2*COMPONENT_MARGIN, offsetY, w - 2*COMPONENT_MARGIN, h);
+ p.drawRect(offsetX, offsetY + h/2 - fontHeight/2 - fontHeight, COMPONENT_MARGIN*4, fontHeight);
+ p.drawRect(offsetX, offsetY + h/2 + fontHeight/2, COMPONENT_MARGIN*4, fontHeight);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ int lines = 1;
+
+ if (!stereotype.isEmpty()) {
+ p.drawText(offsetX + (COMPONENT_MARGIN*4), offsetY + (h/2) - fontHeight,
+ w - (COMPONENT_MARGIN*4), fontHeight, Qt::AlignCenter,
+ m_pObject->getStereotype(true));
+ lines = 2;
+ }
+
+ if ( UMLWidget::getIsInstance() ) {
+ font.setUnderline(true);
+ p.setFont(font);
+ name = UMLWidget::getInstanceName() + " : " + name;
+ }
+
+ if (lines == 1) {
+ p.drawText(offsetX + (COMPONENT_MARGIN*4), offsetY + (h/2) - (fontHeight/2),
+ w - (COMPONENT_MARGIN*4), fontHeight, Qt::AlignCenter, name );
+ } else {
+ p.drawText(offsetX + (COMPONENT_MARGIN*4), offsetY + (h/2),
+ w - (COMPONENT_MARGIN*4), fontHeight, Qt::AlignCenter, name );
+ }
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize ComponentWidget::calculateSize() {
+ if ( !m_pObject) {
+ return QSize(70, 70);
+ }
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ QString name = m_pObject->getName();
+ if ( UMLWidget::getIsInstance() ) {
+ name = UMLWidget::getInstanceName() + " : " + name;
+ }
+
+ int width = fm.width(name);
+
+ int stereoWidth = 0;
+ if (!m_pObject->getStereotype().isEmpty()) {
+ stereoWidth = fm.width(m_pObject->getStereotype(true));
+ }
+ if (stereoWidth > width)
+ width = stereoWidth;
+ width += COMPONENT_MARGIN * 6;
+ width = 70>width ? 70 : width; //minumin width of 70
+
+ int height = (2*fontHeight) + (COMPONENT_MARGIN * 3);
+
+ return QSize(width, height);
+}
+
+void ComponentWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement conceptElement = qDoc.createElement("componentwidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
diff --git a/umbrello/umbrello/componentwidget.h b/umbrello/umbrello/componentwidget.h
new file mode 100644
index 00000000..7266ef01
--- /dev/null
+++ b/umbrello/umbrello/componentwidget.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef COMPONENTWIDGET_H
+#define COMPONENTWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLComponent;
+
+#define COMPONENT_MARGIN 10
+
+/**
+ * Defines a graphical version of the Component. Most of the functionality
+ * will come from the @ref UMLComponent class.
+ *
+ * @short A graphical version of a Component.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ComponentWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a ComponentWidget.
+ *
+ * @param view The parent of this ComponentWidget.
+ * @param c The UMLComponent this will be representing.
+ */
+ ComponentWidget(UMLView * view, UMLComponent *c);
+
+ /**
+ * destructor
+ */
+ virtual ~ComponentWidget();
+
+ /**
+ * Overrides standard method
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "componentwidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * The right mouse button menu
+ */
+ ListPopupMenu* m_pMenu;
+};
+
+#endif
diff --git a/umbrello/umbrello/configurable.cpp b/umbrello/umbrello/configurable.cpp
new file mode 100644
index 00000000..5aaec43c
--- /dev/null
+++ b/umbrello/umbrello/configurable.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "configurable.h"
+
+// Qt includes
+#include <qstringlist.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <kconfig.h>
+
+// local includes
+#include "pluginloader.h"
+#include "plugin.h"
+
+using namespace Umbrello;
+
+
+Configurable::Configurable() :
+ _plugins()
+{
+ _plugins.setAutoDelete(false);
+}
+
+Configurable::~Configurable()
+{
+ unloadPlugins();
+}
+
+bool
+Configurable::loadPlugins(KConfig *config,
+ const QString &key)
+{
+ bool ret = true;
+
+ QStringList names = config->readListEntry(key);
+ for(uint i = 0; i != names.size(); i++) {
+ const QString &name = names[i];
+
+ kdDebug() << "loading plugin " << name << endl;
+
+ // load the plugin
+ Plugin *plugin = PluginLoader::instance()->loadPlugin(name);
+
+ // keep the plugin
+ if(plugin) {
+ _plugins.append(plugin);
+ }
+ }
+
+ return ret;
+}
+
+bool
+Configurable::unloadPlugins()
+{
+ // just iterate through and dereference all the
+ // plugins.
+ for(uint i = 0; i != _plugins.count(); i++) {
+ Plugin *plugin = _plugins.at(i);
+ plugin->unload();
+ }
+ _plugins.clear();
+ return true;
+}
diff --git a/umbrello/umbrello/configurable.h b/umbrello/umbrello/configurable.h
new file mode 100644
index 00000000..8debcba1
--- /dev/null
+++ b/umbrello/umbrello/configurable.h
@@ -0,0 +1,118 @@
+/***************************************************************************
+ configurable.h
+ -------------------
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMBRELLO_CONFIGURABLE_H
+#define UMBRELLO_CONFIGURABLE_H
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+// forward declarations
+class KLibrary;
+class KConfig;
+
+/**
+ * @defgroup U2_Lib Umbrello2 API
+ * The Umbrello2 API consists of classes available to applications, command
+ * line tools and plugins. These classes define common subsets of functionality
+ * these objects. Primarily, these classes provide application support for
+ * features such as configurability and plugin management. Also provided
+ * within this API are the core interfaces for GUI management.
+ */
+
+namespace Umbrello
+{
+// forward declarations
+class Plugin;
+
+/**
+ * @ingroup U2_Lib
+ *
+ * The Configurable class is the base class of all functional objects that
+ * can be created for modeling applications. There are three types of
+ * functionality: applications (with GUIs), command line tools and plugins.
+ * This class provides a common configuration interface that the functional
+ * classes use for default configuration and plugin management. Although
+ * the Configurable class is primarily an interface it does provide some
+ * convenience methods that can be used by derived classes to help manage
+ * plugins. These methods are conceptually part of a larger (althought
+ * currently undefined) set of configuration helper methods that reduce
+ * the amount of code duplication for applications, tools and plugins.
+ *
+ * At this time, this class only assists with the configuration of the
+ * event-driven plugin management system. All interfaces and convenience
+ * methods support the hidden configuration functionality for derived
+ * classes.
+ *
+ * @todo Do we have to delete the plugin object when its unloaded? Is it
+ * possible that we can just unload the library and created objects are
+ * automatically destroyed? I need some clarification of what actually
+ * happens here...
+ */
+class Configurable
+{
+public:
+ /** Construct a configurable object. */
+ Configurable();
+
+ /**
+ * Destroy a configurable object. If there are any plugins that (for
+ * some reason) have not been unloaded, we need to unload them here.
+ */
+ virtual ~Configurable();
+
+ /**
+ * The configure interface is required to be implemented by all subclasses
+ * of this class. It is expected that configuration implementations all
+ * understand how to attain their session configuration file. These files
+ * are stored in ~/.kde/share/config. What actions are taken with the
+ * configuration class are defined by implementing classes.
+ */
+ virtual bool configure() = 0;
+
+protected:
+ /**
+ * This is a convenience method for derived classes. Configuration actions
+ * that are intended to load plugins can use this method to parse the string
+ * and actually load the plugins. The string is a set of space separated names.
+ * Each name corresponds the the share object implementing the plugin.
+ *
+ * @param config The object used for configuration.
+ * @param key The key in the group that contains libraries to load.
+ *
+ * @return True on success, false on failure.
+ */
+ bool loadPlugins(KConfig *config, const QString &key);
+
+ /**
+ * This is a convenience method for derived classes. When a functional object
+ * (i.e., application, tool or plugin) is shutdown, it can use this method
+ * to automatically unload all dependant plugins.
+ *
+ * @return True on success false on failure.
+ */
+ bool unloadPlugins();
+
+private:
+ typedef QPtrList<Plugin> PluginList;
+
+ PluginList _plugins; ///< List of loaded plugins
+};
+}
+
+#endif
diff --git a/umbrello/umbrello/cr128-mime-umbrellofile.png b/umbrello/umbrello/cr128-mime-umbrellofile.png
new file mode 100644
index 00000000..2c5684bf
--- /dev/null
+++ b/umbrello/umbrello/cr128-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/cr16-mime-umbrellofile.png b/umbrello/umbrello/cr16-mime-umbrellofile.png
new file mode 100644
index 00000000..1f239c95
--- /dev/null
+++ b/umbrello/umbrello/cr16-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/cr22-mime-umbrellofile.png b/umbrello/umbrello/cr22-mime-umbrellofile.png
new file mode 100644
index 00000000..6cc27cff
--- /dev/null
+++ b/umbrello/umbrello/cr22-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/cr32-mime-umbrellofile.png b/umbrello/umbrello/cr32-mime-umbrellofile.png
new file mode 100644
index 00000000..5019e291
--- /dev/null
+++ b/umbrello/umbrello/cr32-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/cr48-mime-umbrellofile.png b/umbrello/umbrello/cr48-mime-umbrellofile.png
new file mode 100644
index 00000000..14946716
--- /dev/null
+++ b/umbrello/umbrello/cr48-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/cr64-mime-umbrellofile.png b/umbrello/umbrello/cr64-mime-umbrellofile.png
new file mode 100644
index 00000000..b258c668
--- /dev/null
+++ b/umbrello/umbrello/cr64-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/crsc-mime-umbrellofile.svgz b/umbrello/umbrello/crsc-mime-umbrellofile.svgz
new file mode 100644
index 00000000..0c0eb5e4
--- /dev/null
+++ b/umbrello/umbrello/crsc-mime-umbrellofile.svgz
Binary files differ
diff --git a/umbrello/umbrello/datatypewidget.cpp b/umbrello/umbrello/datatypewidget.cpp
new file mode 100644
index 00000000..33509b95
--- /dev/null
+++ b/umbrello/umbrello/datatypewidget.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "datatypewidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+
+// app includes
+#include "classifier.h"
+#include "operation.h"
+#include "classifierlistitem.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "listpopupmenu.h"
+
+
+#define CIRCLE_SIZE 30
+
+DatatypeWidget::DatatypeWidget(UMLView* view, UMLClassifier *d) : UMLWidget(view, d) {
+ init();
+}
+
+DatatypeWidget::~DatatypeWidget() {}
+
+void DatatypeWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Datatype);
+ setSize(100, 30);
+ m_pMenu = 0;
+}
+
+void DatatypeWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if (UMLWidget::getUseFillColour()) {
+ p.setBrush(UMLWidget::getFillColour());
+ } else {
+ p.setBrush(m_pView->viewport()->backgroundColor());
+ }
+
+ int w = width();
+ int h = height();
+
+ QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int fontHeight = fm.lineSpacing();
+ QString name = getName();
+
+ p.drawRect(offsetX, offsetY, w, h);
+ p.setPen(QPen(Qt::black));
+
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ p.setFont(font);
+ p.drawText(offsetX + DATATYPE_MARGIN, offsetY,
+ w - DATATYPE_MARGIN* 2,fontHeight,
+ Qt::AlignCenter, m_pObject->getStereotype(true));
+
+ font.setItalic( m_pObject->getAbstract() );
+ p.setFont(font);
+ p.drawText(offsetX + DATATYPE_MARGIN, offsetY + fontHeight,
+ w - DATATYPE_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize DatatypeWidget::calculateSize() {
+ if (!m_pObject) {
+ return UMLWidget::calculateSize();
+ }
+ int width, height;
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ lines++; //for the stereotype
+
+ height = width = 0;
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ //set width to name to start with
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_pObject->getFullyQualifiedName()).width();
+ int w = getFontMetrics(FT_BOLD).boundingRect(m_pObject->getStereotype(true)).width();
+
+ width = w > width?w:width;
+
+ //allow for width margin
+ width += DATATYPE_MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void DatatypeWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement conceptElement = qDoc.createElement("datatypewidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
+bool DatatypeWidget::loadFromXMI( QDomElement & qElement ) {
+ return UMLWidget::loadFromXMI(qElement);
+}
+
diff --git a/umbrello/umbrello/datatypewidget.h b/umbrello/umbrello/datatypewidget.h
new file mode 100644
index 00000000..fb60d536
--- /dev/null
+++ b/umbrello/umbrello/datatypewidget.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef DATATYPEWIDGET_H
+#define DATATYPEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLClassifier;
+
+#define DATATYPE_MARGIN 5
+
+/**
+ * Defines a graphical version of the datatype. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an datatype.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class DatatypeWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs an DatatypeWidget.
+ *
+ * @param view The parent of this DatatypeWidget.
+ * @param d The UMLClassifier this will be representing.
+ */
+ DatatypeWidget(UMLView* view, UMLClassifier *d);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~DatatypeWidget();
+
+ /**
+ * Overrides standard method.
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "datatypewidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Loads from a "datatypewidget" XMI element.
+ */
+ bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * The right mouse button menu.
+ */
+ ListPopupMenu* m_pMenu;
+
+public slots:
+};
+
+#endif
diff --git a/umbrello/umbrello/dialog_utils.cpp b/umbrello/umbrello/dialog_utils.cpp
new file mode 100644
index 00000000..a6d1ff2c
--- /dev/null
+++ b/umbrello/umbrello/dialog_utils.cpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "dialog_utils.h"
+
+// qt/kde includes
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "uml.h"
+#include "umlwidget.h"
+
+namespace Dialog_Utils {
+
+QLineEdit* makeLabeledEditField(QGroupBox *containingBox, QGridLayout *layout, int row,
+ QLabel * &label, const QString& labelText,
+ QLineEdit * &editField,
+ const QString& editFieldText /* = QString::null */)
+{
+ label = new QLabel(labelText, containingBox);
+ layout->addWidget(label, row, 0);
+ editField = new QLineEdit(editFieldText, containingBox);
+ layout->addWidget(editField, row, 1 );
+ label->setBuddy(editField);
+ return editField;
+}
+
+
+void askNameForWidget(UMLWidget * &targetWidget, const QString& dialogTitle,
+ const QString& dialogPrompt, const QString& defaultName) {
+
+ bool pressedOK = false;
+
+ QString name = KInputDialog::getText(dialogTitle, dialogPrompt, defaultName, &pressedOK, UMLApp::app());
+
+ if (pressedOK) {
+ targetWidget->setName(name);
+ } else {
+ targetWidget->cleanup();
+ delete targetWidget;
+ targetWidget = NULL;
+ }
+}
+
+
+} // end namespace Dialog_Utils
+
diff --git a/umbrello/umbrello/dialog_utils.h b/umbrello/umbrello/dialog_utils.h
new file mode 100644
index 00000000..a414a7a7
--- /dev/null
+++ b/umbrello/umbrello/dialog_utils.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef DIALOG_UTILS_H
+#define DIALOG_UTILS_H
+
+#include <qstring.h>
+
+class QGroupBox;
+class QGridLayout;
+class QLabel;
+class QLineEdit;
+class UMLWidget;
+
+/**
+ * Dialog utilities.
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Dialog_Utils {
+
+/**
+ * Create a labeled text lineedit widget.
+ *
+ * @param containingBox The containing QGroupBox.
+ * @param layout The QGridLayout to use.
+ * @param row The row number within the QGridLayout.
+ * @param label The QLabel object allocated (return value)
+ * @param labelText The label text.
+ * @param editField The QLineEdit object allocated (return value)
+ * @param editFieldText Initialization text in the editField (optional.)
+ * @return a pointer to the QLineEdit so you can setFocus() if necessary
+ */
+QLineEdit* makeLabeledEditField(QGroupBox *containingBox, QGridLayout *layout, int row,
+ QLabel * &label, const QString& labelText,
+ QLineEdit * &editField,
+ const QString& editFieldText = QString::null);
+
+/**
+ * Helper function for requesting a name for an UMLWidget using a dialog.
+ *
+ * @param targetWidget By-reference pointer to the widget to request the name for.
+ * The widget may be deallocated, and the pointer returned
+ * set to NULL, if the user presses Cancel in the dialog.
+ * @param dialogTitle Title of the dialog.
+ * @param dialogPrompt Prompt of the dialog.
+ * @param defaultName Default value of the name field.
+ */
+void askNameForWidget(UMLWidget * &targetWidget, const QString& dialogTitle,
+ const QString& dialogPrompt, const QString& defaultName);
+
+}
+
+#endif
+
diff --git a/umbrello/umbrello/dialogs/Makefile.am b/umbrello/umbrello/dialogs/Makefile.am
new file mode 100644
index 00000000..0def48d4
--- /dev/null
+++ b/umbrello/umbrello/dialogs/Makefile.am
@@ -0,0 +1,54 @@
+noinst_LTLIBRARIES = libdialogs.la
+
+INCLUDES = -I$(top_srcdir) $(all_includes)
+
+libdialogs_la_METASOURCES = AUTO
+
+libdialogs_la_SOURCES = \
+ codegenerationoptionsbase.ui \
+ codegenerationpolicybase.ui \
+ codegenerationwizardbase.ui \
+ codeviewerdialogbase.ui \
+ codevieweroptionsbase.ui \
+ diagrampropertiespage.ui \
+ exportallviewsdialogbase.ui \
+ umlrolepropertiesbase.ui \
+activitydialog.cpp \
+activitypage.cpp \
+assocgenpage.cpp \
+assocpage.cpp \
+assocpropdlg.cpp \
+assocrolepage.cpp \
+classgenpage.cpp \
+classifierlistpage.cpp\
+classoptionspage.cpp \
+classpropdlg.cpp \
+classwizard.cpp \
+codeeditor.cpp \
+codegenerationoptionspage.cpp \
+codegenerationpolicypage.cpp \
+codegenerationwizard.cpp \
+codeviewerdialog.cpp \
+codevieweroptionspage.cpp \
+defaultcodegenpolicypage.cpp \
+diagramprintpage.cpp \
+exportallviewsdialog.cpp \
+notedialog.cpp \
+overwritedialogue.cpp \
+pkgcontentspage.cpp \
+parmpropdlg.cpp \
+selectopdlg.cpp \
+settingsdlg.cpp \
+statedialog.cpp \
+umlattributedialog.cpp \
+umlentityattributedialog.cpp \
+umloperationdialog.cpp \
+umltemplatedialog.cpp \
+umlroledialog.cpp \
+umlroleproperties.cpp \
+umlviewdialog.cpp \
+umlwidgetcolorpage.cpp
+
+libdialogs_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -export-dynamic
+
+
diff --git a/umbrello/umbrello/dialogs/activitydialog.cpp b/umbrello/umbrello/dialogs/activitydialog.cpp
new file mode 100644
index 00000000..d34782a5
--- /dev/null
+++ b/umbrello/umbrello/dialogs/activitydialog.cpp
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "activitydialog.h"
+
+//qt includes
+#include <qlayout.h>
+
+//kde includes
+#include <kiconloader.h>
+#include <klocale.h>
+
+//local includes
+#include "../umlview.h"
+#include "../activitywidget.h"
+#include "../dialog_utils.h"
+
+ActivityDialog::ActivityDialog( UMLView * pView, ActivityWidget * pWidget )
+ : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help, Ok, pView, "_STATEDIALOG_", true, true) {
+ m_pView = pView;
+ m_pActivityWidget = pWidget;
+ m_bChangesMade = false;
+ setupPages();
+}
+
+void ActivityDialog::slotOk() {
+ applyPage( GeneralPage );
+ applyPage( ColorPage );
+ applyPage( FontPage );
+ accept();
+}
+
+void ActivityDialog::slotApply() {
+ applyPage( (Page) activePageIndex() );
+}
+
+void ActivityDialog::setupPages() {
+ setupGeneralPage();
+ setupColorPage();
+ setupFontPage();
+}
+
+void ActivityDialog::applyPage( Page page ) {
+ m_bChangesMade = true;
+ switch( page ) {
+ case GeneralPage:
+ m_pActivityWidget -> setName( m_GenPageWidgets.nameLE -> text() );
+ m_pActivityWidget -> setDoc( m_GenPageWidgets.docMLE -> text() );
+ break;
+
+ case ColorPage:
+ m_pColorPage -> updateUMLWidget();
+
+ case FontPage:
+ m_pActivityWidget -> setFont( m_pChooser -> font() );
+ break;
+ }//end switch
+}
+
+void ActivityDialog::setupGeneralPage() {
+ QString types[ ] = { i18n("Initial activity"), i18n("Activity"), i18n("End activity"), i18n( "Branch/Merge"), i18n( "Fork/Join" ) };
+ ActivityWidget::ActivityType type = m_pActivityWidget -> getActivityType();
+
+ QVBox * page = addVBoxPage( i18n("General"), i18n("General Properties"), DesktopIcon( "misc") );
+ m_GenPageWidgets.generalGB = new QGroupBox( i18n( "Properties"), (QWidget *)page );
+
+ QGridLayout * generalLayout = new QGridLayout( m_GenPageWidgets.generalGB, 2, 2 );
+ generalLayout -> setSpacing( spacingHint() );
+ generalLayout -> setMargin( fontMetrics().height() );
+
+ QString actType ( types[ (int)type ] );
+ Dialog_Utils::makeLabeledEditField( m_GenPageWidgets.generalGB, generalLayout, 0,
+ m_GenPageWidgets.typeL, i18n("Activity type:"),
+ m_GenPageWidgets.typeLE, actType );
+ m_GenPageWidgets.typeLE -> setEnabled( false );
+
+ Dialog_Utils::makeLabeledEditField( m_GenPageWidgets.generalGB, generalLayout, 1,
+ m_GenPageWidgets.nameL, i18n("Activity name:"),
+ m_GenPageWidgets.nameLE );
+
+ m_GenPageWidgets.docGB = new QGroupBox( i18n( "Documentation"), (QWidget *)page );
+
+ QHBoxLayout * docLayout = new QHBoxLayout( m_GenPageWidgets.docGB );
+ docLayout -> setSpacing( spacingHint() );
+ docLayout -> setMargin( fontMetrics().height() );
+
+ m_GenPageWidgets.docMLE = new QMultiLineEdit( m_GenPageWidgets.docGB );
+ m_GenPageWidgets.docMLE -> setText( m_pActivityWidget -> getDoc() );
+ docLayout -> addWidget( m_GenPageWidgets.docMLE );
+
+ if( type != ActivityWidget::Normal ) {
+ m_GenPageWidgets.nameLE -> setEnabled( false );
+ m_GenPageWidgets.nameLE -> setText( "" );
+ } else
+ m_GenPageWidgets.nameLE -> setText( m_pActivityWidget -> getName() );
+}
+
+void ActivityDialog::setupFontPage() {
+ QVBox * page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts") );
+ m_pChooser = new KFontChooser( (QWidget*)page, "font", false, QStringList(), false);
+ m_pChooser -> setFont( m_pActivityWidget -> getFont() );
+}
+
+void ActivityDialog::setupColorPage() {
+ QFrame * colorPage = addPage( i18n("Color"), i18n("Widget Colors"), DesktopIcon( "colors") );
+ QHBoxLayout * m_pColorLayout = new QHBoxLayout(colorPage);
+ m_pColorPage = new UMLWidgetColorPage( colorPage, m_pActivityWidget );
+ m_pColorLayout -> addWidget(m_pColorPage);
+}
+
+
+
+
+
+
+#include "activitydialog.moc"
diff --git a/umbrello/umbrello/dialogs/activitydialog.h b/umbrello/umbrello/dialogs/activitydialog.h
new file mode 100644
index 00000000..4dc5980b
--- /dev/null
+++ b/umbrello/umbrello/dialogs/activitydialog.h
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ACTIVITYDIALOG_H
+#define ACTIVITYDIALOG_H
+
+//qt class includes
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qmultilineedit.h>
+#include <qgroupbox.h>
+
+//kde class includes
+#include <kdialogbase.h>
+#include <kfontdialog.h>
+
+//local class includes
+#include "umlwidgetcolorpage.h"
+
+//forward declarations
+class UMLView;
+class ActivityWidget;
+
+/**
+ * Displays the properties for a @ref ActivityWidget
+ *
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class ActivityDialog : public KDialogBase {
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ ActivityDialog( UMLView * pView, ActivityWidget * pWidget );
+
+ /**
+ * Returns whether changes were made.
+ */
+ bool getChangesMade() {
+ return m_bChangesMade;
+ }
+
+protected slots:
+
+ /**
+ * Entered when OK button pressed.
+ */
+ void slotOk();
+
+ /**
+ * Entered when Apply button pressed.
+ */
+ void slotApply();
+
+protected:
+
+ enum Page
+ {
+ GeneralPage = 0,
+ ColorPage,
+ FontPage
+ };
+
+ /**
+ * Sets up the pages of the dialog.
+ */
+ void setupPages();
+
+ /**
+ * Sets up the general page of the dialog.
+ */
+ void setupGeneralPage();
+
+ /**
+ * Sets up the color page.
+ */
+ void setupColorPage();
+
+ /**
+ * Sets up the font selection page.
+ */
+ void setupFontPage();
+
+ /**
+ * Applys changes to the given page.
+ */
+ void applyPage( Page page );
+
+ /**
+ * Font chooser widget for font page.
+ */
+ KFontChooser * m_pChooser;
+
+ /**
+ * Color page
+ */
+ UMLWidgetColorPage * m_pColorPage;
+
+ /**
+ * The widget to represent.
+ */
+ ActivityWidget * m_pActivityWidget;
+
+ /**
+ * The diagram the widget is on.
+ */
+ UMLView * m_pView;
+
+ /**
+ * Holds whether changes in the dialog have been made.
+ */
+ bool m_bChangesMade;
+
+ struct GeneralPageWidgets {
+ QLabel * nameL, * typeL;
+ QLineEdit * nameLE, * typeLE;
+ QMultiLineEdit * docMLE;
+
+ QGroupBox * docGB, * generalGB;
+ }
+ m_GenPageWidgets;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/activitypage.cpp b/umbrello/umbrello/dialogs/activitypage.cpp
new file mode 100644
index 00000000..8d3f5931
--- /dev/null
+++ b/umbrello/umbrello/dialogs/activitypage.cpp
@@ -0,0 +1,325 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "activitypage.h"
+#include "../statewidget.h"
+#include "../listpopupmenu.h"
+#include "../uml.h"
+
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kbuttonbox.h>
+#include <kdebug.h>
+#include <qlayout.h>
+#include <qstringlist.h>
+
+ActivityPage::ActivityPage( QWidget * pParent, StateWidget * pWidget ) : QWidget( pParent ) {
+ m_pStateWidget = pWidget;
+ m_pMenu = 0;
+ setupPage();
+}
+
+ActivityPage::~ActivityPage() {}
+
+void ActivityPage::setupPage() {
+ int margin = fontMetrics().height();
+
+ QVBoxLayout * mainLayout = new QVBoxLayout( this );
+ mainLayout -> setSpacing(10);
+
+ m_pActivityGB = new QGroupBox(i18n("Activities"), this );
+
+ // vertical box layout for the activity lists, arrow buttons and the button box
+ QVBoxLayout* listVBoxLayout = new QVBoxLayout( m_pActivityGB );
+ listVBoxLayout -> setMargin(margin);
+ listVBoxLayout -> setSpacing ( 10 );
+
+ //horizontal box contains the list box and the move up/down buttons
+ QHBoxLayout* listHBoxLayout = new QHBoxLayout( listVBoxLayout );
+
+ m_pActivityLB = new QListBox(m_pActivityGB );
+
+ listHBoxLayout -> addWidget(m_pActivityLB);
+
+ QVBoxLayout * buttonLayout = new QVBoxLayout( listHBoxLayout );
+
+ m_pTopArrowB = new KArrowButton( m_pActivityGB );
+ m_pTopArrowB -> setEnabled( false );
+ buttonLayout -> addWidget( m_pTopArrowB );
+
+ m_pUpArrowB = new KArrowButton( m_pActivityGB );
+ m_pUpArrowB -> setEnabled( false );
+ buttonLayout -> addWidget( m_pUpArrowB );
+
+ m_pDownArrowB = new KArrowButton( m_pActivityGB, Qt::DownArrow );
+ m_pDownArrowB -> setEnabled( false );
+ buttonLayout -> addWidget( m_pDownArrowB );
+
+ m_pBottomArrowB = new KArrowButton( m_pActivityGB, Qt::DownArrow );
+ m_pBottomArrowB -> setEnabled( false );
+ buttonLayout -> addWidget( m_pBottomArrowB );
+
+
+ KButtonBox* buttonBox = new KButtonBox(m_pActivityGB);
+ buttonBox->addButton( i18n("New Activity..."), this, SLOT(slotNewActivity()) );
+ m_pDeleteActivityButton = buttonBox->addButton( i18n("Delete"),
+ this, SLOT(slotDelete()) );
+ m_pRenameButton = buttonBox->addButton( i18n("Rename"), this, SLOT(slotRename()) );
+ listVBoxLayout->addWidget(buttonBox);
+
+ mainLayout -> addWidget( m_pActivityGB );
+
+ //now fill activity list box
+ QStringList list = m_pStateWidget -> getActivityList();
+ QStringList::Iterator end(list.end());
+
+ for( QStringList::Iterator it(list.begin()); it != end; ++it ) {
+ m_pActivityLB -> insertItem( *it );
+ }
+
+ //now setup the signals
+ connect(m_pActivityLB, SIGNAL(clicked(QListBoxItem *)), this, SLOT(slotClicked(QListBoxItem *)));
+ connect(m_pActivityLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ connect(m_pActivityLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem *, const QPoint &)));
+
+ connect( m_pTopArrowB, SIGNAL( clicked() ), this, SLOT( slotTopClicked() ) );
+ connect( m_pUpArrowB, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) );
+ connect( m_pDownArrowB, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) );
+ connect( m_pBottomArrowB, SIGNAL( clicked() ), this, SLOT( slotBottomClicked() ) );
+
+ connect( m_pActivityLB, SIGNAL( doubleClicked( QListBoxItem* ) ), this, SLOT( slotDoubleClicked( QListBoxItem* ) ) );
+
+ enableWidgets(false);
+}
+
+void ActivityPage::updateActivities() {
+ QStringList list;
+ int count = m_pActivityLB -> count();
+ for( int i = 0; i < count; i++ ) {
+ list.append( m_pActivityLB -> text( i ) );
+ }
+ m_pStateWidget -> setActivities( list );
+}
+
+void ActivityPage::slotMenuSelection( int sel ) {
+ switch( sel ) {
+ case ListPopupMenu::mt_New_Activity:
+ slotNewActivity();
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ slotDelete();
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ slotRename();
+ break;
+ }
+}
+
+void ActivityPage::slotNewActivity() {
+ bool ok = false;
+ QString name = m_pActivityLB->currentText();
+ name = KInputDialog::getText( i18n("New Activity"), i18n("Enter the name of the new activity:"),
+ i18n("new activity"), &ok, UMLApp::app() );
+ if( ok && name.length() > 0 ) {
+ m_pActivityLB->insertItem( name );
+ m_pStateWidget->addActivity( name );
+ }
+}
+
+void ActivityPage::slotDelete() {
+ QString name = m_pActivityLB->currentText();
+ m_pStateWidget->removeActivity(name);
+ m_pActivityLB->removeItem( m_pActivityLB->currentItem() );
+ slotClicked(0);
+}
+
+void ActivityPage::slotRename() {
+ bool ok = false;
+ QString name = m_pActivityLB -> currentText();
+ QString oldName = name;
+ name = KInputDialog::getText( i18n("Rename Activity"), i18n("Enter the new name of the activity:"), name, &ok, UMLApp::app() );
+ if( ok && name.length() > 0 ) {
+ m_pActivityLB -> changeItem( name, m_pActivityLB -> currentItem());
+ m_pStateWidget -> renameActivity( oldName, name );
+ }
+}
+
+void ActivityPage::slotRightButtonClicked(QListBoxItem * /*item*/, const QPoint &/* p*/) {
+ if(m_pMenu) {
+ m_pMenu->hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void ActivityPage::slotRightButtonPressed(QListBoxItem * item, const QPoint & p)
+{
+ ListPopupMenu::Menu_Type type = ListPopupMenu::mt_Undefined;
+ if( item ) { //pressed on an item
+ type = ListPopupMenu::mt_Activity_Selected;
+ } else { //pressed into fresh air
+ type = ListPopupMenu::mt_New_Activity;
+ }
+
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ m_pMenu = new ListPopupMenu(this, type);
+ m_pMenu->popup(p);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+}
+
+
+void ActivityPage::slotTopClicked() {
+ int count = m_pActivityLB->count();
+ int index = m_pActivityLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index <= 0 )
+ return;
+
+ //swap the text around in the ListBox
+ QString currentString = m_pActivityLB->text( index );
+ m_pActivityLB->removeItem( index );
+ m_pActivityLB->insertItem( currentString, 0 );
+ //set the moved item selected
+ QListBoxItem* item = m_pActivityLB->item( 0 );
+ m_pActivityLB->setSelected( item, true );
+
+ slotClicked(item);
+}
+
+void ActivityPage::slotUpClicked() {
+ int count = m_pActivityLB -> count();
+ int index = m_pActivityLB -> currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index <= 0 ) {
+ return;
+ }
+
+ //swap the text around ( meaning attributes )
+ QString aboveString = m_pActivityLB -> text( index - 1 );
+ QString currentString = m_pActivityLB -> text( index );
+ m_pActivityLB -> changeItem( currentString, index -1 );
+ m_pActivityLB -> changeItem( aboveString, index );
+ //set the moved atttribute selected
+ QListBoxItem * item = m_pActivityLB -> item( index - 1 );
+ m_pActivityLB -> setSelected( item, true );
+ slotClicked(item);
+}
+
+void ActivityPage::slotDownClicked() {
+ int count = m_pActivityLB -> count();
+ int index = m_pActivityLB -> currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index >= count - 1 ) {
+ return;
+ }
+
+ //swap the text around ( meaning attributes )
+ QString belowString = m_pActivityLB -> text( index + 1 );
+ QString currentString = m_pActivityLB -> text( index );
+ m_pActivityLB -> changeItem( currentString, index + 1 );
+ m_pActivityLB -> changeItem( belowString, index );
+ //set the moved atttribute selected
+ QListBoxItem * item = m_pActivityLB -> item( index + 1 );
+ m_pActivityLB -> setSelected( item, true );
+ slotClicked(item);
+}
+
+
+void ActivityPage::slotBottomClicked() {
+ int count = m_pActivityLB->count();
+ int index = m_pActivityLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index >= count - 1 )
+ return;
+
+ //swap the text around in the ListBox
+ QString currentString = m_pActivityLB->text( index );
+ m_pActivityLB->removeItem( index );
+ m_pActivityLB->insertItem( currentString, m_pActivityLB->count() );
+ //set the moved item selected
+ QListBoxItem* item = m_pActivityLB->item( m_pActivityLB->count() - 1 );
+ m_pActivityLB->setSelected( item, true );
+
+ slotClicked( item );
+}
+
+
+void ActivityPage::slotClicked(QListBoxItem *item) {
+ //make sure clicked on an item
+ if(!item) {
+ enableWidgets(false);
+ m_pActivityLB -> clearSelection();
+ } else {
+ enableWidgets(true);
+ }
+}
+
+void ActivityPage::slotDoubleClicked(QListBoxItem* item) {
+ if (item) {
+ slotRename();
+ }
+}
+
+void ActivityPage::enableWidgets(bool state) {
+ if( !state ) {
+ m_pTopArrowB->setEnabled( false );
+ m_pUpArrowB->setEnabled( false );
+ m_pDownArrowB->setEnabled( false );
+ m_pBottomArrowB->setEnabled( false );
+ m_pDeleteActivityButton->setEnabled(false);
+ m_pRenameButton->setEnabled(false);
+ return;
+ }
+ /*now check the order buttons.
+ Double check an item is selected
+ If only one att. in list make sure there disabled.
+ If at top item,only allow down arrow to be enabled.
+ If at bottom item. only allow up arrow to be enabled.
+ */
+ int index = m_pActivityLB->currentItem();
+ if( m_pActivityLB->count() == 1 || index == -1 ) {
+ m_pTopArrowB->setEnabled(false);
+ m_pUpArrowB->setEnabled(false);
+ m_pDownArrowB->setEnabled(false);
+ m_pBottomArrowB->setEnabled( false );
+ } else if( index == 0 ) {
+ m_pTopArrowB->setEnabled( false );
+ m_pUpArrowB->setEnabled(false);
+ m_pDownArrowB->setEnabled(true);
+ m_pBottomArrowB->setEnabled(true);
+ } else if( index == (int)m_pActivityLB->count() - 1 ) {
+ m_pTopArrowB->setEnabled(true);
+ m_pUpArrowB->setEnabled(true);
+ m_pDownArrowB->setEnabled(false);
+ m_pBottomArrowB->setEnabled(false);
+ } else {
+ m_pTopArrowB->setEnabled(true);
+ m_pUpArrowB->setEnabled(true);
+ m_pDownArrowB->setEnabled(true);
+ m_pBottomArrowB->setEnabled(true);
+ }
+ m_pDeleteActivityButton->setEnabled(true);
+ m_pRenameButton->setEnabled(true);
+}
+
+
+#include "activitypage.moc"
diff --git a/umbrello/umbrello/dialogs/activitypage.h b/umbrello/umbrello/dialogs/activitypage.h
new file mode 100644
index 00000000..7d391b96
--- /dev/null
+++ b/umbrello/umbrello/dialogs/activitypage.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ACTIVITYPAGE_H
+#define ACTIVITYPAGE_H
+//qt includes
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+//kde includes
+#include <karrowbutton.h>
+//app includes
+
+class StateWidget;
+class ListPopupMenu;
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ActivityPage : public QWidget {
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ ActivityPage( QWidget * pParent, StateWidget * pWidget );
+
+ /**
+ * Deconstructor
+ */
+ ~ActivityPage();
+
+ /**
+ * Sets up the page.
+ */
+ void setupPage();
+
+ /**
+ * Sets the activities of the widget.
+ */
+ void updateActivities();
+
+protected:
+ /**
+ * Set the state of the widgets on the page with the given value.
+ *
+ * @param state The state to set the widgets as.
+ */
+ void enableWidgets(bool state);
+
+ /**
+ * The widget to get the activities from.
+ */
+ StateWidget * m_pStateWidget;
+
+ /**
+ * Popup menu used.
+ */
+ ListPopupMenu * m_pMenu;
+ //GUI widgets
+ QListBox * m_pActivityLB;
+ QGroupBox * m_pActivityGB;
+ KArrowButton * m_pUpArrowB, * m_pDownArrowB, * m_pTopArrowB, *m_pBottomArrowB;
+ QPushButton* m_pDeleteActivityButton;
+ QPushButton* m_pRenameButton;
+
+public slots:
+ /**
+ * Popup menu item selected
+ */
+ void slotMenuSelection( int sel );
+ void slotClicked( QListBoxItem* item );
+ void slotDoubleClicked( QListBoxItem* item );
+ void slotRightButtonClicked(QListBoxItem* item, const QPoint& p);
+ void slotRightButtonPressed(QListBoxItem* item, const QPoint& p);
+ void slotTopClicked();
+ void slotUpClicked();
+ void slotDownClicked();
+ void slotBottomClicked();
+ void slotNewActivity();
+ void slotDelete();
+ void slotRename();
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/assocgenpage.cpp b/umbrello/umbrello/dialogs/assocgenpage.cpp
new file mode 100644
index 00000000..9be13ee0
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocgenpage.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "assocgenpage.h"
+
+// qt includes
+#include <qlayout.h>
+#include <kcombobox.h>
+
+// kde includes
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// local includes
+#include "../association.h"
+#include "../dialog_utils.h"
+
+AssocGenPage::AssocGenPage (UMLDoc *d, QWidget *parent, AssociationWidget *assoc)
+ : QWidget(parent)
+{
+
+ m_pAssociationWidget = assoc;
+ m_pWidget = 0;
+ m_pTypeCB = 0;
+ m_pAssocNameLE = 0;
+ m_pUmldoc = d;
+
+ constructWidget();
+
+}
+
+AssocGenPage::~AssocGenPage() {}
+
+void AssocGenPage::constructWidget() {
+
+ // general configuration of the GUI
+ int margin = fontMetrics().height();
+ setMinimumSize(310,330);
+ QVBoxLayout * topLayout = new QVBoxLayout(this);
+ topLayout -> setSpacing(6);
+
+ // group boxes for name, documentation properties
+ QGroupBox *nameGB = new QGroupBox(this);
+ QGroupBox *docGB = new QGroupBox(this);
+ nameGB -> setTitle(i18n("Properties"));
+ docGB -> setTitle(i18n("Documentation"));
+ topLayout -> addWidget(nameGB);
+ topLayout -> addWidget(docGB);
+
+ QGridLayout * nameLayout = new QGridLayout(nameGB, 2, 2);
+ nameLayout -> setSpacing(6);
+ nameLayout -> setMargin(margin);
+
+ //Association name
+ QLabel *pAssocNameL = NULL;
+ QLineEdit* nameField = Dialog_Utils::makeLabeledEditField( nameGB, nameLayout, 0,
+ pAssocNameL, i18n("Name:"),
+ m_pAssocNameLE, m_pAssociationWidget->getName() );
+ nameField->setFocus();
+
+ // document
+ QHBoxLayout * docLayout = new QHBoxLayout(docGB);
+ docLayout -> setMargin(margin);
+
+ m_pDoc = new QMultiLineEdit(docGB);
+ docLayout -> addWidget(m_pDoc);
+ m_pDoc-> setText(m_pAssociationWidget-> getDoc());
+ Uml::Association_Type currentType = m_pAssociationWidget->getAssocType();
+ QString currentTypeAsString = UMLAssociation::typeAsString(currentType);
+ QLabel *pTypeL = new QLabel(i18n("Type:"), nameGB);
+ nameLayout->addWidget(pTypeL, 1, 0);
+
+ /* Here is a list of all the supported choices for changing
+ association types */
+ m_AssocTypes.clear();
+ m_AssocTypes << Uml::at_Aggregation
+ << Uml::at_Composition << Uml::at_Containment;
+
+ bool found=false;
+ m_AssocTypeStrings.clear();
+ for (uint i=0; i<m_AssocTypes.size(); ++i) {
+ if (m_AssocTypes[i] == currentType) found=true;
+ QString typeStr = UMLAssociation::typeAsString(m_AssocTypes[i]);
+ m_AssocTypeStrings << typeStr;
+ }
+
+ if (!found) {
+ m_AssocTypes.clear();
+ m_AssocTypes << currentType;
+ m_AssocTypeStrings.clear();
+ m_AssocTypeStrings << currentTypeAsString;
+ }
+
+ m_pTypeCB = new KComboBox(nameGB);
+ pTypeL->setBuddy(m_pTypeCB);
+ m_pTypeCB->insertStringList(m_AssocTypeStrings);
+ m_pTypeCB->setCompletedItems(m_AssocTypeStrings);
+ m_pTypeCB->setCurrentText(currentTypeAsString);
+ m_pTypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ m_pDoc->setWordWrap(QMultiLineEdit::WidgetWidth);
+ nameLayout->addWidget(m_pTypeCB, 1, 1);
+
+
+}
+
+
+void AssocGenPage::updateObject() {
+
+ if (m_pAssociationWidget) {
+ int comboBoxItem = m_pTypeCB->currentItem();
+ Uml::Association_Type newType = m_AssocTypes[comboBoxItem];
+ m_pAssociationWidget->setAssocType(newType);
+ m_pAssociationWidget->setName(m_pAssocNameLE->text());
+ m_pAssociationWidget->setDoc(m_pDoc->text());
+
+ } //end if m_pAssociationWidget
+}
+
+
+#include "assocgenpage.moc"
diff --git a/umbrello/umbrello/dialogs/assocgenpage.h b/umbrello/umbrello/dialogs/assocgenpage.h
new file mode 100644
index 00000000..3eff137f
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocgenpage.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCGENPAGE_H
+#define ASSOCGENPAGE_H
+
+//quicktime class includes
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qbuttongroup.h>
+#include <qmultilineedit.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qvaluelist.h>
+
+//my class includes
+#include "../umlobject.h"
+#include "../objectwidget.h"
+#include "../umldoc.h"
+#include "../associationwidget.h"
+
+class KComboBox;
+
+
+/**
+ * Displays properties of a UMLObject in a dialog box. This is not usually directly
+ * called. The class @ref AssocPropDlg will set this up for you.
+ *
+ * @short Display properties on a UMLObject.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssocGenPage : public QWidget {
+ Q_OBJECT
+public:
+
+ /**
+ * Sets up the AssocGenPage.
+ *
+ * @param d The UMLDoc which controls controls object creation.
+ * @param parent The parent to the AssocGenPage.
+ * @param a The AssociationWidget to display the properties of.
+ */
+ AssocGenPage(UMLDoc *d, QWidget *parent, AssociationWidget *a);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~AssocGenPage();
+
+ /**
+ * Will move information from the dialog into the object.
+ * Call when the ok or apply button is pressed.
+ */
+ void updateObject();
+
+private:
+ QLineEdit * m_pAssocNameLE;
+ KComboBox *m_pTypeCB;
+
+ /* Choices for the QComboBox, and we store ints and strings
+ so we can translate both ways */
+ QValueList<Uml::Association_Type> m_AssocTypes;
+ QStringList m_AssocTypeStrings;
+
+ QMultiLineEdit * m_pDoc;
+
+ AssociationWidget *m_pAssociationWidget;
+ UMLDoc * m_pUmldoc;
+ ObjectWidget * m_pWidget;
+
+ void constructWidget();
+
+public slots:
+ /**
+ * When the draw as actor check box is toggled, the draw
+ * as multi instance need to be enabled/disabled. They
+ * both can't be available at the same time.
+ */
+ // void slotActorToggled( bool state );
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/assocpage.cpp b/umbrello/umbrello/dialogs/assocpage.cpp
new file mode 100644
index 00000000..1b3cf5ad
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocpage.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "assocpage.h"
+#include <qlayout.h>
+#include <klocale.h>
+#include "assocpropdlg.h"
+
+AssocPage::AssocPage(QWidget *parent, UMLView * v, UMLObject * o) : QWidget(parent) {
+ m_pObject = o;
+ m_pView = v;
+ int margin = fontMetrics().height();
+
+ QHBoxLayout * mainLayout = new QHBoxLayout(this);
+ mainLayout -> setSpacing(10);
+
+ m_pAssocGB = new QGroupBox(i18n("Associations"), this);
+ mainLayout -> addWidget(m_pAssocGB);
+
+ QHBoxLayout * layout = new QHBoxLayout(m_pAssocGB);
+ layout -> setSpacing(10);
+ layout -> setMargin(margin);
+
+ m_pAssocLB = new QListBox(m_pAssocGB);
+ layout -> addWidget(m_pAssocLB);
+ setMinimumSize(310, 330);
+ fillListBox();
+ m_pMenu = 0;
+
+ connect(m_pAssocLB, SIGNAL(doubleClicked(QListBoxItem *)),
+ this, SLOT(slotDoubleClick(QListBoxItem *)));
+
+ connect(m_pAssocLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ connect(m_pAssocLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem *, const QPoint &)));
+}
+
+AssocPage::~AssocPage() {
+ disconnect(m_pAssocLB, SIGNAL(doubleClicked(QListBoxItem *)),
+ this, SLOT(slotDoubleClick(QListBoxItem *)));
+
+ disconnect(m_pAssocLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ disconnect(m_pAssocLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem *, const QPoint &)));
+}
+
+void AssocPage::slotDoubleClick(QListBoxItem * i) {
+
+ if(!i)
+ return;
+
+ int item = m_pAssocLB -> currentItem();
+
+ AssociationWidget * a = m_List.at(item);
+
+ if (a->showDialog())
+ fillListBox();
+}
+
+void AssocPage::fillListBox() {
+ m_List.clear();
+ m_pAssocLB->clear();
+ m_pView->getWidgetAssocs(m_pObject, m_List);
+ AssociationWidgetListIt assoc_it(m_List);
+ AssociationWidget* assocwidget = 0;
+ int i = 0;
+ while((assocwidget = assoc_it.current())) {
+ if( assocwidget->getAssocType() != Uml::at_Anchor) {
+ m_pAssocLB -> insertItem(assocwidget->toString(), i++);
+ }
+ ++assoc_it;
+ }
+}
+
+void AssocPage::slotRightButtonClicked(QListBoxItem */* item*/, const QPoint &/* p*/) {
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void AssocPage::slotRightButtonPressed(QListBoxItem * item, const QPoint & p) {
+ if(!item)
+ return;
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ m_pMenu = new ListPopupMenu(this, ListPopupMenu::mt_Association_Selected);
+ m_pMenu->popup(p);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+}
+
+void AssocPage::slotPopupMenuSel(int id) {
+ AssociationWidget * a = m_List.at(m_pAssocLB -> currentItem());
+ switch(id) {
+ case ListPopupMenu::mt_Delete:
+ m_pView->removeAssocInViewAndDoc(a);
+ fillListBox();
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ slotDoubleClick(m_pAssocLB -> item(m_pAssocLB -> currentItem()));
+ break;
+ }
+}
+
+
+
+
+#include "assocpage.moc"
diff --git a/umbrello/umbrello/dialogs/assocpage.h b/umbrello/umbrello/dialogs/assocpage.h
new file mode 100644
index 00000000..60e1e339
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocpage.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef ASSOCPAGE_H
+#define ASSOCPAGE_H
+
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qptrlist.h>
+
+#include "../umlobject.h"
+#include "../umlview.h"
+#include "../associationwidgetlist.h"
+#include "../associationwidget.h"
+#include "../listpopupmenu.h"
+
+
+/**
+ * Displays a page on the tabbed dialog window of @ref ClassPropDlg.
+ * The page shows all the Associations that belong to a UMLClassifier.
+ *
+ *
+ * @see ClassPropDlg
+
+ * @see UMLClassifier
+ *
+ * @short The page shows all the Associations that belong to a UMLClassifier.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssocPage : public QWidget {
+ Q_OBJECT
+public:
+ /**
+ * Constructs an instance of AssocPage.
+ *
+ * @param parent The parent of the page
+ * @param v The view the UMLObject being represented.
+ * @param o The UMLObject being represented
+ */
+ AssocPage(QWidget *parent, UMLView * v, UMLObject * o);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~AssocPage();
+private:
+ UMLObject * m_pObject;
+ UMLView * m_pView;
+ QListBox * m_pAssocLB;
+ QGroupBox * m_pAssocGB;
+ AssociationWidgetList m_List;
+ ListPopupMenu * m_pMenu;
+
+ /**
+ * Fills the list box with the objects associations.
+ */
+ void fillListBox();
+public slots:
+ void slotDoubleClick(QListBoxItem * i);
+ void slotRightButtonClicked(QListBoxItem */* item*/, const QPoint &/* p*/);
+ void slotRightButtonPressed(QListBoxItem * item, const QPoint & p);
+ void slotPopupMenuSel(int id);
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/assocpropdlg.cpp b/umbrello/umbrello/dialogs/assocpropdlg.cpp
new file mode 100644
index 00000000..2458da13
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocpropdlg.cpp
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "assocpropdlg.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+// local includes
+#include "assocgenpage.h"
+#include "assocrolepage.h"
+#include "classpropdlg.h"
+#include "classgenpage.h"
+#include "umlwidgetcolorpage.h"
+
+#include "../umlobject.h"
+#include "../umldoc.h"
+#include "../objectwidget.h"
+#include "../uml.h"
+#include "../umlview.h"
+
+
+AssocPropDlg::AssocPropDlg (QWidget *parent, AssociationWidget * assocWidget, int pageNum)
+ : KDialogBase(IconList, i18n("Association Properties"), Ok | Apply | Cancel | Help,
+ Ok, parent, "_ASSOCPROPDLG_", true, true)
+{
+ init();
+ m_pAssoc = assocWidget;
+
+ m_pDoc = ((UMLApp *)parent) -> getDocument(); // needed?
+
+ setupPages(assocWidget);
+ showPage(pageNum);
+}
+
+AssocPropDlg::~AssocPropDlg() { }
+
+void AssocPropDlg::init ( )
+{
+ m_pAssoc = 0;
+ m_pGenPage = 0;
+ m_pRolePage = 0;
+}
+
+void AssocPropDlg::slotOk() {
+ slotApply();
+ KDialogBase::accept();
+}
+
+void AssocPropDlg::slotApply() {
+
+ if (m_pGenPage) {
+ m_pGenPage->updateObject();
+ }
+
+ if (m_pRolePage) {
+ m_pRolePage->updateObject();
+ }
+
+ if (m_pAssoc) {
+ m_pAssoc->lwSetFont( m_pChooser->font() );
+ }
+
+
+}
+
+// void AssocPropDlg::setupPages (UMLObject * c)
+void AssocPropDlg::setupPages (AssociationWidget *assocWidget)
+{
+
+ // general page
+ QFrame *page = addPage( i18n("General"), i18n("General Settings"), DesktopIcon( "misc") );
+ QHBoxLayout *genLayout = new QHBoxLayout(page);
+ page -> setMinimumSize(310, 330);
+ m_pGenPage = new AssocGenPage (m_pDoc, page, assocWidget);
+ genLayout -> addWidget(m_pGenPage);
+
+ // role page
+ QFrame * newPage = addPage( i18n("Roles"), i18n("Role Settings"), DesktopIcon( "misc") );
+ QHBoxLayout * roleLayout = new QHBoxLayout(newPage);
+ // newPage -> setMinimumSize(310, 330);
+ m_pRolePage = new AssocRolePage(m_pDoc, newPage, assocWidget);
+ roleLayout -> addWidget(m_pRolePage);
+
+ setupFontPage();
+
+}
+
+void AssocPropDlg::setupFontPage()
+{
+ if( !m_pAssoc)
+ return;
+
+ QVBox *page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts"));
+ m_pChooser = new KFontChooser( (QWidget*)page, "font", false, QStringList(), false);
+ m_pChooser->setFont( m_pAssoc->getFont());
+ m_pChooser->setSampleText(i18n("Association font"));
+}
+
+#include "assocpropdlg.moc"
diff --git a/umbrello/umbrello/dialogs/assocpropdlg.h b/umbrello/umbrello/dialogs/assocpropdlg.h
new file mode 100644
index 00000000..a5bdad6e
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocpropdlg.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCPROPDLG_H
+#define ASSOCPROPDLG_H
+
+//kde class includes
+#include <kdialogbase.h>
+#include <kfontdialog.h>
+#include "../associationwidget.h"
+
+class AssocRolePage;
+class AssocGenPage;
+class UMLDoc;
+// class ObjectWidget;
+// class UMLObject;
+// class UMLWidget;
+
+/**
+ * Based off of AssocPropDlg class
+ * @author Brian Thomas <Brian.A.Thomas@gsfc.nasa.gov>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssocPropDlg : public KDialogBase {
+ Q_OBJECT
+public:
+
+ /**
+ * Sets up a Association Properties Dialog.
+ * @param parent The parent of the AssocPropDlg
+ * @param a The Association Widget to display properties of.
+ * @param pageNum The page to show first.
+ */
+
+ AssocPropDlg(QWidget *parent, AssociationWidget *a, int pageNum = 0);
+
+ /**
+ * Standard deconstructor
+ */
+ ~AssocPropDlg();
+
+ enum Page { page_gen = 0, page_role, page_font };
+
+protected:
+ void setupPages(AssociationWidget * assocWidget);
+ void setupFontPage();
+ void init();
+
+protected slots:
+ void slotOk();
+ void slotApply();
+
+private:
+ AssocGenPage *m_pGenPage;
+ AssocRolePage *m_pRolePage;
+ KFontChooser * m_pChooser;
+ AssociationWidget *m_pAssoc;
+
+ UMLDoc *m_pDoc; // is this needed??
+
+};
+
+#endif /* ASSOCPROPDLG_H */
+
diff --git a/umbrello/umbrello/dialogs/assocrolepage.cpp b/umbrello/umbrello/dialogs/assocrolepage.cpp
new file mode 100644
index 00000000..807a7e1e
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocrolepage.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "assocrolepage.h"
+
+// qt includes
+#include <qlayout.h>
+
+// kde includes
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// local includes
+#include "../dialog_utils.h"
+
+AssocRolePage::AssocRolePage (UMLDoc *d, QWidget *parent, AssociationWidget *assoc)
+ : QWidget(parent)
+{
+
+ m_pAssociationWidget = assoc;
+ m_pWidget = 0;
+ m_pUmldoc = d;
+
+ m_pRoleALE = 0;
+ m_pRoleBLE = 0;
+ m_pMultiALE = 0;
+ m_pMultiBLE = 0;
+
+ constructWidget();
+
+}
+
+AssocRolePage::~AssocRolePage() {}
+
+void AssocRolePage::constructWidget() {
+
+ // underlying roles and objects
+ QString nameA = m_pAssociationWidget->getRoleName(Uml::A);
+ QString nameB = m_pAssociationWidget->getRoleName(Uml::B);
+ QString titleA = i18n("Role A Properties");
+ QString titleB = i18n("Role B Properties");
+ QString widgetNameA = m_pAssociationWidget->getWidget(Uml::A)->getName();
+ QString widgetNameB = m_pAssociationWidget->getWidget(Uml::B)->getName();
+ if(!widgetNameA.isEmpty())
+ titleA.append(" (" + widgetNameA + ')');
+ if(!widgetNameB.isEmpty())
+ titleB.append(" (" + widgetNameB + ')');
+
+ // general configuration of the GUI
+ int margin = fontMetrics().height();
+
+ QGridLayout * mainLayout = new QGridLayout(this, 4, 2);
+ mainLayout -> setSpacing(6);
+
+ // group boxes for role, documentation properties
+ QGroupBox *propsAGB = new QGroupBox(this);
+ QGroupBox *propsBGB = new QGroupBox(this);
+ QButtonGroup * scopeABG = new QButtonGroup(i18n("Role A Visibility"), this );
+ QButtonGroup * scopeBBG = new QButtonGroup(i18n("Role B Visibility"), this );
+ QButtonGroup * changeABG = new QButtonGroup(i18n("Role A Changeability"), this );
+ QButtonGroup * changeBBG = new QButtonGroup(i18n("Role B Changeability"), this );
+ QGroupBox *docAGB = new QGroupBox(this);
+ QGroupBox *docBGB = new QGroupBox(this);
+ propsAGB -> setTitle(titleA);
+ propsBGB -> setTitle(titleB);
+ docAGB -> setTitle(i18n("Documentation"));
+ docBGB -> setTitle(i18n("Documentation"));
+
+ QGridLayout * propsALayout = new QGridLayout(propsAGB, 2, 2);
+ propsALayout -> setSpacing(6);
+ propsALayout -> setMargin(margin);
+
+ QGridLayout * propsBLayout = new QGridLayout(propsBGB, 3, 2);
+ propsBLayout -> setSpacing(6);
+ propsBLayout -> setMargin(margin);
+
+ // Properties
+ //
+
+ // Rolename A
+ QLabel *pRoleAL = NULL;
+ Dialog_Utils::makeLabeledEditField( propsAGB, propsALayout, 0,
+ pRoleAL, i18n("Rolename:"),
+ m_pRoleALE, nameA );
+
+ // Multi A
+ QLabel *pMultiAL = NULL;
+ Dialog_Utils::makeLabeledEditField( propsAGB, propsALayout, 1,
+ pMultiAL, i18n("Multiplicity:"),
+ m_pMultiALE, m_pAssociationWidget->getMulti(Uml::A) );
+
+ // Visibility A
+ QHBoxLayout * scopeALayout = new QHBoxLayout(scopeABG);
+ scopeALayout -> setMargin(margin);
+
+ m_PublicARB = new QRadioButton(i18n("Public"), scopeABG);
+ scopeALayout -> addWidget(m_PublicARB);
+
+ m_PrivateARB = new QRadioButton(i18n("Private"), scopeABG);
+ scopeALayout -> addWidget(m_PrivateARB);
+
+ m_ProtectedARB = new QRadioButton(i18n("Protected"), scopeABG);
+ scopeALayout -> addWidget(m_ProtectedARB);
+
+ m_ImplementationARB = new QRadioButton(i18n("Implementation"), scopeABG);
+ scopeALayout -> addWidget(m_ImplementationARB);
+
+ Uml::Visibility scope = m_pAssociationWidget->getVisibility(Uml::A);
+ if( scope == Uml::Visibility::Public )
+ m_PublicARB -> setChecked( true );
+ else if( scope == Uml::Visibility::Private )
+ m_PrivateARB -> setChecked( true );
+ else if( scope == Uml::Visibility::Implementation )
+ m_PrivateARB -> setChecked( true );
+ else
+ m_ProtectedARB -> setChecked( true );
+
+ // Changeability A
+ QHBoxLayout * changeALayout = new QHBoxLayout(changeABG);
+ changeALayout -> setMargin(margin);
+
+ m_ChangeableARB = new QRadioButton(i18n("Changeable"), changeABG);
+ changeALayout -> addWidget(m_ChangeableARB);
+
+ m_FrozenARB = new QRadioButton(i18n("Frozen"), changeABG);
+ changeALayout -> addWidget(m_FrozenARB);
+
+ m_AddOnlyARB = new QRadioButton(i18n("Add only"), changeABG);
+ changeALayout -> addWidget(m_AddOnlyARB);
+
+ Uml::Changeability_Type changeability = m_pAssociationWidget->getChangeability(Uml::A);
+ if( changeability == Uml::chg_Changeable )
+ m_ChangeableARB -> setChecked( true );
+ else if( changeability == Uml::chg_Frozen )
+ m_FrozenARB -> setChecked( true );
+ else
+ m_AddOnlyARB -> setChecked( true );
+
+ // Rolename B
+ QLabel * pRoleBL = NULL;
+ Dialog_Utils::makeLabeledEditField( propsBGB, propsBLayout, 0,
+ pRoleBL, i18n("Rolename:"),
+ m_pRoleBLE, nameB );
+
+ // Multi B
+ QLabel * pMultiBL = NULL;
+ Dialog_Utils::makeLabeledEditField( propsBGB, propsBLayout, 1,
+ pMultiBL, i18n("Multiplicity:"),
+ m_pMultiBLE, m_pAssociationWidget->getMulti(Uml::B) );
+
+ // Visibility B
+
+ QHBoxLayout * scopeBLayout = new QHBoxLayout(scopeBBG);
+ scopeBLayout -> setMargin(margin);
+
+ m_PublicBRB = new QRadioButton(i18n("Public"), scopeBBG);
+ scopeBLayout -> addWidget(m_PublicBRB);
+
+ m_PrivateBRB = new QRadioButton(i18n("Private"), scopeBBG);
+ scopeBLayout -> addWidget(m_PrivateBRB);
+
+ m_ProtectedBRB = new QRadioButton(i18n("Protected"), scopeBBG);
+ scopeBLayout -> addWidget(m_ProtectedBRB);
+
+ m_ImplementationBRB = new QRadioButton(i18n("Implementation"), scopeBBG);
+ scopeBLayout -> addWidget(m_ImplementationBRB);
+
+ scope = m_pAssociationWidget->getVisibility(Uml::B);
+ if( scope == Uml::Visibility::Public )
+ m_PublicBRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Private )
+ m_PrivateBRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Protected )
+ m_ProtectedBRB -> setChecked( true );
+ else
+ m_ImplementationBRB -> setChecked( true );
+
+ // Changeability B
+ QHBoxLayout * changeBLayout = new QHBoxLayout(changeBBG);
+ changeBLayout -> setMargin(margin);
+
+ m_ChangeableBRB = new QRadioButton(i18n("Changeable"), changeBBG);
+ changeBLayout -> addWidget(m_ChangeableBRB);
+
+ m_FrozenBRB = new QRadioButton(i18n("Frozen"), changeBBG);
+ changeBLayout -> addWidget(m_FrozenBRB);
+
+ m_AddOnlyBRB = new QRadioButton(i18n("Add only"), changeBBG);
+ changeBLayout -> addWidget(m_AddOnlyBRB);
+
+ changeability = m_pAssociationWidget->getChangeability(Uml::B);
+ if( changeability == Uml::chg_Changeable )
+ m_ChangeableBRB -> setChecked( true );
+ else if( changeability == Uml::chg_Frozen )
+ m_FrozenBRB -> setChecked( true );
+ else
+ m_AddOnlyBRB -> setChecked( true );
+
+ // Documentation
+ //
+
+ // Document A
+ QHBoxLayout * docALayout = new QHBoxLayout(docAGB);
+ docALayout -> setMargin(margin);
+ m_pDocA = new QMultiLineEdit(docAGB);
+ docALayout -> addWidget(m_pDocA);
+ m_pDocA-> setText(m_pAssociationWidget-> getRoleDoc(Uml::A));
+ // m_pDocA-> setText("<<not implemented yet>>");
+ // m_pDocA-> setEnabled(false);
+ m_pDocA->setWordWrap(QMultiLineEdit::WidgetWidth);
+
+ // Document B
+ QHBoxLayout * docBLayout = new QHBoxLayout(docBGB);
+ docBLayout -> setMargin(margin);
+ m_pDocB = new QMultiLineEdit(docBGB);
+ docBLayout -> addWidget(m_pDocB);
+ m_pDocB-> setText(m_pAssociationWidget-> getRoleDoc(Uml::B));
+ // m_pDocB-> setEnabled(false);
+ m_pDocB->setWordWrap(QMultiLineEdit::WidgetWidth);
+
+ // add group boxes to main layout
+ mainLayout -> addWidget( propsAGB, 0, 0);
+ mainLayout -> addWidget( scopeABG, 1, 0);
+ mainLayout -> addWidget(changeABG, 2, 0);
+ mainLayout -> addWidget( docAGB, 3, 0);
+ mainLayout -> addWidget( propsBGB, 0, 1);
+ mainLayout -> addWidget( scopeBBG, 1, 1);
+ mainLayout -> addWidget(changeBBG, 2, 1);
+ mainLayout -> addWidget( docBGB, 3, 1);
+
+}
+
+void AssocRolePage::updateObject() {
+
+ if(m_pAssociationWidget) {
+
+ // set props
+ m_pAssociationWidget->setRoleName(m_pRoleALE->text(), Uml::A);
+ m_pAssociationWidget->setRoleName(m_pRoleBLE->text(), Uml::B);
+ m_pAssociationWidget->setMulti(m_pMultiALE->text(), Uml::A);
+ m_pAssociationWidget->setMulti(m_pMultiBLE->text(), Uml::B);
+
+ if(m_PrivateARB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Private, Uml::A);
+ else if(m_ProtectedARB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Protected, Uml::A);
+ else if(m_PublicARB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Public, Uml::A);
+ else if(m_ImplementationARB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Implementation, Uml::A);
+
+ if(m_PrivateBRB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Private, Uml::B);
+ else if(m_ProtectedBRB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Protected, Uml::B);
+ else if(m_PublicBRB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Public, Uml::B);
+ else if(m_ImplementationBRB->isChecked())
+ m_pAssociationWidget->setVisibility(Uml::Visibility::Implementation, Uml::B);
+
+ if(m_FrozenARB->isChecked())
+ m_pAssociationWidget->setChangeability(Uml::chg_Frozen, Uml::A);
+ else if(m_AddOnlyARB->isChecked())
+ m_pAssociationWidget->setChangeability(Uml::chg_AddOnly, Uml::A);
+ else
+ m_pAssociationWidget->setChangeability(Uml::chg_Changeable, Uml::A);
+
+ if(m_FrozenBRB->isChecked())
+ m_pAssociationWidget->setChangeability(Uml::chg_Frozen, Uml::B);
+ else if(m_AddOnlyBRB->isChecked())
+ m_pAssociationWidget->setChangeability(Uml::chg_AddOnly, Uml::B);
+ else
+ m_pAssociationWidget->setChangeability(Uml::chg_Changeable, Uml::B);
+
+ m_pAssociationWidget->setRoleDoc(m_pDocA->text(), Uml::A);
+ m_pAssociationWidget->setRoleDoc(m_pDocB->text(), Uml::B);
+
+ } //end if m_pAssociationWidget
+
+}
+
+
+#include "assocrolepage.moc"
diff --git a/umbrello/umbrello/dialogs/assocrolepage.h b/umbrello/umbrello/dialogs/assocrolepage.h
new file mode 100644
index 00000000..c1c4d603
--- /dev/null
+++ b/umbrello/umbrello/dialogs/assocrolepage.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ASSOCROLEPAGE_H
+#define ASSOCROLEPAGE_H
+
+//quicktime class includes
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qbuttongroup.h>
+#include <qmultilineedit.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+
+//my class includes
+#include "../umlobject.h"
+#include "../objectwidget.h"
+#include "../umldoc.h"
+#include "../associationwidget.h"
+
+/**
+ * Displays properties of a UMLObject in a dialog box. This is not usually directly
+ * called. The class @ref AssocPropDlg will set this up for you.
+ *
+ * @short Display properties on a UMLObject.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AssocRolePage : public QWidget {
+ Q_OBJECT
+public:
+
+ /**
+ * Sets up the AssocRolePage.
+ *
+ * @param d The UMLDoc which controls controls object creation.
+ * @param parent The parent to the AssocRolePage.
+ * @param a The AssociationWidget to display the properties of.
+ */
+ AssocRolePage(UMLDoc *d, QWidget *parent, AssociationWidget *a);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~AssocRolePage();
+
+ /**
+ * Will move information from the dialog into the object.
+ * Call when the ok or apply button is pressed.
+ */
+ void updateObject();
+
+private:
+ QLineEdit *m_pRoleALE, *m_pRoleBLE, *m_pMultiALE, *m_pMultiBLE;
+ QMultiLineEdit *m_pDocA, *m_pDocB;
+ AssociationWidget *m_pAssociationWidget;
+ UMLDoc * m_pUmldoc;
+ ObjectWidget *m_pWidget;
+ QRadioButton *m_PublicARB, *m_ProtectedARB, *m_PrivateARB, *m_ImplementationARB;
+ QRadioButton *m_PublicBRB, *m_ProtectedBRB, *m_PrivateBRB, *m_ImplementationBRB;
+ QRadioButton *m_ChangeableARB, *m_AddOnlyARB, *m_FrozenARB;
+ QRadioButton *m_ChangeableBRB, *m_AddOnlyBRB, *m_FrozenBRB;
+
+ void constructWidget();
+
+public slots:
+ /**
+ * When the draw as actor check box is toggled, the draw
+ * as multi instance need to be enabled/disabled. They
+ * both can't be available at the same time.
+ */
+ // void slotActorToggled( bool state );
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/classgenpage.cpp b/umbrello/umbrello/dialogs/classgenpage.cpp
new file mode 100644
index 00000000..01b3d3c7
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classgenpage.cpp
@@ -0,0 +1,472 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// my own header
+#include "classgenpage.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qbuttongroup.h>
+#include <qmultilineedit.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kcombobox.h>
+
+// my class includes
+#include "../umlobject.h"
+#include "../objectwidget.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../artifact.h"
+#include "../component.h"
+#include "../umlview.h"
+#include "../stereotype.h"
+
+ClassGenPage::ClassGenPage(UMLDoc* d, QWidget* parent, UMLObject* o) : QWidget(parent) {
+ m_pWidget = 0;
+ m_pObject = 0;
+ m_pInstanceWidget = 0;
+ QString name;
+ int margin = fontMetrics().height();
+ Uml::Object_Type t = o -> getBaseType();
+ m_pUmldoc = d;
+ if (t == Uml::ot_Class) {
+ name = i18n("Class &name:");
+ } else if (t == Uml::ot_Actor) {
+ name = i18n("Actor &name:");
+ } else if (t == Uml::ot_Package) {
+ name = i18n("Package &name:");
+ } else if (t == Uml::ot_UseCase) {
+ name = i18n("Use case &name:");
+ } else if (t == Uml::ot_Interface) {
+ name = i18n("Interface &name:");
+ } else if (t == Uml::ot_Component) {
+ name = i18n("Component &name:");
+ } else if (t == Uml::ot_Artifact) {
+ name = i18n("Artifact &name:");
+ } else if (t == Uml::ot_Enum) {
+ name = i18n("Enum &name:");
+ } else if (t == Uml::ot_Datatype) {
+ name = i18n("Datatype &name:");
+ } else if (t == Uml::ot_Entity) {
+ name = i18n("Entity &name:");
+ } else {
+ kWarning() << "creating class gen page for unknown widget type" << endl;
+ }
+ setMinimumSize(310,330);
+ QVBoxLayout * topLayout = new QVBoxLayout(this);
+ topLayout -> setSpacing(6);
+
+ //setup name
+ QGridLayout * m_pNameLayout = new QGridLayout(topLayout, 4, 2);
+ m_pNameLayout -> setSpacing(6);
+ m_pNameL = new QLabel(this);
+ m_pNameL -> setText(name);
+ m_pNameLayout -> addWidget(m_pNameL, 0, 0);
+
+ m_pClassNameLE = new QLineEdit(this);
+ m_pNameLayout -> addWidget(m_pClassNameLE, 0, 1);
+ m_pClassNameLE->setFocus();
+ m_pNameL->setBuddy(m_pClassNameLE);
+
+ m_pStereoTypeCB = 0;
+ m_pPackageLE = 0;
+ m_pAbstractCB = 0;
+ m_pDeconCB = 0;
+
+ m_pStereoTypeL = new QLabel(i18n("&Stereotype name:"), this);
+ m_pNameLayout -> addWidget(m_pStereoTypeL, 1, 0);
+
+ m_pStereoTypeCB = new KComboBox(true, this);
+ m_pNameLayout -> addWidget(m_pStereoTypeCB, 1, 1);
+
+ m_pStereoTypeCB->setCurrentText( o->getStereotype() );
+ m_pStereoTypeL->setBuddy(m_pStereoTypeCB);
+
+ if (t == Uml::ot_Interface || t == Uml::ot_Datatype || t == Uml::ot_Enum) {
+ m_pStereoTypeCB->setEditable(false);
+ }
+
+ if (t == Uml::ot_Class || t == Uml::ot_Interface) {
+ m_pPackageL = new QLabel(i18n("&Package name:"), this);
+ m_pNameLayout -> addWidget(m_pPackageL, 2, 0);
+
+ m_pPackageLE = new QLineEdit(this);
+ m_pNameLayout -> addWidget(m_pPackageLE, 2, 1);
+
+ m_pPackageLE -> setText(o -> getPackage());
+ m_pPackageLE -> setEnabled(false);
+ m_pPackageL->setBuddy(m_pPackageLE);
+ }
+
+ if (t == Uml::ot_Class || t == Uml::ot_UseCase ) {
+ QString abstractCaption;
+ if ( t == Uml::ot_Class ) {
+ abstractCaption = i18n("A&bstract class");
+ } else {
+ abstractCaption = i18n("A&bstract use case");
+ }
+ m_pAbstractCB = new QCheckBox( abstractCaption, this );
+ m_pAbstractCB -> setChecked( o -> getAbstract() );
+ m_pNameLayout -> addWidget( m_pAbstractCB, 3, 0 );
+ }
+
+ if (t == Uml::ot_Component) {
+ m_pExecutableCB = new QCheckBox(i18n("&Executable"), this);
+ m_pExecutableCB->setChecked( (static_cast<UMLComponent*>(o))->getExecutable() );
+ m_pNameLayout->addWidget( m_pExecutableCB, 3, 0 );
+ }
+
+ if (t == Uml::ot_Artifact) {
+ //setup artifact draw as
+ m_pDrawAsBG = new QButtonGroup(i18n("Draw As"), this);
+ QHBoxLayout* drawAsLayout = new QHBoxLayout(m_pDrawAsBG);
+ drawAsLayout->setMargin(margin);
+ m_pDrawAsBG->setExclusive(true);
+
+ m_pDefaultRB = new QRadioButton(i18n("&Default"), m_pDrawAsBG);
+ drawAsLayout->addWidget(m_pDefaultRB);
+
+ m_pFileRB = new QRadioButton(i18n("&File"), m_pDrawAsBG);
+ drawAsLayout->addWidget(m_pFileRB);
+
+ m_pLibraryRB = new QRadioButton(i18n("&Library"), m_pDrawAsBG);
+ drawAsLayout->addWidget(m_pLibraryRB);
+
+ m_pTableRB = new QRadioButton(i18n("&Table"), m_pDrawAsBG);
+ drawAsLayout->addWidget(m_pTableRB);
+
+ topLayout->addWidget(m_pDrawAsBG);
+
+ UMLArtifact::Draw_Type drawAs = (static_cast<UMLArtifact*>(o))->getDrawAsType();
+
+ if (drawAs == UMLArtifact::file) {
+ m_pFileRB->setChecked(true);
+ } else if (drawAs == UMLArtifact::library) {
+ m_pLibraryRB->setChecked(true);
+ } else if (drawAs == UMLArtifact::table) {
+ m_pTableRB->setChecked(true);
+ } else {
+ m_pDefaultRB->setChecked(true);
+ }
+ }
+
+ //setup scope
+ m_pButtonBG = new QButtonGroup(i18n("Visibility"), this);
+ QHBoxLayout * scopeLayout = new QHBoxLayout(m_pButtonBG);
+ scopeLayout -> setMargin(margin);
+ m_pButtonBG -> setExclusive(true);
+
+ m_pPublicRB = new QRadioButton(i18n("P&ublic"), m_pButtonBG);
+ scopeLayout -> addWidget(m_pPublicRB);
+
+ m_pPrivateRB = new QRadioButton(i18n("P&rivate"), m_pButtonBG);
+ scopeLayout -> addWidget(m_pPrivateRB);
+
+ m_pProtectedRB = new QRadioButton(i18n("Pro&tected"), m_pButtonBG);
+ scopeLayout -> addWidget(m_pProtectedRB);
+ topLayout -> addWidget(m_pButtonBG);
+
+ m_pImplementationRB = new QRadioButton(i18n("Imple&mentation"), m_pButtonBG);
+ scopeLayout -> addWidget(m_pImplementationRB);
+ topLayout -> addWidget(m_pButtonBG);
+ //setup documentation
+ m_pDocGB = new QGroupBox(this);
+ QHBoxLayout * docLayout = new QHBoxLayout(m_pDocGB);
+ docLayout -> setMargin(margin);
+ m_pDocGB -> setTitle(i18n("Documentation"));
+
+ m_pDoc = new QMultiLineEdit(m_pDocGB);
+ docLayout -> addWidget(m_pDoc);
+ topLayout -> addWidget(m_pDocGB);
+
+ m_pObject = o;
+ //setup fields
+ m_pClassNameLE -> setText(o -> getName());
+ m_pDoc-> setText(o -> getDoc());
+ Uml::Visibility s = o -> getVisibility();
+ if(s == Uml::Visibility::Public)
+ m_pPublicRB->setChecked(true);
+ else if(s == Uml::Visibility::Private)
+ m_pPrivateRB->setChecked(true);
+ else if(s == Uml::Visibility::Protected)
+ m_pProtectedRB->setChecked(true);
+ else
+ m_pImplementationRB -> setChecked(true);
+
+ // manage stereotypes
+ m_pStereoTypeCB -> setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pStereoTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ insertStereotype (QString("")); // an empty stereotype is the default
+ int defaultStereotype=0;
+ bool foundDefaultStereotype = false;
+ for (UMLStereotypeListIt it(m_pUmldoc->getStereotypes()); it.current(); ++it) {
+ if (!foundDefaultStereotype) {
+ if ( m_pObject->getStereotype() == it.current()->getName()) {
+ foundDefaultStereotype = true;
+ }
+ defaultStereotype++;
+ }
+ insertStereotype (it.current()->getName());
+ }
+ // lookup for a default stereotype, if the operation doesn't have one
+ if (foundDefaultStereotype)
+ m_pStereoTypeCB -> setCurrentItem(defaultStereotype);
+ else
+ m_pStereoTypeCB -> setCurrentItem(-1);
+
+ ///////////
+ m_pDoc->setWordWrap(QMultiLineEdit::WidgetWidth);
+ //////////
+}
+
+ClassGenPage::ClassGenPage(UMLDoc* d, QWidget* parent, ObjectWidget* o) : QWidget(parent) {
+ m_pObject = 0;
+ m_pInstanceWidget = 0;
+ m_pWidget = o;
+ m_pDeconCB = 0;
+ m_pMultiCB = 0;
+ int margin = fontMetrics().height();
+ //int t = o -> getBaseType();
+ m_pUmldoc = d;
+ setMinimumSize(310,330);
+ QGridLayout * topLayout = new QGridLayout(this, 2, 1);
+ topLayout -> setSpacing(6);
+
+ //setup name
+ QGridLayout * m_pNameLayout = new QGridLayout(topLayout, 3, 2);
+ m_pNameLayout -> setSpacing(6);
+ m_pNameL = new QLabel(this);
+ m_pNameL -> setText(i18n("Class name:"));
+ m_pNameLayout -> addWidget(m_pNameL, 0, 0);
+
+ m_pClassNameLE = new QLineEdit(this);
+ m_pClassNameLE -> setText(o -> getName());
+ m_pNameLayout -> addWidget(m_pClassNameLE, 0, 1);
+
+ m_pInstanceL = new QLabel(this);
+ m_pInstanceL -> setText(i18n("Instance name:"));
+ m_pNameLayout -> addWidget(m_pInstanceL, 1, 0);
+
+ m_pInstanceLE = new QLineEdit(this);
+ m_pInstanceLE -> setText(o -> getInstanceName());
+ m_pNameLayout -> addWidget(m_pInstanceLE, 1, 1);
+ UMLView *view = UMLApp::app()->getCurrentView();
+
+ m_pDrawActorCB = new QCheckBox( i18n( "Draw as actor" ) , this );
+ m_pDrawActorCB -> setChecked( o -> getDrawAsActor() );
+ m_pNameLayout -> addWidget( m_pDrawActorCB, 2, 0 );
+
+ if(view -> getType() == Uml::dt_Collaboration) {
+ m_pMultiCB = new QCheckBox(i18n("Multiple instance"), this);
+ m_pMultiCB -> setChecked(o -> getMultipleInstance());
+ m_pNameLayout -> addWidget(m_pMultiCB, 2,1);
+ if( m_pDrawActorCB -> isChecked() )
+ m_pMultiCB -> setEnabled( false );
+ } else//sequence diagram
+ {
+ m_pDeconCB = new QCheckBox(i18n("Show destruction"), this);
+ m_pDeconCB->setChecked(o->getShowDestruction());
+ m_pNameLayout -> addWidget(m_pDeconCB, 2,1);
+ }
+ //setup documentation
+ m_pDocGB = new QGroupBox(this);
+ topLayout -> addWidget(m_pDocGB, 1, 0);
+ QHBoxLayout * docLayout = new QHBoxLayout(m_pDocGB);
+ docLayout -> setMargin(margin);
+ m_pDocGB -> setTitle(i18n("Documentation"));
+
+ m_pDoc = new QMultiLineEdit(m_pDocGB);
+ m_pDoc->setWordWrap(QMultiLineEdit::WidgetWidth);
+ m_pDoc-> setText(o -> getDoc());
+ docLayout -> addWidget(m_pDoc);
+ m_pObject = 0;//needs to be set to zero
+ if( m_pMultiCB )
+ connect( m_pDrawActorCB, SIGNAL( toggled( bool ) ), this, SLOT( slotActorToggled( bool ) ) );
+}
+
+ClassGenPage::ClassGenPage(UMLDoc* d, QWidget* parent, UMLWidget* widget) : QWidget(parent) {
+ m_pWidget = 0;
+ m_pObject = 0;
+ m_pInstanceWidget = widget;
+ m_pDeconCB = 0;
+ m_pMultiCB = 0;
+ int margin = fontMetrics().height();
+ //int t = o -> getBaseType();
+ m_pUmldoc = d;
+ setMinimumSize(310,330);
+ QGridLayout* topLayout = new QGridLayout(this, 2, 1);
+ topLayout->setSpacing(6);
+
+ //setup name
+ QGridLayout* m_pNameLayout = new QGridLayout(topLayout, 3, 2);
+ m_pNameLayout->setSpacing(6);
+ m_pNameL = new QLabel(this);
+ if (widget->getBaseType() == Uml::wt_Component) {
+ m_pNameL->setText(i18n("Component name:"));
+ } else if (widget->getBaseType() == Uml::wt_Node) {
+ m_pNameL->setText(i18n("Node name:"));
+ } else {
+ kWarning() << "ClassGenPage called on unknown widget type" << endl;
+ }
+ m_pNameLayout->addWidget(m_pNameL, 0, 0);
+
+ m_pClassNameLE = new QLineEdit(this);
+ m_pClassNameLE->setText(widget->getName());
+ m_pNameLayout->addWidget(m_pClassNameLE, 0, 1);
+
+ m_pStereoTypeL = new QLabel(i18n("Stereotype name:"), this);
+ m_pNameLayout->addWidget(m_pStereoTypeL, 1, 0);
+
+ m_pStereoTypeCB = new KComboBox(true, this);
+ m_pNameLayout->addWidget(m_pStereoTypeCB, 1, 1);
+
+ m_pStereoTypeCB->setCurrentText( widget->getUMLObject()->getStereotype() );
+ m_pStereoTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+
+ m_pInstanceL = new QLabel(this);
+ m_pInstanceL->setText(i18n("Instance name:"));
+ m_pNameLayout->addWidget(m_pInstanceL, 2, 0);
+
+ m_pInstanceLE = new QLineEdit(this);
+ m_pInstanceLE->setText(widget->getInstanceName());
+ m_pNameLayout->addWidget(m_pInstanceLE, 2, 1);
+
+ //setup documentation
+ m_pDocGB = new QGroupBox(this);
+ topLayout->addWidget(m_pDocGB, 1, 0);
+ QHBoxLayout* docLayout = new QHBoxLayout(m_pDocGB);
+ docLayout->setMargin(margin);
+ m_pDocGB->setTitle(i18n("Documentation"));
+
+ m_pDoc = new QMultiLineEdit(m_pDocGB);
+ m_pDoc->setWordWrap(QMultiLineEdit::WidgetWidth);
+ m_pDoc->setText(widget->getDoc());
+ docLayout->addWidget(m_pDoc);
+ m_pObject = 0;//needs to be set to zero
+}
+
+ClassGenPage::~ClassGenPage() {}
+
+void ClassGenPage::insertStereotype( const QString& type, int index )
+{
+ m_pStereoTypeCB->insertItem( type, index );
+ m_pStereoTypeCB->completionObject()->addItem( type );
+}
+
+void ClassGenPage::updateObject() {
+ if(m_pObject) {
+ QString name = m_pClassNameLE -> text();
+
+ m_pObject -> setDoc(m_pDoc -> text());
+
+ if(m_pStereoTypeCB)
+ m_pObject -> setStereotype(m_pStereoTypeCB->currentText());
+ /**
+ * @todo enable the package lineedit field amd add logic for changing the package
+ if(m_pPackageLE)
+ m_pObject -> setPackage(m_pPackageLE -> text());
+ */
+
+ if ( m_pObject->getUMLPackage() == NULL ) {
+ kDebug() << k_funcinfo << "Parent package not set, setting it to Logical View folder"<<endl;
+ UMLFolder* folder = m_pUmldoc->getRootFolder( Uml::mt_Logical );
+ m_pObject->setUMLPackage( ( UMLPackage* )folder );
+ }
+
+ if( m_pAbstractCB )
+ m_pObject -> setAbstract( m_pAbstractCB -> isChecked() );
+ //make sure unique name
+ UMLObject *o = m_pUmldoc -> findUMLObject(name);
+ if(o && m_pObject != o) {
+ KMessageBox::sorry(this, i18n("The name you have chosen\nis already being used.\nThe name has been reset."),
+ i18n("Name is Not Unique"), false);
+ m_pClassNameLE -> setText( m_pObject -> getName() );
+ } else
+ m_pObject -> setName(name);
+ Uml::Visibility s;
+ if(m_pPublicRB -> isChecked())
+ s = Uml::Visibility::Public;
+ else if(m_pPrivateRB -> isChecked())
+ s = Uml::Visibility::Private;
+ else if(m_pProtectedRB->isChecked())
+ s = Uml::Visibility::Protected;
+ else
+ s = Uml::Visibility::Implementation;
+ m_pObject -> setVisibility(s);
+
+ if (m_pObject->getBaseType() == Uml::ot_Component) {
+ (static_cast<UMLComponent*>(m_pObject))->setExecutable( m_pExecutableCB->isChecked() );
+ }
+
+ if (m_pObject->getBaseType() == Uml::ot_Artifact) {
+ UMLArtifact::Draw_Type drawAsType;
+ if ( m_pFileRB->isChecked() ) {
+ drawAsType = UMLArtifact::file;
+ } else if ( m_pLibraryRB->isChecked() ) {
+ drawAsType = UMLArtifact::library;
+ } else if (m_pTableRB->isChecked() ) {
+ drawAsType = UMLArtifact::table;
+ } else {
+ drawAsType = UMLArtifact::defaultDraw;
+ }
+ (static_cast<UMLArtifact*>(m_pObject))->setDrawAsType(drawAsType);
+ }
+
+ }//end if m_pObject
+ else if(m_pWidget) {
+ m_pWidget -> setInstanceName(m_pInstanceLE -> text());
+ if(m_pMultiCB)
+ m_pWidget -> setMultipleInstance(m_pMultiCB -> isChecked());
+ m_pWidget -> setDrawAsActor( m_pDrawActorCB -> isChecked() );
+ if( m_pDeconCB )
+ m_pWidget -> setShowDestruction( m_pDeconCB -> isChecked() );
+ QString name = m_pClassNameLE -> text();
+ m_pWidget -> setDoc(m_pDoc -> text());
+ UMLObject * o = m_pWidget -> getUMLObject();
+ UMLObject * old = m_pUmldoc -> findUMLObject(name);
+ if(old && o != old) {
+ KMessageBox::sorry(this, i18n("The name you have chosen\nis already being used.\nThe name has been reset."),
+ i18n("Name is Not Unique"), false);
+ } else
+ o -> setName(name);
+ } else if (m_pInstanceWidget) {
+ m_pInstanceWidget->setInstanceName(m_pInstanceLE->text());
+ QString name = m_pClassNameLE->text();
+ m_pInstanceWidget->setDoc(m_pDoc->text());
+ UMLObject* o = m_pInstanceWidget->getUMLObject();
+ UMLObject* old = m_pUmldoc->findUMLObject(name);
+ if(old && o != old) {
+ KMessageBox::sorry(this, i18n("The name you have chosen\nis already being used.\nThe name has been reset."),
+ i18n("Name is Not Unique"), false);
+ } else {
+ o->setName(name);
+ }
+ o->setStereotype( m_pStereoTypeCB->currentText() );
+ }
+}
+
+void ClassGenPage::slotActorToggled( bool state ) {
+ if( m_pMultiCB )
+ m_pMultiCB -> setEnabled( !state );
+}
+
+
+
+#include "classgenpage.moc"
diff --git a/umbrello/umbrello/dialogs/classgenpage.h b/umbrello/umbrello/dialogs/classgenpage.h
new file mode 100644
index 00000000..6fd0f7d3
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classgenpage.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSGENPAGE_H
+#define CLASSGENPAGE_H
+
+#include <qwidget.h>
+
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QButtonGroup;
+class QMultiLineEdit;
+class QRadioButton;
+class QCheckBox;
+class KComboBox;
+
+class UMLObject;
+class UMLWidget;
+class ObjectWidget;
+class UMLDoc;
+
+/**
+ * Displays properties of a UMLObject in a dialog box. This is not usually directly
+ * called. The class @ref ClassPropDlg will set this up for you.
+ *
+ * @short Display properties on a UMLObject.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassGenPage : public QWidget {
+ Q_OBJECT
+public:
+
+ /**
+ * Sets up the ClassGenPage.
+ *
+ * @param d The UMLDoc which controls controls object creation.
+ * @param parent The parent to the ClassGenPage.
+ * @param o The UMLObject to display the properties of.
+ */
+ ClassGenPage(UMLDoc *d, QWidget *parent, UMLObject * o);
+
+ /**
+ * Sets up the ClassGenPage for an ObjectWidget
+ *
+ * @param d The UMLDoc which controls controls object creation.
+ * @param parent The parent to the ClassGenPage.
+ * @param o The ObjectWidget to display the properties of.
+ */
+ ClassGenPage(UMLDoc *d, QWidget *parent, ObjectWidget * o);
+
+ /**
+ * Sets up the ClassGenPage for a UMLWidget instance (used
+ * for component instances on deployment diagrams)
+ *
+ * @param d The UMLDoc which controls controls object creation.
+ * @param parent The parent to the ClassGenPage.
+ * @param widget The UMLWidget to display the properties of.
+ */
+ ClassGenPage(UMLDoc* d, QWidget* parent, UMLWidget* widget);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~ClassGenPage();
+
+ /**
+ * Will move information from the dialog into the object.
+ * Call when the ok or apply button is pressed.
+ */
+ void updateObject();
+private:
+ QGroupBox *m_pDocGB;
+ QButtonGroup * m_pButtonBG;
+ QLabel * m_pNameL, * m_pInstanceL, * m_pStereoTypeL, * m_pPackageL;
+ QLineEdit * m_pClassNameLE, *m_pInstanceLE, * m_pPackageLE;
+ KComboBox * m_pStereoTypeCB;
+ QRadioButton *m_pPublicRB, *m_pPrivateRB, *m_pProtectedRB, *m_pImplementationRB;
+ QCheckBox * m_pMultiCB, * m_pDrawActorCB, * m_pAbstractCB, * m_pDeconCB;
+ QMultiLineEdit * m_pDoc;
+ UMLObject * m_pObject;
+ UMLDoc * m_pUmldoc;
+ ObjectWidget * m_pWidget;
+ UMLWidget* m_pInstanceWidget;
+ QButtonGroup* m_pDrawAsBG;
+ QRadioButton* m_pDefaultRB,* m_pFileRB,* m_pLibraryRB,* m_pTableRB;
+ QCheckBox* m_pExecutableCB;
+
+ void insertStereotype(const QString& type, int index = -1);
+
+public slots:
+ /**
+ * When the draw as actor check box is toggled, the draw
+ * as multi instance need to be enabled/disabled. They
+ * both can't be available at the same time.
+ */
+ void slotActorToggled( bool state );
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/classifierlistpage.cpp b/umbrello/umbrello/dialogs/classifierlistpage.cpp
new file mode 100644
index 00000000..d7148660
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classifierlistpage.cpp
@@ -0,0 +1,607 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "classifierlistpage.h"
+#include "../classifierlistitem.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../entity.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../enumliteral.h"
+#include "../entityattribute.h"
+#include "../object_factory.h"
+#include <kapplication.h>
+#include <kbuttonbox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <qlayout.h>
+
+using namespace Uml;
+
+ClassifierListPage::ClassifierListPage(QWidget* parent, UMLClassifier* classifier,
+ UMLDoc* doc, Uml::Object_Type type) : QWidget(parent) {
+ m_itemType = type;
+ QString typeName("");
+ QString newItemType("");
+ if (type == ot_Attribute) {
+ typeName = i18n("Attributes");
+ newItemType = i18n("N&ew Attribute...");
+ } else if (type == ot_Operation) {
+ typeName = i18n("Operations");
+ newItemType = i18n("N&ew Operation...");
+ } else if (type == ot_Template) {
+ typeName = i18n("Templates");
+ newItemType = i18n("N&ew Template...");
+ } else if (type == ot_EnumLiteral) {
+ typeName = i18n("Enum Literals");
+ newItemType = i18n("N&ew Enum Literal...");
+ } else if (type == ot_EntityAttribute) {
+ typeName = i18n("Entity Attributes");
+ newItemType = i18n("N&ew Entity Attribute...");
+ } else {
+ kWarning() << "unknown listItem type in ClassifierListPage" << endl;
+ }
+
+ m_bSigWaiting = false;
+ m_pDoc = doc;
+ m_pClassifier = classifier;
+ m_pMenu = 0;
+ int margin = fontMetrics().height();
+ setMinimumSize(310,330);
+
+ //main layout contains our two group boxes, the list and the documentation
+ QVBoxLayout* mainLayout = new QVBoxLayout( this );
+ mainLayout->setSpacing(10);
+
+ //top group box, contains a vertical layout with list box above and buttons below
+ m_pItemListGB = new QGroupBox(typeName, this );
+ QVBoxLayout* listVBoxLayout = new QVBoxLayout( m_pItemListGB );
+ listVBoxLayout->setMargin(margin);
+ listVBoxLayout->setSpacing ( 10 );
+
+ //horizontal box contains the list box and the move up/down buttons
+ QHBoxLayout* listHBoxLayout = new QHBoxLayout( listVBoxLayout );
+ m_pItemListLB = new QListBox(m_pItemListGB);
+ listHBoxLayout->addWidget(m_pItemListLB);
+
+ //the move up/down buttons (another vertical box)
+ QVBoxLayout* buttonLayout = new QVBoxLayout( listHBoxLayout );
+ m_pTopArrowB = new KArrowButton( m_pItemListGB );
+ m_pTopArrowB->setEnabled( false );
+ buttonLayout->addWidget( m_pTopArrowB );
+
+ m_pUpArrowB = new KArrowButton( m_pItemListGB );
+ m_pUpArrowB->setEnabled( false );
+ buttonLayout->addWidget( m_pUpArrowB );
+
+ m_pDownArrowB = new KArrowButton( m_pItemListGB, Qt::DownArrow );
+ m_pDownArrowB->setEnabled( false );
+ buttonLayout->addWidget( m_pDownArrowB );
+
+ m_pBottomArrowB = new KArrowButton( m_pItemListGB, Qt::DownArrow );
+ m_pBottomArrowB->setEnabled( false );
+ buttonLayout->addWidget( m_pBottomArrowB );
+
+ //the action buttons
+ KButtonBox* buttonBox = new KButtonBox(m_pItemListGB);
+ buttonBox->addButton( newItemType, this, SLOT(slotNewListItem()) );
+ m_pDeleteListItemButton = buttonBox->addButton( i18n("&Delete"),
+ this, SLOT(slotDelete()) );
+ m_pPropertiesButton = buttonBox->addButton( i18n("&Properties"), this, SLOT(slotProperties()) );
+ listVBoxLayout->addWidget(buttonBox);
+
+ mainLayout->addWidget(m_pItemListGB);
+
+ m_pDocGB = new QGroupBox(i18n("Documentation"), this);
+ QVBoxLayout* docLayout = new QVBoxLayout( m_pDocGB );
+ m_pDocTE = new QTextEdit( m_pDocGB );
+ docLayout->setMargin(margin);
+ docLayout->setSpacing ( 10 );
+ docLayout->addWidget( m_pDocTE );
+ mainLayout->addWidget(m_pDocGB);
+
+ UMLClassifierListItemList itemList(getItemList());
+
+ // add each item in the list to the ListBox and connect each item modified signal
+ // to the ListItemModified slot in this class
+ for (UMLClassifierListItem* listItem = itemList.first(); listItem != 0; listItem = itemList.next() ) {
+ m_pItemListLB->insertItem(listItem->toString(Uml::st_SigNoVis));
+ connect( listItem, SIGNAL(modified()),this,SLOT(slotListItemModified()) );
+ }
+
+ enableWidgets(false);//disable widgets until an att is chosen
+ m_pOldListItem = 0;
+ connect(m_pItemListLB, SIGNAL(clicked(QListBoxItem*)), this, SLOT(slotClicked(QListBoxItem*)));
+ connect(m_pItemListLB, SIGNAL(selectionChanged(QListBoxItem*)), this, SLOT(slotClicked(QListBoxItem*)));
+
+ connect(m_pItemListLB, SIGNAL(rightButtonPressed(QListBoxItem*, const QPoint&)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem*, const QPoint&)));
+
+ connect(m_pItemListLB, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem*, const QPoint&)));
+ connect(m_pDoc, SIGNAL(sigObjectCreated(UMLObject*)), this, SLOT(slotListItemCreated(UMLObject*)));
+
+ connect( m_pTopArrowB, SIGNAL( clicked() ), this, SLOT( slotTopClicked() ) );
+ connect( m_pUpArrowB, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) );
+ connect( m_pDownArrowB, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) );
+ connect( m_pBottomArrowB, SIGNAL( clicked() ), this, SLOT( slotBottomClicked() ) );
+ connect( m_pItemListLB, SIGNAL( doubleClicked( QListBoxItem* ) ),
+ this, SLOT( slotDoubleClick( QListBoxItem* ) ) );
+}
+
+ClassifierListPage::~ClassifierListPage() {
+
+}
+
+void ClassifierListPage::enableWidgets(bool state) {
+ m_pDocTE->setEnabled( state );
+ //if disabled clear contents
+ if( !state ) {
+ m_pDocTE->setText( "" );
+ m_pTopArrowB->setEnabled( false );
+ m_pUpArrowB->setEnabled( false );
+ m_pDownArrowB->setEnabled( false );
+ m_pBottomArrowB->setEnabled( false );
+ m_pDeleteListItemButton->setEnabled(false);
+ m_pPropertiesButton->setEnabled(false);
+ return;
+ }
+ /*now check the order buttons.
+ Double check an item is selected
+ If only one item in list make sure they are disabled.
+ If at top item, only allow down arrow to be enabled.
+ If at bottom item, only allow up arrow to be enabled.
+ */
+ int index = m_pItemListLB->currentItem();
+ if( m_pItemListLB->count() == 1 || index == -1 ) {
+ m_pTopArrowB->setEnabled( false );
+ m_pUpArrowB->setEnabled( false );
+ m_pDownArrowB->setEnabled( false );
+ m_pBottomArrowB->setEnabled( false );
+ } else if( index == 0 ) {
+ m_pTopArrowB->setEnabled( false );
+ m_pUpArrowB->setEnabled( false );
+ m_pDownArrowB->setEnabled( true );
+ m_pBottomArrowB->setEnabled( true );
+ } else if( index == (int)m_pItemListLB->count() - 1 ) {
+ m_pTopArrowB->setEnabled( true );
+ m_pUpArrowB->setEnabled( true );
+ m_pDownArrowB->setEnabled( false );
+ m_pBottomArrowB->setEnabled( false );
+ } else {
+ m_pTopArrowB->setEnabled( true );
+ m_pUpArrowB->setEnabled( true );
+ m_pDownArrowB->setEnabled( true );
+ m_pBottomArrowB->setEnabled( true );
+ }
+ m_pDeleteListItemButton->setEnabled(true);
+ m_pPropertiesButton->setEnabled(true);
+}
+
+void ClassifierListPage::slotClicked(QListBoxItem*item) {
+ //if not first time an item is highlighted
+ //save old highlighted item first
+ if(m_pOldListItem) {
+ m_pOldListItem->setDoc( m_pDocTE->text() );
+ }
+
+ // make sure clicked on an item
+ // it is impossible to deselect all items, because our list box has keyboard
+ // focus and so at least one item is always selected; this doesn't happen, if
+ // there are no items of course;
+ //
+ // for more information see Qt doc for void QListBox::clearSelection()
+ UMLClassifierListItem* listItem;
+ if (item == NULL) {
+ if (m_pItemListLB->count() == 0) {
+ enableWidgets(false);
+ m_pOldListItem = 0;
+ m_pItemListLB->clearSelection();
+ return;
+ }
+ m_pItemListLB->setSelected(0, true);
+ listItem = getItemList().at(0);
+ } else {
+ listItem = getItemList().at( m_pItemListLB->index(item) );
+ }
+
+ if (listItem) {
+ //now update screen
+ m_pDocTE->setText( listItem->getDoc() );
+ enableWidgets(true);
+ m_pOldListItem = listItem;
+ }
+}
+
+void ClassifierListPage::updateObject() {
+ saveCurrentItemDocumentation();
+ QListBoxItem*i = m_pItemListLB->item(m_pItemListLB->currentItem());
+ slotClicked(i);
+
+ // The rest of this function does nothing?!
+ QStringList stringList;
+ int count = m_pItemListLB->count();
+ for( int j = 0; j < count ; j++ )
+ stringList.append( m_pItemListLB->text( j ) );
+}
+
+void ClassifierListPage::slotListItemCreated(UMLObject* object) {
+ if(!m_bSigWaiting) {
+ return;
+ }
+ UMLClassifierListItem *listItem = dynamic_cast<UMLClassifierListItem*>(object);
+ if (listItem == NULL) {
+ return;
+ }
+ int index = m_pItemListLB->count();
+ m_pItemListLB->insertItem(listItem->toString(Uml::st_SigNoVis), index);
+ m_bSigWaiting = false;
+
+ // now select the new item, so that the user can go on adding doc or calling
+ // the property dialog
+ m_pItemListLB->setSelected(index, true);
+ slotClicked(m_pItemListLB->item(index));
+}
+
+void ClassifierListPage::slotListItemModified() {
+ if(!m_bSigWaiting) {
+ return;
+ }
+ //is this safe???
+ UMLClassifierListItem* object = const_cast<UMLClassifierListItem*>(dynamic_cast<const UMLClassifierListItem*>(sender()));
+ if (object == NULL)
+ return;
+ int index = m_pItemListLB->currentItem();
+ m_pItemListLB->changeItem(object->toString(Uml::st_SigNoVis), index);
+ m_bSigWaiting = false;
+}
+
+void ClassifierListPage::slotRightButtonClicked(QListBoxItem* /*item*/, const QPoint& /* p*/) {
+ if (m_pMenu) {
+ m_pMenu->hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void ClassifierListPage::slotRightButtonPressed(QListBoxItem* item, const QPoint& p) {
+ ListPopupMenu::Menu_Type type = ListPopupMenu::mt_Undefined;
+ if (item) { //pressed on a list item
+ if (m_itemType == ot_Attribute) {
+ type = ListPopupMenu::mt_Attribute_Selected;
+ } else if (m_itemType == ot_Operation) {
+ type = ListPopupMenu::mt_Operation_Selected;
+ } else if (m_itemType == ot_Template) {
+ type = ListPopupMenu::mt_Template_Selected;
+ } else if (m_itemType == ot_EnumLiteral) {
+ type = ListPopupMenu::mt_EnumLiteral_Selected;
+ } else if (m_itemType == ot_EntityAttribute) {
+ type = ListPopupMenu::mt_EntityAttribute_Selected;
+ } else {
+ kWarning() << "unknown type in ClassifierListPage" << endl;
+ }
+ } else { //pressed into fresh air
+ if (m_itemType == ot_Attribute) {
+ type = ListPopupMenu::mt_New_Attribute;
+ } else if (m_itemType == ot_Operation) {
+ type = ListPopupMenu::mt_New_Operation;
+ } else if (m_itemType == ot_Template) {
+ type = ListPopupMenu::mt_New_Template;
+ } else if (m_itemType == ot_EnumLiteral) {
+ type = ListPopupMenu::mt_New_EnumLiteral;
+ } else if (m_itemType == ot_EntityAttribute) {
+ type = ListPopupMenu::mt_New_EntityAttribute;
+ } else {
+ kWarning() << "unknown type in ClassifierListPage" << endl;
+ }
+ }
+ if(m_pMenu) {
+ m_pMenu->hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ m_pMenu = new ListPopupMenu(this, type);
+
+ m_pMenu->popup(p);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+}
+
+void ClassifierListPage::slotPopupMenuSel(int id) {
+ UMLClassifierListItem* listItem = getItemList().at( m_pItemListLB->currentItem() );
+ if(!listItem && id != ListPopupMenu::mt_New_Attribute) {
+ kDebug() << "can't find att from selection" << endl;
+ return;
+ }
+ switch(id) {
+ case ListPopupMenu::mt_New_Attribute:
+ case ListPopupMenu::mt_New_Operation:
+ case ListPopupMenu::mt_New_Template:
+ case ListPopupMenu::mt_New_EnumLiteral:
+ case ListPopupMenu::mt_New_EntityAttribute:
+ slotNewListItem();
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ slotDelete();
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ m_bSigWaiting = true;
+ m_pDoc->renameChildUMLObject(listItem);
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ slotProperties();
+ break;
+ }
+}
+
+void ClassifierListPage::printItemList(QString prologue) {
+#ifdef VERBOSE_DEBUGGING
+ UMLClassifierListItem* item;
+ QString buf;
+ UMLClassifierListItemList itemList = getItemList();
+ for (UMLClassifierListItemListIt it(itemList); (item = it.current()) != NULL; ++it)
+ buf.append(' ' + item->getName());
+ kDebug() << prologue << buf << endl;
+#endif
+}
+
+void ClassifierListPage::slotTopClicked() {
+ int count = m_pItemListLB->count();
+ int index = m_pItemListLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index <= 0 )
+ return;
+ m_pOldListItem = NULL;
+
+ //swap the text around in the ListBox
+ QString currentString = m_pItemListLB->text( index );
+ m_pItemListLB->removeItem( index );
+ m_pItemListLB->insertItem( currentString, 0 );
+ //set the moved item selected
+ QListBoxItem* item = m_pItemListLB->item( 0 );
+ m_pItemListLB->setSelected( item, true );
+
+ //now change around in the list
+ printItemList("itemList before change: ");
+ UMLClassifierListItem* currentAtt = getItemList().at(index);
+ // NB: The index in the m_pItemListLB is not necessarily the same
+ // as the index in the UMLClassifier::m_List.
+ // Reason: getItemList() returns only a subset of all entries
+ // in UMLClassifier::m_List.
+ takeItem(currentAtt, true, index); // now we index the UMLClassifier::m_List
+ kDebug() << "ClassifierListPage::slotTopClicked(" << currentAtt->getName()
+ << "): peer index in UMLCanvasItem::m_List is " << index << endl;
+ addClassifier(currentAtt, 0);
+ printItemList("itemList after change: ");
+ slotClicked(item);
+}
+
+void ClassifierListPage::slotUpClicked() {
+ int count = m_pItemListLB->count();
+ int index = m_pItemListLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index <= 0 )
+ return;
+ m_pOldListItem = NULL;
+
+ //swap the text around in the ListBox
+ QString aboveString = m_pItemListLB->text( index - 1 );
+ QString currentString = m_pItemListLB->text( index );
+ m_pItemListLB->changeItem( currentString, index -1 );
+ m_pItemListLB->changeItem( aboveString, index );
+ //set the moved item selected
+ QListBoxItem* item = m_pItemListLB->item( index - 1 );
+ m_pItemListLB->setSelected( item, true );
+
+ //now change around in the list
+ printItemList("itemList before change: ");
+ UMLClassifierListItem* currentAtt = getItemList().at(index);
+ // NB: The index in the m_pItemListLB is not necessarily the same
+ // as the index in the UMLClassifier::m_List.
+ // Reason: getItemList() returns only a subset of all entries
+ // in UMLClassifier::m_List.
+ takeItem(currentAtt, true, index); // now we index the UMLClassifier::m_List
+ kDebug() << "ClassifierListPage::slotUpClicked(" << currentAtt->getName()
+ << "): peer index in UMLCanvasItem::m_List is " << index << endl;
+ if (index == -1)
+ index = 0;
+ addClassifier(currentAtt, index);
+ printItemList("itemList after change: ");
+ slotClicked( item );
+}
+
+void ClassifierListPage::slotDownClicked() {
+ int count = m_pItemListLB->count();
+ int index = m_pItemListLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index >= count - 1 )
+ return;
+ m_pOldListItem = NULL;
+
+ //swap the text around in the ListBox
+ QString belowString = m_pItemListLB->text( index + 1 );
+ QString currentString = m_pItemListLB->text( index );
+ m_pItemListLB->changeItem( currentString, index + 1 );
+ m_pItemListLB->changeItem( belowString, index );
+ //set the moved item selected
+ QListBoxItem* item = m_pItemListLB->item( index + 1 );
+ m_pItemListLB->setSelected( item, true );
+ //now change around in the list
+ printItemList("itemList before change: ");
+ UMLClassifierListItem* currentAtt = getItemList().at(index);
+ // NB: The index in the m_pItemListLB is not necessarily the same
+ // as the index in the UMLClassifier::m_List.
+ // Reason: getItemList() returns only a subset of all entries
+ // in UMLClassifier::m_List.
+ takeItem(currentAtt, false, index); // now we index the UMLClassifier::m_List
+ kDebug() << "ClassifierListPage::slotDownClicked(" << currentAtt->getName()
+ << "): peer index in UMLCanvasItem::m_List is " << index << endl;
+ if (index != -1)
+ index++; // because we want to go _after_ the following peer item
+ addClassifier(currentAtt, index);
+ printItemList("itemList after change: ");
+ slotClicked( item );
+}
+
+void ClassifierListPage::slotBottomClicked() {
+ int count = m_pItemListLB->count();
+ int index = m_pItemListLB->currentItem();
+ //shouldn't occur, but just in case
+ if( count <= 1 || index >= count - 1 )
+ return;
+ m_pOldListItem = NULL;
+
+ //swap the text around in the ListBox
+ QString currentString = m_pItemListLB->text( index );
+ m_pItemListLB->removeItem( index );
+ m_pItemListLB->insertItem( currentString, m_pItemListLB->count() );
+ //set the moved item selected
+ QListBoxItem* item = m_pItemListLB->item( m_pItemListLB->count() - 1 );
+ m_pItemListLB->setSelected( item, true );
+
+ //now change around in the list
+ printItemList("itemList before change: ");
+ UMLClassifierListItem* currentAtt = getItemList().at(index);
+ // NB: The index in the m_pItemListLB is not necessarily the same
+ // as the index in the UMLClassifier::m_List.
+ // Reason: getItemList() returns only a subset of all entries
+ // in UMLClassifier::m_List.
+ takeItem(currentAtt, false, index); // now we index the UMLClassifier::m_List
+ kDebug() << "ClassifierListPage::slotDownClicked(" << currentAtt->getName()
+ << "): peer index in UMLCanvasItem::m_List is " << index << endl;
+ addClassifier(currentAtt, getItemList().count());
+ printItemList("itemList after change: ");
+ slotClicked( item );
+}
+
+void ClassifierListPage::slotDoubleClick( QListBoxItem* item ) {
+ if( !item )
+ return;
+
+ UMLClassifierListItem* listItem = getItemList().at( m_pItemListLB->index( item ) );
+ if( !listItem ) {
+ kDebug() << "can't find att from selection" << endl;
+ return;
+ }
+
+ if( listItem->showPropertiesDialog(this) ) {
+ m_pItemListLB->changeItem( listItem->toString(Uml::st_SigNoVis), m_pItemListLB->index(item) );
+ }
+}
+
+void ClassifierListPage::slotDelete() {
+ UMLClassifierListItem* selectedItem = getItemList().at( m_pItemListLB->currentItem() );
+ //should really wait for signal back
+ //but really shouldn't matter
+ m_pDoc->removeUMLObject(selectedItem);
+ m_pItemListLB->removeItem( m_pItemListLB->currentItem());
+ m_pOldListItem = 0;
+ slotClicked(0);
+}
+
+void ClassifierListPage::slotProperties() {
+ saveCurrentItemDocumentation();
+ slotDoubleClick( m_pItemListLB->item( m_pItemListLB->currentItem() ) );
+}
+
+void ClassifierListPage::slotNewListItem() {
+ saveCurrentItemDocumentation();
+ m_bSigWaiting = true;
+ Object_Factory::createChildObject(m_pClassifier, m_itemType);
+}
+
+void ClassifierListPage::saveCurrentItemDocumentation() {
+ UMLClassifierListItem* selectedItem = getItemList().at( m_pItemListLB->currentItem() );
+ if (selectedItem) {
+ selectedItem->setDoc( m_pDocTE->text() );
+ }
+}
+
+UMLClassifierListItemList ClassifierListPage::getItemList() {
+ return m_pClassifier->getFilteredList(m_itemType);
+}
+
+bool ClassifierListPage::addClassifier(UMLClassifierListItem* listitem, int position) {
+ switch (m_itemType) {
+ case ot_Attribute: {
+ UMLAttribute *att = dynamic_cast<UMLAttribute*>(listitem);
+ return m_pClassifier->addAttribute(att, NULL, position);
+ }
+ case ot_Operation: {
+ UMLOperation *op = dynamic_cast<UMLOperation*>(listitem);
+ return m_pClassifier->addOperation(op, position);
+ }
+ case ot_Template: {
+ UMLTemplate* t = dynamic_cast<UMLTemplate*>(listitem);
+ return m_pClassifier->addTemplate(t, position);
+ }
+ case ot_EnumLiteral: {
+ UMLEnum* c = dynamic_cast<UMLEnum*>(m_pClassifier);
+ if (c) {
+ return c->addEnumLiteral(dynamic_cast<UMLEnumLiteral*>(listitem), position);
+ }
+ break;
+ }
+ case ot_EntityAttribute: {
+ UMLEntity* c = dynamic_cast<UMLEntity*>(m_pClassifier);
+ if (c) {
+ return c->addEntityAttribute(dynamic_cast<UMLEntityAttribute*>(listitem), position);
+ }
+ break;
+ }
+ default: {
+ kWarning() << "unknown type in ClassifierListPage" << endl;
+ return false;
+ }
+ }
+ kError() << "ClassifierListPage::addClassifier unable to handle listitem type in current state" << endl;
+ return false;
+}
+
+bool ClassifierListPage::takeItem(UMLClassifierListItem* listItem,
+ bool seekPeerBefore, int &peerIndex) {
+ int wasAtIndex = m_pClassifier->takeItem(listItem);
+ if (wasAtIndex == -1)
+ return false;
+ kapp->processEvents();
+ peerIndex = -1;
+ UMLObject *o;
+ const Uml::Object_Type seekType = listItem->getBaseType();
+ UMLObjectList listItems = m_pClassifier->subordinates();
+ UMLObjectListIt it(listItems);
+ for (int i = 0; (o = it.current()) != NULL; ++i, ++it) {
+ if (seekPeerBefore) {
+ if (i >= wasAtIndex)
+ break;
+ if (o->getBaseType() == seekType)
+ peerIndex = i;
+ } else { // seekPeerAfter
+ if (i < wasAtIndex)
+ continue;
+ if (o->getBaseType() == seekType) {
+ peerIndex = i;
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+
+#include "classifierlistpage.moc"
+
diff --git a/umbrello/umbrello/dialogs/classifierlistpage.h b/umbrello/umbrello/dialogs/classifierlistpage.h
new file mode 100644
index 00000000..ea1c0b9f
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classifierlistpage.h
@@ -0,0 +1,191 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIFIERLISTPAGE_H
+#define CLASSIFIERLISTPAGE_H
+
+//qt includes
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qtextedit.h>
+//kde includes
+#include <karrowbutton.h>
+
+//app includes
+#include "../listpopupmenu.h"
+#include "../umlclassifierlistitemlist.h"
+
+class UMLObject;
+class UMLClassifier;
+class UMLDoc;
+
+/**
+ * A dialog page to display classifier list properties. This is not normally setup
+ * by you. It is used by the @ref ClassPropDlg and new class wizard.
+ *
+ * @short A dialog page to display classifier properties.
+ * @author Paul Hensgen, Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassifierListPage : public QWidget {
+ Q_OBJECT
+public:
+ /**
+ * Sets up the ClassifierListPage
+ *
+ * @param parent The parent to the ClassAttPage.
+ * @param classifier The Concept to display the properties of.
+ * @param doc The UMLDoc document
+ * @param type The type of listItem this handles
+ */
+ ClassifierListPage(QWidget* parent, UMLClassifier* classifier, UMLDoc* doc, Uml::Object_Type type);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~ClassifierListPage();
+
+ /**
+ * Will move information from the dialog into the object.
+ * Call when the ok or apply button is pressed.
+ */
+ void updateObject();
+
+private:
+ /**
+ * Set the state of the widgets on the page with the given value.
+ *
+ * @param state The state to set the widgets as.
+ */
+ void enableWidgets(bool state);
+
+ /**
+ * Saves the documentation for the currently selected item
+ */
+ void saveCurrentItemDocumentation();
+
+ /**
+ * Get classifiers
+ */
+ UMLClassifierListItemList getItemList();
+
+ /**
+ * Attempts to add classifier to the appropriate list
+ *
+ * @param classifier Pointer to the classifier to add.
+ * @param position Index at which to insert into the list.
+ * @return true if the classifier could be added
+ *
+ */
+ bool addClassifier(UMLClassifierListItem* classifier, int position = -1);
+
+ /**
+ * Take a classifier's subordinate item.
+ * Ownership of the classifier list item is transferred to the caller.
+ * @param listitem UMLClassifierListItem to take.
+ * @param seekPeerBefore True if a peer index should be sought which
+ * is smaller than the current listitem's index.
+ * @param peerIndex Return value: Index in the UMLClassifier's
+ * item list at which a peer item, i.e. another
+ * UMLClassifierListItem of the same type as
+ * listItem, is found. If no such item exists
+ * then return -1.
+ * @return True for success.
+ */
+ bool takeItem(UMLClassifierListItem* listitem,
+ bool seekPeerBefore, int &peerIndex);
+
+ /**
+ * Utility for debugging, prints the current item list.
+ * Only effective if VERBOSE_DEBUGGING is defined.
+ */
+ void printItemList(QString prologue);
+
+ UMLClassifier* m_pClassifier;
+ QGroupBox* m_pDocGB;
+ QGroupBox* m_pItemListGB;
+ QListBox* m_pItemListLB;
+ QTextEdit* m_pDocTE;
+ Uml::Object_Type m_itemType;
+
+ KArrowButton* m_pTopArrowB;
+ KArrowButton* m_pUpArrowB;
+ KArrowButton* m_pDownArrowB;
+ KArrowButton* m_pBottomArrowB;
+ QPushButton* m_pDeleteListItemButton;
+ QPushButton* m_pPropertiesButton;
+
+ UMLClassifierListItem* m_pOldListItem;
+ UMLDoc* m_pDoc;
+ ListPopupMenu* m_pMenu;
+ bool m_bSigWaiting;
+
+public slots:
+ /**
+ * called when list view is clicked on
+ * calls enableWidgets()
+ */
+ void slotClicked(QListBoxItem* item);
+
+ /**
+ * Called when an item is selected in a right click menu
+ */
+ void slotPopupMenuSel(int id);
+
+ void slotListItemCreated(UMLObject* object);
+ void slotListItemModified();
+ void slotRightButtonClicked(QListBoxItem* item, const QPoint& p);
+ void slotRightButtonPressed(QListBoxItem* item, const QPoint& p);
+
+ /**
+ * shows properties dialog for the attribute clicked on
+ */
+ void slotDoubleClick(QListBoxItem* item);
+
+
+ /**
+ * moves selected attribute to the top of the list
+ */
+ void slotTopClicked();
+
+ /**
+ * moves selected attribute up in list
+ */
+ void slotUpClicked();
+
+ /**
+ * moved selected attribute down in list
+ */
+ void slotDownClicked();
+
+ /**
+ * moved selected attribute to the bottom of the list
+ */
+ void slotBottomClicked();
+
+ /**
+ * shows dialog for new attribute
+ */
+ void slotNewListItem();
+
+ /**
+ * removes currently seleted attribute
+ */
+ void slotDelete();
+
+ /**
+ * shows properties dialog for currently selected attribute
+ */
+ void slotProperties();
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/classoptionspage.cpp b/umbrello/umbrello/dialogs/classoptionspage.cpp
new file mode 100644
index 00000000..7a54f2dc
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classoptionspage.cpp
@@ -0,0 +1,195 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classoptionspage.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// local includes
+#include "../umlview.h"
+#include "../classifierwidget.h"
+
+
+ClassOptionsPage::ClassOptionsPage(QWidget* pParent, ClassifierWidget* pWidget)
+ : QWidget( pParent ) {
+ init();
+ //Uml::Widget_Type type = pWidget->getBaseType();
+ m_pWidget = pWidget;
+ setupPage();
+}
+
+ClassOptionsPage::ClassOptionsPage(QWidget* pParent, Settings::OptionState *options) : QWidget( pParent )
+{
+ init();
+ m_options = options;
+ setupClassPageOption();
+}
+
+void ClassOptionsPage::init() {
+ m_options = NULL;
+ m_pWidget = NULL;
+ m_pShowStereotypeCB = NULL;
+ m_pShowAttsCB = NULL;
+ m_pShowAttSigCB = NULL;
+ m_pDrawAsCircleCB = NULL;
+}
+
+ClassOptionsPage::~ClassOptionsPage() {}
+
+void ClassOptionsPage::setupPage() {
+ int margin = fontMetrics().height();
+
+ bool sig = false;
+ Uml::Signature_Type sigtype;
+
+ QVBoxLayout * topLayout = new QVBoxLayout(this);
+ topLayout -> setSpacing(6);
+ m_pVisibilityGB = new QGroupBox(i18n("Show"), this);
+ topLayout -> addWidget(m_pVisibilityGB);
+ QGridLayout * visibilityLayout = new QGridLayout(m_pVisibilityGB);
+ visibilityLayout -> setSpacing(10);
+ visibilityLayout -> setMargin(margin);
+ visibilityLayout -> setRowStretch(3, 1);
+
+ m_pShowOpsCB = new QCheckBox(i18n("Operatio&ns"), m_pVisibilityGB);
+ m_pShowOpsCB -> setChecked(m_pWidget -> getShowOps());
+ visibilityLayout -> addWidget(m_pShowOpsCB, 0, 0);
+
+ m_pShowVisibilityCB = new QCheckBox(i18n("&Visibility"), m_pVisibilityGB);
+ m_pShowVisibilityCB -> setChecked(m_pWidget -> getShowVisibility());
+ visibilityLayout -> addWidget(m_pShowVisibilityCB, 0, 1);
+
+ sigtype = m_pWidget -> getShowOpSigs();
+ if(sigtype == Uml::st_NoSig || sigtype == Uml::st_NoSigNoVis)
+ sig = false;
+ else
+ sig = true;
+ m_pShowOpSigCB = new QCheckBox(i18n("O&peration signature"), m_pVisibilityGB);
+ m_pShowOpSigCB -> setChecked(sig);
+ visibilityLayout -> addWidget(m_pShowOpSigCB, 1, 0);
+
+ m_pShowPackageCB = new QCheckBox(i18n("Pac&kage"), m_pVisibilityGB);
+ m_pShowPackageCB -> setChecked(m_pWidget -> getShowPackage());
+ visibilityLayout -> addWidget(m_pShowPackageCB, 1, 1);
+
+ Uml::Widget_Type type = m_pWidget->getBaseType();
+
+ if (type == Uml::wt_Class) {
+ m_pShowAttsCB = new QCheckBox(i18n("Att&ributes"), m_pVisibilityGB);
+ m_pShowAttsCB->setChecked(m_pWidget->getShowAtts());
+ visibilityLayout->addWidget(m_pShowAttsCB, 2, 0);
+
+ m_pShowStereotypeCB = new QCheckBox(i18n("Stereot&ype"), m_pVisibilityGB);
+ m_pShowStereotypeCB->setChecked(m_pWidget->getShowStereotype());
+ visibilityLayout->addWidget(m_pShowStereotypeCB, 2, 1);
+
+ m_pShowAttSigCB = new QCheckBox(i18n("Attr&ibute signature"), m_pVisibilityGB);
+ sigtype = m_pWidget->getShowAttSigs();
+ if(sigtype == Uml::st_NoSig || sigtype == Uml::st_NoSigNoVis)
+ sig = false;
+ else
+ sig = true;
+ m_pShowAttSigCB->setChecked(sig);
+ visibilityLayout->addWidget(m_pShowAttSigCB, 3, 0);
+
+ } else if (type == Uml::wt_Interface) {
+ m_pDrawAsCircleCB = new QCheckBox(i18n("Draw as circle"), m_pVisibilityGB);
+ m_pDrawAsCircleCB->setChecked( m_pWidget->getDrawAsCircle() );
+ visibilityLayout->addWidget(m_pDrawAsCircleCB, 2, 0);
+ }
+}
+
+void ClassOptionsPage::setupClassPageOption() {
+
+ int margin = fontMetrics().height();
+
+ QVBoxLayout * topLayout = new QVBoxLayout(this);
+ topLayout -> setSpacing(6);
+ m_pVisibilityGB = new QGroupBox(i18n("Show"), this);
+ topLayout -> addWidget(m_pVisibilityGB);
+ QGridLayout * visibilityLayout = new QGridLayout(m_pVisibilityGB);
+ visibilityLayout -> setSpacing(10);
+ visibilityLayout -> setMargin(margin);
+
+ m_pShowOpsCB = new QCheckBox(i18n("Operatio&ns"), m_pVisibilityGB);
+ m_pShowOpsCB -> setChecked( m_options->classState.showOps );
+ visibilityLayout -> addWidget(m_pShowOpsCB, 0, 0);
+
+ m_pShowOpSigCB = new QCheckBox(i18n("O&peration signature"), m_pVisibilityGB);
+ m_pShowOpSigCB -> setChecked(m_options->classState.showOpSig);
+ visibilityLayout -> addWidget(m_pShowOpSigCB, 1, 0);
+ visibilityLayout -> setRowStretch(3, 1);
+
+ m_pShowAttsCB = new QCheckBox(i18n("Att&ributes"), m_pVisibilityGB);
+ m_pShowAttsCB -> setChecked(m_options->classState.showAtts );
+ visibilityLayout -> addWidget(m_pShowAttsCB, 2, 0);
+
+ m_pShowAttSigCB = new QCheckBox(i18n("Attr&ibute signature"), m_pVisibilityGB);
+ m_pShowAttSigCB -> setChecked(m_options->classState.showAttSig);
+ visibilityLayout -> addWidget(m_pShowAttSigCB, 3, 0);
+
+ m_pShowVisibilityCB = new QCheckBox(i18n("&Visibility"), m_pVisibilityGB);
+ m_pShowVisibilityCB -> setChecked(m_options->classState.showVisibility);
+ visibilityLayout -> addWidget(m_pShowVisibilityCB, 0, 1);
+
+ m_pShowPackageCB = new QCheckBox(i18n("Pac&kage"), m_pVisibilityGB);
+ m_pShowPackageCB -> setChecked(m_options->classState.showPackage);
+ visibilityLayout -> addWidget(m_pShowPackageCB, 1, 1);
+
+ m_pShowStereotypeCB = new QCheckBox(i18n("Stereot&ype"), m_pVisibilityGB);
+ m_pShowStereotypeCB -> setChecked(m_options->classState.showStereoType);
+ visibilityLayout -> addWidget(m_pShowStereotypeCB, 2, 1);
+
+}
+
+void ClassOptionsPage::updateUMLWidget() {
+ if (m_pWidget) {
+ updateWidget();
+ } else if (m_options) {
+ updateOptionState();
+ }
+}
+
+void ClassOptionsPage::updateWidget() {
+ m_pWidget->setShowPackage( m_pShowPackageCB->isChecked() );
+ m_pWidget->setShowVisibility( m_pShowVisibilityCB->isChecked() );
+ m_pWidget->setShowOps( m_pShowOpsCB->isChecked() );
+ m_pWidget->setShowOpSigs( m_pShowOpSigCB->isChecked() );
+ Uml::Widget_Type type = m_pWidget->getBaseType();
+ if (type == Uml::wt_Class) {
+ m_pWidget->setShowStereotype( m_pShowStereotypeCB->isChecked() );
+ m_pWidget->setShowAtts( m_pShowAttsCB->isChecked() );
+ m_pWidget->setShowAttSigs( m_pShowAttSigCB->isChecked() );
+ } else if (type == Uml::wt_Interface) {
+ if (m_pDrawAsCircleCB)
+ m_pWidget->setDrawAsCircle( m_pDrawAsCircleCB->isChecked() );
+ }
+}
+
+void ClassOptionsPage::updateOptionState() {
+ m_options->classState.showVisibility = m_pShowVisibilityCB->isChecked();
+ if (m_pShowAttsCB)
+ m_options->classState.showAtts = m_pShowAttsCB->isChecked();
+ m_options->classState.showOps = m_pShowOpsCB->isChecked();
+ if (m_pShowStereotypeCB)
+ m_options->classState.showStereoType = m_pShowStereotypeCB->isChecked();
+ m_options->classState.showPackage = m_pShowPackageCB->isChecked();
+ if (m_pShowAttSigCB)
+ m_options->classState.showAttSig = m_pShowAttSigCB->isChecked();
+ m_options->classState.showOpSig = m_pShowOpSigCB->isChecked();
+}
+
+
+//#include "classoptionspage.moc"
diff --git a/umbrello/umbrello/dialogs/classoptionspage.h b/umbrello/umbrello/dialogs/classoptionspage.h
new file mode 100644
index 00000000..50d43f8c
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classoptionspage.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef CLASSOPTIONSPAGE_H
+#define CLASSOPTIONSPAGE_H
+
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+
+#include "../optionstate.h"
+
+class ClassifierWidget;
+
+/**
+ * A dialog page to display options for a @ref UMLWidget and its
+ * children. This is not normally called by you. It is used by
+ * the @ref ClassPropDlg.
+ *
+ * @short A dialog page to display the options for a UMLWidget.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see ClassPropDlg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassOptionsPage : public QWidget {
+public:
+ /**
+ * Constructor - observe and modify a Widget
+ */
+ ClassOptionsPage(QWidget* pParent, ClassifierWidget* pWidget);
+
+ /**
+ * Constructor - observe and modify an OptionState structure
+ */
+ ClassOptionsPage(QWidget* pParent, Settings::OptionState *options );
+
+ /**
+ * destructor
+ */
+ virtual ~ClassOptionsPage();
+
+ /**
+ * Updates the widget with the dialog page properties.
+ */
+ void updateUMLWidget();
+
+ /**
+ * Sets the widget to be used. Only used by @ref UMLView to set
+ * settings of a widget.
+ */
+ void setWidget( ClassifierWidget * pWidget ) {
+ m_pWidget = pWidget;
+ }
+
+protected:
+ /**
+ * Initialize optional items
+ */
+ void init();
+
+ /**
+ * Creates the page with the correct options for the class/interface
+ */
+ void setupPage();
+
+ /**
+ * Creates the page based on the OptionState
+ */
+ void setupClassPageOption();
+
+ /**
+ * Sets the ClassifierWidget's properties to those selected in this dialog page.
+ */
+ void updateWidget();
+
+ /**
+ * Sets the OptionState to the values selected in this dialog page.
+ */
+ void updateOptionState();
+
+ //GUI widgets
+ QGroupBox * m_pVisibilityGB;
+ QCheckBox * m_pShowVisibilityCB, * m_pShowAttSigCB;
+ QCheckBox * m_pShowOpSigCB, * m_pShowAttsCB, * m_pShowOpsCB;
+ QCheckBox * m_pShowStereotypeCB, * m_pShowPackageCB;
+ QCheckBox* m_pDrawAsCircleCB;
+
+ /**
+ * The classifier widget to represent in the dialog page.
+ */
+ ClassifierWidget* m_pWidget;
+ /**
+ * The OptionState structure to represent in the dialog page.
+ */
+ Settings::OptionState *m_options;
+};
+#endif
diff --git a/umbrello/umbrello/dialogs/classpropdlg.cpp b/umbrello/umbrello/dialogs/classpropdlg.cpp
new file mode 100644
index 00000000..9c4848a1
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classpropdlg.cpp
@@ -0,0 +1,250 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classpropdlg.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// app includes
+#include "classgenpage.h"
+#include "classifierlistpage.h"
+#include "pkgcontentspage.h"
+#include "assocpage.h"
+#include "classoptionspage.h"
+#include "umlwidgetcolorpage.h"
+#include "../umlobject.h"
+#include "../umldoc.h"
+#include "../classifierwidget.h"
+#include "../objectwidget.h"
+#include "../componentwidget.h"
+#include "../uml.h"
+#include "../umlview.h"
+
+ClassPropDlg::ClassPropDlg(QWidget *parent, UMLObject * c, int pageNum, bool assoc)
+ : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help,
+ Ok, parent, "_CLASSDLG_", true, true) {
+ m_pWidget = 0;
+ m_pGenPage = 0;
+ m_pAttPage = 0;
+ m_pOpsPage = 0;
+ m_pTemplatePage = 0;
+ m_pEnumLiteralPage = 0;
+ m_pEntityAttributePage = 0;
+ m_pOptionsPage = 0;
+ m_pColorPage = 0;
+ m_Type = pt_Object;
+ m_pDoc = UMLApp::app()->getDocument();
+ m_pObject = c;
+ setupPages(c, assoc);
+ showPage(pageNum);
+}
+
+ClassPropDlg::ClassPropDlg(QWidget *parent, ObjectWidget * o)
+ : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help,
+ Ok, parent, "_CLASSDLG_", true, true) {
+ m_pWidget = o;
+ m_pGenPage = 0;
+ m_pAttPage = 0;
+ m_pOpsPage = 0;
+ m_pTemplatePage = 0;
+ m_pEnumLiteralPage = 0;
+ m_pEntityAttributePage = 0;
+ m_pOptionsPage = 0;
+ m_Type = pt_ObjectWidget;
+ m_pObject = m_pWidget->getUMLObject();
+ m_pDoc = UMLApp::app()->getDocument();
+ QFrame *page = addPage( i18n("General"), i18n("General Settings"), DesktopIcon( "misc") );
+ page -> setMinimumSize(310, 330);
+ QHBoxLayout * topLayout = new QHBoxLayout(page);
+ m_pGenPage = new ClassGenPage(m_pDoc, page, o);
+ topLayout -> addWidget(m_pGenPage);
+
+ QFrame * newPage = addPage( i18n("Color"), i18n("Widget Colors"), DesktopIcon( "colors") );
+ QHBoxLayout * m_pColorLayout = new QHBoxLayout(newPage);
+ m_pColorPage = new UMLWidgetColorPage(newPage, o);
+ m_pColorLayout -> addWidget(m_pColorPage);
+
+ setupFontPage();
+ showPage(0);
+ setMinimumSize(340,420);
+}
+
+ClassPropDlg::ClassPropDlg(QWidget *parent, UMLWidget * w)
+ : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help,
+ Ok, parent, "_CLASSDLG_", true, true) {
+ m_pWidget = w;
+ m_pGenPage = 0;
+ m_pAttPage = 0;
+ m_pOpsPage = 0;
+ m_pTemplatePage = 0;
+ m_pEnumLiteralPage = 0;
+ m_pEntityAttributePage = 0;
+ m_pOptionsPage = 0;
+ m_Type = pt_Widget;
+ m_pObject = w -> getUMLObject();
+ m_pDoc = ((UMLApp *)parent) -> getDocument();
+
+ if (w->getBaseType() == Uml::wt_Class
+ || w->getBaseType() == Uml::wt_Interface
+ || w->getBaseType() == Uml::wt_Package) {
+ setupPages(m_pObject, true);
+ } else if (w->getBaseType() == Uml::wt_Component) {
+ if ( w->getIsInstance() ) {
+ setupInstancePages(w);
+ } else {
+ setupPages(m_pObject);
+ }
+ } else if (w->getBaseType() == Uml::wt_Node) {
+ setupInstancePages(w);
+ } else {
+ setupPages(m_pObject);
+ }
+
+ //now setup the options page for classes
+ if (w->getBaseType() == Uml::wt_Class || w->getBaseType() == Uml::wt_Interface) {
+ QFrame* newPage = addPage( i18n("Display"), i18n("Display Options"), DesktopIcon("info") );
+ QHBoxLayout* m_pOptionsLayout = new QHBoxLayout(newPage);
+ ClassifierWidget *cw = static_cast<ClassifierWidget*>(w);
+ m_pOptionsPage = new ClassOptionsPage( newPage, cw );
+ m_pOptionsLayout -> addWidget(m_pOptionsPage);
+ }
+
+ QFrame* colorPage = addPage( i18n("Color"), i18n("Widget Colors"), DesktopIcon("colors") );
+ QHBoxLayout * m_pColorLayout = new QHBoxLayout(colorPage);
+ m_pColorPage = new UMLWidgetColorPage(colorPage, w);
+ m_pColorLayout -> addWidget(m_pColorPage);
+ setupFontPage();
+}
+
+ClassPropDlg::~ClassPropDlg() {}
+
+void ClassPropDlg::slotOk() {
+ slotApply();
+ KDialogBase::accept();
+}
+
+void ClassPropDlg::slotApply() {
+ if (m_pGenPage) {
+ m_pGenPage->updateObject();
+ }
+ if (m_pAttPage) {
+ m_pAttPage->updateObject();
+ }
+ if (m_pOpsPage) {
+ m_pOpsPage->updateObject();
+ }
+ if (m_pTemplatePage) {
+ m_pTemplatePage->updateObject();
+ }
+ if (m_pEnumLiteralPage) {
+ m_pEnumLiteralPage->updateObject();
+ }
+ if (m_pEntityAttributePage) {
+ m_pEntityAttributePage->updateObject();
+ }
+ if (m_pOptionsPage) {
+ m_pOptionsPage->updateUMLWidget();
+ }
+ if (m_pColorPage) {
+ m_pColorPage->updateUMLWidget();
+ }
+ if (m_pWidget) {
+ m_pWidget->setFont( m_pChooser->font() );
+ }
+}
+
+void ClassPropDlg::setupPages(UMLObject * c, bool assoc) {
+ QFrame *page = addPage(i18n("General"), i18n("General Settings"), DesktopIcon( "misc") );
+ QHBoxLayout * genLayout = new QHBoxLayout(page);
+ page -> setMinimumSize(310, 330);
+ m_pGenPage = new ClassGenPage(m_pDoc, page, c);
+ genLayout -> addWidget(m_pGenPage);
+ Uml::Object_Type ot = c->getBaseType();
+ //add extra pages for class
+ if (ot == Uml::ot_Class ) {
+ //setup attributes page
+ QFrame* newPage = addPage( i18n("Attributes"), i18n("Attribute Settings"), DesktopIcon("misc") );
+ m_pAttPage = new ClassifierListPage(newPage, (UMLClassifier *)c, m_pDoc, Uml::ot_Attribute);
+ QHBoxLayout * attLayout = new QHBoxLayout(newPage);
+ attLayout -> addWidget(m_pAttPage);
+ }
+
+ if (ot == Uml::ot_Class || ot == Uml::ot_Interface) {
+ //setup operations page
+ QFrame* newPage = addPage( i18n("Operations"), i18n("Operation Settings"), DesktopIcon("misc") );
+ m_pOpsPage = new ClassifierListPage(newPage, (UMLClassifier*)c, m_pDoc, Uml::ot_Operation);
+ QHBoxLayout* pOpsLayout = new QHBoxLayout(newPage);
+ pOpsLayout -> addWidget(m_pOpsPage);
+ }
+
+ if (ot == Uml::ot_Class || ot == Uml::ot_Interface) {
+ //setup templates page
+ QFrame* newPage = addPage( i18n("Templates"), i18n("Templates Settings"), DesktopIcon("misc") );
+ m_pTemplatePage = new ClassifierListPage(newPage, (UMLClassifier *)c, m_pDoc, Uml::ot_Template);
+ QHBoxLayout* templatesLayout = new QHBoxLayout(newPage);
+ templatesLayout->addWidget(m_pTemplatePage);
+ }
+ if (ot == Uml::ot_Enum) {
+ //setup enum literals page
+ QFrame* newPage = addPage( i18n("Enum Literals"), i18n("Enum Literals Settings"), DesktopIcon("misc") );
+ m_pEnumLiteralPage = new ClassifierListPage(newPage, (UMLClassifier*)c, m_pDoc, Uml::ot_EnumLiteral);
+ QHBoxLayout* enumLiteralsLayout = new QHBoxLayout(newPage);
+ enumLiteralsLayout->addWidget(m_pEnumLiteralPage);
+ }
+ if (ot == Uml::ot_Entity) {
+ //setup enum literals page
+ QFrame* newPage = addPage( i18n("Entity Attributes"), i18n("Entity Attributes Settings"), DesktopIcon("misc") );
+ m_pEntityAttributePage = new ClassifierListPage(newPage, (UMLClassifier*)c, m_pDoc, Uml::ot_EntityAttribute);
+ QHBoxLayout* entityAttributesLayout = new QHBoxLayout(newPage);
+ entityAttributesLayout->addWidget(m_pEntityAttributePage);
+ }
+ if (ot == Uml::ot_Package ) {
+ // Set up containment page.
+ QFrame* newPage = addPage( i18n("Contents"), i18n("Contents Settings"), DesktopIcon("misc") );
+ m_pPkgContentsPage = new PkgContentsPage(newPage, (UMLPackage*)(c));
+ QHBoxLayout* contentsLayout = new QHBoxLayout(newPage);
+ contentsLayout->addWidget(m_pPkgContentsPage);
+ }
+ if (assoc) {
+ QFrame* newPage = addPage(i18n("Associations"), i18n("Class Associations"), DesktopIcon( "misc") );
+ m_pAssocPage = new AssocPage(newPage, UMLApp::app()->getCurrentView(), m_pObject);
+ QHBoxLayout* assocLayout = new QHBoxLayout(newPage);
+ assocLayout -> addWidget(m_pAssocPage);
+ } else {
+ m_pAssocPage = 0;
+ }
+}
+
+void ClassPropDlg::setupInstancePages(UMLWidget* widget) {
+ QFrame* page = addPage( i18n("General"), i18n("General Settings"), DesktopIcon("misc") );
+ QHBoxLayout* genLayout = new QHBoxLayout(page);
+ page->setMinimumSize(310, 330);
+ m_pGenPage = new ClassGenPage(m_pDoc, page, widget);
+ genLayout->addWidget(m_pGenPage);
+ m_pAssocPage = 0;
+}
+
+void ClassPropDlg::setupFontPage() {
+ if( !m_pWidget )
+ return;
+ QVBox * page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts") );
+ m_pChooser = new KFontChooser( (QWidget*)page, "font", false, QStringList(), false);
+ m_pChooser -> setFont( m_pWidget -> getFont() );
+}
+
+
+
+#include "classpropdlg.moc"
diff --git a/umbrello/umbrello/dialogs/classpropdlg.h b/umbrello/umbrello/dialogs/classpropdlg.h
new file mode 100644
index 00000000..90c5b4ec
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classpropdlg.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSPROPDLG_H
+#define CLASSPROPDLG_H
+
+//kde class includes
+#include <kdialogbase.h>
+#include <kfontdialog.h>
+
+#include "../umlnamespace.h"
+
+class ClassGenPage;
+class ClassifierListPage;
+class ClassOpsPage;
+class ClassTemplatePage;
+class PkgContentsPage;
+class AssocPage;
+class ClassOptionsPage;
+class UMLWidgetColorPage;
+
+class ComponentWidget;
+class ObjectWidget;
+class UMLDoc;
+class UMLObject;
+class UMLWidget;
+
+/**
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @version 1.0
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassPropDlg : public KDialogBase {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a ClassPropDlg.
+ *
+ * @param parent The parent of the ClassPropDlg
+ * @param c The UMLObject to display properties of.
+ * @param pageNum The page to show first.
+ * @param assoc Determines whether to display associations
+ */
+ ClassPropDlg(QWidget *parent, UMLObject *c, int pageNum = 0, bool assoc = false);
+
+ /**
+ * Sets up a ClassPropDlg.
+ *
+ * @param parent The parent of the ClassPropDlg
+ * @param o The ObjectWidget to display properties of.
+ */
+ ClassPropDlg(QWidget *parent, ObjectWidget * o);
+
+ /**
+ * Sets up a ClassPropDlg.
+ *
+ * @param parent The parent of the ClassPropDlg
+ * @param o The UMLWidget to display properties of.
+ */
+ ClassPropDlg(QWidget *parent, UMLWidget * o);
+
+
+ /**
+ * Standard deconstructor
+ */
+ ~ClassPropDlg();
+
+ enum Page{page_gen = 0, page_att, page_op, page_template,
+ page_assoc, page_options, page_color, page_font};
+
+protected slots:
+ /**
+ * Calls slotApply() and accepts (closes) the dialog
+ */
+ void slotOk();
+
+ /**
+ * Applies the settings in the dialog to the widget and object
+ */
+ void slotApply();
+
+protected:
+ /**
+ * Sets up the general, attribute, operations, template and association pages as appropriate
+ */
+ void setupPages(UMLObject * c, bool assoc = false);
+
+ /**
+ * Sets up the general page for the component
+ */
+ void setupInstancePages(UMLWidget* widget);
+
+ /**
+ * Sets up the font page
+ */
+ void setupFontPage();
+private:
+ KFontChooser * m_pChooser;
+ ClassGenPage * m_pGenPage;
+ ClassifierListPage* m_pAttPage;
+ ClassifierListPage* m_pOpsPage;
+ ClassifierListPage* m_pTemplatePage;
+ ClassifierListPage* m_pEnumLiteralPage;
+ ClassifierListPage* m_pEntityAttributePage;
+ PkgContentsPage * m_pPkgContentsPage;
+ AssocPage * m_pAssocPage;
+ ClassOptionsPage * m_pOptionsPage;
+ UMLWidgetColorPage * m_pColorPage;
+ UMLDoc *m_pDoc;
+
+ UMLObject *m_pObject;
+ UMLWidget * m_pWidget;
+
+ enum Page_Type{ pt_Object = 1, //Show General page + Assoc. page if Class i.e. no colours page
+ pt_ObjectWidget, //Shows pages needed for an ObjectWidget
+ pt_Widget //Shows pages needed for any other widget
+ };
+ Page_Type m_Type;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/classwizard.cpp b/umbrello/umbrello/dialogs/classwizard.cpp
new file mode 100644
index 00000000..7ac1cb27
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classwizard.cpp
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classwizard.h"
+
+// system includes
+#include <khelpmenu.h>
+#include <klocale.h>
+
+// local includes
+#include "classifierlistpage.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../classifierlistitem.h"
+
+ClassWizard::ClassWizard( UMLDoc * pDoc ) : KWizard( (QWidget*)pDoc -> parent(), "_CLASSWIZARD_", true) {
+ m_pDoc = pDoc;
+ //create a unique class to start with
+ UMLObject * pTemp = 0;
+ QString name = i18n("new_class");
+ QString newName = name;
+ QString num = "";
+ int i = 0;
+ m_pClass = new UMLClassifier( newName );
+ do {
+ m_pClass -> setName( newName );
+ pTemp = m_pDoc -> findUMLObject( newName );
+ num.setNum( ++i);
+ newName = name;
+ newName.append("_").append( num );
+ } while( pTemp );
+ //setup pages
+ setupPages();
+}
+
+ClassWizard::~ClassWizard() {}
+
+void ClassWizard::setupPages() {
+ //Setup General Page
+ m_pGenPage = new ClassGenPage( m_pDoc, this, m_pClass );
+ addPage( m_pGenPage, i18n("New Class") );
+ setHelpEnabled(m_pGenPage, false);
+
+ //Setup Attribute Page
+ m_pAttPage = new ClassifierListPage(this, m_pClass, m_pDoc, Uml::ot_Attribute);
+ addPage( m_pAttPage, i18n("Class Attributes") );
+
+ //Setup Operation Page
+ m_pOpPage = new ClassifierListPage(this, m_pClass, m_pDoc, Uml::ot_Operation);
+ addPage( m_pOpPage, i18n("Class Operations") );
+}
+
+void ClassWizard::showPage( QWidget * pWidget ) {
+ QWizard::showPage( pWidget );
+ if( pWidget == m_pOpPage )
+ finishButton() -> setEnabled( true );
+}
+
+void ClassWizard::next() {
+ QWidget * pWidget = currentPage();
+ if( pWidget == m_pGenPage ) {
+ m_pGenPage -> updateObject();
+ } else if( pWidget == m_pAttPage ) {
+ m_pAttPage -> updateObject();
+ }
+ QWizard::next();
+}
+
+void ClassWizard::back() {
+ QWidget * pWidget = currentPage();
+ if( pWidget == m_pAttPage ) {
+ m_pAttPage -> updateObject();
+ } else if( pWidget == m_pOpPage ) {
+ m_pOpPage -> updateObject();
+ }
+ QWizard::back();
+}
+
+void ClassWizard::accept() {
+ m_pDoc -> addUMLObject( m_pClass );
+ m_pDoc->signalUMLObjectCreated(m_pClass);
+
+ QWizard::accept();
+}
+
+void ClassWizard::reject() {
+ delete m_pClass;
+ QWizard::reject();
+}
+
+void ClassWizard::help() {
+ KHelpMenu helpMenu(this);
+ helpMenu.appHelpActivated();
+}
diff --git a/umbrello/umbrello/dialogs/classwizard.h b/umbrello/umbrello/dialogs/classwizard.h
new file mode 100644
index 00000000..bc2dabf8
--- /dev/null
+++ b/umbrello/umbrello/dialogs/classwizard.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSWIZARD_H
+#define CLASSWIZARD_H
+//kde includes
+#include <kwizard.h>
+//app includes
+#include "classgenpage.h"
+
+class ClassifierListPage;
+class UMLClassifier;
+class UMLDoc;
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ClassWizard : public KWizard {
+public:
+ /**
+ * Consrtuctor
+ */
+ ClassWizard( UMLDoc * pDoc );
+
+ /**
+ * Deconstructor
+ */
+ ~ClassWizard();
+
+protected:
+
+ /**
+ * Overrides the default method.
+ */
+ void showPage( QWidget * pWidget );
+
+ /**
+ * Overrides the default method.
+ */
+ void next();
+
+ /**
+ * Overrides the default method.
+ */
+ void back();
+
+ /**
+ * Overrides the default method.
+ */
+ void accept();
+
+ /**
+ * Overrides the default method.
+ */
+ void reject();
+
+ /**
+ * Setup the wizard pages.
+ */
+ void setupPages();
+
+ /**
+ * Page 1 - General class info
+ */
+ ClassGenPage * m_pGenPage;
+
+ /**
+ * Page 2 - Class Attributes
+ */
+ ClassifierListPage* m_pAttPage;
+
+ /**
+ * Page 3 - Class Operations
+ */
+ ClassifierListPage* m_pOpPage;
+
+ /**
+ * Document currently opened
+ */
+ UMLDoc * m_pDoc;
+
+ /**
+ * Class to create
+ */
+ UMLClassifier * m_pClass;
+
+protected slots:
+ /**
+ * Opens Umbrello handbook
+ */
+ void help();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/codeeditor.cpp b/umbrello/umbrello/dialogs/codeeditor.cpp
new file mode 100644
index 00000000..c05b80bb
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codeeditor.cpp
@@ -0,0 +1,1231 @@
+
+/***************************************************************************
+ codeviewerdialog.cpp - description
+ -------------------
+ begin : Fri Aug 1 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codeeditor.h"
+
+// qt/kde includes
+#include <qkeysequence.h>
+#include <qcursor.h>
+#include <qcolor.h>
+#include <qlabel.h>
+#include <qbrush.h>
+#include <qlayout.h>
+#include <qregexp.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// local includes
+#include "../attribute.h"
+#include "../classifier.h"
+#include "../umldoc.h"
+#include "../umlrole.h"
+
+#include "../codeaccessormethod.h"
+#include "../codegenerator.h"
+#include "../codeclassfield.h"
+#include "../codeclassfielddeclarationblock.h"
+#include "../codedocument.h"
+#include "../codeoperation.h"
+#include "../codemethodblock.h"
+#include "../classifiercodedocument.h"
+#include "../ownedhierarchicalcodeblock.h"
+#include "../codegenerators/codegenfactory.h"
+
+#include "codeviewerdialog.h"
+#include "classpropdlg.h"
+#include "umlattributedialog.h"
+#include "umlroledialog.h"
+#include "umloperationdialog.h"
+
+CodeEditor::CodeEditor ( const QString & text, const QString & context, CodeViewerDialog * parent, const char * name , CodeDocument * doc)
+ : QTextEdit ( text, context, parent, name)
+{
+ init(parent, doc);
+}
+
+CodeEditor::CodeEditor ( CodeViewerDialog * parent, const char* name, CodeDocument * doc )
+ : QTextEdit ( parent, name )
+{
+ init(parent, doc);
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+CodeEditor::~CodeEditor() { }
+
+// clear the display of all text
+void CodeEditor::clearText () {
+
+ // setCaption( tr2i18n("") );
+ m_selectedTextBlock = 0;
+ m_textBlockList.clear();
+ m_tbInfoMap->clear();
+
+ // now call super-class
+ clear();
+
+}
+
+Settings::CodeViewerState CodeEditor::getState()
+{
+ return m_parentDlg->getState();
+}
+
+QLabel * CodeEditor::getComponentLabel() {
+ return m_parentDlg->componentLabel;
+}
+
+
+// FIX: used only for debugging right now.. eliminate eventually -b.t.
+void CodeEditor::clicked(int para, int pos)
+{
+ getComponentLabel()->setText("para:"+QString::number(para)+" pos:"+QString::number(pos));
+}
+
+
+bool CodeEditor::close ( bool alsoDelete )
+{
+
+ // capture last code block, if it exists
+ if(m_lastTextBlockToBeEdited)
+ {
+ updateTextBlockFromText (m_lastTextBlockToBeEdited);
+ m_lastTextBlockToBeEdited = 0;
+ }
+
+ return QTextEdit::close(alsoDelete);
+
+}
+
+void CodeEditor::doubleClicked(int para, int pos)
+{
+
+ m_lastPara = para;
+ m_lastPos = pos;
+
+ // ugh. more ugliness. We want to be able to call up the
+ // correct editing dialog for the given attribute.
+ TextBlock * tBlock = m_textBlockList.at(para);
+ editTextBlock(tBlock, para);
+
+}
+
+// allow us to edit, as appropriate, the parent UMLObject of the
+// given text block.
+void CodeEditor::editTextBlock(TextBlock * tBlock, int para) {
+
+ if(tBlock)
+ {
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ if(info) {
+ UMLObject *obj = info->getParent();
+ if(obj)
+ {
+
+ UMLAttribute * at = 0;
+ UMLRole * role = 0;
+ UMLOperation * op = 0;
+
+ if( (at = dynamic_cast<UMLAttribute*>(obj)) )
+ {
+ UMLAttributeDialog dlg( this, at);
+ if( dlg.exec() ) { rebuildView(para); }
+ }
+ else if( (dynamic_cast<UMLClassifier*>(obj)) )
+ {
+ if (obj->showProperties())
+ rebuildView(para);
+ }
+ else if( (role = dynamic_cast<UMLRole*>(obj)))
+ {
+ UMLRoleDialog dlg(this,role);
+ if( dlg.exec() ) { rebuildView(para); }
+ }
+ else if( (op = dynamic_cast<UMLOperation*>(obj)) )
+ //else if( (cop = dynamic_cast<CodeOperation*>(tBlock)) )
+ {
+ UMLOperationDialog dlg(this,op);
+ if( dlg.exec() ) { rebuildView(para); }
+ }
+ else
+ {
+ kError()<<" CodeViewerDlg ERROR: UNKNOWN parent for textBlock"<<endl;
+ }
+
+ }
+ }
+ }
+}
+
+// return whether is empty or just whitespace
+bool CodeEditor::StringIsBlank(const QString &str)
+{
+ if(str.isEmpty() || str.stripWhiteSpace().isEmpty())
+ return true;
+ return false;
+}
+
+void CodeEditor::keyPressEvent ( QKeyEvent * e ) {
+
+ // kDebug() <<"KEY PRESS EVENT:["<<e->text().latin1()<<"] ascii CODE:"<<e->ascii();
+
+ if((e->ascii() == 8) ) // || (e->ascii() == 127)) // what about delete?
+ m_backspacePressed = true;
+
+ // Q: can the MAC or WIN/DOS sequences occur?
+ if((e->ascii() == 10) || (e->ascii() == 13) || (e->text() == "\r\n"))
+ m_newLinePressed = true;
+
+ QTextEdit::keyPressEvent(e);
+}
+
+void CodeEditor::loadFromDocument ()
+{
+
+ // clear the tool
+ clearText();
+
+ // set caption on tool
+ QString caption = m_parentDoc->getFileName() + m_parentDoc->getFileExtension();
+ setCaption( tr2i18n( caption.latin1() ) );
+
+ // header for document
+ QString header = m_parentDoc->getHeader()->toString();
+ QString componentName = QString("header for file ") +caption;
+ if(!StringIsBlank(header))
+ insert(header,m_parentDoc->getHeader(),false,getState().fontColor,
+ getState().nonEditBlockColor,0,componentName);
+
+ // now all the text blocks in the document
+ TextBlockList * items = m_parentDoc->getTextBlockList();
+ appendText(items);
+
+ setCursorPosition(0,0);
+
+}
+
+void CodeEditor::insert (const QString & text, TextBlock * parent, bool editable, const QColor & fgcolor, const QColor & bgcolor, UMLObject * umlobj, const QString & displayName, int startLine)
+{
+
+ // set some params
+ bool isInsert = false;
+ setColor(fgcolor);
+
+ // its an append op if startLine is -1, otherwise its
+ // an actual insert, which is more complicated
+ if(startLine == -1)
+ {
+ startLine = paragraphs()-1;
+ QTextEdit::append(text); // put actual text in. Use insert instead of append so history is preserved?
+ }
+ else
+ {
+ isInsert = true;
+ QTextEdit::insertAt(text, startLine, 0);
+ }
+
+ // actual put in text
+
+ // now do 'paragraph' background highlighting
+ // int endLine = paragraphs()-2;
+ int endLine = text.contains(QRegExp("\n")) + startLine -1;
+ if(m_isHighlighted)
+ for(int para=startLine;para<=endLine;para++)
+ setParagraphBackgroundColor(para,bgcolor);
+
+ // record paragraph information
+ // Did we already start recording info for this parent object?
+ TextBlockInfo * tbinfo;
+ if(m_tbInfoMap->contains(parent))
+ tbinfo = (*m_tbInfoMap)[parent];
+ else {
+ tbinfo = new TextBlockInfo();
+ tbinfo->displayName = displayName;
+ tbinfo->isCodeAccessorMethod = dynamic_cast<CodeAccessorMethod*>(parent) ? true : false;
+ m_tbInfoMap->insert(parent,tbinfo);
+ }
+
+ // set a parent, if its not already set
+ if(umlobj && !tbinfo->getParent())
+ {
+ tbinfo->displayName = displayName;
+ tbinfo->setParent(umlobj);
+ tbinfo->isClickable = textBlockIsClickable(umlobj);
+ }
+
+ // now mark all lines that we just inserted as belonging to the parent
+ for(int para=startLine;para<=endLine;para++)
+ m_textBlockList.insert(para,parent);
+
+ // lastly, update the para info
+ // start position is relative to the FIRST parent position
+ int start = startLine - m_textBlockList.findRef(parent);
+ int size = endLine-startLine;
+
+ // create the object that records this particular "paragraph"
+ ParaInfo * item = new ParaInfo();
+ item->start = start;
+ item->size= size;
+ item->fgcolor = fgcolor;
+ item->bgcolor = bgcolor;
+ item->isEditable = editable;
+
+ if(isInsert)
+ {
+ // now we have to fix the 'start' value for all the para
+ // info blocks that coorspond to textblocks that we inserted
+ // inside of. This means parent tblock paragraph locations
+ // that are greater than zero in that type of textblock
+
+ int increase = size + 1;
+ QMap<TextBlock*,TextBlockInfo*>::Iterator it;
+ for ( it = m_tbInfoMap->begin(); it != m_tbInfoMap->end(); ++it )
+ {
+ TextBlock * tblock = it.key();
+ TextBlockInfo * thisTbInfo = it.data();
+ int firstLoc = m_textBlockList.findRef(tblock);
+ ParaInfo * lastPi = thisTbInfo->m_paraList.last();
+
+ for(ParaInfo * pi = thisTbInfo->m_paraList.first(); pi; pi = thisTbInfo->m_paraList.next())
+ {
+ int minPara = pi->start+firstLoc;
+
+ // only worth doing if in range of the whole
+ // representation
+ if(!pi->start && (startLine > (lastPi->start+firstLoc+lastPi->size) || endLine < minPara) )
+ break;
+
+ // now, only for those paraInfo blocks which
+ // have exceeded our last line, we increase them
+ if(pi->start && minPara >= endLine )
+ pi->start += increase;
+
+ }
+ }
+
+ }
+
+ tbinfo->m_paraList.append(item);
+
+}
+
+void CodeEditor::appendText(TextBlockList * items)
+{
+
+ for (TextBlock *tb = items->first(); tb; tb = items->next())
+ {
+ // types of things we may cast our text block into
+ // This isnt efficient, and is a vote for recording
+ // code block types in an enumerated list somewhere,
+ // as well as a generic attribute "blockType" we could
+ // quickly access, rather than casting. -b.t.
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock *>(tb);
+ CodeMethodBlock * mb = 0;
+ CodeClassFieldDeclarationBlock * db = 0;
+ CodeBlockWithComments * cb = 0;
+ // CodeComment * cm = 0;
+ if(hb)
+ appendText(hb);
+ else if ( (mb = dynamic_cast<CodeMethodBlock*>(tb)) )
+ appendText(mb);
+ else if ( (db = dynamic_cast<CodeClassFieldDeclarationBlock*>(tb)) )
+ appendText(db);
+ else if ( (cb = dynamic_cast<CodeBlockWithComments*>(tb)) )
+ appendText(cb);
+ /*
+ // no! shouldn't be any 'naked' comments floating about. Always
+ // are assocated with a parent code block
+ else if ( (cm = dynamic_cast<CodeComment*>(tb)) )
+ appendText(cm);
+ */
+ else
+ appendText(tb); // no cast worked. Just do a text block
+ }
+
+}
+
+void CodeEditor::appendText (CodeComment * comment, TextBlock * parent, UMLObject * umlObj , const QString & componentName)
+{
+
+ if(!comment->getWriteOutText() && !m_showHiddenBlocks)
+ return;
+
+ QColor bgcolor = getState().nonEditBlockColor;
+ if(!comment->getWriteOutText() && m_showHiddenBlocks)
+ bgcolor = getState().hiddenColor;
+
+ QString indent = comment->getIndentationString();
+ QString text = comment->toString(); // use comment formatting, NOT formatMultiLineText(comment->toString(), indent, "\n");
+ if(!StringIsBlank(text))
+ insert(text,parent,true,getState().fontColor, bgcolor, umlObj, componentName);
+
+}
+
+void CodeEditor::appendText (CodeBlockWithComments * cb ) {
+
+ if(!cb->getWriteOutText() && !m_showHiddenBlocks)
+ return;
+
+ QString indent = cb->getIndentationString();
+ QString body = cb->formatMultiLineText (cb->getText(), indent, "\n");
+
+ QColor bgcolor = getState().editBlockColor;
+ QString componentName = QString("CodeBlock");
+
+ appendText(cb->getComment(), cb, 0, componentName);
+
+ if(!cb->getWriteOutText() && m_showHiddenBlocks)
+ bgcolor = getState().hiddenColor;
+
+ if(!StringIsBlank(body))
+ insert(body,cb,true,getState().fontColor,bgcolor,0);
+
+}
+
+void CodeEditor::appendText (CodeClassFieldDeclarationBlock * db ) {
+
+ if(!db->getWriteOutText() && !m_showHiddenBlocks)
+ return;
+
+ QString indent = db->getIndentationString();
+ QString body = db->formatMultiLineText (db->getText(), indent, "\n");
+
+ UMLObject * parentObj = db->getParentClassField()->getParentObject();
+
+ QColor bgcolor = getState().editBlockColor;
+ QString componentName = QString("");
+ if(parentObj)
+ {
+ if(db->getParentClassField()->parentIsAttribute()) {
+ componentName = parentDocName + "::attribute_field(" + parentObj->getName() + ')';
+ } else {
+ UMLRole * role = dynamic_cast<UMLRole*>(parentObj);
+ componentName = parentDocName + "::association_field(" + role->getName() + ')';
+ }
+ bgcolor = getState().umlObjectColor;
+ }
+
+ appendText(db->getComment(), db, parentObj,componentName);
+
+ if(!db->getWriteOutText() && m_showHiddenBlocks)
+ bgcolor = getState().hiddenColor;
+
+ if(!StringIsBlank(body))
+ insert(body,db,false,getState().fontColor,bgcolor,parentObj);
+
+
+}
+
+void CodeEditor::appendText (CodeMethodBlock * mb) {
+
+ // Note: IF CodeAccessors are hidden, we DON'T show
+ // it even when requested as the hiddeness of these methods
+ // should be controled by the class fields, not the user in the editor.
+ if(!mb->getWriteOutText() && (!m_showHiddenBlocks || dynamic_cast<CodeAccessorMethod*>(mb)))
+ return;
+
+ QColor bgcolor = getState().umlObjectColor;
+ QString indent = mb->getIndentationString();
+ QString bodyIndent = mb->getIndentationString(mb->getIndentationLevel()+1);
+
+ QString startText = mb->formatMultiLineText ( mb->getStartMethodText(), indent, "\n");
+ QString body = mb->formatMultiLineText (mb->getText(), bodyIndent, "\n");
+ QString endText = mb->formatMultiLineText( mb->getEndMethodText(), indent, "\n");
+
+ if(body.isEmpty())
+ body = " \n";
+
+ if(!mb->getWriteOutText() && m_showHiddenBlocks)
+ {
+ // it gets the 'hidden' color
+ bgcolor = getState().hiddenColor;
+ }
+
+ QString componentName = QString("<b>parentless method\?</b>");
+
+ // ugly, but we need to know if there is a parent object here.
+ CodeOperation * op = dynamic_cast<CodeOperation*>(mb);
+ CodeAccessorMethod * accessor = dynamic_cast<CodeAccessorMethod*>(mb);
+ UMLObject * parentObj = 0;
+ if(op)
+ {
+ parentObj = op->getParentOperation();
+ if(((UMLOperation*)parentObj)->isConstructorOperation())
+ componentName = parentDocName + "::operation("+ parentObj->getName()+") constructor method";
+ else
+ componentName = parentDocName + "::operation("+ parentObj->getName()+") method";
+ }
+ if(accessor)
+ {
+ parentObj = accessor->getParentObject();
+ if(accessor->getParentClassField()->parentIsAttribute()) {
+ componentName = parentDocName + "::attribute_field(" + parentObj->getName() + ") accessor method";
+ } else {
+ UMLRole * role = dynamic_cast<UMLRole*>(parentObj);
+ componentName = parentDocName + "::association_field(" + role->getName() + ") accessor method";
+ }
+
+ }
+
+ //appendText(mb->getComment(), mb, parentObj, componentName);
+ appendText(mb->getComment(), mb->getComment(), parentObj, componentName);
+
+ if(!StringIsBlank(startText))
+ insert(startText,mb,false,getState().fontColor,bgcolor,parentObj);
+ // always insert body for methods..IF we don't, we create a
+ // situation where the user cant edit the body (!)
+ insert(body,mb,true,getState().fontColor,bgcolor,parentObj);
+ if(!StringIsBlank(endText))
+ insert(endText,mb,false,getState().fontColor,bgcolor,parentObj);
+
+}
+
+void CodeEditor::appendText (TextBlock * tb) {
+
+ if(!tb->getWriteOutText() && !m_showHiddenBlocks)
+ return;
+
+ QColor bgcolor = getState().nonEditBlockColor;
+ if(!tb->getWriteOutText() && m_showHiddenBlocks)
+ bgcolor = getState().hiddenColor;
+
+ QString str = tb->toString();
+ insert(str,tb,false,getState().fontColor,bgcolor);
+
+}
+
+void CodeEditor::appendText(HierarchicalCodeBlock * hblock)
+{
+
+ if(!hblock->getWriteOutText() && !m_showHiddenBlocks)
+ return;
+
+ OwnedHierarchicalCodeBlock * test = dynamic_cast<OwnedHierarchicalCodeBlock *>(hblock);
+ UMLObject * parentObj = 0;
+ QString componentName = QString("");
+ QColor paperColor = getState().nonEditBlockColor;
+ if(test)
+ {
+ parentObj = test->getParentObject();
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(parentObj);
+ if (c) {
+ QString typeStr;
+ if (c->isInterface())
+ typeStr = "Interface";
+ else
+ typeStr = "Class";
+ componentName = parentDocName + "::" + typeStr + '(' + parentObj->getName() + ')';
+ } else {
+ componentName = parentDocName + "::UNKNOWN(" + parentObj->getName() + ')';
+ }
+
+ paperColor = getState().umlObjectColor;
+ }
+
+ if(!hblock->getWriteOutText() && m_showHiddenBlocks)
+ paperColor = getState().hiddenColor;
+
+ TextBlockList * items = hblock->getTextBlockList();
+ QString indent = hblock->getIndentationString();
+ QString startText = hblock->formatMultiLineText ( hblock->getStartText(), indent, "\n");
+ QString endText = hblock->formatMultiLineText( hblock->getEndText(), indent, "\n");
+
+ appendText(hblock->getComment(), hblock, parentObj, componentName);
+
+ if(!StringIsBlank(startText))
+ insert(startText,hblock,false,getState().fontColor,paperColor, parentObj);
+ appendText(items);
+ if(!StringIsBlank(endText))
+ insert(endText,hblock,false,getState().fontColor,paperColor);
+
+}
+
+void CodeEditor::insertParagraph ( const QString & text, int para )
+{
+ QTextEdit::insertParagraph(text,para);
+}
+
+void CodeEditor::removeParagraph ( int para )
+{
+ QTextEdit::removeParagraph(para);
+}
+
+// All umlobjects which may have pop-up boxes should return true here
+// Yes, a CRAPPY way of doing this. Im not proud. =b.t.
+bool CodeEditor::textBlockIsClickable(UMLObject * obj)
+{
+
+ if( dynamic_cast<UMLAttribute*>(obj) )
+ return true;
+ else if( dynamic_cast<UMLClassifier*>(obj) )
+ return true;
+ else if( dynamic_cast<UMLRole*>(obj) )
+ return true;
+ else if( dynamic_cast<UMLOperation*>(obj) )
+ return true;
+
+ return false;
+}
+
+void CodeEditor::slotChangeSelectedBlockView()
+{
+ TextBlock * tb = m_selectedTextBlock;
+ if(tb) {
+ tb->setWriteOutText(tb->getWriteOutText() ? false : true );
+ rebuildView(m_lastPara);
+ }
+
+}
+
+// change the status of the comment writeOutText value to
+// opposite of current value
+void CodeEditor::slotChangeSelectedBlockCommentView()
+{
+
+ TextBlock * tb = m_selectedTextBlock;
+ CodeBlockWithComments * cb = 0;
+ if(tb && (cb = dynamic_cast<CodeBlockWithComments*>(tb)))
+ {
+ cb->getComment()->setWriteOutText(cb->getComment()->getWriteOutText() ? false : true );
+ rebuildView( m_lastPara );
+ }
+
+}
+
+void CodeEditor::slotInsertCodeBlockBeforeSelected()
+{
+
+ TextBlock * tb = m_selectedTextBlock;
+ CodeBlockWithComments * newBlock = m_parentDoc->newCodeBlockWithComments();
+ newBlock->setText("<<INSERT>>");
+ newBlock->getComment()->setWriteOutText(false);
+
+ m_parentDoc->insertTextBlock(newBlock, tb, false);
+
+ int location = m_textBlockList.findRef(m_selectedTextBlock); // find first para of selected block
+
+ QString body = newBlock->formatMultiLineText (newBlock->getText(), newBlock->getIndentationString(), "\n");
+
+ insert(body,newBlock,true,getState().fontColor,
+ getState().editBlockColor,0,QString("CodeBlock"),location);
+
+}
+
+void CodeEditor::slotInsertCodeBlockAfterSelected()
+{
+
+ TextBlock * tb = m_selectedTextBlock;
+ CodeBlockWithComments * newBlock = m_parentDoc->newCodeBlockWithComments();
+ newBlock->setText("<<INSERT>>");
+ newBlock->getComment()->setWriteOutText(false);
+
+ m_parentDoc->insertTextBlock(newBlock, tb, true);
+
+ // find last para of selected block
+ TextBlockInfo *tbinfo = (*m_tbInfoMap)[m_selectedTextBlock];
+ ParaInfo * lastpi = tbinfo->m_paraList.last();
+ int location = m_textBlockList.findRef(m_selectedTextBlock) + lastpi->start + lastpi->size + 1;
+
+ QString body = newBlock->formatMultiLineText (newBlock->getText(), newBlock->getIndentationString(), "\n");
+
+ insert(body,newBlock,true,getState().fontColor,
+ getState().editBlockColor,0,QString("CodeBlock"),location);
+
+}
+
+QPopupMenu * CodeEditor::createPopupMenu ( const QPoint & pos )
+{
+
+ TextBlock * tb = m_selectedTextBlock;
+ m_lastPara = paragraphAt(pos);
+
+ QPopupMenu * menu = new QPopupMenu(this);
+ // ugh. A bug in the Qt interaction between QTextEdit and Menu
+ // can sometimes trigger a clear() call of the text area after
+ // the popup menu is destroyed. The workaround is to disable
+ // the behavior by blocking the destroy signal from the menu.
+ menu->blockSignals(true);
+
+ if (m_selectedTextBlock)
+ {
+ if(tb->getWriteOutText())
+ menu->insertItem("Hide",this,SLOT(slotChangeSelectedBlockView()), Key_H, 0);
+ else
+ menu->insertItem("Show",this,SLOT(slotChangeSelectedBlockView()), Key_S, 0);
+
+ CodeBlockWithComments * cb = dynamic_cast<CodeBlockWithComments*>(tb);
+ if(cb)
+ if(cb->getComment()->getWriteOutText())
+ menu->insertItem("Hide Comment",this,SLOT(slotChangeSelectedBlockCommentView()), CTRL+Key_H, 1);
+ else
+ menu->insertItem("Show Comment",this,SLOT(slotChangeSelectedBlockCommentView()), CTRL+Key_S, 1);
+ menu->insertSeparator();
+
+ menu->insertItem("Insert Code Block Before",this,SLOT(slotInsertCodeBlockBeforeSelected()), CTRL+Key_B, 2);
+ menu->insertItem("Insert Code Block After",this,SLOT(slotInsertCodeBlockAfterSelected()), CTRL+Key_A, 3);
+
+ menu->insertSeparator();
+
+ menu->insertItem("Copy",this,SLOT(slotCopyTextBlock()), CTRL+Key_C, 4);
+ menu->insertItem("Paste",this,SLOT(slotPasteTextBlock()), CTRL+Key_V, 5);
+ menu->insertItem("Cut",this,SLOT(slotCutTextBlock()), CTRL+Key_X, 6);
+
+ // enable/disable based on conditions
+ if(m_selectedTextBlock == m_parentDoc->getHeader())
+ menu->setItemEnabled (2, false);
+
+ if(!m_textBlockToPaste)
+ menu->setItemEnabled (5, false);
+
+ if(!tb->canDelete())
+ menu->setItemEnabled (6, false);
+
+ // manythings cant be copied. RIght now, lets just limit ourselves to
+ // owned things and hierarchicalcodeblocks
+ if(dynamic_cast<OwnedCodeBlock*>(m_selectedTextBlock) ||
+ dynamic_cast<HierarchicalCodeBlock*>(m_selectedTextBlock))
+ menu->setItemEnabled (4, false);
+
+ // TBD
+ // m_selectedTextBlock->insertCodeEditMenuItems(menu, this);
+ }
+
+ return menu;
+}
+
+void CodeEditor::slotCopyTextBlock ( )
+{
+ // make a copy
+ if(dynamic_cast<HierarchicalCodeBlock*>(m_selectedTextBlock))
+ m_textBlockToPaste = m_parentDoc->newHierarchicalCodeBlock();
+ else if(dynamic_cast<CodeBlockWithComments*>(m_selectedTextBlock))
+ m_textBlockToPaste = m_parentDoc->newCodeBlockWithComments();
+ else if(dynamic_cast<CodeBlock*>(m_selectedTextBlock))
+ m_textBlockToPaste = m_parentDoc->newCodeBlock();
+ else if(dynamic_cast<CodeComment*>(m_selectedTextBlock))
+ m_textBlockToPaste = CodeGenFactory::newCodeComment(m_parentDoc);
+ else
+ {
+ kError()<<" ERROR: CodeEditor can't copy selected block:"<<m_selectedTextBlock<<" of unknown type"<<endl;
+ m_textBlockToPaste = 0;
+ return; // error!
+ }
+
+ m_textBlockToPaste->setAttributesFromObject(m_selectedTextBlock);
+
+}
+
+void CodeEditor::slotCutTextBlock ( ) {
+
+ // make a copy first
+ slotCopyTextBlock();
+
+ // This could cause problems, but we are OK as
+ // long as we only try to delete 'canDelete' textblocks
+ if(m_selectedTextBlock->canDelete())
+ {
+ // just in case there are pending edits
+ // we don't want to lose them
+ if (m_lastTextBlockToBeEdited && m_lastTextBlockToBeEdited == (CodeBlock*) m_selectedTextBlock)
+ {
+ updateTextBlockFromText (m_lastTextBlockToBeEdited);
+ m_lastTextBlockToBeEdited = 0;
+ }
+
+ m_parentDoc->removeTextBlock(m_selectedTextBlock);
+ rebuildView(m_lastPara);
+ // removeTextBlock(m_selectedTextBlock);
+ m_selectedTextBlock = 0;
+ }
+
+}
+
+void CodeEditor::slotPasteTextBlock ( ) {
+
+ if(m_textBlockToPaste)
+ {
+ m_parentDoc->insertTextBlock(m_textBlockToPaste, m_selectedTextBlock);
+ m_textBlockToPaste = 0;
+ rebuildView(m_lastPara);
+ }
+
+}
+
+void CodeEditor::slotRedrawText() {
+ rebuildView(m_lastPara);
+}
+
+void CodeEditor::init ( CodeViewerDialog * parentDlg, CodeDocument * parentDoc ) {
+
+ // safety to insure that we are up to date
+ parentDoc->synchronize();
+
+ m_parentDlg = parentDlg;
+ m_parentDoc = parentDoc;
+
+ setUndoRedoEnabled( false );
+ setCursor( QCursor( 0 ) );
+ setMouseTracking( true );
+ setReadOnly (true);
+ m_isHighlighted = getState().blocksAreHighlighted;
+ m_showHiddenBlocks = getState().showHiddenBlocks;
+
+ m_newLinePressed = false;
+ m_backspacePressed = false;
+ m_textBlockToPaste = 0;
+ m_selectedTextBlock = 0;
+ m_lastTextBlockToBeEdited = 0;
+ m_tbInfoMap = new QMap<TextBlock *, TextBlockInfo*>;
+
+ setFont( getState().font );
+
+ // set name of parent doc
+ ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument*>(m_parentDoc);
+ if(cdoc)
+ parentDocName = cdoc->getParentClassifier()->getName();
+ else
+ parentDocName = "";
+
+ // set some viewability parameters
+ //int margin = fontMetrics().height();
+
+ QBrush pbrush = QBrush ( getState().paperColor);
+ setPaper(pbrush);
+
+ // setMargin(margin);
+
+ // connect(this,SIGNAL(newLinePressed()),this,SLOT(newLinePressed()));
+ // connect(this,SIGNAL(backspacePressed()),this,SLOT(backspacePressed()));
+ connect(this,SIGNAL(doubleClicked(int,int)),this,SLOT(doubleClicked(int,int)));
+ connect(this,SIGNAL(cursorPositionChanged(int,int)),this,SLOT(cursorPositionChanged(int,int)));
+
+ // do this last
+ loadFromDocument();
+
+}
+
+void CodeEditor::updateTextBlockFromText (TextBlock * block) {
+
+ if (block) {
+
+ CodeMethodBlock * cmb = dynamic_cast<CodeMethodBlock*>(block);
+ //QString baseIndent = block->getNewEditorLine(block->getIndentationLevel()+(cmb ? 1 : 0));
+ QString baseIndent = block->getIndentationString(block->getIndentationLevel()+(cmb ? 1 : 0));
+
+ TextBlockInfo *info = (*m_tbInfoMap)[block];
+ UMLObject * parentObj = info->getParent();
+ int pstart = m_textBlockList.findRef(block);
+ QString content = "";
+
+ // Assemble content from editiable paras
+ QPtrList<ParaInfo> list = info->m_paraList;
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ {
+ if(item->isEditable)
+ {
+ int lastpara = item->start+pstart+item->size;
+ int endEdit = block->lastEditableLine();
+ int lastLineToAddNewLine = lastpara + endEdit;
+ for(int para=(item->start+pstart);para<=lastpara;para++)
+ {
+ QString line = block->unformatText(text(para), baseIndent);
+ content += line;
+ // \n are implicit in the editor (!) so we should put them
+ // back in, if there is any content from the line
+ if(!line.isEmpty() && para != lastLineToAddNewLine)
+ content += "\n";
+ }
+ }
+ }
+
+ //cerr<<"UPDATE GOT CONTENT:["<<content.latin1()<<"] to block:"<<block<<endl;
+ block->setText(content);
+
+ // if a parent for the block, try to set its documentation
+ // as long as its NOT an accessor codeblock.
+ if(parentObj && !info->isCodeAccessorMethod)
+ parentObj->setDoc(content);
+
+ // make note that its now user generated
+ if(cmb)
+ cmb->setContentType(CodeBlock::UserGenerated);
+
+ }
+}
+
+void CodeEditor::cursorPositionChanged(int para, int pos)
+{
+
+ // safety.. this is endemic of a 'bad' pointer event and can crash us otherwise
+ if(pos < 0)
+ return;
+
+ // bool lastParaIsEditable = isReadOnly() ? false : true;
+ bool lastParaIsEditable = isParaEditable(m_lastPara);
+
+ // IF last para where cursor is coming from was editable
+ // we have a variety of things to look out for.
+ if(lastParaIsEditable)
+ {
+ // If we got here as the result of a newline, then expansion
+ // of a para editablity occurs.
+ if((para-1) == m_lastPara && m_newLinePressed )
+ expandSelectedParagraph ( m_lastPara );
+
+ // conversely, we contract the zone of editablity IF we
+ // got to current position as result of backspace
+ if((para+1) == m_lastPara && m_backspacePressed )
+ contractSelectedParagraph( para );
+
+ }
+
+ // now check if the current paragraph is really editiable, and if so,
+ // so some things
+ bool editPara = isParaEditable(para);
+ if(editPara) {
+
+ TextBlock * tBlock = m_textBlockList.at(para);
+ CodeMethodBlock * cmb = dynamic_cast<CodeMethodBlock*>(tBlock);
+
+ // auto-indent new lines
+ QString currentParaText = text(para);
+ QString baseIndent = tBlock->getNewEditorLine(tBlock->getIndentationLevel()+(cmb ? 1 : 0));
+ // cerr<<"AUTO INDENT:["<<baseIndent.latin1()<<"] isMethod?"<<(cmb?"true":"false")<<endl;
+ int minPos = baseIndent.length();
+
+ // add indent chars to the current line, if missing
+ if(!m_backspacePressed && !currentParaText.contains(QRegExp('^'+baseIndent)))
+ {
+ insertAt(baseIndent,para,0);
+ setCursorPosition(para,pos+minPos);
+ return;
+ }
+
+ if(pos<minPos)
+ {
+
+ bool priorParaIsEditable = isParaEditable(para-1);
+ if(m_backspacePressed && para && priorParaIsEditable)
+ {
+ int endOfPriorLine = paragraphLength(para-1);
+ // IN this case, we remove old (para) line, and tack its
+ // contents on the line we are going to.
+ QString contents = text(para);
+ contents = contents.right(contents.length()-m_lastPos+1);
+
+ // this next thing happens when we arent deleting last line
+ // of editable text, so we want to append whats left of this line
+ // onto the one we are backspacing into
+ if(paraIsNotSingleLine(para))
+ {
+ removeParagraph(para);
+ insertAt(contents,(para-1),endOfPriorLine);
+ setCursorPosition((para-1),endOfPriorLine);
+ }
+
+ } else {
+ // well, if the following is true, then they
+ // are trying to hack away at the last line, which
+ // we cant allow to entirely disappear. Lets preserve
+ // the indentation
+ if(m_backspacePressed && !priorParaIsEditable)
+ {
+ QString contents = text(para);
+ contents = contents.right(contents.length()-m_lastPos+1);
+ contents = baseIndent + contents.left(contents.length()-1); // left is to remove trailing space
+ insertParagraph(contents,para+1);
+ removeParagraph(para);
+
+ // furthermore, IF its nothing but indentation + whitespace
+ // we switch this back to Auto-Generated.
+ if(cmb && contents.contains(QRegExp('^'+baseIndent+"\\s$")))
+ {
+ cmb->setContentType(CodeBlock::AutoGenerated);
+ cmb->syncToParent();
+ }
+
+ }
+
+ // send them to the first spot in the line which is editable
+ setCursorPosition(para,minPos);
+
+ }
+ return;
+ }
+ }
+
+ // look for changes in editability, if they occur, we need to record
+ // the edits which have been made
+ if((editPara && !m_lastTextBlockToBeEdited) || (!editPara && m_lastTextBlockToBeEdited)) {
+
+ setReadOnly(editPara ? false : true);
+
+ // IF this is a different text block, update the body of the method
+ // it belongs to
+ if(m_lastTextBlockToBeEdited && (m_lastTextBlockToBeEdited != m_textBlockList.at(para) || !editPara))
+ {
+ updateTextBlockFromText (m_lastTextBlockToBeEdited);
+ m_lastTextBlockToBeEdited = 0;
+ }
+
+ if(editPara)
+ m_lastTextBlockToBeEdited = m_textBlockList.at(para);
+ else
+ m_lastTextBlockToBeEdited = 0;
+
+ }
+
+ m_lastPara = para;
+ m_lastPos = pos;
+ m_newLinePressed = false;
+ m_backspacePressed = false;
+
+}
+
+bool CodeEditor::paraIsNotSingleLine (int para)
+{
+ TextBlock * tBlock = m_textBlockList.at(para);
+ if(tBlock)
+ {
+ int pstart = m_textBlockList.findRef(tBlock);
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ QPtrList<ParaInfo> list = info->m_paraList;
+
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ if((pstart+item->start) <= para && (item->start+pstart+item->size) >= para )
+ if(item->size > 0)
+ return true;
+ }
+ return false;
+}
+
+bool CodeEditor::isParaEditable (int para) {
+
+ if (para <0)
+ return false;
+
+ TextBlock * tBlock = m_textBlockList.at(para);
+ if(tBlock)
+ {
+ int editStart = tBlock->firstEditableLine();
+ int editEnd = tBlock->lastEditableLine();
+ bool hasEditableRange = (editStart > 0 || editEnd < 0) ? true : false;
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ int pstart = m_textBlockList.findRef(tBlock);
+ int relativeLine = para - pstart;
+ QPtrList<ParaInfo> list = info->m_paraList;
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ {
+ if((item->start+pstart) <= para && (item->start+pstart+item->size) >= para)
+ if(item->isEditable && hasEditableRange)
+ {
+ if ( relativeLine >= editStart && relativeLine <= (item->size + editEnd) )
+ return true;
+ else
+ return false;
+ } else
+ return item->isEditable;
+ }
+ }
+ return false;
+}
+
+void CodeEditor::changeTextBlockHighlighting(TextBlock * tBlock, bool selected) {
+
+ if(tBlock)
+ {
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ QPtrList<ParaInfo> list = info->m_paraList;
+ int pstart = m_textBlockList.findRef(tBlock);
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ for(int p=(item->start+pstart);p<=(item->start+pstart+item->size);p++)
+ if(selected)
+ if(info->isClickable)
+ setParagraphBackgroundColor(p,getState().selectedColor);
+ else
+ setParagraphBackgroundColor(p,getState().nonEditBlockColor);
+ else if(m_isHighlighted)
+ setParagraphBackgroundColor(p,item->bgcolor);
+ else
+ setParagraphBackgroundColor(p,getState().paperColor);
+ }
+
+}
+
+void CodeEditor::changeShowHidden (int signal) {
+
+ if(signal)
+ m_showHiddenBlocks = true;
+ else
+ m_showHiddenBlocks = false;
+
+ rebuildView(m_lastPara);
+
+}
+
+// colorizes/uncolorizes type for ALL paragraphs
+void CodeEditor::changeHighlighting(int signal) {
+
+ int total_para = paragraphs()-1;
+ if(signal) {
+ // we want to highlight
+ m_isHighlighted = true;
+ for(int para=0;para<total_para;para++)
+ {
+ TextBlock * tblock = m_textBlockList.at(para);
+ changeTextBlockHighlighting(tblock,false);
+ }
+
+
+ } else {
+ // we DON'T want to highlight
+ m_isHighlighted = false;
+ for(int para=0;para<total_para;para++)
+ setParagraphBackgroundColor(para,getState().paperColor);
+ }
+
+ // now redo the "selected" para, should it exist
+ if(m_selectedTextBlock)
+ changeTextBlockHighlighting(m_selectedTextBlock,true);
+
+}
+
+void CodeEditor::contractSelectedParagraph( int paraToRemove ) {
+ TextBlock * tBlock = m_textBlockList.at(paraToRemove);
+ if(tBlock)
+ {
+ int pstart = m_textBlockList.findRef(tBlock);
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ QPtrList<ParaInfo> list = info->m_paraList;
+
+ bool lowerStartPosition = false;
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ {
+ if(lowerStartPosition)
+ item->start -= 1;
+
+ if((pstart+item->start) <= paraToRemove && (item->start+pstart+item->size) >= paraToRemove)
+ {
+ item->size -= 1;
+ // a little cheat.. we don't want to remove last line as we need
+ // to leave a place that can be 'edited' by the tool IF the user
+ // changes their mind about method body content
+ if(item->size < 0)
+ item->size = 0;
+ lowerStartPosition = true;
+ }
+ }
+
+ m_textBlockList.remove(paraToRemove);
+ }
+}
+
+void CodeEditor::expandSelectedParagraph( int priorPara ) {
+
+
+ TextBlock * tBlock = m_textBlockList.at(priorPara);
+ if(tBlock)
+ {
+ // add this tBlock in
+ m_textBlockList.insert(priorPara,tBlock);
+ TextBlockInfo *info = (*m_tbInfoMap)[tBlock];
+ QPtrList<ParaInfo> list = info->m_paraList;
+ int pstart = m_textBlockList.findRef(tBlock);
+
+ // now update the paragraph information
+ bool upStartPosition = false;
+ for(ParaInfo * item = list.first(); item; item=list.next())
+ {
+ // AFTER we get a match, then following para's need to have start position upped too
+ if(upStartPosition)
+ item->start += 1;
+
+ if((pstart+item->start) <= priorPara && (item->start+pstart+item->size) >= priorPara)
+ {
+ item->size += 1;
+ cursorPositionChanged(m_lastPara, m_lastPos);
+ upStartPosition = true;
+ }
+ }
+ }
+
+}
+
+void CodeEditor::contentsMouseMoveEvent ( QMouseEvent * e )
+{
+
+ int para = paragraphAt(e->pos());
+
+ if (para < 0)
+ return; // shouldn't happen..
+
+ TextBlock * tblock = m_textBlockList.at(para);
+ if (tblock && m_selectedTextBlock != tblock ) {
+ TextBlockInfo * info = (*m_tbInfoMap)[tblock];
+
+ // unhighlight old selected textblock regardless of whether
+ // it was selected or not.
+ changeTextBlockHighlighting(m_selectedTextBlock,false);
+
+ // highlight new block
+ changeTextBlockHighlighting(tblock,true);
+
+ // FIX: update the label that shows what type of component this is
+ getComponentLabel()->setText("<b>"+info->displayName+"</b>");
+
+ m_selectedTextBlock = tblock;
+
+ if(m_lastTextBlockToBeEdited)
+ {
+ updateTextBlockFromText (m_lastTextBlockToBeEdited);
+ m_lastTextBlockToBeEdited = 0;
+ }
+ }
+
+ // record this as the last paragraph
+
+}
+
+
+// Rebuild our view of the document. Happens whenever we change
+// some field/aspect of an underlying UML object used to create
+// the view.
+// If connections are right, then the UMLObject will send out the modified()
+// signal which will trigger a call to re-generate the appropriate code within
+// the code document. Our burden is to appropriately prepare the tool: we clear
+// out ALL the textblocks in the QTextEdit widget and then re-show them
+// after the dialog disappears
+void CodeEditor::rebuildView( int startCursorPos ) {
+
+ loadFromDocument();
+
+ // make a minima attempt to leave the cursor (view of the code) where
+ // we started
+ int new_nrof_para = paragraphs() -1;
+ setCursorPosition((startCursorPos < new_nrof_para ? startCursorPos : 0), 0);
+
+}
+
+
+
+
+#include "codeeditor.moc"
diff --git a/umbrello/umbrello/dialogs/codeeditor.h b/umbrello/umbrello/dialogs/codeeditor.h
new file mode 100644
index 00000000..57f1fb37
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codeeditor.h
@@ -0,0 +1,191 @@
+
+/***************************************************************************
+ codeeditor.h - description
+ -------------------
+ begin : Fri Aug 1 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef CODEEDITOR_H
+#define CODEEDITOR_H
+
+#include <qpopupmenu.h>
+#include <qstring.h>
+#include <qlabel.h>
+#include <qtextedit.h>
+#include "../codeviewerstate.h"
+#include "../textblocklist.h"
+
+class UMLObject;
+
+class CodeViewerDialog;
+class CodeComment;
+class CodeDocument;
+class CodeClassFieldDeclarationBlock;
+class CodeMethodBlock;
+class CodeBlockWithComments;
+class HierarchicalCodeBlock;
+
+class TextBlockInfo;
+class TextBlock;
+class ParaInfo;
+
+class CodeEditor : public QTextEdit
+{
+ Q_OBJECT
+public:
+
+ explicit CodeEditor ( const QString & text, const QString & context = QString(), CodeViewerDialog * parent = 0, const char * name = 0 , CodeDocument * doc = 0);
+ explicit CodeEditor ( CodeViewerDialog * parent, const char* name = 0, CodeDocument * doc = 0);
+ ~CodeEditor ();
+
+ // return code viewer state
+ Settings::CodeViewerState getState( );
+
+protected:
+
+ bool close ( bool alsoDelete );
+
+ // various methods for appending various types of text blocks in the editor.
+ void appendText (TextBlock * tblock);
+ void appendText (HierarchicalCodeBlock * hblock);
+ void appendText (CodeClassFieldDeclarationBlock * db );
+ void appendText (TextBlockList * items);
+ void appendText (CodeMethodBlock * mb);
+ void appendText (CodeComment * comment, TextBlock * parent, UMLObject * umlObj = 0, const QString & compName="");
+ void appendText (CodeBlockWithComments * cb );
+
+ // Rebuild our view of the document. Happens whenever we change
+ // some field/aspect of an underlying UML object used to create
+ // the view.
+ // If connections are right, then the UMLObject will send out the modified()
+ // signal which will trigger a call to re-generate the appropriate code within
+ // the code document. Our burden is to appropriately prepare the tool: we clear
+ // out ALL the textblocks in the QTextEdit widget and then re-show them
+ // after the dialog disappears
+ void rebuildView( int startCursorPos );
+
+ // override the QT event so we can do appropriate things
+ void contentsMouseMoveEvent ( QMouseEvent * e );
+
+ // implemented so we may capture certain key presses, namely backspace
+ // and 'return' events.
+ void keyPressEvent ( QKeyEvent * e );
+
+ // (re) load the parent code document into the editor
+ void loadFromDocument();
+
+ // specialized popup menu for our tool
+ QPopupMenu * createPopupMenu ( const QPoint & pos );
+
+private:
+
+ QString parentDocName;
+ CodeDocument * m_parentDoc;
+ CodeViewerDialog * m_parentDlg;
+
+ int m_lastPara;
+ int m_lastPos;
+
+ bool m_newLinePressed;
+ bool m_backspacePressed;
+ bool m_isHighlighted;
+ bool m_showHiddenBlocks;
+
+ TextBlock * m_textBlockToPaste;
+ TextBlock * m_selectedTextBlock;
+ TextBlock * m_lastTextBlockToBeEdited;
+
+ QMap<TextBlock*, TextBlockInfo*> *m_tbInfoMap;
+ TextBlockList m_textBlockList;
+
+ // main insert routine. Will append if startline is not supplied.
+ void insert (const QString & text, TextBlock * parent, bool isEditable = false,
+ const QColor & fgcolor = QColor("black"), const QColor & bgcolor = QColor("white"),
+ UMLObject * umlobj = 0, const QString & displayName = "", int startLine = -1);
+
+ void editTextBlock(TextBlock * tBlock, int para);
+ void clearText();
+ QLabel * getComponentLabel();
+ bool paraIsNotSingleLine (int para);
+ void expandSelectedParagraph( int where );
+ void contractSelectedParagraph( int where );
+ void updateTextBlockFromText (TextBlock * block);
+
+ void initText ( CodeDocument * doc );
+ void init ( CodeViewerDialog * parentDlg, CodeDocument * parentDoc );
+
+ void changeTextBlockHighlighting(TextBlock * tb, bool selected);
+ bool isParaEditable (int para);
+ bool textBlockIsClickable(UMLObject * obj);
+
+ // return whether or not the passed string is empty or
+ // contains nothing but whitespace
+ static bool StringIsBlank( const QString &str );
+
+public slots:
+
+ void insertParagraph ( const QString & text, int para );
+ void removeParagraph ( int para );
+ void changeHighlighting(int signal);
+ void changeShowHidden (int signal);
+ void slotRedrawText();
+
+protected slots:
+
+ void clicked(int para, int pos );
+ void doubleClicked(int para, int pos );
+ void cursorPositionChanged(int para, int pos );
+ void slotCopyTextBlock ( );
+ void slotCutTextBlock ( );
+ void slotPasteTextBlock ( );
+ void slotChangeSelectedBlockView();
+ void slotChangeSelectedBlockCommentView();
+ void slotInsertCodeBlockAfterSelected();
+ void slotInsertCodeBlockBeforeSelected();
+
+signals:
+
+ /*
+ void sigNewLinePressed ();
+ void sigBackspacePressed ();
+ */
+
+};
+
+class ParaInfo {
+public:
+ int start; // this is a relative offset from the beginning of the tblock
+ int size;
+ QColor fgcolor;
+ QColor bgcolor;
+ bool isEditable;
+
+ ParaInfo () { isEditable = false; }
+};
+
+class TextBlockInfo {
+public:
+ QPtrList<ParaInfo> m_paraList;
+ UMLObject * m_parent;
+ QString displayName;
+ bool isClickable;
+ bool isCodeAccessorMethod;
+
+ TextBlockInfo () { m_parent = 0; isClickable = false; isCodeAccessorMethod = false; }
+ void setParent(UMLObject *p = 0) { m_parent = p; }
+ UMLObject * getParent() { return m_parent; }
+
+};
+
+#endif // CODEEDITOR_H
diff --git a/umbrello/umbrello/dialogs/codegenerationoptionsbase.ui b/umbrello/umbrello/dialogs/codegenerationoptionsbase.ui
new file mode 100644
index 00000000..f0df1e17
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationoptionsbase.ui
@@ -0,0 +1,533 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CodeGenerationOptionsBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CodeGenerationOptionsBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>581</width>
+ <height>525</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Code Generation Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_SelectLanguageGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Language</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_SelectLanguageBox</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Folders</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Write all generated files to folder:</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="2">
+ <property name="name">
+ <cstring>m_browseOutput</cstring>
+ </property>
+ <property name="text">
+ <string>Bro&amp;wse...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="2">
+ <property name="name">
+ <cstring>m_browseHeadings</cstring>
+ </property>
+ <property name="text">
+ <string>B&amp;rowse...</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_includeHeadings</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Include heading files from folder:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_outputDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Files generated by Code Generator will be written to this folder</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>m_headingsDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Files in this folder will be used as heading files in the generated code</string>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_overwriteGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Overwrite Policy</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>If a file with the same name as the name code
+generator wants to use as output file already exists:</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_overwrite</cstring>
+ </property>
+ <property name="text">
+ <string>O&amp;verwrite</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Overwrite existing files if they exist in the destination folder</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_ask</cstring>
+ </property>
+ <property name="text">
+ <string>As&amp;k</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If a file with the same name already exists, ask what to do</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_changeName</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use a different name</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If a file already exists in the destination folder, select a different name to use by adding a suffix to the file name</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Formatting</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="title">
+ <string>Lines</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="0">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer3_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Line ending style:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Indentation type:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Indentation amount:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="2" column="2" rowspan="1" colspan="3">
+ <item>
+ <property name="text">
+ <string>*NIX ("\n")</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Windows ("\r\n")</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mac ("\r")</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_SelectEndLineCharsBox</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="3" rowspan="1" colspan="2">
+ <item>
+ <property name="text">
+ <string>No Indentation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Tab</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Space</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_SelectIndentationTypeBox</cstring>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="4">
+ <property name="name">
+ <cstring>m_SelectIndentationNumber</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Comment Verbosity</string>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_forceSections</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>60</y>
+ <width>446</width>
+ <height>52</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Write comments &amp;for sections even if section
+is empty</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Writes comments to indicate the different sections (public, private etc) in a class, even if the sections are empty</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_forceDoc</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>29</y>
+ <width>446</width>
+ <height>28</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>&amp;Write documentation comments even if empty</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Write comments &amp;for class and method documentation even if empty</string>
+ </property>
+ </widget>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Language Options</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame" row="0" column="0">
+ <property name="name">
+ <cstring>languageOptionsFrame</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_includeHeadings</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_browseHeadings</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_includeHeadings</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_headingsDir</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_browseOutput</sender>
+ <signal>clicked()</signal>
+ <receiver>CodeGenerationOptionsBase</receiver>
+ <slot>browseClicked()</slot>
+ </connection>
+ <connection>
+ <sender>m_browseHeadings</sender>
+ <signal>clicked()</signal>
+ <receiver>CodeGenerationOptionsBase</receiver>
+ <slot>browseClicked()</slot>
+ </connection>
+ <connection>
+ <sender>m_SelectLanguageBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>CodeGenerationOptionsBase</receiver>
+ <slot>activeLanguageChanged(int)</slot>
+ </connection>
+</connections>
+<slots>
+ <slot access="protected">browseClicked()</slot>
+ <slot access="protected">activeLanguageChanged(int id)</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/umbrello/umbrello/dialogs/codegenerationoptionspage.cpp b/umbrello/umbrello/dialogs/codegenerationoptionspage.cpp
new file mode 100644
index 00000000..f3dc25be
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationoptionspage.cpp
@@ -0,0 +1,188 @@
+/***************************************************************************
+ begin : Thu Jul 25 2002
+ copyright : (C) 2002 by Luis De la Parra
+ email : luis@delaparra.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+// own header
+#include "codegenerationoptionspage.h"
+// qt/kde includes
+#include <qcheckbox.h>
+#include <kdebug.h>
+// app includes
+#include "../codegenerator.h"
+#include "codegenerationpolicypage.h"
+#include "../codegenerators/codegenpolicyext.h"
+#include "defaultcodegenpolicypage.h"
+#include "../model_utils.h"
+#include "../uml.h"
+
+//kde include
+#include <knuminput.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+
+//qt include
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qbuttongroup.h>
+
+CodeGenerationOptionsPage::CodeGenerationOptionsPage(QWidget *parent)
+ : CodeGenerationOptionsBase(parent)
+{
+ init();
+}
+
+CodeGenerationOptionsPage::~CodeGenerationOptionsPage() { }
+
+void CodeGenerationOptionsPage::init()
+{
+ m_pCodePolicyPage = 0;
+
+ CodeGenerationPolicy *policy = UMLApp::app()->getCommonPolicy();
+ m_parentPolicy = policy;
+ CodeGenerator *gen = UMLApp::app()->getGenerator();
+
+ m_forceDoc->setChecked(policy->getCodeVerboseDocumentComments());
+ m_forceSections->setChecked(policy->getCodeVerboseSectionComments());
+
+ m_outputDir->setText(policy->getOutputDirectory().absPath());
+ m_includeHeadings->setChecked(policy->getIncludeHeadings());
+ m_headingsDir->setText(policy->getHeadingFileDir());
+ m_overwriteGroup->setButton(overwriteToInteger(policy->getOverwritePolicy()));
+
+ m_SelectEndLineCharsBox->setCurrentItem(newLineToInteger(policy->getLineEndingType()));
+ m_SelectIndentationTypeBox->setCurrentItem(indentTypeToInteger(policy->getIndentationType()));
+ m_SelectIndentationNumber->setValue(policy->getIndentationAmount());
+
+ connect(this,SIGNAL(syncCodeDocumentsToParent()),gen,SLOT(syncCodeToDocument()));
+
+ // now insert the language-dependant page, should there be one
+ updateCodeGenerationPolicyTab();
+
+ setupActiveLanguageBox();
+}
+
+void CodeGenerationOptionsPage::setupActiveLanguageBox()
+{
+ int indexCounter = 0;
+ while (indexCounter < Uml::pl_Reserved) {
+ QString language = Model_Utils::progLangToString((Uml::Programming_Language) indexCounter);
+ m_SelectLanguageBox->insertItem(language, indexCounter);
+ indexCounter++;
+ }
+ m_SelectLanguageBox->setCurrentItem(UMLApp::app()->getActiveLanguage());
+}
+
+int CodeGenerationOptionsPage::indentTypeToInteger(CodeGenerationPolicy::IndentationType value) {
+ switch (value) {
+ case CodeGenerationPolicy::SPACE:
+ return 2;
+ case CodeGenerationPolicy::TAB:
+ return 1;
+ default:
+ case CodeGenerationPolicy::NONE:
+ return 0;
+ }
+}
+
+int CodeGenerationOptionsPage::newLineToInteger(CodeGenerationPolicy::NewLineType value) {
+ switch (value) {
+ case CodeGenerationPolicy::DOS:
+ return 1;
+ case CodeGenerationPolicy::MAC:
+ return 2;
+ default:
+ case CodeGenerationPolicy::UNIX:
+ return 0;
+ }
+}
+
+//0 = overwrite, 1 = ask, 2 = change name
+int CodeGenerationOptionsPage::overwriteToInteger(CodeGenerationPolicy::OverwritePolicy value) {
+ switch (value) {
+ case CodeGenerationPolicy::Ok:
+ return 0;
+ case CodeGenerationPolicy::Never:
+ return 2;
+ default:
+ case CodeGenerationPolicy::Ask:
+ return 1;
+ }
+}
+
+void CodeGenerationOptionsPage::updateCodeGenerationPolicyTab() {
+
+ if(m_pCodePolicyPage)
+ {
+ m_pCodePolicyPage->disconnect();
+ m_pCodePolicyPage = 0;
+ }
+
+ CodeGenPolicyExt *policyExt = UMLApp::app()->getPolicyExt();
+ if (policyExt)
+ m_pCodePolicyPage = policyExt->createPage(languageOptionsFrame, "codelangpolicypage");
+ else
+ m_pCodePolicyPage = new DefaultCodeGenPolicyPage(languageOptionsFrame, "codelangpolicypage");
+
+ connect(this,SIGNAL(applyClicked()),m_pCodePolicyPage,SLOT(apply()));
+
+}
+
+void CodeGenerationOptionsPage::apply() {
+
+ if(m_parentPolicy) {
+
+ m_parentPolicy->setCodeVerboseDocumentComments(m_forceDoc->isChecked());
+ m_parentPolicy->setCodeVerboseSectionComments(m_forceSections->isChecked());
+ m_parentPolicy->setOutputDirectory(QDir(m_outputDir->text()));
+ m_parentPolicy->setIncludeHeadings(m_includeHeadings->isChecked());
+ m_parentPolicy->setHeadingFileDir(m_headingsDir->text());
+ m_parentPolicy->setOverwritePolicy((CodeGenerationPolicy::OverwritePolicy)m_overwriteGroup->id(m_overwriteGroup->selected()));
+ m_parentPolicy->setLineEndingType((CodeGenerationPolicy::NewLineType) m_SelectEndLineCharsBox->currentItem());
+ m_parentPolicy->setIndentationType((CodeGenerationPolicy::IndentationType) m_SelectIndentationTypeBox->currentItem());
+ m_parentPolicy->setIndentationAmount(m_SelectIndentationNumber->value());
+
+ // emit in THIS order.. the first signal triggers any sub-class to do its apply
+ // slot, THEN, once we are all updated, we may sync the parent generator's code
+ // documents
+ emit applyClicked();
+ emit syncCodeDocumentsToParent();
+ }
+}
+
+void CodeGenerationOptionsPage::activeLanguageChanged(int /*id*/)
+{
+ emit languageChanged();
+}
+
+void CodeGenerationOptionsPage::setDefaults() {
+}
+
+void CodeGenerationOptionsPage::browseClicked() {
+
+ QString button = sender()->name();
+ QString dir = KFileDialog::getExistingDirectory();
+ if(dir.isEmpty())
+ return;
+ if(button=="m_browseOutput")
+ m_outputDir->setText(dir);
+ else if(button=="m_browseHeadings")
+ m_headingsDir->setText(dir);
+}
+
+QString CodeGenerationOptionsPage::getCodeGenerationLanguage() {
+ return m_SelectLanguageBox->currentText();
+}
+
+#include "codegenerationoptionspage.moc"
diff --git a/umbrello/umbrello/dialogs/codegenerationoptionspage.h b/umbrello/umbrello/dialogs/codegenerationoptionspage.h
new file mode 100644
index 00000000..ff939d08
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationoptionspage.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ codegenerationoptionspage.h - description
+ -------------------
+ begin : Thu Jul 25 2002
+ copyright : (C) 2002 by Luis De la Parra
+ email : luis@delaparra.org
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGENERATIONOPTIONSPAGE_H
+#define CODEGENERATIONOPTIONSPAGE_H
+
+#include <qwidget.h>
+#include "codegenerationoptionsbase.h"
+#include "../codegenerationpolicy.h"
+#include "../umlnamespace.h"
+
+/**
+ * @author Luis De la Parra
+ * @author Brian Thomas
+ */
+
+class CodeGenerationPolicy;
+class CodeGenerationPolicyPage;
+
+// 2003-07-30 : Updated for new code generation system. No longer need Yucky codegenstate
+// structure.
+
+class CodeGenerationOptionsPage : public CodeGenerationOptionsBase {
+ Q_OBJECT
+public:
+ CodeGenerationOptionsPage(QWidget *parent=0);
+ ~CodeGenerationOptionsPage();
+ void setDefaults();
+ QString getCodeGenerationLanguage();
+ void updateCodeGenerationPolicyTab();
+ void apply();
+
+protected:
+ CodeGenerationPolicy * m_parentPolicy;
+
+private:
+
+ CodeGenerationPolicyPage * m_pCodePolicyPage;
+ void init();
+ int overwriteToInteger(CodeGenerationPolicy::OverwritePolicy value);
+ int newLineToInteger(CodeGenerationPolicy::NewLineType value);
+ int indentTypeToInteger(CodeGenerationPolicy::IndentationType value);
+ void setupActiveLanguageBox();
+
+protected slots:
+ void activeLanguageChanged(int id);
+ void browseClicked();
+
+signals:
+ void applyClicked();
+ void languageChanged();
+ void syncCodeDocumentsToParent();
+
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/codegenerationpolicybase.ui b/umbrello/umbrello/dialogs/codegenerationpolicybase.ui
new file mode 100644
index 00000000..bbc739a7
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationpolicybase.ui
@@ -0,0 +1,39 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CodeGenerationPolicyBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CodeGenerationPolicyBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>519</width>
+ <height>515</height>
+ </rect>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>policyFrame</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>20</y>
+ <width>470</width>
+ <height>470</height>
+ </rect>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ </widget>
+</widget>
+<slots>
+ <slot access="protected">apply()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/dialogs/codegenerationpolicypage.cpp b/umbrello/umbrello/dialogs/codegenerationpolicypage.cpp
new file mode 100644
index 00000000..8deb3387
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationpolicypage.cpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+ begin : Tue Jul 29 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codegenerationpolicypage.h"
+
+// qt/kde includes
+#include <qlabel.h>
+#include <klocale.h>
+
+// local includes
+#include "../codegenerationpolicy.h"
+
+
+/** This is the page which comes up IF there is no special options for the
+ * code generator.
+ */
+CodeGenerationPolicyPage::CodeGenerationPolicyPage( QWidget *parent, const char *name, CodeGenPolicyExt * policy )
+ :CodeGenerationPolicyBase(parent,name)
+{
+ m_parentPolicy = policy;
+}
+
+CodeGenerationPolicyPage::~CodeGenerationPolicyPage()
+{
+ this->disconnect();
+}
+
+void CodeGenerationPolicyPage::apply() {
+ // do nothing in vanilla version
+}
+
+void CodeGenerationPolicyPage::setDefaults() { }
+
+#include "codegenerationpolicypage.moc"
+
diff --git a/umbrello/umbrello/dialogs/codegenerationpolicypage.h b/umbrello/umbrello/dialogs/codegenerationpolicypage.h
new file mode 100644
index 00000000..16590dd3
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationpolicypage.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ codegenerationpolicypage.h - description
+ -------------------
+ begin : Tue Jul 29 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGENERATIONPOLICYPAGE_H
+#define CODEGENERATIONPOLICYPAGE_H
+
+#include <qwidget.h>
+#include "codegenerationpolicybase.h"
+
+class CodeGenPolicyExt;
+
+/**
+ * @author Brian Thomas
+ */
+
+class CodeGenerationPolicyPage : public CodeGenerationPolicyBase {
+ Q_OBJECT
+public:
+ explicit CodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, CodeGenPolicyExt * policy = 0);
+
+ virtual ~CodeGenerationPolicyPage();
+
+ void setDefaults();
+
+protected:
+
+ CodeGenPolicyExt * m_parentPolicy;
+
+private:
+
+public slots:
+
+ virtual void apply();
+
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/dialogs/codegenerationwizard.cpp b/umbrello/umbrello/dialogs/codegenerationwizard.cpp
new file mode 100644
index 00000000..ca726398
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationwizard.cpp
@@ -0,0 +1,258 @@
+/***************************************************************************
+ codegenerationwizard.cpp - description
+ -------------------
+ begin : Wed Jul 24 2002
+ copyright : (C) 2002 by Paul Hensgen
+ email : phensgen@users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codegenerationwizard.h"
+
+// qt/kde includes
+#include <qdir.h>
+#include <qlistview.h>
+#include <qfileinfo.h>
+#include <qapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// local includes
+#include "codegenerationoptionspage.h"
+#include "../classifier.h"
+#include "../codegenerator.h"
+#include "../uml.h"
+#include "../umldoc.h"
+
+
+CodeGenerationWizard::CodeGenerationWizard(UMLClassifierList *classList)
+ : CodeGenerationWizardBase((QWidget*)UMLApp::app()) {
+ m_doc = UMLApp::app()->getDocument();
+ m_app = UMLApp::app();
+ m_availableList -> setAllColumnsShowFocus(true);
+ m_availableList -> setResizeMode(QListView::AllColumns);
+ m_selectedList -> setAllColumnsShowFocus(true);
+ m_selectedList -> setResizeMode(QListView::AllColumns);
+ m_statusList -> setAllColumnsShowFocus(true);
+ m_statusList -> setResizeMode(QListView::AllColumns);
+
+ m_CodeGenerationOptionsPage = new CodeGenerationOptionsPage(this);
+ connect( m_CodeGenerationOptionsPage, SIGNAL(languageChanged()), this, SLOT(changeLanguage()) );
+
+ insertPage(m_CodeGenerationOptionsPage, i18n("Code Generation Options"), 1);
+
+ UMLClassifierList cList;
+
+ if (classList == NULL) {
+ cList = m_doc->getClassesAndInterfaces();
+ classList = &cList;
+ }
+ for (UMLClassifier *c = classList->first(); c ; c = classList->next()) {
+ new QListViewItem( m_selectedList, c->getFullyQualifiedName());
+ }
+
+ setNextEnabled(page(0),m_selectedList->childCount() > 0);
+
+ setFinishEnabled(page(2),true);
+ finishButton()->disconnect();
+ finishButton()->setText(i18n("&Generate"));
+ connect(finishButton(),SIGNAL(clicked()),this,SLOT(generateCode()));
+ if ( QApplication::reverseLayout() )
+ {
+ QPixmap tmpPixmap( *m_addButton->pixmap() );
+ m_addButton->setPixmap(*m_removeButton->pixmap());
+ m_removeButton->setPixmap(tmpPixmap);
+ }
+}
+
+CodeGenerationWizard::~CodeGenerationWizard() {}
+
+
+void CodeGenerationWizard::selectClass() {
+ moveSelectedItems(m_availableList, m_selectedList);
+
+ if (m_selectedList->childCount() > 0) {
+ setNextEnabled(currentPage(), true);
+ }
+}
+
+void CodeGenerationWizard::deselectClass() {
+ moveSelectedItems(m_selectedList, m_availableList);
+
+ if (m_selectedList->childCount() == 0) {
+ setNextEnabled(currentPage(), false);
+ }
+}
+
+void CodeGenerationWizard::generateCode() {
+ backButton()->setEnabled(false);
+
+ CodeGenerator* codeGenerator = m_app->getGenerator();
+
+ if (codeGenerator) {
+
+ cancelButton()->setEnabled(false);
+
+ connect( codeGenerator, SIGNAL(codeGenerated(UMLClassifier*, bool)),
+ this, SLOT(classGenerated(UMLClassifier*, bool)) );
+
+ UMLClassifierList cList;
+ cList.setAutoDelete(false);
+
+ for(QListViewItem *item = m_statusList->firstChild(); item;
+ item = item-> nextSibling()) {
+ UMLClassifier *concept = m_doc->findUMLClassifier(item->text(0));
+ cList.append(concept);
+ }
+ codeGenerator->writeCodeToFile(cList);
+ finishButton()->setText(i18n("Finish"));
+ finishButton()->disconnect();
+ connect(finishButton(),SIGNAL(clicked()),this,SLOT(accept()));
+
+ }
+}
+
+void CodeGenerationWizard::classGenerated(UMLClassifier* concept, bool generated) {
+ QListViewItem* item = m_statusList->findItem( concept->getFullyQualifiedName(), 0 );
+ if( !item ) {
+ kError()<<"GenerationStatusPage::Error finding class in list view"<<endl;
+ } else if (generated) {
+ item->setText( 1, i18n("Code Generated") );
+ } else {
+ item->setText( 1, i18n("Not Generated") );
+ }
+}
+
+void CodeGenerationWizard::populateStatusList() {
+ m_statusList->clear();
+ for(QListViewItem* item = m_selectedList->firstChild(); item; item = item->nextSibling()) {
+ new QListViewItem(m_statusList,item->text(0),i18n("Not Yet Generated"));
+ }
+}
+
+void CodeGenerationWizard::showPage(QWidget *page) {
+ if (indexOf(page) == 2)
+ {
+ // first save the settings to the selected generator policy
+ ((CodeGenerationOptionsPage*)QWizard::page(1))->apply();
+
+ // before going on to the final page, check that the output directory exists and is
+ // writable
+
+ // get the policy for the current code generator
+ CodeGenerationPolicy *policy = UMLApp::app()->getCommonPolicy();
+
+ // get the output directory path
+ QFileInfo info(policy->getOutputDirectory().absPath());
+ if(!info.exists())
+ {
+ if (KMessageBox::questionYesNo(this,
+ i18n("The folder %1 does not exist. Do you want to create it now?").arg(info.filePath()),
+ i18n("Output Folder Does Not Exist"), i18n("Create Folder"), i18n("Do Not Create")) == KMessageBox::Yes)
+ {
+ QDir dir;
+ if(!dir.mkdir(info.filePath()))
+ {
+ KMessageBox::sorry(this,i18n("The folder could not be created.\nPlease make sure you have write access to its parent folder or select another, valid, folder."),
+ i18n("Error Creating Folder"));
+ return;
+ }
+ //else, directory created
+ }
+ else // do not create output directory
+ {
+ KMessageBox::information(this,i18n("Please select a valid folder."),
+ i18n("Output Folder Does Not Exist"));
+ return;
+ }
+ } else {
+ //directory exists.. make sure we can write to it
+ if(!info.isWritable())
+ {
+ KMessageBox::sorry(this,i18n("The output folder exists, but it is not writable.\nPlease set the appropriate permissions or choose another folder."),
+ i18n("Error Writing to Output Folder"));
+ return;
+ }
+ // it exits and we can write... make sure it is a directory
+ if(!info.isDir())
+ {
+ KMessageBox::sorry(this,i18n("%1 does not seem to be a folder. Please choose a valid folder.").arg(info.filePath()),
+ i18n("Please Choose Valid Folder"));
+ return;
+ }
+ }
+ }
+ populateStatusList();
+ QWizard::showPage(page);
+}
+
+CodeGenerator* CodeGenerationWizard::generator() {
+ // FIX
+ /*
+ KLibLoader* loader = KLibLoader::self();
+ if(!loader) {
+ kDebug()<<"error getting KLibLoader!"<<endl;
+ return 0;
+ }
+
+ KLibFactory* fact = loader->factory(info->library.latin1());
+ if(!fact) {
+ kDebug()<<"error getting the Factory"<<endl;
+ return 0;
+ }
+
+ QObject* o=fact->create(m_doc, 0, info->object.latin1());
+ if(!o) {
+ kDebug()<<"could not create object"<<endl;
+ return 0;
+ }
+
+ CodeGenerator* g = (CodeGenerator*)o;
+ // g->setDocument(m_doc);
+ return g;
+ */
+ return (CodeGenerator*) NULL;
+}
+
+void CodeGenerationWizard::moveSelectedItems(QListView* fromList, QListView* toList) {
+ QListViewItemIterator it(fromList, QListViewItemIterator::Selected);
+ while (it.current()) {
+ QListViewItem* selectedItem = it.current();
+
+ QString name = selectedItem->text(0);
+ if (!toList->findItem(name, 0)) {
+ new QListViewItem(toList, name);
+ }
+
+ ++it;
+
+ //Removed here because it can't (really, shouldn't) be removed while
+ //iterator is pointing to it
+ fromList->removeItem(selectedItem);
+ }
+}
+
+// when we change language, we need to update the codegenoptions page
+// language-dependent stuff. THe way to do this is to call its "apply" method.
+void CodeGenerationWizard::changeLanguage()
+{
+ m_app->setActiveLanguage( m_CodeGenerationOptionsPage->getCodeGenerationLanguage() );
+ /* @todo is this needed? if yes adapt to new scheme
+ m_CodeGenerationOptionsPage->setCodeGenerator(m_doc->getCurrentCodeGenerator());
+ */
+ m_CodeGenerationOptionsPage->apply();
+}
+
+#include "codegenerationwizard.moc"
diff --git a/umbrello/umbrello/dialogs/codegenerationwizard.h b/umbrello/umbrello/dialogs/codegenerationwizard.h
new file mode 100644
index 00000000..14d5f157
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationwizard.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ codegenerationwizard.h - description
+ -------------------
+ begin : Wed Jul 24 2002
+ copyright : (C) 2002 by Luis De la Parra
+ email : luis@delaparra.org
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CODEGENERATIONWIZARD_H
+#define CODEGENERATIONWIZARD_H
+
+#include <qwidget.h>
+#include <qptrlist.h>
+#include "codegenerationwizardbase.h"
+#include "settingsdlg.h"
+#include "../umlclassifierlist.h"
+
+class UMLApp;
+class UMLDoc;
+class CodeGenerator;
+class CodeGenerationOptionsPage;
+
+/**
+ * @author Luis De la Parra
+ * based on wizard from Paul Hensgen
+ */
+
+class CodeGenerationWizard : public CodeGenerationWizardBase {
+ Q_OBJECT
+public:
+ CodeGenerationWizard(UMLClassifierList *classList);
+ ~CodeGenerationWizard();
+
+ void showPage(QWidget *);
+
+ int exec() {
+ return QWizard::exec();
+ }
+protected slots:
+
+ /**
+ * Adds the classes selected in the available classes list to the
+ * list of classes used to generate the code.
+ */
+ void selectClass();
+
+ /**
+ * Removes the classes selected in the selected classes list from the
+ * list of classes used to generate the code.
+ */
+ void deselectClass();
+ void populateStatusList();
+ void generateCode();
+ void classGenerated(UMLClassifier* concept, bool generated);
+
+private slots:
+ void changeLanguage();
+
+
+private:
+ CodeGenerator* generator();
+
+ /**
+ * Moves the selected items from first list to second list.
+ * The selected items are removed from the first list and added to the
+ * second. An item is added to the second list only if it isn't already
+ * there (no duplicated items are created).
+ */
+ void moveSelectedItems(QListView* fromList, QListView* toList);
+
+ UMLApp* m_app;
+ UMLDoc* m_doc;
+ CodeGenerationOptionsPage* m_CodeGenerationOptionsPage;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/codegenerationwizardbase.ui b/umbrello/umbrello/dialogs/codegenerationwizardbase.ui
new file mode 100644
index 00000000..732aa0c7
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codegenerationwizardbase.ui
@@ -0,0 +1,309 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>CodeGenerationWizardBase</class>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>CodeGenerationWizardBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>396</width>
+ <height>386</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Code Generation Wizard</string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>select</cstring>
+ </property>
+ <attribute name="title">
+ <string>Select Classes</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Place all the classes you want to generate code
+for in the right hand side list</string>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>Frame4</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>20</number>
+ </property>
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_addButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Add class for code generation</string>
+ </property>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name" stdset="0">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QListView" row="0" column="2" rowspan="5" colspan="1">
+ <column>
+ <property name="text">
+ <string>Classes Selected</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizeable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_selectedList</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode">
+ <enum>Extended</enum>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>m_removeButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image1</pixmap>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Remove class from Code Generation</string>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name" stdset="0">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QListView" row="0" column="0" rowspan="5" colspan="1">
+ <column>
+ <property name="text">
+ <string>Classes Available</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizeable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_availableList</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode">
+ <enum>Extended</enum>
+ </property>
+ </widget>
+ <spacer row="4" column="1">
+ <property name="name" stdset="0">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>status</cstring>
+ </property>
+ <attribute name="title">
+ <string>Code Generation Status</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label</cstring>
+ </property>
+ <property name="text">
+ <string>Press the Generation button to start the code generation</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Generation Status</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>20</number>
+ </property>
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <widget class="QListView">
+ <column>
+ <property name="text">
+ <string>Class</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizeable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Generation Status</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizeable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_statusList</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="915">789c65d1c96ec2301006e03b4f61c10d5580431262553db0158ad4aac74a550f633bec5b21a4d0aaefdecc8c1395605ffc79fe71e2a459176fafcfa2deac1c1348164698391c44dd9e369bcbfbc7c34fa52a432103d18e84acde55aa0d61c4cb6e1be35a67eb5aabe5b7420f592b08c8d8d1670231ca3941ca28b091463e21bd5628958f1c1355a8988f050d72e4689903645b762473e81800f5f689aaa3983d47cbec227d1949a0de8b63c0fc2642a4986764e04556536fca5492f955d022132228c53c395ae611197a109800792042ce9d63ccdc233bed8cd4fb49d43a64ae1d81b9ca69a977838cda39e74ce33117449d917ee814a97c13c721724b3406b8ba44826f3daece88c6424c55eb18330d52fb391b386ad0c847bea7b386f21e98a981726e365fe4c922b75cad372e59e4b6bbfd6ecfc922f7793866939245ee909c70eaffb9244dbfd234bdca9d2fdfd9bc3eafdbed757ba5e7f607c341f9fd1e47e39b7b3c4d6eee7bf55d7eef2b7f4698d01d</data>
+ </image>
+ <image name="image1">
+ <data format="XPM.GZ" length="915">789c65d1c76e83401006e0bb9f62656e56147b316056510eee454a9463a428872db81b775ca2bc7b9899c502c21cd86fe71f6abdc63e3fde58ad5e399ee469a1999ecb03ab99f36673fbfa7efda95479c0b8cf9a21e3d5a74af59969f6be8d235847e9da6934bc46e002e58312a82c3da2830c338e813cf44da88013a0db08b8f08003a4080471f4a0060e2d0db10b6cf21627f62c7d89b37da4680962dbd2103b408f875ce2ecd5d227de903214c43bd07743a37036210a4ebc3c688067a4148278b234c4033070a5af7de01e29336e2d23620c6c3553e2ec11a954405c594ae232a3c1d935306c669c13b54b9c21554afca153a0f0741405c01d526b49dd0d507ac6a5ee02a98d8cb0ab2d23a2012a2fe3b33d1c49e7dc9e4a674a7b8e991aa7b8a7f46cbe28e61cb35cad37859cd2f1368e77f99c63f687b48ef95c743a43ed0bb9e49224c9e55cbcdef596d6bd74df76a7dde9949fafdbebf6ffbdc760382ae5d2e47852cee5becbef4be50f94aacd35</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_addButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CodeGenerationWizardBase</receiver>
+ <slot>selectClass()</slot>
+ </connection>
+ <connection>
+ <sender>m_removeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CodeGenerationWizardBase</receiver>
+ <slot>deselectClass()</slot>
+ </connection>
+</connections>
+<forwards>
+ <forward>class UMLClassifier</forward>
+</forwards>
+<slots>
+ <slot>selectClass()</slot>
+ <slot access="protected">deselectClass()</slot>
+ <slot>classGenerated( UMLClassifier * /* c */ )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/dialogs/codeviewerdialog.cpp b/umbrello/umbrello/dialogs/codeviewerdialog.cpp
new file mode 100644
index 00000000..5672e576
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codeviewerdialog.cpp
@@ -0,0 +1,122 @@
+/***************************************************************************
+ begin : Fri Aug 1 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codeviewerdialog.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// local includes
+#include "../codedocument.h"
+#include "../classifiercodedocument.h"
+#include "codeeditor.h"
+
+CodeViewerDialog::CodeViewerDialog ( QWidget* parent, CodeDocument * doc,
+ Settings::CodeViewerState state,
+ const char* name, bool modal, WFlags fl )
+ : CodeViewerDialogBase ( parent, name, modal, fl )
+
+{
+ m_state = state;
+
+ initGUI(name);
+
+ addCodeDocument(doc);
+
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+CodeViewerDialog::~CodeViewerDialog()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+void CodeViewerDialog::initGUI ( const char * name) {
+
+ if ( !name )
+ setName( "CodeViewerDialog" );
+
+ setFont( getState().font );
+
+ // set some viewability parameters
+ int margin = fontMetrics().height();
+ int width = fontMetrics().maxWidth() * getState().width;
+ int height = fontMetrics().lineSpacing() * getState().height;
+
+ m_highlightCheckBox->setChecked( getState().blocksAreHighlighted );
+ m_showHiddenCodeCB->setChecked ( getState().showHiddenBlocks );
+
+ CodeViewerDialogBaseLayout->setMargin(margin);
+
+ resize( QSize(width, height).expandedTo(minimumSizeHint()) );
+
+}
+
+/*
+ * Adds a code document to the tabbed output
+ */
+void CodeViewerDialog::addCodeDocument( CodeDocument * doc)
+{
+ CodeEditor * page = new CodeEditor ( this, "_codedocumenteditor_", doc );
+ QString fname = doc->getFileName();
+ QString ext = doc->getFileExtension();
+ m_tabWidget->insertTab(page, (fname + (ext.isEmpty()? "" : ext)));
+
+ connect( m_highlightCheckBox, SIGNAL( stateChanged(int) ), page, SLOT( changeHighlighting(int) ) );
+ connect( m_showHiddenCodeCB, SIGNAL( stateChanged(int) ), page, SLOT( changeShowHidden(int) ) );
+
+}
+
+Settings::CodeViewerState CodeViewerDialog::getState() {
+ return m_state;
+}
+
+bool CodeViewerDialog::close ( bool alsoDelete )
+{
+
+ // remember widget size for next time
+ m_state.height = height() / fontMetrics().lineSpacing();
+ m_state.width = width() / fontMetrics().maxWidth();
+
+ // remember block highlighting
+ m_state.blocksAreHighlighted = m_highlightCheckBox->isChecked();
+
+ // remember block show status
+ m_state.showHiddenBlocks = m_showHiddenCodeCB->isChecked();
+
+ // run superclass close now
+ return CodeViewerDialogBase::close(alsoDelete);
+
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void CodeViewerDialog::languageChange()
+{
+ setCaption( tr2i18n( "Code Viewer" ) );
+}
+
+#include "codeviewerdialog.moc"
diff --git a/umbrello/umbrello/dialogs/codeviewerdialog.h b/umbrello/umbrello/dialogs/codeviewerdialog.h
new file mode 100644
index 00000000..7315384f
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codeviewerdialog.h
@@ -0,0 +1,80 @@
+
+/***************************************************************************
+ codeviewerdialog.h - description
+ -------------------
+ begin : Fri Aug 1 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef CODEVIEWERDIALOG_H
+#define CODEVIEWERDIALOG_H
+
+#include <qcolor.h>
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qtextedit.h>
+#include "../codeviewerstate.h"
+#include "codeviewerdialogbase.h"
+
+class CodeDocument;
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QFrame;
+
+class UMLObject;
+
+/** This class is sooo ugly I don't know where to begin. For now, its a prototype
+ * that works, and thats all we need. In the future, a re-write is mandated to
+ * bring a bit of beauty to this beast. -b.t.
+ */
+class CodeViewerDialog : public CodeViewerDialogBase
+{
+ Q_OBJECT
+public:
+
+ CodeViewerDialog ( QWidget* parent, CodeDocument * doc, Settings::CodeViewerState state,
+ const char* name = 0, bool modal = false, WFlags fl = 0 );
+ ~CodeViewerDialog ();
+
+ /** return the code viewer state */
+ Settings::CodeViewerState getState( );
+
+ QString parentDocName;
+
+ /**
+ * Adds a code document to the tabbed output
+ */
+ void addCodeDocument( CodeDocument * doc);
+
+protected:
+
+ bool close ( bool alsoDelete );
+
+private:
+
+ Settings::CodeViewerState m_state;
+
+ void initGUI ( const char * name );
+
+public slots:
+
+protected slots:
+
+ virtual void languageChange();
+
+};
+
+
+#endif // CODEVIEWERDIALOG_H
diff --git a/umbrello/umbrello/dialogs/codeviewerdialogbase.ui b/umbrello/umbrello/dialogs/codeviewerdialogbase.ui
new file mode 100644
index 00000000..672aefdb
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codeviewerdialogbase.ui
@@ -0,0 +1,113 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CodeViewerDialogBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>CodeViewerDialogBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>615</width>
+ <height>728</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <family>Courier</family>
+ </font>
+ </property>
+ <property name="caption">
+ <string>Code Viewer</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_showHiddenCodeCB</cstring>
+ </property>
+ <property name="text">
+ <string>Show hidden blocks</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>componentLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;component name here&lt;/p&gt;</string>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_exitButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_highlightCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show block type</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QTabWidget" row="1" column="0">
+ <property name="name">
+ <cstring>m_tabWidget</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>m_exitButton</sender>
+ <signal>released()</signal>
+ <receiver>CodeViewerDialogBase</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>changeHighlighting(int)</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/dialogs/codevieweroptionsbase.ui b/umbrello/umbrello/dialogs/codevieweroptionsbase.ui
new file mode 100644
index 00000000..99fd198d
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codevieweroptionsbase.ui
@@ -0,0 +1,369 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CodeViewerOptionsBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CodeViewerOptionsBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>486</width>
+ <height>545</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KFontChooser" row="0" column="0">
+ <property name="name">
+ <cstring>fontChooser</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>colorGroupBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>colorLayout</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>fontLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Font:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="5">
+ <property name="name">
+ <cstring>selectColorButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>paperLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Paper:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>paperColorButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="4">
+ <property name="name">
+ <cstring>selectedLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Selected:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="3">
+ <property name="name">
+ <cstring>fontColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton" row="1" column="3">
+ <property name="name">
+ <cstring>nonEditBlockColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>213</red>
+ <green>213</green>
+ <blue>213</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton" row="0" column="3">
+ <property name="name">
+ <cstring>m_hiddenBlockColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>166</red>
+ <green>254</green>
+ <blue>248</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>umlObjectColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>170</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;UML object block:&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;Hidden block:&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;Uneditable text:&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>editBlockColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>170</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;Editable text:&lt;/p&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KFontChooser</class>
+ <header location="global">kfontdialog.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="4462">789c9d97c76e24490e86effd1442f3d65870d2451a0ce6206f5adeb4cc620f8c34f2553225b5a4c1befb46927fe6a1d4c0ccac4287fa8a0c26834193f5dbb785b3fd9d856fbf7d799ec9ecba5ea8afe469e15bf3727ffffeeffffcf1e797af49b2d0ffc7d142f2f55f5fbe1ecc16ea85dde9a4ed81290045faa77ca49cf4ab67ba1e3953969173651ab9d4fdf1c8a27c3872ad7c3c72d3b32c2a67c3f3444636fbef23eb7e590267e68fcc4656395d8dacf6d938ef97eaef289781cddebdb2846fccff44b989ba58e3411f3dc75158e6df1d3889539517ca49bf54fe43398d1dec4f46567f685fd9c539f43fc025f80c1c3ce8d93f28e77185f8bf0c6cfae4c0b5f9c3c6e5c0542a4b5876fe13708df39d2bd7716372aa8c93c4e4723bb2f977aadc26ceec4bdb7310e6b0bfab9c2445ecd49f1370694cebca65d260ffa6711a41aef14d24e94cee6be3348e0ae5e9c8765f07ca3e8db17f0f9c825794eb3489351fe9bb7217e4969f29388bd51ee9fda5715a19730696b852fea95c6471647ca95cf64bcf43e0cef4657b647bfe6acf213d6bb32f9a9f5992b5a64f9a8f990b6cf9ecc15d6cf9acf6b2da55a8a75cb973dee4b2d1b38b5c05de02434e87e01aacfb351df5bebddea74b5c67f9c795711ea15e357e2ecde358fb87efc0a867df8cac728a074e62e527706afb59f3cf6583be5c28bb3c35f693812d1fbdc6dbe57966fec932d899ffa4f7e38adca17e34beaeca4b9c271a18f1d5fc739257b0d70d9c68be7bed7fcee7827ab91cd8e4740cf6b19d4ffb87ab07b9bf516e72d4a3ac821b9cef6e60d84f47367ded2fae1d9f7704f6163f79000ffde27660f387ed3c5dbf54dfeebb0bf6acbe6b706bfa5ef32f8f8b18f5bf0f463f20edb77956a4e68fbc80b3c4facd163847be6bfde72ec86dbeac82715fbc0286be683cf3bc081d44f7df80d344fb0b6b7de64581fb916765297263d6fccd9b7ee97e566e8b06cfdb1f59cf2bda2f8bbc2c11df0c5c41aefdb328ca22b1feb0012eedbce24736f91b18fb796d64eb87cb60817dcdafb07d906bfd14d22f659d8785ef97b2f6d7b2df6ef1d6fb2babaac6f92e8c25b27ecc1f239b7f3a5fca5a8678ea7c2d9bc0e6ef1238b3fca2c7814d5f4cbf9334b5f833384bed3c7a5f5514f4adbe2ec07962e7590457f06f6f649b977afe2a16f42f5e070bfc591e18f7a5f1a812a9e0df39d827da4fbd8c6ccfd7785569bf945f953371a9d5a3de67950bfa2d75c63eb2fb15bdcfaaf011e6c7263846bf8f4636f91618f3c7d3c0f047fb69550efab2074e12bd6fd27957553ec33c5b043bcc7f9d0795f818fdb501a3df8ae673e507ff69021eea37063bc45ffb73550736ff36c0a84f3e0317a86f8b5f139e6ffe1f821de6d9127898ff3be00a7c3ab2cd03e3d697560ff40016e47b3bb2e96bbd559d8f32bbff4b7065f193042c98873acf240af6adbf3c83c5f2954bb0c7bcd77c107d81d2fdebc63e33ff640aaecc9e1c8151df5c803dfaadc64b52dfa03ed64636ffb4ff4b2867f453ede7227586fcd3f9264ded91fffafe236d5da37fe83c91ceb7b9e5b7f6731ff92ed7f747d6fbf7e185cf58347e3e6932e47b3430fa893edf87d795c2fc3f003b67f5f902cec17abfde0dfa3c053b3c5ffb832fc2eb8fddcf233887fc195c801f46b6f3cdc02558fba72f7d2d1a7f7e321ee58fe0cad86bbff24dd3e2fe74fef836b0c6eb60d62fa6bf5e07b3419f853dd7dc70fb8bd5f1255fd90ed30f9f3c5ff30ddff21ddff384a7fcc08ffcc4cf61cdf8855ff9e79c7e1db4dff89d3f7891977899577895d7789d377893b7f83b6fcfe937bc13b477798ff7f9800ff928ac633ee11f7cca6761d7f99c7e1b3cb908da11c7413be1943376e153cc39175c72f549ff9e17c31744429e6a6aa8a58e2ee98aaee9866e7f617fc24b7417a4f734a1293dd0233dd133cd8285177aa5f9f3b63ca5377aa78f607b919668995682e62aadd17ab0b1419b9ff41f682b48bed336edd02eed05ed7d5ea3033a0cdf1ed1f127fd273ae123fa41a774a6b685cee982228a837e42e927fd47caf8985c38651eb40b2ac38e4a5842658a97fab33fd248cb87d2c9a55cc9b5dcc82d1fc99ddccb44a6f230af2f8ff224cf417f262ff22a3fe54ddee543166549966545567f617f4dd66523dc6b2c9bb225df655b7682f692ecca9eeccfe97772c09b722847722c27c1f3eb70f66bf9116c9fca999ccbc59cfe25bf4a143a5ef8992561324a78bd92522acf9ebc78efe7cf7b153276db37bef59dbff457fedadff85b7f27abfede4ffcd4cf9ff76faeff4fffefeff8c7f5fedfdfbffc0fa355c495</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/umbrello/umbrello/dialogs/codevieweroptionspage.cpp b/umbrello/umbrello/dialogs/codevieweroptionspage.cpp
new file mode 100644
index 00000000..dd120569
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codevieweroptionspage.cpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ codegenerationoptionspage.cpp - description
+ -------------------
+ begin : Thu Jul 25 2002
+ copyright : (C) 2002 by Luis De la Parra
+ email : luis@delaparra.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "codevieweroptionspage.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <kfontdialog.h>
+#include <kcolorbutton.h>
+
+
+CodeViewerOptionsPage::CodeViewerOptionsPage( Settings::CodeViewerState options, QWidget *parent, const char *name )
+ :CodeViewerOptionsBase(parent,name)
+{
+ init (options);
+}
+
+CodeViewerOptionsPage::~CodeViewerOptionsPage() { }
+
+void CodeViewerOptionsPage::init( Settings::CodeViewerState options )
+{
+ m_options = options;
+
+ // set widget stuff
+ /*
+ fontChooser->setFont( options.font );
+ selectColorButton -> setColor (options.selectedColor);
+ fontColorButton -> setColor (options.fontColor);
+ paperColorButton -> setColor (options.paperColor);
+ editBlockColorButton -> setColor (options.editBlockColor);
+ nonEditBlockColorButton -> setColor (options.nonEditBlockColor);
+ umlObjectColorButton -> setColor (options.umlObjectColor);
+ */
+}
+
+void CodeViewerOptionsPage::apply() {
+ /*
+ m_options.umlObjectColor = umlObjectColorButton->color();
+ m_options.editBlockColor = editBlockColorButton->color();
+ m_options.nonEditBlockColor = nonEditBlockColorButton->color();
+ m_options.selectedColor = selectColorButton->color();
+ m_options.paperColor = paperColorButton->color();
+ m_options.fontColor = fontColorButton->color();
+ m_options.font = fontChooser->font();
+ */
+ emit applyClicked();
+}
+
+Settings::CodeViewerState CodeViewerOptionsPage::getOptions() {
+ return m_options;
+}
+
+#include "codevieweroptionspage.moc"
diff --git a/umbrello/umbrello/dialogs/codevieweroptionspage.h b/umbrello/umbrello/dialogs/codevieweroptionspage.h
new file mode 100644
index 00000000..ec01f170
--- /dev/null
+++ b/umbrello/umbrello/dialogs/codevieweroptionspage.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ codegenerationoptionspage.h - description
+ -------------------
+ begin : Thu Jul 25 2002
+ copyright : (C) 2002 by Luis De la Parra
+ email : luis@delaparra.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef CODEVIEWEROPTIONSPAGE_H
+#define CODEVIEWEROPTIONSPAGE_H
+
+#include <qwidget.h>
+#include "codevieweroptionsbase.h"
+#include "../codeviewerstate.h"
+
+/**
+ * @author Brian Thomas
+ */
+
+class CodeViewerOptionsPage : public CodeViewerOptionsBase {
+ Q_OBJECT
+public:
+ CodeViewerOptionsPage (Settings::CodeViewerState options, QWidget *parent, const char *name=0);
+ ~CodeViewerOptionsPage();
+
+ Settings::CodeViewerState getOptions();
+ void apply();
+
+protected:
+
+private:
+
+ Settings::CodeViewerState m_options;
+ void init ( Settings::CodeViewerState options);
+
+protected slots:
+
+signals:
+ void applyClicked();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/defaultcodegenpolicypage.cpp b/umbrello/umbrello/dialogs/defaultcodegenpolicypage.cpp
new file mode 100644
index 00000000..668d732d
--- /dev/null
+++ b/umbrello/umbrello/dialogs/defaultcodegenpolicypage.cpp
@@ -0,0 +1,41 @@
+
+/***************************************************************************
+ codegenerationpolicypage.cpp - description
+ -------------------
+ begin : Tue Jul 29 2003
+ copyright : (C) 2003 by Brian Thomas
+ email : brian.thomas@gsfc.nasa.gov
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "defaultcodegenpolicypage.h"
+
+// qt/kde includes
+#include <qlabel.h>
+#include <klocale.h>
+
+
+/** This is the page which comes up IF there is no special options for the
+ * code generator.
+ */
+DefaultCodeGenPolicyPage::DefaultCodeGenPolicyPage ( QWidget *parent, const char *name, CodeGenPolicyExt * policy )
+ :CodeGenerationPolicyPage(parent,name,policy)
+{
+ textLabel = new QLabel(parent,"textLabel");
+ textLabel->setText(tr2i18n("<p align=\"center\">No Options Available.</p>"));
+}
+
+DefaultCodeGenPolicyPage::~DefaultCodeGenPolicyPage() { }
+
+#include "defaultcodegenpolicypage.moc"
diff --git a/umbrello/umbrello/dialogs/defaultcodegenpolicypage.h b/umbrello/umbrello/dialogs/defaultcodegenpolicypage.h
new file mode 100644
index 00000000..c3d36332
--- /dev/null
+++ b/umbrello/umbrello/dialogs/defaultcodegenpolicypage.h
@@ -0,0 +1,42 @@
+
+/****************************************************************************
+** Form interface generated from reading ui file 'Defaultcodegenpolicypage.ui'
+**
+** Created: Fri Aug 1 12:47:23 2003
+** by: The User Interface Compiler ($Id$)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+
+#ifndef DEFAULTCODEGENPOLICYPAGE_H
+#define DEFAULTCODEGENPOLICYPAGE_H
+
+#include <qvariant.h>
+#include <qwidget.h>
+#include "codegenerationpolicypage.h"
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QLabel;
+class CodeGenePolicyExt;
+
+class DefaultCodeGenPolicyPage : public CodeGenerationPolicyPage
+{
+ Q_OBJECT
+
+public:
+
+ explicit DefaultCodeGenPolicyPage( QWidget* parent = 0, const char* name = 0, CodeGenPolicyExt * policy =0);
+
+ ~DefaultCodeGenPolicyPage();
+
+ QLabel* textLabel;
+
+protected:
+
+protected slots:
+
+};
+
+#endif // DEFAULTCODEGENPOLICYPAGE_H
diff --git a/umbrello/umbrello/dialogs/diagramprintpage.cpp b/umbrello/umbrello/dialogs/diagramprintpage.cpp
new file mode 100644
index 00000000..cf366197
--- /dev/null
+++ b/umbrello/umbrello/dialogs/diagramprintpage.cpp
@@ -0,0 +1,225 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "diagramprintpage.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <qptrlist.h>
+#include <qlistbox.h>
+#include <qradiobutton.h>
+#include <qcombobox.h>
+#include <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <klocale.h>
+
+// local includes
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlview.h"
+#include "../umlviewlist.h"
+#include "../umlnamespace.h"
+
+
+DiagramPrintPage::DiagramPrintPage(QWidget * parent, UMLDoc * m_pDoc) : KPrintDialogPage(parent), m_pDoc(m_pDoc) {
+ int margin = fontMetrics().height();
+ setTitle(i18n("&Diagrams"));
+ QHBoxLayout * mainLayout = new QHBoxLayout(this);
+ mainLayout -> setSpacing(10);
+ mainLayout -> setMargin(margin);
+
+ m_pFilterBG = new QButtonGroup(i18n("Filter"), this);
+ mainLayout -> addWidget(m_pFilterBG);
+ m_pFilterBG -> setExclusive(true);
+
+ QVBoxLayout * filter = new QVBoxLayout(m_pFilterBG);
+ filter -> setSpacing(10);
+ filter-> setMargin(margin);
+
+ m_pCurrentRB = new QRadioButton(i18n("&Current diagram"), m_pFilterBG);
+ filter -> addWidget(m_pCurrentRB);
+ m_pCurrentRB -> setChecked(true);
+ m_pFilterBG -> insert(m_pCurrentRB, Current);
+
+ m_pAllRB = new QRadioButton(i18n("&All diagrams"), m_pFilterBG);
+ filter -> addWidget(m_pAllRB);
+ m_pFilterBG -> insert(m_pAllRB, All);
+
+ m_pSelectRB = new QRadioButton(i18n("&Select diagrams"), m_pFilterBG);
+ filter -> addWidget(m_pSelectRB);
+ m_pFilterBG -> insert(m_pSelectRB, Select);
+
+ m_pTypeRB = new QRadioButton(i18n("&Type of diagram"), m_pFilterBG);
+ filter -> addWidget(m_pTypeRB);
+ m_pFilterBG -> insert(m_pTypeRB, Type);
+
+ m_pSelectGB = new QGroupBox(i18n("Selection"), this);
+ mainLayout -> addWidget(m_pSelectGB);
+
+ QVBoxLayout * select = new QVBoxLayout(m_pSelectGB);
+ select -> setSpacing(10);
+ select-> setMargin(margin);
+
+ m_pTypeCB = new QComboBox(m_pSelectGB);
+ select -> addWidget(m_pTypeCB);
+ m_pTypeCB -> setEnabled(false);
+
+ m_pSelectLB = new QListBox(m_pSelectGB);
+ select -> addWidget(m_pSelectLB);
+ m_pSelectLB -> setEnabled(false);
+ m_pSelectLB -> setSelectionMode(QListBox::Multi);
+ m_pSelectLB -> insertItem(UMLApp::app()->getCurrentView()->getName());
+ m_pSelectLB -> setSelected(0, true);
+ m_nIdList.clear();
+ m_nIdList.append(UMLApp::app()->getCurrentView()->getID());
+
+
+
+ m_ViewType = Uml::dt_Class;
+ connect(m_pFilterBG, SIGNAL(clicked(int)), this, SLOT(slotClicked(int)));
+ connect(m_pTypeCB, SIGNAL(activated(const QString&)), this, SLOT(slotActivated(const QString&)));
+
+ m_pTypeCB -> insertItem(i18n("Class"));
+ m_pTypeCB -> insertItem(i18n("Use Case"));
+ m_pTypeCB -> insertItem(i18n("Collaboration"));
+ m_pTypeCB -> insertItem(i18n("Sequence"));
+ m_pTypeCB -> insertItem(i18n("State"));
+ m_pTypeCB -> insertItem(i18n("Activity"));
+ m_pTypeCB -> insertItem(i18n("Component"));
+ m_pTypeCB -> insertItem(i18n("Deployment"));
+}
+
+DiagramPrintPage::~DiagramPrintPage()
+{
+ disconnect(m_pFilterBG, SIGNAL(clicked(int)), this, SLOT(slotClicked(int)));
+ disconnect(m_pTypeCB, SIGNAL(activated(const QString&)), this, SLOT(slotActivated(const QString&)));
+}
+
+void DiagramPrintPage::getOptions( QMap<QString,QString>& opts, bool /*incldef = false*/ ) {
+ int listCount = m_pSelectLB -> count();
+ int count = 0;
+
+ QString diagram(i18n("kde-uml-Diagram"));
+ for(int i=0;i<listCount;i++) {
+ if(m_pSelectLB -> isSelected(i)) {
+ UMLView *view = (UMLView *)m_pDoc -> findView(m_nIdList[i]);
+ QString sCount = QString("%1").arg(count);
+ QString sID = QString("%1").arg(ID2STR(view -> getID()));
+ opts.insert(diagram + sCount, sID);
+ count++;
+ }
+ }
+ opts.insert("kde-uml-count", QString("%1").arg(count));
+}
+
+void DiagramPrintPage::setOptions( const QMap<QString,QString>& /*opts*/ ) {}
+
+bool DiagramPrintPage::isValid( QString& msg ) {
+ int listCount = m_pSelectLB -> count();
+ bool sel = false;
+ for(int i =0;i<listCount;i++) {
+ if(m_pSelectLB -> isSelected(i)) {
+ sel = true;
+ i = listCount;
+ }
+ }
+ msg = i18n("No diagrams selected.");
+ return sel;
+}
+
+void DiagramPrintPage::slotClicked(int id) {
+ UMLViewList list = m_pDoc -> getViewIterator();
+ UMLView * view = 0;
+ QString type;
+
+ // clear list with diagrams to print
+ m_nIdList.clear();
+
+ switch(id) {
+ case Current:
+ m_pTypeCB -> setEnabled(false);
+ m_pSelectLB -> setEnabled(false);
+ m_pSelectLB -> clear();
+ m_pSelectLB -> insertItem(UMLApp::app()->getCurrentView()->getName());
+ m_pSelectLB -> setSelected(0, true);
+ m_nIdList.append(UMLApp::app()->getCurrentView()->getID());
+ break;
+
+ case All:
+
+ m_pTypeCB -> setEnabled(false);
+ m_pSelectLB -> setEnabled(false);
+ m_pSelectLB -> clear();
+ for(view = list.first(); view; view = list.next()) {
+ m_pSelectLB -> insertItem(view -> getName());
+ m_nIdList.append(view -> getID());
+ }
+ m_pSelectLB -> selectAll(true);
+ break;
+
+ case Select:
+ m_pTypeCB -> setEnabled(false);
+ m_pSelectLB -> setEnabled(true);
+ m_pSelectLB -> clear();
+ for(view = list.first(); view; view = list.next()) {
+ m_pSelectLB -> insertItem(view -> getName());
+ m_nIdList.append(view -> getID());
+ }
+ break;
+
+ case Type:
+ m_pTypeCB -> setEnabled(true);
+ m_pSelectLB -> setEnabled(true);
+ m_pSelectLB -> clear();
+ for(view = list.first(); view; view = list.next()) {
+ if(view -> getType() == m_ViewType) {
+ m_pSelectLB -> insertItem(view -> getName());
+ m_nIdList.append(view -> getID());
+ }
+ }
+ m_pSelectLB -> selectAll(true);
+ break;
+ }
+}
+
+void DiagramPrintPage::slotActivated(const QString & text) {
+ UMLViewList list = m_pDoc -> getViewIterator();
+ UMLView * view = 0;
+
+ if(text == i18n("Class"))
+ m_ViewType = Uml::dt_Class;
+ else if(text == i18n("Sequence"))
+ m_ViewType = Uml::dt_Sequence;
+ else if(text == i18n("Use Case"))
+ m_ViewType = Uml::dt_UseCase;
+ else if(text == i18n("Collaboration"))
+ m_ViewType = Uml::dt_Collaboration;
+ else if(text == i18n("State"))
+ m_ViewType = Uml::dt_State;
+ else if(text == i18n("Activity"))
+ m_ViewType = Uml::dt_Activity;
+ else if(text == i18n("Component"))
+ m_ViewType = Uml::dt_Component;
+ else if(text == i18n("Deployment"))
+ m_ViewType = Uml::dt_Deployment;
+ m_pSelectLB -> clear();
+ m_nIdList.clear();
+ for(view = list.first(); view; view = list.next()) {
+ if(view -> getType() == m_ViewType) {
+ m_pSelectLB -> insertItem(view -> getName());
+ m_nIdList.append(view -> getID());
+ }
+ }
+ m_pSelectLB -> selectAll(true);
+}
+
+#include "diagramprintpage.moc"
diff --git a/umbrello/umbrello/dialogs/diagramprintpage.h b/umbrello/umbrello/dialogs/diagramprintpage.h
new file mode 100644
index 00000000..f2184a27
--- /dev/null
+++ b/umbrello/umbrello/dialogs/diagramprintpage.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef DIAGRAMPRINTPAGE_H
+#define DIAGRAMPRINTPAGE_H
+
+class QListBox;
+class QRadioButton;
+class QComboBox;
+class QButtonGroup;
+class QGroupBox;
+
+#include <kdeprint/kprintdialogpage.h>
+
+#include "../umldoc.h"
+#include "../umlview.h"
+/**
+ * This is a page on the print dialog to select what diagram(s)
+ * you wish to print. You add it to the @ref KPrinter instance.
+ *
+ * You will then need to get the options as shown in @ref KPrinter.
+ *
+ * @short A print dialog page.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see KPrinter
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class DiagramPrintPage : public KPrintDialogPage {
+ Q_OBJECT
+public:
+ /**
+ * Constructs the diagram print page.
+ *
+ * @param parent The parent to the page.
+ * @param doc The @ref UMLDoc class instance being used.
+ */
+ DiagramPrintPage(QWidget * parent, UMLDoc *doc);
+
+ /**
+ * Stnadard deconstructor.
+ */
+ ~DiagramPrintPage();
+
+ /**
+ * Overriden method. It builds a list with the diagram name and the diagram
+ * IDs.
+ */
+ void getOptions(QMap<QString,QString>& opts, bool /* incldef=false */);
+
+ /**
+ * Overriden method.
+ */
+ void setOptions( const QMap<QString,QString>& /*opts*/ );
+
+ /**
+ * Overriden method.
+ */
+ bool isValid( QString& msg );
+
+private:
+ QButtonGroup * m_pFilterBG;
+ QGroupBox * m_pSelectGB;
+ QListBox * m_pSelectLB;
+ QRadioButton * m_pAllRB, * m_pCurrentRB, * m_pSelectRB, * m_pTypeRB;
+ QComboBox * m_pTypeCB;
+
+ UMLDoc * m_pDoc;
+ Uml::Diagram_Type m_ViewType;
+
+ /**
+ * list containing the IDs of diagrams to print
+ */
+ QValueList<Uml::IDType> m_nIdList;
+
+ enum FilterType{Current = 0, All, Select, Type};
+public slots:
+
+ /**
+ * Gets called when the users chooses to print all diagrams, the current
+ * diagram, a selection of diagrams or diagrams by type. It will change the
+ * listed diagrams in the diagram box.
+ */
+ void slotClicked(int id);
+
+ /**
+ * Gets called when the user chooses another diagram type. Only diagrams of
+ * this type will be shown in the diagram box.
+ */
+ void slotActivated(const QString & text);
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/diagrampropertiespage.ui b/umbrello/umbrello/dialogs/diagrampropertiespage.ui
new file mode 100644
index 00000000..8a8d2826
--- /dev/null
+++ b/umbrello/umbrello/dialogs/diagrampropertiespage.ui
@@ -0,0 +1,410 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>DiagramPropertiesPage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DiagramPropertiesPage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>388</width>
+ <height>388</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Diagram Properties</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>diagramName</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout20</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Zoom:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>zoom</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxValue">
+ <number>500</number>
+ </property>
+ <property name="minValue">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>%</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>50</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showOpSigs</cstring>
+ </property>
+ <property name="text">
+ <string>Show operation signature</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showGrid</cstring>
+ </property>
+ <property name="text">
+ <string>Show &amp;grid</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>snapToGrid</cstring>
+ </property>
+ <property name="text">
+ <string>Snap &amp;to grid</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>snapComponentSizeToGrid</cstring>
+ </property>
+ <property name="text">
+ <string>Snap component size</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Snap the size of the components to be a multiple of the grid spacing.
+If 'Snap to Grid' is enabled a component will always be aligned with the grid on all 4 sides.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Grid spacing: </string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabelX</cstring>
+ </property>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>gridSpaceX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>5</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>gridSpaceY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>5</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabe15</cstring>
+ </property>
+ <property name="text">
+ <string>Line width: </string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>lineWidth</cstring>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Documentation</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTextEdit" row="0" column="0">
+ <property name="name">
+ <cstring>documentation</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/dialogs/exportallviewsdialog.cpp b/umbrello/umbrello/dialogs/exportallviewsdialog.cpp
new file mode 100644
index 00000000..9f47afa5
--- /dev/null
+++ b/umbrello/umbrello/dialogs/exportallviewsdialog.cpp
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "exportallviewsdialog.h"
+
+// include files for Qt
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+
+// kde include files
+#include <kfilefiltercombo.h>
+#include <klocale.h>
+
+// application specific includes
+#include "../umlviewimageexportermodel.h"
+
+ExportAllViewsDialog::ExportAllViewsDialog(
+ QWidget* parent /* = 0 */,
+ const char* name /* = 0 */,
+ bool modal /* = false */,
+ WFlags fl /* = 0*/,
+ const QString &defaultMimeType /*= "image/png"*/)
+ : ExportAllViewsDialogBase(parent,name, modal,fl) {
+ // create and initialize m_imageType
+ m_imageType = new KFileFilterCombo(this, "m_imageType");
+ m_imageType->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed, 0, 0, m_imageType->sizePolicy().hasHeightForWidth()));
+ m_imageType->setEditable(false);
+
+ m_imageType->setMimeFilter(UMLViewImageExporterModel::supportedMimeTypes(), defaultMimeType);
+
+ imageTypeLayout->addWidget(m_imageType);
+
+ imageTypeLabel->setBuddy(m_imageType);
+
+ // reload the strings so the m_imageType tooltip is added
+ languageChange();
+}
+
+void ExportAllViewsDialog::languageChange() {
+ ExportAllViewsDialogBase::languageChange();
+ QToolTip::add(m_imageType, tr2i18n("The format that the images will be exported to"));
+}
+
+#include "exportallviewsdialog.moc"
+
diff --git a/umbrello/umbrello/dialogs/exportallviewsdialog.h b/umbrello/umbrello/dialogs/exportallviewsdialog.h
new file mode 100644
index 00000000..37b0a2f3
--- /dev/null
+++ b/umbrello/umbrello/dialogs/exportallviewsdialog.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef EXPORTALLVIEWSDIALOG_H
+#define EXPORTALLVIEWSDIALOG_H
+
+// application specific includes
+#include "exportallviewsdialogbase.h"
+
+// KDE forward declarations
+class KFileFilterCombo;
+
+/**
+ * Dialog for collecting the "Export all views" params.
+ * Inherits ExportAllViewsDialogBase and adds a KFileFilterCombo that uses
+ * only the mime types of the supported images types.
+ *
+ * The KFileFilterCombo is declared here instead of in the .ui file because QT
+ * Designer and uic don't recognize it.
+ */
+class ExportAllViewsDialog : public ExportAllViewsDialogBase {
+ Q_OBJECT
+
+public:
+
+ /**
+ * Constructor for UMLViewImageExporterModel.
+ *
+ * @param parent The parent of the dialog.
+ * @param name The internal name.
+ * @param modal If modal is true the dialog will block input to other the windows
+ * in the application until it's closed.
+ * @param fl Window flags.
+ * @param defaultMimeType The default mime type that appears in the mime types list.
+ *
+ * @see QDialog::QDialog
+ */
+ explicit ExportAllViewsDialog(QWidget* parent = 0, const char* name = 0,
+ bool modal = false, WFlags fl = 0,
+ const QString& defaultMimeType = "image/png");
+
+ /**
+ * Destructor for UMLViewImageExporterModel.
+ */
+ ~ExportAllViewsDialog() {
+ }
+
+ /**
+ * The image type selected.
+ */
+ KFileFilterCombo* m_imageType;
+
+protected slots:
+
+ /**
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+ virtual void languageChange();
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/dialogs/exportallviewsdialogbase.ui b/umbrello/umbrello/dialogs/exportallviewsdialogbase.ui
new file mode 100644
index 00000000..c82820a3
--- /dev/null
+++ b/umbrello/umbrello/dialogs/exportallviewsdialogbase.ui
@@ -0,0 +1,216 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ExportAllViewsDialogBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>ExportAllViewsDialogBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>366</width>
+ <height>197</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Export all views</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>mainLayout</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>15</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>kURLRequesterLayout</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>kURLRequesterLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Directory to save the diagrams in:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_kURL</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The base directory used to save the images</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>m_kURL</cstring>
+ </property>
+ <property name="mode">
+ <number>2</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The base directory used to save the images</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>imageTypeLayout</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>imageTypeLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Image type:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_imageType</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>The format that the images will be exported to</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_useFolders</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;folders</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Create in the target directory the same tree structure used
+in the document to store the views</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The views are stored in folders in the document. The same tree structure used in the document to store the views can be created in the selected base directory with this option.
+Only the folders made by the user are created in the base directory (Logical view, use case view and so on aren't created).</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>buttonsLayout</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>ExportAllViewsDialogBase</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>ExportAllViewsDialogBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/umbrello/umbrello/dialogs/notedialog.cpp b/umbrello/umbrello/dialogs/notedialog.cpp
new file mode 100644
index 00000000..f310990d
--- /dev/null
+++ b/umbrello/umbrello/dialogs/notedialog.cpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "notedialog.h"
+
+// qt/kde includes
+#include <qlineedit.h>
+#include <qgroupbox.h>
+#include <qtextedit.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+NoteDialog::NoteDialog( QWidget * parent, NoteWidget * pNote ) : KDialogBase(Plain, i18n("Note Documentation"), Help | Ok | Cancel , Ok, parent, "_NOTEDIALOG_", true, true) {
+ m_pNoteWidget = pNote;
+ int margin = fontMetrics().height();
+
+ m_pDocGB = new QGroupBox(i18n("Documentation"), plainPage());
+ QVBoxLayout * mainLayout = new QVBoxLayout(plainPage());
+ mainLayout -> addWidget(m_pDocGB);
+ mainLayout -> setSpacing(10);
+ mainLayout -> setMargin(margin);
+
+ QHBoxLayout * docLayout = new QHBoxLayout(m_pDocGB);
+ docLayout -> setSpacing(10);
+ docLayout -> setMargin(margin);
+
+ m_pDocTE = new QTextEdit( m_pDocGB );
+ m_pDocTE -> setFocus();
+ docLayout -> addWidget( m_pDocTE );
+ m_pDocTE -> setText( pNote -> getDoc() );
+ setMinimumSize(330, 160);
+}
+
+NoteDialog::~NoteDialog() {}
+
+void NoteDialog::slotOk() {
+ m_pNoteWidget -> setDoc( m_pDocTE -> text() );
+ accept();
+}
+
+#include "notedialog.moc"
diff --git a/umbrello/umbrello/dialogs/notedialog.h b/umbrello/umbrello/dialogs/notedialog.h
new file mode 100644
index 00000000..3efd1404
--- /dev/null
+++ b/umbrello/umbrello/dialogs/notedialog.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NOTEDIALOG_H
+#define NOTEDIALOG_H
+//kde includes
+#include <kdialogbase.h>
+//app includes
+#include "../notewidget.h"
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class QGroupBox;
+class QLineEdit;
+class QTextEdit;
+
+class NoteDialog : public KDialogBase {
+
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs an NoteDialog.
+ */
+ NoteDialog( QWidget * parent, NoteWidget * pNote );
+
+ /**
+ * Standard deconstructor.
+ */
+ ~NoteDialog();
+
+public slots:
+ void slotOk();
+private:
+ //GUI widgets
+ QGroupBox * m_pDocGB;
+ QTextEdit * m_pDocTE;
+
+ /**
+ * Note widget to show documentation for.
+ */
+ NoteWidget * m_pNoteWidget;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/overwritedialogue.cpp b/umbrello/umbrello/dialogs/overwritedialogue.cpp
new file mode 100644
index 00000000..b7c4a4f4
--- /dev/null
+++ b/umbrello/umbrello/dialogs/overwritedialogue.cpp
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "overwritedialogue.h"
+
+// qt/kde includes
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+
+OverwriteDialogue::OverwriteDialogue(
+ const QString& fileName,
+ const QString& outputDirectory,
+ bool applyToAllRemaining, QWidget* parent, const char* name) :
+KDialogBase(Plain, i18n("Destination File Already Exists"), Ok|Apply|Cancel, Yes, parent, name) {
+
+ QVBoxLayout* layout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+
+ QLabel* dialogueLabel = new QLabel(i18n("The file %1 already exists in %2.\n\nUmbrello can overwrite the file, generate a similar\nfile name or not generate this file.").arg(fileName).arg(outputDirectory), plainPage() );
+ layout->addWidget(dialogueLabel);
+
+ m_applyToAllRemaining = new QCheckBox( i18n("&Apply to all remaining files"), plainPage() );
+ m_applyToAllRemaining->setChecked(applyToAllRemaining);
+ layout->addWidget(m_applyToAllRemaining);
+
+ setButtonText(KDialogBase::Ok, i18n("&Overwrite"));
+ setButtonText(KDialogBase::Apply, i18n("&Generate Similar File Name"));
+ setButtonText(KDialogBase::Cancel, i18n("&Do Not Generate File"));
+}
+
+OverwriteDialogue::~OverwriteDialogue() {
+}
+
+void OverwriteDialogue::slotOk() {
+ done(Yes);
+}
+
+void OverwriteDialogue::slotApply() {
+ done(No);
+}
+
+void OverwriteDialogue::slotCancel() {
+ done(Cancel);
+}
+
+bool OverwriteDialogue::applyToAllRemaining() {
+ return m_applyToAllRemaining->isChecked();
+}
+
+#include "overwritedialogue.moc"
diff --git a/umbrello/umbrello/dialogs/overwritedialogue.h b/umbrello/umbrello/dialogs/overwritedialogue.h
new file mode 100644
index 00000000..a01e3366
--- /dev/null
+++ b/umbrello/umbrello/dialogs/overwritedialogue.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OVERWRITEDIALOGUE_H
+#define OVERWRITEDIALOGUE_H
+
+#include <kdialogbase.h>
+
+class QCheckBox;
+
+/**
+ * Used by CodeGenerator::findFileName when it needs to ask
+ * the user if they want to overwrite and existing file, generate a similar name
+ * or cancel. Gives an option to apply the choice to all remaining files.
+ *
+ * Uses OK and Apply buttons but overrides their text and behaviour, probably
+ * better to use user defined buttons but I couldn't work out how. KDialogBase guru needed.
+ *
+ * @author Jonathan Riddell <jr@jriddell.org>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class OverwriteDialogue: public KDialogBase {
+ Q_OBJECT
+
+public:
+ /**
+ * constructor sets up the dialog, adding checkbox and label
+ */
+ OverwriteDialogue(const QString& fileName, const QString& outputDirectory,
+ bool applyToAllRemaining, QWidget* parent=0, const char* name=0);
+
+ /**
+ * destrictor doesn't do anything
+ */
+ ~OverwriteDialogue();
+
+ /**
+ * @return the value of the Apply To All Remaining Files checkbox
+ */
+ bool applyToAllRemaining();
+
+protected slots:
+ /**
+ * Overrides standard operation to call QDialog::done(Yes).
+ * This is a kludge, see note in class description.
+ */
+ virtual void slotOk();
+
+ /**
+ * Overrides standard operation to call QDialog::done(No).
+ */
+ virtual void slotApply();
+
+
+ /**
+ * Overrides standard operation to call QDialog::done(Cancel).
+ */
+ virtual void slotCancel();
+
+private:
+ QCheckBox* m_applyToAllRemaining;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/parmpropdlg.cpp b/umbrello/umbrello/dialogs/parmpropdlg.cpp
new file mode 100644
index 00000000..e8ddc245
--- /dev/null
+++ b/umbrello/umbrello/dialogs/parmpropdlg.cpp
@@ -0,0 +1,257 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "parmpropdlg.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qtooltip.h>
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+
+// local includes
+#include "../classifier.h"
+#include "../umltemplatelist.h"
+#include "../template.h"
+#include "../umldoc.h"
+#include "../dialog_utils.h"
+#include "../object_factory.h"
+#include "../stereotype.h"
+
+#include "parmpropdlg.moc"
+
+ParmPropDlg::ParmPropDlg(QWidget * parent, UMLDoc * doc, UMLAttribute * a)
+ : KDialogBase(Plain, i18n("Parameter Properties"), Help | Ok | Cancel , Ok, parent, "_PARMPROPDLG_", true, true)
+{
+ m_pUmldoc = doc;
+ m_pAtt = a;
+ QString type, text, name, initialValue;
+ if(!a) {
+ type = text = name = initialValue = "";
+ } else {
+ type = a -> getTypeName();
+ name = a -> getName();
+ initialValue = a -> getInitialValue();
+ text = a -> getDoc();
+ }
+ int margin = fontMetrics().height();
+ setMinimumSize(300, 400);
+ //disableResize();
+ QVBoxLayout * topLayout = new QVBoxLayout(plainPage());
+ topLayout -> setSpacing(10);
+ topLayout -> setMargin(margin);
+
+ m_pParmGB = new QGroupBox(i18n("Properties"), plainPage());
+ topLayout -> addWidget(m_pParmGB);
+
+ QGridLayout * propLayout = new QGridLayout(m_pParmGB, 4, 2);
+ propLayout -> setSpacing(10);
+ propLayout -> setMargin(margin);
+
+ m_pTypeL = new QLabel(i18n("&Type:"), m_pParmGB);
+ propLayout -> addWidget(m_pTypeL, 0, 0);
+
+ m_pTypeCB = new KComboBox(m_pParmGB);
+ propLayout -> addWidget(m_pTypeCB, 0, 1);
+ m_pTypeL->setBuddy(m_pTypeCB);
+
+ Dialog_Utils::makeLabeledEditField( m_pParmGB, propLayout, 1,
+ m_pNameL, i18n("&Name:"),
+ m_pNameLE, name );
+
+ Dialog_Utils::makeLabeledEditField( m_pParmGB, propLayout, 2,
+ m_pInitialL, i18n("&Initial value:"),
+ m_pInitialLE, initialValue );
+
+ m_pStereoTypeL = new QLabel( i18n("Stereotype name:"), m_pParmGB );
+ propLayout -> addWidget(m_pStereoTypeL, 3, 0);
+ m_pStereoTypeCB = new KComboBox(true, m_pParmGB );
+ propLayout -> addWidget(m_pStereoTypeCB, 3, 1);
+
+ m_pKind = new QButtonGroup(i18n("Passing Direction"), plainPage());
+ m_pKind->setExclusive(true);
+ QToolTip::add(m_pKind, i18n("\"in\" is a readonly parameter, \"out\" is a writeonly parameter and \"inout\" is a parameter for reading and writing."));
+
+ QHBoxLayout * kindLayout = new QHBoxLayout( m_pKind );
+ kindLayout->setMargin(margin);
+
+ m_pIn = new QRadioButton( "in", m_pKind );
+ kindLayout->addWidget( m_pIn );
+
+ m_pInOut = new QRadioButton( "inout", m_pKind );
+ kindLayout->addWidget( m_pInOut );
+
+ m_pOut = new QRadioButton( "out", m_pKind );
+ kindLayout->addWidget( m_pOut );
+
+ topLayout -> addWidget(m_pKind);
+
+ m_pDocGB = new QGroupBox(i18n("Documentation"), plainPage());
+ QHBoxLayout * docLayout = new QHBoxLayout(m_pDocGB);
+ docLayout -> setMargin(margin);
+
+ m_pDoc = new QMultiLineEdit(m_pDocGB);
+ ///////////
+ m_pDoc->setWordWrap(QMultiLineEdit::WidgetWidth);
+ //////////
+ m_pDoc -> setText(text);
+ docLayout -> addWidget(m_pDoc);
+ topLayout -> addWidget(m_pDocGB);
+
+ // Check the proper Kind radiobutton.
+ if (a) {
+ Uml::Parameter_Direction kind = a->getParmKind();
+ if (kind == Uml::pd_Out)
+ m_pOut->setChecked(true);
+ else if (kind == Uml::pd_InOut)
+ m_pInOut->setChecked(true);
+ else
+ m_pIn->setChecked(true);
+ } else
+ m_pIn->setChecked(true);
+
+ m_pTypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pTypeCB->setEditable(true);
+ m_pTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+// m_pTypeCB->setAutoCompletion(false);
+
+ //add template parameters
+ UMLClassifier *pConcept = dynamic_cast<UMLClassifier*>( m_pAtt->parent()->parent() );
+ if (pConcept == NULL) {
+ kError() << "ParmPropDlg: grandparent of " << m_pAtt->getName()
+ << " is not a UMLClassifier" << endl;
+ } else {
+ UMLTemplateList tmplParams( pConcept->getTemplateList() );
+ for (UMLTemplate *t = tmplParams.first(); t; t = tmplParams.next())
+ insertType( t->getName() );
+ }
+ //now add the Concepts
+ UMLClassifierList namesList( m_pUmldoc->getConcepts() );
+ UMLClassifier * obj;
+ for(obj=namesList.first(); obj!=0 ;obj=namesList.next()) {
+ insertType( obj->getFullyQualifiedName() );
+ }
+
+ //work out which one to select
+ int typeBoxCount = 0;
+ bool foundType = false;
+ while (typeBoxCount < m_pTypeCB->count() && foundType == false) {
+ QString typeBoxString = m_pTypeCB->text(typeBoxCount);
+ if ( typeBoxString == type ) { //getTypeName()
+ foundType = true;
+ m_pTypeCB->setCurrentItem(typeBoxCount);
+ } else {
+ typeBoxCount++;
+ }
+ }
+
+ if (!foundType) {
+ insertType( type, 0 );
+ m_pTypeCB->setCurrentItem(0);
+ }
+
+ // manage stereotypes
+ m_pStereoTypeCB->setDuplicatesEnabled(false); //only allow one of each type in box
+ m_pStereoTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ insertStereotype (QString("")); // an empty stereotype is the default
+ int defaultStereotype=0;
+ bool foundDefaultStereotype = false;
+ for (UMLStereotypeListIt it(m_pUmldoc->getStereotypes()); it.current(); ++it) {
+ if (!foundDefaultStereotype) {
+ if ( m_pAtt->getStereotype() == it.current()->getName()) {
+ foundDefaultStereotype = true;
+ }
+ defaultStereotype++;
+ }
+ insertStereotype (it.current()->getName());
+ }
+ // lookup for a default stereotype, if the operation doesn't have one
+ if (foundDefaultStereotype)
+ m_pStereoTypeCB->setCurrentItem(defaultStereotype);
+ else
+ m_pStereoTypeCB->setCurrentItem(-1);
+
+ // set tab order
+ setTabOrder(m_pKind, m_pTypeCB);
+ setTabOrder(m_pTypeCB, m_pNameLE);
+ setTabOrder(m_pNameLE, m_pInitialLE);
+ setTabOrder(m_pInitialLE, m_pStereoTypeCB);
+ setTabOrder(m_pStereoTypeCB, m_pIn);
+ setTabOrder(m_pIn, m_pDoc);
+
+ m_pNameLE->setFocus();
+}
+
+void ParmPropDlg::insertType( const QString& type, int index )
+{
+ m_pTypeCB->insertItem( type, index );
+ m_pTypeCB->completionObject()->addItem( type );
+}
+
+void ParmPropDlg::insertStereotype( const QString& type, int index )
+{
+ m_pStereoTypeCB->insertItem( type, index );
+ m_pStereoTypeCB->completionObject()->addItem( type );
+}
+
+Uml::Parameter_Direction ParmPropDlg::getParmKind() {
+ Uml::Parameter_Direction pk = Uml::pd_In;
+ if (m_pOut->isChecked())
+ pk = Uml::pd_Out;
+ else if (m_pInOut->isChecked())
+ pk = Uml::pd_InOut;
+ return pk;
+}
+
+void ParmPropDlg::slotOk() {
+ if (m_pAtt != NULL) {
+ m_pAtt->setParmKind( getParmKind() );
+ m_pAtt->setStereotype( m_pStereoTypeCB->currentText() );
+ QString typeName = m_pTypeCB->currentText();
+ UMLClassifier * pConcept = dynamic_cast<UMLClassifier*>( m_pAtt->parent()->parent() );
+ if (pConcept == NULL) {
+ kError() << "ParmPropDlg::slotOk: grandparent of " << m_pAtt->getName()
+ << " is not a UMLClassifier" << endl;
+ } else {
+ UMLTemplate *tmplParam = pConcept->findTemplate(typeName);
+ if (tmplParam) {
+ m_pAtt->setType(tmplParam);
+ accept();
+ return;
+ }
+ }
+ UMLClassifierList namesList( m_pUmldoc->getConcepts() );
+ UMLClassifier * obj;
+ for (obj = namesList.first(); obj; obj = namesList.next()) {
+ if (obj->getFullyQualifiedName() == typeName) {
+ m_pAtt->setType( obj );
+ break;
+ }
+ }
+ if (obj == NULL) {
+ // Nothing found: Create a new type on the fly.
+ // @todo There should be an extra dialog to decide whether to
+ // create a datatype or a class. For now, we create a class.
+ kDebug() << "ParmPropDlg::slotOk: " << typeName << " not found."
+ << " Creating a new class for the type." << endl;
+ UMLObject *o = Object_Factory::createUMLObject(Uml::ot_Class, typeName);
+ m_pAtt->setType(o);
+ }
+
+ }
+ accept();
+}
+
+ParmPropDlg::~ParmPropDlg() {}
+
diff --git a/umbrello/umbrello/dialogs/parmpropdlg.h b/umbrello/umbrello/dialogs/parmpropdlg.h
new file mode 100644
index 00000000..25a6153a
--- /dev/null
+++ b/umbrello/umbrello/dialogs/parmpropdlg.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PARMPROPDLG_H
+#define PARMPROPDLG_H
+
+#include <kdialogbase.h>
+#include <kcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qlineedit.h>
+#include <qbuttongroup.h>
+#include <qmultilineedit.h>
+#include <qcombobox.h>
+#include "../attribute.h"
+
+class UMLDoc;
+
+/**
+ * Displays a dialog box that displays properties of a paramater.
+ * You need to make sure that @ref UMLDoc is made to be the
+ * parent.
+ *
+ * @short A properties dialog box for a parameter.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ParmPropDlg : public KDialogBase {
+ Q_OBJECT
+public:
+ /**
+ * Constructs a ParmPropDlg.
+ *
+ * @param parent The parent of the dialog.
+ * @param a The parameter to represent.
+ */
+ ParmPropDlg(QWidget * parent, UMLDoc * doc, UMLAttribute * a);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~ParmPropDlg();
+
+ /**
+ * Returns the documentation.
+ *
+ * @return Returns the documentation.
+ */
+ QString getDoc() {
+ return m_pDoc -> text();
+ }
+
+ /**
+ * Return the name of the parameter.
+ *
+ * @return Return the name of the parameter.
+ */
+ QString getName() {
+ return m_pNameLE -> text();
+ }
+
+ /**
+ * Return the initial value of the parameter.
+ *
+ * @return Return the initial value of the parameter.
+ */
+ QString getInitialValue() {
+ return m_pInitialLE -> text();
+ }
+
+ /**
+ * Return the type name of the parameter.
+ *
+ * @return Return the type name of the parameter.
+ */
+ QString getTypeName() {
+ return m_pTypeCB -> currentText();
+ }
+
+ /**
+ * Return the kind of the parameter (in, out, or inout).
+ *
+ * @return The Uml::Parameter_Direction corresponding to
+ * the selected "Kind" radiobutton.
+ */
+ Uml::Parameter_Direction getParmKind();
+
+public slots:
+ void slotOk();
+
+protected:
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertType( const QString& type, int index = -1 );
+
+ /**
+ * Inserts @p type into the stereotype-combobox as well as its completion object.
+ */
+ void insertStereotype( const QString& type, int index = -1 );
+
+
+private:
+ QGroupBox * m_pParmGB, * m_pDocGB;
+ QButtonGroup *m_pKind;
+ QRadioButton * m_pIn, * m_pOut, *m_pInOut;
+ QLabel * m_pTypeL, * m_pNameL, * m_pInitialL, * m_pStereoTypeL;
+ KComboBox * m_pTypeCB, * m_pStereoTypeCB;
+ QLineEdit * m_pNameLE, * m_pInitialLE;
+ QMultiLineEdit * m_pDoc;
+ UMLDoc * m_pUmldoc;
+ UMLAttribute * m_pAtt;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/pkgcontentspage.cpp b/umbrello/umbrello/dialogs/pkgcontentspage.cpp
new file mode 100644
index 00000000..dd70f7fc
--- /dev/null
+++ b/umbrello/umbrello/dialogs/pkgcontentspage.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "pkgcontentspage.h"
+#include <qlayout.h>
+#include <klocale.h>
+#include "../umlobjectlist.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "classpropdlg.h"
+
+PkgContentsPage::PkgContentsPage(QWidget *parent, UMLPackage *pkg)
+ : QWidget(parent)
+{
+ m_pPackage = pkg;
+ int margin = fontMetrics().height();
+
+ QHBoxLayout * mainLayout = new QHBoxLayout(this);
+ mainLayout -> setSpacing(10);
+
+ m_pContentGB = new QGroupBox(i18n("Contained Items"), this);
+ mainLayout -> addWidget(m_pContentGB);
+
+ QHBoxLayout * layout = new QHBoxLayout(m_pContentGB);
+ layout -> setSpacing(10);
+ layout -> setMargin(margin);
+
+ m_pContentLB = new QListBox(m_pContentGB);
+ layout -> addWidget(m_pContentLB);
+ setMinimumSize(310, 330);
+ fillListBox();
+ m_pMenu = 0;
+
+ connect(m_pContentLB, SIGNAL(doubleClicked(QListBoxItem *)),
+ this, SLOT(slotDoubleClick(QListBoxItem *)));
+
+ connect(m_pContentLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ connect(m_pContentLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem *, const QPoint &)));
+}
+
+PkgContentsPage::~PkgContentsPage() {
+ disconnect(m_pContentLB, SIGNAL(doubleClicked(QListBoxItem *)),
+ this, SLOT(slotDoubleClick(QListBoxItem *)));
+
+ disconnect(m_pContentLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ disconnect(m_pContentLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotRightButtonClicked(QListBoxItem *, const QPoint &)));
+}
+
+void PkgContentsPage::slotDoubleClick(QListBoxItem * i) {
+ if (!i)
+ return;
+ int item = m_pContentLB -> currentItem();
+ UMLObjectList contents = m_pPackage->containedObjects();
+ UMLObject *o = contents.at(item);
+ ClassPropDlg dlg(this, o, item, true);
+ dlg.exec();
+}
+
+void PkgContentsPage::fillListBox() {
+ m_pContentLB->clear();
+ UMLObjectList contents = m_pPackage->containedObjects();
+ UMLObjectListIt objList_it(contents);
+ UMLObject* umlo = NULL;
+ int i = 0;
+ while ((umlo = objList_it.current()) != NULL) {
+ m_pContentLB->insertItem(umlo->getName(), i++);
+ ++objList_it;
+ }
+}
+
+void PkgContentsPage::slotRightButtonClicked(QListBoxItem */* item*/, const QPoint &/* p*/) {
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void PkgContentsPage::slotRightButtonPressed(QListBoxItem * item, const QPoint & p) {
+ if(!item)
+ return;
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ m_pMenu = new ListPopupMenu(this, ListPopupMenu::mt_Association_Selected);
+ m_pMenu->popup(p);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotPopupMenuSel(int)));
+}
+
+void PkgContentsPage::slotPopupMenuSel(int id) {
+ switch(id) {
+ case ListPopupMenu::mt_Delete:
+ {
+ UMLObjectList contents = m_pPackage->containedObjects();
+ UMLObject *o = contents.at( m_pContentLB->currentItem() );
+ UMLApp::app()->getDocument()->removeUMLObject(o);
+ fillListBox();
+ }
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ slotDoubleClick(m_pContentLB->item(m_pContentLB->currentItem()));
+ break;
+ }
+}
+
+
+
+#include "pkgcontentspage.moc"
diff --git a/umbrello/umbrello/dialogs/pkgcontentspage.h b/umbrello/umbrello/dialogs/pkgcontentspage.h
new file mode 100644
index 00000000..8659e672
--- /dev/null
+++ b/umbrello/umbrello/dialogs/pkgcontentspage.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PKGCONTENTSPAGE_H
+#define PKGCONTENTSPAGE_H
+
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qptrlist.h>
+
+#include "../package.h"
+#include "../listpopupmenu.h"
+
+/**
+ * @short The page shows all the objects that belong to a @ref UMLPackage.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PkgContentsPage : public QWidget {
+ Q_OBJECT
+public:
+ /**
+ * Constructs an instance of PkgContentsPage.
+ *
+ * @param parent The parent of the page.
+ * @param pkg The UMLPackage being represented.
+ */
+ PkgContentsPage(QWidget *parent, UMLPackage *pkg);
+
+ /**
+ * Standard destructor.
+ */
+ ~PkgContentsPage();
+
+private:
+ UMLPackage * m_pPackage;
+ QListBox * m_pContentLB;
+ QGroupBox * m_pContentGB;
+ ListPopupMenu * m_pMenu;
+
+ /**
+ * Fills the list box with the package's contents.
+ */
+ void fillListBox();
+
+public slots:
+ void slotDoubleClick(QListBoxItem * i);
+ void slotRightButtonClicked(QListBoxItem */* item*/, const QPoint &/* p*/);
+ void slotRightButtonPressed(QListBoxItem * item, const QPoint & p);
+ void slotPopupMenuSel(int id);
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/selectopdlg.cpp b/umbrello/umbrello/dialogs/selectopdlg.cpp
new file mode 100644
index 00000000..cb9e344d
--- /dev/null
+++ b/umbrello/umbrello/dialogs/selectopdlg.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "selectopdlg.h"
+
+// qt includes
+#include <qlayout.h>
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+
+// local includes
+#include "../attribute.h"
+#include "../operation.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../umlview.h"
+#include "../dialog_utils.h"
+
+SelectOpDlg::SelectOpDlg(UMLView * parent, UMLClassifier * c)
+ : KDialogBase(Plain, i18n("Select Operation"), Ok | Cancel , Ok, parent, "_SELOPDLG_", true, true)
+{
+ m_pView = parent;
+ QVBoxLayout * topLayout = new QVBoxLayout(plainPage());
+
+ m_pOpGB = new QGroupBox(i18n("Select Operation"), plainPage());
+ topLayout -> addWidget(m_pOpGB);
+
+ QGridLayout * mainLayout = new QGridLayout(m_pOpGB, 3, 2);
+ mainLayout -> setSpacing(spacingHint());
+ mainLayout -> setMargin(fontMetrics().height());
+
+ Dialog_Utils::makeLabeledEditField( m_pOpGB, mainLayout, 0,
+ m_pSeqL, i18n("Sequence number:"),
+ m_pSeqLE );
+
+ m_pOpRB = new QRadioButton(i18n("Class operation:"), m_pOpGB);
+ mainLayout -> addWidget(m_pOpRB, 1, 0);
+
+ m_pOpCB = new KComboBox(m_pOpGB);
+ m_pOpCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ m_pOpCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ mainLayout -> addWidget(m_pOpCB, 1, 1);
+
+ m_pCustomRB = new QRadioButton(i18n("Custom operation:"), m_pOpGB);
+ mainLayout -> addWidget(m_pCustomRB, 2, 0);
+
+ m_pOpLE = new QLineEdit(m_pOpGB);
+ mainLayout -> addWidget(m_pOpLE, 2, 1);
+
+ m_pOpBG = new QButtonGroup(0);
+ m_pOpBG -> insert(m_pOpRB, OP);
+ m_pOpBG -> insert(m_pCustomRB, CUSTOM);
+ m_pOpBG -> setExclusive(true);
+ m_pOpBG -> setButton(OP);
+
+ UMLOperationList list = c -> getOpList(true);
+ for (UMLOperation *obj = list.first(); obj; obj=list.next()) {
+ insertOperation( obj->toString(Uml::st_SigNoVis) );
+ }
+ //disableResize();
+ connect(m_pOpBG, SIGNAL(clicked(int)), this, SLOT(slotSelected(int)));
+ m_nOpCount = c -> operations();
+ slotSelected(OP);
+}
+
+SelectOpDlg::~SelectOpDlg() {
+ disconnect(m_pOpBG, SIGNAL(clicked(int)), this, SLOT(slotSelected(int)));
+ delete m_pOpBG;
+}
+
+void SelectOpDlg::insertOperation( const QString& type, int index )
+{
+ m_pOpCB->insertItem( type, index );
+ m_pOpCB->completionObject()->addItem( type );
+}
+
+QString SelectOpDlg::getOpText() {
+ if(m_pOpRB -> isChecked())
+ return m_pOpCB -> currentText();
+ else
+ return m_pOpLE -> text();
+}
+
+bool SelectOpDlg::isClassOp() const {
+ return (m_id == OP);
+}
+
+void SelectOpDlg::slotSelected(int id) {
+ if(id == OP) {
+ m_pOpLE -> setEnabled(false);
+ if(m_nOpCount > 0)
+ m_pOpCB -> setEnabled(true);
+ } else {
+ m_pOpLE -> setEnabled(true);
+ m_pOpCB -> setEnabled(false);
+ }
+ m_id = id;
+}
+
+void SelectOpDlg::setCustomOp(const QString &op) {
+ m_pOpLE -> setText(op);
+ if(op.length() > 0) {
+ slotSelected(CUSTOM);
+ m_pCustomRB -> setChecked(true);
+ }
+}
+
+bool SelectOpDlg::setClassOp(const QString &op) {
+ for (int i = 1; i!= m_pOpCB->count(); ++i)
+ {
+ if ( m_pOpCB->text(i) == op ) {
+ m_pOpCB->setCurrentItem(i);
+ m_pCustomRB -> setChecked(false);
+ slotSelected(OP);
+ return true;
+ }
+ }
+ return false;
+}
+
+QString SelectOpDlg::getSeqNumber() {
+ return m_pSeqLE->text();
+}
+
+void SelectOpDlg::setSeqNumber(const QString &num) {
+ m_pSeqLE->setText(num);
+}
+
+
+
+#include "selectopdlg.moc"
diff --git a/umbrello/umbrello/dialogs/selectopdlg.h b/umbrello/umbrello/dialogs/selectopdlg.h
new file mode 100644
index 00000000..c5d8c93b
--- /dev/null
+++ b/umbrello/umbrello/dialogs/selectopdlg.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef SELECTOPDLG_H
+#define SELECTOPDLG_H
+
+#include <kdialogbase.h>
+
+#include <qgroupbox.h>
+#include <kcombobox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include "../classifier.h"
+
+class UMLView;
+
+#define OP 0
+#define CUSTOM 1
+
+/**
+ * A dialog used to select an operation.
+ *
+ * @short A dialog to select an operation.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class SelectOpDlg : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs a SelectOpDlg instance.
+ *
+ * @param parent The parent to this instance.
+ * @param c The concept to get the operations from.
+ */
+ SelectOpDlg(UMLView * parent, UMLClassifier * c);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~SelectOpDlg();
+
+ /**
+ * Returns the operation to display.
+ *
+ * @return The operation to display.
+ */
+ QString getOpText();
+
+ /**
+ * Return whether the user selected a class operation
+ * or a custom operation.
+ *
+ * @return True if user selected a class operation,
+ * false if user selected a custom operation
+ */
+ bool isClassOp() const;
+
+ /**
+ * Returns the sequence number for the operation.
+ *
+ * @return Returns the sequence number for the operation.
+ */
+ QString getSeqNumber();
+
+ /**
+ * Set the sequence number text.
+ *
+ * @param num The number to set the sequence to.
+ */
+ void setSeqNumber(const QString &num);
+
+ /**
+ * Set the custom operation text.
+ *
+ * @param op The operation to set as the custom operation.
+ */
+ void setCustomOp(const QString &op);
+ /**
+ * Set the class operation text.
+ *
+ * @param op The operation to set as the class operation.
+ * @return false if no such operation exists.
+ */
+ bool setClassOp(const QString &op);
+protected:
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertOperation( const QString& type, int index = -1 );
+private:
+ QGroupBox * m_pOpGB;
+ KComboBox * m_pOpCB;
+ QLabel * m_pSeqL;
+ QLineEdit * m_pOpLE, * m_pSeqLE;
+ QRadioButton * m_pCustomRB, * m_pOpRB;
+ QButtonGroup * m_pOpBG, * m_pDocGB;
+ QString m_Text;
+ int m_nOpCount;
+ int m_id; ///< takes on the value OP or CUSTOM according to what the user selected
+ UMLView *m_pView;
+public slots:
+ void slotSelected(int id);
+};
+
+#endif
+
diff --git a/umbrello/umbrello/dialogs/settingsdlg.cpp b/umbrello/umbrello/dialogs/settingsdlg.cpp
new file mode 100644
index 00000000..2bfaaf29
--- /dev/null
+++ b/umbrello/umbrello/dialogs/settingsdlg.cpp
@@ -0,0 +1,443 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "settingsdlg.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+// kde includes
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+// app includes
+#include "codegenerationoptionspage.h"
+#include "codevieweroptionspage.h"
+#include "../dialog_utils.h"
+
+SettingsDlg::SettingsDlg( QWidget * parent, Settings::OptionState *state )
+ : KDialogBase( IconList, i18n("Umbrello Setup"),
+ Help | Default | Apply | Ok | Cancel, Ok, parent, 0, true, true ) {
+ m_bChangesApplied = false;
+ m_pOptionState = state;
+ setHelp( "umbrello/index.html", QString::null );
+ setupGeneralPage();
+ setupFontPage();
+ setupUIPage();
+ setupClassPage();
+ setupCodeGenPage();
+ setupCodeViewerPage(state->codeViewerState);
+}
+
+SettingsDlg::~SettingsDlg() {}
+
+void SettingsDlg::setupUIPage() {
+ //setup UI page
+ QVBox * page = addVBoxPage( i18n("User Interface"), i18n("User Interface Settings"), DesktopIcon( "window_list") );
+
+ m_UiWidgets.colorGB = new QGroupBox( i18n("Color"), page );
+ QGridLayout * colorLayout = new QGridLayout( m_UiWidgets.colorGB, 3, 3 );
+ colorLayout -> setSpacing( spacingHint() );
+ colorLayout -> setMargin( fontMetrics().height() );
+
+ m_UiWidgets.lineColorL = new QLabel( i18n("Line color:"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineColorL, 0, 0 );
+
+ m_UiWidgets.lineColorB = new KColorButton( m_pOptionState->uiState.lineColor, m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineColorB, 0, 1 );
+
+ m_UiWidgets.lineDefaultB = new QPushButton( i18n("D&efault Color"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineDefaultB, 0, 2 );
+
+ m_UiWidgets.fillColorL = new QLabel( i18n("Fill color:"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.fillColorL, 1, 0 );
+
+ m_UiWidgets.fillColorB = new KColorButton( m_pOptionState->uiState.fillColor, m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.fillColorB, 1, 1 );
+
+ m_UiWidgets.fillDefaultB = new QPushButton( i18n("De&fault Color"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.fillDefaultB, 1, 2 );
+
+
+ m_UiWidgets.lineWidthL = new QLabel( i18n("Line width:"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineWidthL, 2, 0 );
+
+ // Low-Limit: 0, High-Limit: 10, Step: 1, Initial-Val: m_pOptionState->uiState.lineWidth
+ // Number-Base: 10 ( decimal ), Parent: m_UiWidgets.colorGB
+ m_UiWidgets.lineWidthB = new KIntSpinBox( 0, 10, 1, m_pOptionState->uiState.lineWidth, 10, m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineWidthB, 2, 1 );
+
+ m_UiWidgets.lineWidthDefaultB = new QPushButton( i18n("D&efault Width"), m_UiWidgets.colorGB );
+ colorLayout -> addWidget( m_UiWidgets.lineWidthDefaultB, 2, 2 );
+
+
+
+ m_UiWidgets.useFillColorCB = new QCheckBox( i18n("&Use fill color"), m_UiWidgets.colorGB );
+ colorLayout -> setRowStretch( 3, 2 );
+ colorLayout -> addWidget( m_UiWidgets.useFillColorCB, 3, 0 );
+ m_UiWidgets.useFillColorCB -> setChecked( m_pOptionState->uiState.useFillColor );
+
+ //connect button signals up
+ connect( m_UiWidgets.lineDefaultB, SIGNAL(clicked()), this, SLOT(slotLineBClicked()) );
+ connect( m_UiWidgets.fillDefaultB, SIGNAL(clicked()), this, SLOT(slotFillBClicked()) );
+}
+
+void SettingsDlg::setupGeneralPage() {
+ //setup General page
+
+ QVBox * page = addVBoxPage( i18n("General"), i18n("General Settings"), DesktopIcon( "misc") );
+
+ // Set up undo setting
+ m_GeneralWidgets.miscGB = new QGroupBox( i18n("Miscellaneous"), page );
+
+ QGridLayout * miscLayout = new QGridLayout( m_GeneralWidgets.miscGB, 2, 2 );
+ miscLayout -> setSpacing( spacingHint() );
+ miscLayout -> setMargin( fontMetrics().height() );
+
+ m_GeneralWidgets.undoCB = new QCheckBox( i18n("Enable undo"), m_GeneralWidgets.miscGB );
+ m_GeneralWidgets.undoCB -> setChecked( m_pOptionState->generalState.undo );
+ miscLayout -> addWidget( m_GeneralWidgets.undoCB, 0, 0 );
+
+ m_GeneralWidgets.tabdiagramsCB = new QCheckBox( i18n("Use tabbed diagrams"), m_GeneralWidgets.miscGB );
+ m_GeneralWidgets.tabdiagramsCB -> setChecked( m_pOptionState->generalState.tabdiagrams );
+ miscLayout -> addWidget( m_GeneralWidgets.tabdiagramsCB, 0, 1 );
+
+ m_GeneralWidgets.newcodegenCB = new QCheckBox( i18n("Use new C++/Java/Ruby generators"), m_GeneralWidgets.miscGB );
+ m_GeneralWidgets.newcodegenCB -> setChecked( m_pOptionState->generalState.newcodegen );
+ miscLayout -> addWidget( m_GeneralWidgets.newcodegenCB, 1, 0 );
+
+ m_GeneralWidgets.angularLinesCB = new QCheckBox( i18n("Use angular association lines"), m_GeneralWidgets.miscGB );
+ m_GeneralWidgets.angularLinesCB -> setChecked( m_pOptionState->generalState.angularlines );
+ miscLayout -> addWidget( m_GeneralWidgets.angularLinesCB, 1, 1 );
+
+ //setup autosave settings
+
+ m_GeneralWidgets.autosaveGB = new QGroupBox( i18n("Autosave"), page );
+
+ QGridLayout * autosaveLayout = new QGridLayout( m_GeneralWidgets.autosaveGB, 3, 2 );
+ autosaveLayout -> setSpacing( spacingHint() );
+ autosaveLayout -> setMargin( fontMetrics().height() );
+
+ m_GeneralWidgets.autosaveCB = new QCheckBox( i18n("E&nable autosave"), m_GeneralWidgets.autosaveGB );
+ m_GeneralWidgets.autosaveCB -> setChecked( m_pOptionState->generalState.autosave );
+ autosaveLayout -> addWidget( m_GeneralWidgets.autosaveCB, 0, 0 );
+
+ m_GeneralWidgets.autosaveL = new QLabel( i18n("Select auto-save time interval (mins):"), m_GeneralWidgets.autosaveGB );
+ autosaveLayout -> addWidget( m_GeneralWidgets.autosaveL, 1, 0 );
+
+ m_GeneralWidgets.timeISB = new KIntSpinBox( 1, 600, 1, m_pOptionState->generalState.autosavetime, 10, m_GeneralWidgets.autosaveGB );
+ m_GeneralWidgets.timeISB -> setEnabled( m_pOptionState->generalState.autosave );
+ autosaveLayout -> addWidget( m_GeneralWidgets.timeISB, 1, 1 );
+
+ // 2004-05-17 Achim Spangler: Allow definition of Suffix for autosave
+ // ( default: ".xmi" )
+ Dialog_Utils::makeLabeledEditField( m_GeneralWidgets.autosaveGB, autosaveLayout, 2,
+ m_GeneralWidgets.autosaveSuffixL, i18n("Set autosave suffix:"),
+ m_GeneralWidgets.autosaveSuffixT, m_pOptionState->generalState.autosavesuffix );
+ QString autoSaveSuffixToolTip = i18n( "<qt><p>The autosave file will be saved to ~/autosave.xmi if the autosaving occurs "
+ "before you have manually saved the file.</p>"
+ "<p>If you've already saved it, the autosave file will be saved in the same folder as the file "
+ "and will be named like the file's name, followed by the suffix specified.</p>"
+ "<p>If the suffix is equal to the suffix of the file you've saved, "
+ "the autosave will overwrite your file automatically.</p></qt>" );
+ QToolTip::add( m_GeneralWidgets.autosaveSuffixL, autoSaveSuffixToolTip );
+ QToolTip::add( m_GeneralWidgets.autosaveSuffixT, autoSaveSuffixToolTip );
+
+ //setup startup settings
+ m_GeneralWidgets.startupGB = new QGroupBox( i18n("Startup"), page );
+
+ QGridLayout * startupLayout = new QGridLayout( m_GeneralWidgets.startupGB, 3, 2 );
+ startupLayout -> setSpacing( spacingHint() );
+ startupLayout -> setMargin( fontMetrics().height() );
+
+ m_GeneralWidgets.logoCB = new QCheckBox( i18n("Sta&rtup logo"), m_GeneralWidgets.startupGB );
+ m_GeneralWidgets.logoCB -> setChecked( m_pOptionState->generalState.logo );
+ startupLayout -> addWidget( m_GeneralWidgets.logoCB, 0, 0 );
+
+ m_GeneralWidgets.tipCB = new QCheckBox( i18n("&Tip of the day"), m_GeneralWidgets.startupGB );
+ m_GeneralWidgets.tipCB -> setChecked( m_pOptionState->generalState.tip );
+ startupLayout -> addWidget( m_GeneralWidgets.tipCB, 0, 1 );
+
+ m_GeneralWidgets.loadlastCB = new QCheckBox( i18n("&Load last project"), m_GeneralWidgets.startupGB );
+ m_GeneralWidgets.loadlastCB -> setChecked( m_pOptionState->generalState.loadlast );
+ startupLayout -> addWidget( m_GeneralWidgets.loadlastCB, 1, 0 );
+
+ m_GeneralWidgets.startL = new QLabel( i18n("Start new project with:"), m_GeneralWidgets.startupGB );
+ startupLayout -> addWidget( m_GeneralWidgets.startL, 2, 0 );
+
+ m_GeneralWidgets.diagramKB = new KComboBox( m_GeneralWidgets.startupGB );
+ m_GeneralWidgets.diagramKB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ startupLayout -> addWidget( m_GeneralWidgets.diagramKB, 2, 1 );
+
+ QString diagrams [] = { i18n("No Diagram"), i18n("Class Diagram"),
+ i18n("Use Case Diagram"), i18n("Sequence Diagram"),
+ i18n("Collaboration Diagram"), i18n("State Diagram"),
+ i18n("Activity Diagram"), i18n("Component Diagram"),
+ i18n("Deployment Diagram") };
+
+ //start at 1 because we don't allow No Diagram any more
+ for (int i=1; i<9; i++) {
+ insertDiagram( diagrams[i] );
+ }
+
+ m_GeneralWidgets.diagramKB->setCurrentItem( (int)m_pOptionState->generalState.diagram-1 );
+ connect( m_GeneralWidgets.autosaveCB, SIGNAL(clicked()), this, SLOT(slotAutosaveCBClicked()) );
+}
+
+/**
+* Inserts @p type into the type-combobox as well as its completion object.
+*/
+void SettingsDlg::insertDiagram( const QString& type, int index )
+{
+ m_GeneralWidgets.diagramKB->insertItem( type, index );
+ m_GeneralWidgets.diagramKB->completionObject()->addItem( type );
+}
+
+void SettingsDlg::setupClassPage() {
+ //setup class settings page
+
+ QVBox * page = addVBoxPage( i18n("Class"), i18n("Class Settings"), DesktopIcon( "edit") );
+ m_ClassWidgets.visibilityGB = new QGroupBox( i18n("Visibility"), page );
+
+ QGridLayout * visibilityLayout = new QGridLayout( m_ClassWidgets.visibilityGB );
+ visibilityLayout -> setSpacing( spacingHint() );
+ visibilityLayout -> setMargin( fontMetrics().height() );
+
+ m_ClassWidgets.showVisibilityCB = new QCheckBox(i18n("Show &visibility"), m_ClassWidgets.visibilityGB);
+ m_ClassWidgets.showVisibilityCB -> setChecked( m_pOptionState->classState.showVisibility );
+ visibilityLayout -> addWidget( m_ClassWidgets.showVisibilityCB, 0, 0 );
+
+ m_ClassWidgets.showAttsCB = new QCheckBox( i18n("Show attributes"), m_ClassWidgets.visibilityGB );
+ m_ClassWidgets.showAttsCB -> setChecked( m_pOptionState->classState.showAtts );
+ visibilityLayout -> addWidget( m_ClassWidgets.showAttsCB, 0, 1 );
+
+ m_ClassWidgets.showOpsCB = new QCheckBox( i18n("Show operations"), m_ClassWidgets.visibilityGB );
+ m_ClassWidgets.showOpsCB -> setChecked( m_pOptionState->classState.showOps );
+ visibilityLayout -> addWidget( m_ClassWidgets.showOpsCB, 1, 0 );
+
+ m_ClassWidgets.showStereotypeCB = new QCheckBox( i18n("Show stereot&ype"), m_ClassWidgets.visibilityGB );
+ m_ClassWidgets.showStereotypeCB -> setChecked( m_pOptionState->classState.showStereoType );
+ visibilityLayout -> addWidget( m_ClassWidgets.showStereotypeCB, 1, 1 );
+
+ m_ClassWidgets.showAttSigCB = new QCheckBox(i18n("Show attribute signature"), m_ClassWidgets.visibilityGB);
+ m_ClassWidgets.showAttSigCB -> setChecked( m_pOptionState->classState.showAttSig );
+ visibilityLayout -> addWidget( m_ClassWidgets.showAttSigCB, 2, 0 );
+
+
+ m_ClassWidgets.showPackageCB = new QCheckBox(i18n("Show package"), m_ClassWidgets.visibilityGB);
+ m_ClassWidgets.showPackageCB -> setChecked( m_pOptionState->classState.showPackage );
+ visibilityLayout -> addWidget( m_ClassWidgets.showPackageCB, 2, 1 );
+
+ m_ClassWidgets.showOpSigCB = new QCheckBox( i18n("Show operation signature"), m_ClassWidgets.visibilityGB );
+ m_ClassWidgets.showOpSigCB -> setChecked( m_pOptionState->classState.showOpSig );
+ visibilityLayout -> addWidget( m_ClassWidgets.showOpSigCB, 3, 0 );
+ visibilityLayout -> setRowStretch( 3, 1 );
+
+ m_ClassWidgets.scopeGB = new QGroupBox( i18n("Starting Scope"), page );
+ QGridLayout * scopeLayout = new QGridLayout( m_ClassWidgets.scopeGB );
+ scopeLayout -> setSpacing( spacingHint() );
+ scopeLayout -> setMargin( fontMetrics().height() );
+
+ m_ClassWidgets.attributeLabel = new QLabel( i18n("Default attribute scope:"), m_ClassWidgets.scopeGB);
+ scopeLayout -> addWidget( m_ClassWidgets.attributeLabel, 0, 0 );
+
+ m_ClassWidgets.operationLabel = new QLabel( i18n("Default operation scope:"), m_ClassWidgets.scopeGB);
+ scopeLayout -> addWidget( m_ClassWidgets.operationLabel, 1, 0 );
+
+ m_ClassWidgets.m_pAttribScopeCB = new KComboBox(m_ClassWidgets.scopeGB);
+ insertAttribScope( tr2i18n( "Public" ) );
+ insertAttribScope( tr2i18n( "Private" ) );
+ insertAttribScope( tr2i18n( "Protected" ) );
+ m_ClassWidgets.m_pAttribScopeCB->setCurrentItem((m_pOptionState->classState.defaultAttributeScope - 200));
+ m_ClassWidgets.m_pAttribScopeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ scopeLayout -> addWidget( m_ClassWidgets.m_pAttribScopeCB, 0, 1 );
+
+ m_ClassWidgets.m_pOperationScopeCB = new KComboBox(m_ClassWidgets.scopeGB);
+ insertOperationScope( tr2i18n( "Public" ) );
+ insertOperationScope( tr2i18n( "Private" ) );
+ insertOperationScope( tr2i18n( "Protected" ) );
+ m_ClassWidgets.m_pOperationScopeCB->setCurrentItem((m_pOptionState->classState.defaultOperationScope - 200));
+ m_ClassWidgets.m_pOperationScopeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ scopeLayout -> addWidget( m_ClassWidgets.m_pOperationScopeCB, 1, 1 );
+
+}
+/**
+* Inserts @p type into the type-combobox as well as its completion object.
+*/
+void SettingsDlg::insertAttribScope( const QString& type, int index )
+{
+ m_ClassWidgets.m_pAttribScopeCB->insertItem( type, index );
+ m_ClassWidgets.m_pAttribScopeCB->completionObject()->addItem( type );
+}
+/**
+* Inserts @p type into the type-combobox as well as its completion object.
+*/
+void SettingsDlg::insertOperationScope( const QString& type, int index )
+{
+ m_ClassWidgets.m_pOperationScopeCB->insertItem( type, index );
+ m_ClassWidgets.m_pOperationScopeCB->completionObject()->addItem( type );
+}
+
+void SettingsDlg::setupCodeGenPage() {
+ //setup code generation settings page
+ QVBox * page = addVBoxPage( i18n("Code Generation"), i18n("Code Generation Settings"), DesktopIcon( "source") );
+ m_pCodeGenPage = new CodeGenerationOptionsPage(page);
+ connect( m_pCodeGenPage, SIGNAL(languageChanged()), this, SLOT(slotApply()) );
+}
+
+void SettingsDlg::setupCodeViewerPage(Settings::CodeViewerState options) {
+ //setup code generation settings page
+ QVBox * page = addVBoxPage( i18n("Code Viewer"), i18n("Code Viewer Settings"), DesktopIcon( "source") );
+ m_pCodeViewerPage = new CodeViewerOptionsPage(options, page);
+}
+
+void SettingsDlg::setupFontPage() {
+ QVBox * page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts") );
+ m_FontWidgets.chooser = new KFontChooser( page, "font", false, QStringList(), false);
+ m_FontWidgets.chooser->setFont( m_pOptionState->uiState.font );
+
+}
+
+void SettingsDlg::slotApply() {
+ applyPage( (Settings::Page) activePageIndex() );
+ //do no emit signal applyClicked in the slot slotApply -> infinite loop
+ //emit applyClicked();
+}
+
+void SettingsDlg::slotOk() {
+ applyPage( Settings::page_general );
+ applyPage( Settings::page_font );
+ applyPage( Settings::page_UI );
+ applyPage( Settings::page_class );
+ applyPage( Settings::page_codegen );
+ applyPage( Settings::page_codeview );
+ accept();
+}
+
+
+void SettingsDlg::slotDefault() {
+ /*
+ Defaults hard coded. Make sure that this is alright.
+ If defaults are set anywhere else, like in setting up config file, make sure the same.
+ */
+ switch( activePageIndex() ) {
+ case Settings::page_general:
+ m_GeneralWidgets.autosaveCB -> setChecked( false );
+ m_GeneralWidgets.timeISB -> setValue( 5 );
+ m_GeneralWidgets.timeISB->setEnabled( true );
+ m_GeneralWidgets.logoCB -> setChecked( true );
+ m_GeneralWidgets.tipCB -> setChecked( true );
+ m_GeneralWidgets.loadlastCB -> setChecked( true );
+ m_GeneralWidgets.diagramKB -> setCurrentItem( 0 );
+ break;
+
+ case Settings::page_font:
+ m_FontWidgets.chooser -> setFont( parentWidget() -> font() );
+ break;
+
+ case Settings::page_UI:
+ m_UiWidgets.useFillColorCB -> setChecked( true );
+ m_UiWidgets.fillColorB -> setColor( QColor( 255, 255, 192 ) );
+ m_UiWidgets.lineColorB -> setColor( Qt::red );
+ m_UiWidgets.lineWidthB -> setValue( 0 );
+ break;
+
+ case Settings::page_class:
+ m_ClassWidgets.showVisibilityCB -> setChecked( false );
+ m_ClassWidgets.showAttsCB -> setChecked( true );
+ m_ClassWidgets.showOpsCB -> setChecked( true );
+ m_ClassWidgets.showStereotypeCB -> setChecked( false );
+ m_ClassWidgets.showAttSigCB -> setChecked( false );
+ m_ClassWidgets.showOpSigCB -> setChecked( false );
+ m_ClassWidgets.showPackageCB -> setChecked( false );
+ m_ClassWidgets.m_pAttribScopeCB->setCurrentItem(1); // Private
+ m_ClassWidgets.m_pOperationScopeCB->setCurrentItem(0); // Public
+ break;
+
+ case Settings::page_codegen:
+ case Settings::page_codeview:
+ // do nothing
+ break;
+ };
+}
+
+void SettingsDlg::applyPage( Settings::Page page ) {
+ m_bChangesApplied = true;
+ switch( page ) {
+ case Settings::page_general:
+ m_pOptionState->generalState.undo = m_GeneralWidgets.undoCB -> isChecked();
+ m_pOptionState->generalState.tabdiagrams = m_GeneralWidgets.tabdiagramsCB->isChecked();
+ m_pOptionState->generalState.newcodegen = m_GeneralWidgets.newcodegenCB->isChecked();
+ m_pOptionState->generalState.angularlines = m_GeneralWidgets.angularLinesCB->isChecked();
+ m_pOptionState->generalState.autosave = m_GeneralWidgets.autosaveCB -> isChecked();
+ m_pOptionState->generalState.autosavetime = m_GeneralWidgets.timeISB -> value();
+ // 2004-05-17 Achim Spangler: retrieve Suffix setting from dialog entry
+ m_pOptionState->generalState.autosavesuffix = m_GeneralWidgets.autosaveSuffixT -> text();
+ m_pOptionState->generalState.logo = m_GeneralWidgets.logoCB -> isChecked();
+ m_pOptionState->generalState.tip = m_GeneralWidgets.tipCB -> isChecked();
+ m_pOptionState->generalState.loadlast = m_GeneralWidgets.loadlastCB -> isChecked();
+ m_pOptionState->generalState.diagram = (Uml::Diagram_Type)(m_GeneralWidgets.diagramKB->currentItem() + 1);
+ break;
+
+ case Settings::page_font:
+ m_pOptionState->uiState.font = m_FontWidgets.chooser -> font();
+ break;
+
+ case Settings::page_UI:
+ m_pOptionState->uiState.useFillColor = m_UiWidgets.useFillColorCB -> isChecked();
+ m_pOptionState->uiState.fillColor = m_UiWidgets.fillColorB -> color();
+ m_pOptionState->uiState.lineColor = m_UiWidgets.lineColorB -> color();
+ m_pOptionState->uiState.lineWidth = m_UiWidgets.lineWidthB -> value();
+ break;
+
+ case Settings::page_class:
+ m_pOptionState->classState.showVisibility = m_ClassWidgets.showVisibilityCB -> isChecked();
+ m_pOptionState->classState.showAtts = m_ClassWidgets.showAttsCB -> isChecked();
+ m_pOptionState->classState.showOps = m_ClassWidgets.showOpsCB -> isChecked();
+ m_pOptionState->classState.showStereoType = m_ClassWidgets.showStereotypeCB -> isChecked();
+ m_pOptionState->classState.showAttSig = m_ClassWidgets.showAttSigCB -> isChecked();
+ m_pOptionState->classState.showOpSig = m_ClassWidgets.showOpSigCB -> isChecked();
+ m_pOptionState->classState.showPackage = m_ClassWidgets.showPackageCB -> isChecked();
+ m_pOptionState->classState.defaultAttributeScope = (Uml::Visibility::Value) (m_ClassWidgets.m_pAttribScopeCB->currentItem() + 200);
+ m_pOptionState->classState.defaultOperationScope = (Uml::Visibility::Value) (m_ClassWidgets.m_pOperationScopeCB->currentItem() + 200);
+ break;
+
+ case Settings::page_codegen:
+ m_pCodeGenPage->apply();
+ break;
+
+ case Settings::page_codeview:
+ m_pCodeViewerPage->apply();
+ m_pOptionState->codeViewerState = m_pCodeViewerPage->getOptions();
+ break;
+ }
+}
+
+void SettingsDlg::slotLineBClicked() {
+ m_UiWidgets.lineColorB -> setColor( Qt::red );
+}
+
+void SettingsDlg::slotFillBClicked() {
+ m_UiWidgets.fillColorB -> setColor( QColor(255, 255, 192) );
+}
+
+void SettingsDlg::slotAutosaveCBClicked() {
+ m_GeneralWidgets.timeISB -> setEnabled( m_GeneralWidgets.autosaveCB -> isChecked() );
+}
+
+QString SettingsDlg::getCodeGenerationLanguage() {
+ return m_pCodeGenPage->getCodeGenerationLanguage();
+}
+
+#include "settingsdlg.moc"
diff --git a/umbrello/umbrello/dialogs/settingsdlg.h b/umbrello/umbrello/dialogs/settingsdlg.h
new file mode 100644
index 00000000..30579990
--- /dev/null
+++ b/umbrello/umbrello/dialogs/settingsdlg.h
@@ -0,0 +1,177 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef SETTINGSDLG_H
+#define SETTINGSDLG_H
+//qt includes
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qdict.h>
+//kde includes
+#include <kcombobox.h>
+#include <kfontdialog.h>
+#include <kdialogbase.h>
+#include <kcolorbutton.h>
+#include <knuminput.h>
+//app includes
+
+#include "../optionstate.h"
+
+class CodeGenerationOptionsPage;
+class CodeViewerOptionsPage;
+class CodeGenerator;
+
+/**
+ * @author Paul Hensgen
+ * modified by brian thomas Aug-2003
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class SettingsDlg : public KDialogBase {
+
+ Q_OBJECT
+
+public:
+ SettingsDlg(QWidget * parent, Settings::OptionState *state);
+ ~SettingsDlg();
+
+ //public methods
+ bool getChangesApplied() {
+ return m_bChangesApplied;
+ }
+
+ QString getCodeGenerationLanguage();
+
+protected:
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertDiagram( const QString& type, int index = -1 );
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertAttribScope( const QString& type, int index = -1 );
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertOperationScope( const QString& type, int index = -1 );
+
+private:
+ //private structs
+ struct UIWidgets {
+ QGroupBox * colorGB;
+
+ QLabel * lineColorL;
+ QLabel * fillColorL;
+ QLabel * lineWidthL;
+
+ QPushButton * lineDefaultB;
+ QPushButton * fillDefaultB;
+ QPushButton * lineWidthDefaultB;
+
+ KColorButton * lineColorB;
+ KColorButton * fillColorB;
+ KIntSpinBox * lineWidthB;
+
+ QCheckBox * useFillColorCB;
+ }
+ ;//end struct UIWidgets
+
+ struct GeneralWidgets {
+ QGroupBox * miscGB;
+ QGroupBox * autosaveGB;
+ QGroupBox * startupGB;
+
+ KIntSpinBox * timeISB;
+ KComboBox * diagramKB;
+
+ QCheckBox * undoCB;
+ QCheckBox * tabdiagramsCB;
+ QCheckBox * newcodegenCB;
+ QCheckBox * angularLinesCB;
+ QCheckBox * autosaveCB;
+ QCheckBox * logoCB;
+ QCheckBox * tipCB;
+ QCheckBox * loadlastCB;
+
+ // 2004-05-17 Achim Spangler: Allow definition of Suffix for autosave
+ // ( Default: ".xmi" )
+ QLineEdit * autosaveSuffixT;
+ QLabel * autosaveSuffixL;
+ // End AutoSave Suffix
+
+ QLabel * startL;
+ QLabel * autosaveL;
+ }
+ ;//end struct GeneralWidgets
+
+ struct ClassWidgets {
+ QGroupBox * visibilityGB;
+ QGroupBox * scopeGB;
+
+ QCheckBox * showVisibilityCB;
+ QCheckBox * showAttsCB;
+ QCheckBox * showOpsCB;
+ QCheckBox * showStereotypeCB;
+ QCheckBox * showAttSigCB;
+ QCheckBox * showPackageCB;
+
+ QCheckBox * showOpSigCB;
+
+ QLabel * attributeLabel;
+ QLabel * operationLabel;
+
+ KComboBox* m_pAttribScopeCB;
+ KComboBox* m_pOperationScopeCB;
+
+ }
+ ;//end struct ClassWidgets
+
+ struct FontWidgets {
+ KFontChooser * chooser;
+ };
+
+ //private methods
+ void setupFontPage();
+ void setupUIPage();
+ void setupGeneralPage();
+ void setupClassPage();
+ void setupCodeGenPage();
+ void setupCodeViewerPage(Settings::CodeViewerState options);
+ void applyPage( Settings::Page page );
+
+ //private attributes
+ FontWidgets m_FontWidgets;
+ GeneralWidgets m_GeneralWidgets;
+ UIWidgets m_UiWidgets;
+ ClassWidgets m_ClassWidgets;
+ Settings::OptionState *m_pOptionState;
+ CodeGenerationOptionsPage * m_pCodeGenPage;
+ CodeViewerOptionsPage * m_pCodeViewerPage;
+
+ KConfig * m_pCfg;
+ bool m_bChangesApplied;
+
+private slots:
+ void slotApply();
+ void slotOk();
+ void slotDefault();
+ void slotLineBClicked();
+ void slotFillBClicked();
+ void slotAutosaveCBClicked();
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/statedialog.cpp b/umbrello/umbrello/dialogs/statedialog.cpp
new file mode 100644
index 00000000..691597e9
--- /dev/null
+++ b/umbrello/umbrello/dialogs/statedialog.cpp
@@ -0,0 +1,147 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "statedialog.h"
+
+//qt includes
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qmultilineedit.h>
+#include <qgroupbox.h>
+
+//kde includes
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kfontdialog.h>
+
+//local includes
+#include "../umlview.h"
+#include "../statewidget.h"
+#include "../dialog_utils.h"
+
+StateDialog::StateDialog( UMLView * pView, StateWidget * pWidget )
+ : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help, Ok, pView, "_STATEDIALOG_", true, true) {
+ m_pActivityPage = 0;
+ m_pView = pView;
+ m_pStateWidget = pWidget;
+ m_bChangesMade = false;
+ setupPages();
+}
+
+void StateDialog::slotOk() {
+ applyPage( GeneralPage );
+ applyPage( Activity_Page );
+ applyPage( ColorPage );
+ applyPage( FontPage );
+ accept();
+}
+
+void StateDialog::slotApply() {
+ applyPage( (Page) activePageIndex() );
+}
+
+void StateDialog::setupPages() {
+ setupGeneralPage();
+ if( m_pStateWidget -> getStateType() == StateWidget::Normal )
+ setupActivityPage();
+ setupColorPage();
+ setupFontPage();
+}
+
+void StateDialog::applyPage( Page page ) {
+ m_bChangesMade = true;
+ switch( page ) {
+ case GeneralPage:
+ m_pStateWidget -> setName( m_GenPageWidgets.nameLE -> text() );
+ m_pStateWidget -> setDoc( m_GenPageWidgets.docMLE -> text() );
+ break;
+
+ case Activity_Page:
+ if( m_pActivityPage )
+ m_pActivityPage -> updateActivities();
+ break;
+
+ case ColorPage:
+ m_pColorPage -> updateUMLWidget();
+ break;
+
+ case FontPage:
+ m_pStateWidget -> setFont( m_pChooser -> font() );
+ break;
+ }//end switch
+}
+
+void StateDialog::setupGeneralPage() {
+ QString types[ ] = { i18n("Initial state"), i18n("State"), i18n("End state") };
+ StateWidget::StateType type = m_pStateWidget -> getStateType();
+
+ QVBox * page = addVBoxPage( i18n("General"), i18n("General Properties"), DesktopIcon( "misc") );
+ m_GenPageWidgets.generalGB = new QGroupBox( i18n( "Properties"), (QWidget *)page );
+
+ QGridLayout * generalLayout = new QGridLayout( m_GenPageWidgets.generalGB, 2, 2 );
+ generalLayout -> setSpacing( spacingHint() );
+ generalLayout -> setMargin( fontMetrics().height() );
+
+ Dialog_Utils::makeLabeledEditField( m_GenPageWidgets.generalGB, generalLayout, 0,
+ m_GenPageWidgets.typeL, i18n("State type:"),
+ m_GenPageWidgets.typeLE, types[ (int)type ] );
+ m_GenPageWidgets.typeLE -> setEnabled( false );
+
+ Dialog_Utils::makeLabeledEditField( m_GenPageWidgets.generalGB, generalLayout, 1,
+ m_GenPageWidgets.nameL, i18n("State name:"),
+ m_GenPageWidgets.nameLE );
+
+ m_GenPageWidgets.docGB = new QGroupBox( i18n( "Documentation"), (QWidget *)page );
+
+ QHBoxLayout * docLayout = new QHBoxLayout( m_GenPageWidgets.docGB );
+ docLayout -> setSpacing( spacingHint() );
+ docLayout -> setMargin( fontMetrics().height() );
+
+ m_GenPageWidgets.docMLE = new QMultiLineEdit( m_GenPageWidgets.docGB );
+ m_GenPageWidgets.docMLE -> setText( m_pStateWidget -> getDoc() );
+ docLayout -> addWidget( m_GenPageWidgets.docMLE );
+
+ if( type != StateWidget::Normal ) {
+ m_GenPageWidgets.nameLE -> setEnabled( false );
+ m_GenPageWidgets.nameLE -> setText( "" );
+ } else
+ m_GenPageWidgets.nameLE -> setText( m_pStateWidget -> getName() );
+}
+
+void StateDialog::setupFontPage() {
+ if ( !m_pStateWidget )
+ return;
+ QVBox * page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts") );
+ m_pChooser = new KFontChooser( (QWidget*)page, "font", false, QStringList(), false);
+ m_pChooser -> setFont( m_pStateWidget -> getFont() );
+}
+
+void StateDialog::setupColorPage() {
+ QFrame * colorPage = addPage( i18n("Color"), i18n("Widget Color"), DesktopIcon( "colors") );
+ QHBoxLayout * m_pColorLayout = new QHBoxLayout(colorPage);
+ m_pColorPage = new UMLWidgetColorPage( colorPage, m_pStateWidget );
+ m_pColorLayout -> addWidget(m_pColorPage);
+}
+
+void StateDialog::setupActivityPage() {
+ QFrame * activityPage = addPage( i18n("Activities"), i18n("Activities"), DesktopIcon( "misc") );
+ QHBoxLayout * activityLayout = new QHBoxLayout( activityPage );
+ m_pActivityPage = new ActivityPage( activityPage, m_pStateWidget );
+ activityLayout -> addWidget( m_pActivityPage );
+}
+
+
+
+
+
+#include "statedialog.moc"
diff --git a/umbrello/umbrello/dialogs/statedialog.h b/umbrello/umbrello/dialogs/statedialog.h
new file mode 100644
index 00000000..d364d6be
--- /dev/null
+++ b/umbrello/umbrello/dialogs/statedialog.h
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef STATEDIALOG_H
+#define STATEDIALOG_H
+
+//kde class includes
+#include <kdialogbase.h>
+
+//local class includes
+#include "umlwidgetcolorpage.h"
+#include "activitypage.h"
+
+//forward declarations
+class UMLView;
+class StateWidget;
+class QLabel;
+class QLineEdit;
+class QMultiLineEdit;
+class QGroupBox;
+class KFontChooser;
+
+/**
+ * Displays the properties for a @ref StateWidget
+ *
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class StateDialog : public KDialogBase {
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ StateDialog( UMLView * pView, StateWidget * pWidget );
+
+ /**
+ * Returns whether changes were made.
+ */
+ bool getChangesMade() {
+ return m_bChangesMade;
+ }
+
+protected slots:
+
+ enum Page
+ {
+ GeneralPage = 0,
+ Activity_Page,
+ ColorPage,
+ FontPage
+ };
+
+ /**
+ * Entered when OK button pressed.
+ */
+ void slotOk();
+
+ /**
+ * Entered when Apply button pressed.
+ */
+ void slotApply();
+protected:
+ /**
+ * Sets up the pages of the dialog.
+ */
+ void setupPages();
+
+ /**
+ * Sets up the general page of the dialog.
+ */
+ void setupGeneralPage();
+
+ /**
+ * Sets up the color page.
+ */
+ void setupColorPage();
+
+ /**
+ * Sets up the font selection page.
+ */
+ void setupFontPage();
+
+ /**
+ * Sets up the activity page.
+ */
+ void setupActivityPage();
+
+ /**
+ * Applys changes to the given page.
+ */
+ void applyPage( Page page );
+
+ /**
+ * Font chooser widget for font page.
+ */
+ KFontChooser * m_pChooser;
+
+ /**
+ * Color page
+ */
+ UMLWidgetColorPage * m_pColorPage;
+
+ /**
+ * Activity page.
+ */
+ ActivityPage * m_pActivityPage;
+
+ /**
+ * The widget to represent.
+ */
+ StateWidget * m_pStateWidget;
+
+ /**
+ * The diagram the widget is on.
+ */
+ UMLView * m_pView;
+
+ /**
+ * Holds whether changes in the dialog have been made.
+ */
+ bool m_bChangesMade;
+
+ struct GeneralPageWidgets {
+ QLabel * nameL, * typeL;
+ QLineEdit * nameLE, * typeLE;
+ QMultiLineEdit * docMLE;
+
+ QGroupBox * docGB, * generalGB;
+ }
+ m_GenPageWidgets;
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlattributedialog.cpp b/umbrello/umbrello/dialogs/umlattributedialog.cpp
new file mode 100644
index 00000000..e6a52725
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlattributedialog.cpp
@@ -0,0 +1,235 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlattributedialog.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+
+// kde includes
+#include <kcombobox.h>
+#include <kcompletion.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// app includes
+#include "../attribute.h"
+#include "../classifier.h"
+#include "../template.h"
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../dialog_utils.h"
+#include "../object_factory.h"
+#include "../codeimport/import_utils.h"
+
+UMLAttributeDialog::UMLAttributeDialog( QWidget * pParent, UMLAttribute * pAttribute )
+ : KDialogBase( Plain, i18n("Attribute Properties"), Help | Ok | Cancel , Ok, pParent, "_UMLATTRIBUTEDLG_", true, true) {
+ m_pAttribute = pAttribute;
+ setupDialog();
+}
+
+UMLAttributeDialog::~UMLAttributeDialog() {}
+
+void UMLAttributeDialog::setupDialog() {
+ UMLDoc * pDoc = UMLApp::app()->getDocument();
+ int margin = fontMetrics().height();
+
+ QVBoxLayout * mainLayout = new QVBoxLayout( plainPage() );
+
+ m_pValuesGB = new QGroupBox(i18n("General Properties"), plainPage() );
+ QGridLayout * valuesLayout = new QGridLayout(m_pValuesGB, 5, 2);
+ valuesLayout -> setMargin(margin);
+ valuesLayout -> setSpacing(10);
+
+ m_pTypeL = new QLabel(i18n("&Type:"), m_pValuesGB);
+ valuesLayout -> addWidget(m_pTypeL, 0, 0);
+
+ m_pTypeCB = new KComboBox(true, m_pValuesGB);
+ valuesLayout -> addWidget(m_pTypeCB, 0, 1);
+ m_pTypeL->setBuddy(m_pTypeCB);
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 1,
+ m_pNameL, i18n("&Name:"),
+ m_pNameLE, m_pAttribute->getName() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 2,
+ m_pInitialL, i18n("&Initial value:"),
+ m_pInitialLE, m_pAttribute->getInitialValue() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 3,
+ m_pStereoTypeL, i18n("Stereotype name:"),
+ m_pStereoTypeLE, m_pAttribute->getStereotype() );
+
+ m_pStaticCB = new QCheckBox( i18n("Classifier &scope (\"static\")"), m_pValuesGB );
+ m_pStaticCB -> setChecked( m_pAttribute -> getStatic() );
+ valuesLayout -> addWidget(m_pStaticCB, 4, 0);
+
+
+ mainLayout -> addWidget(m_pValuesGB);
+
+
+ m_pScopeBG = new QButtonGroup(i18n("Visibility"), plainPage() );
+ QHBoxLayout * scopeLayout = new QHBoxLayout(m_pScopeBG);
+ scopeLayout -> setMargin(margin);
+
+ m_pPublicRB = new QRadioButton(i18n("&Public"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pPublicRB);
+
+ m_pPrivateRB = new QRadioButton(i18n("P&rivate"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pPrivateRB);
+
+ m_pProtectedRB = new QRadioButton(i18n("Prot&ected"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pProtectedRB);
+
+ m_pImplementationRB = new QRadioButton(i18n("I&mplementation"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pImplementationRB);
+
+ mainLayout -> addWidget(m_pScopeBG);
+ Uml::Visibility scope = m_pAttribute -> getVisibility();
+ if( scope == Uml::Visibility::Public )
+ m_pPublicRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Private )
+ m_pPrivateRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Protected )
+ m_pProtectedRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Implementation )
+ m_pImplementationRB -> setChecked( true );
+
+ m_pTypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+
+ //now add the Concepts
+ UMLClassifierList namesList( pDoc->getConcepts() );
+ UMLClassifier* obj;
+ for (obj=namesList.first(); obj!=0; obj=namesList.next()) {
+ insertType( obj->getFullyQualifiedName() );
+ }
+
+ //work out which one to select
+ int typeBoxCount = 0;
+ bool foundType = false;
+ while (typeBoxCount < m_pTypeCB->count() && foundType == false) {
+ QString typeBoxString = m_pTypeCB->text(typeBoxCount);
+ if ( typeBoxString == m_pAttribute->getTypeName() ) {
+ foundType = true;
+ m_pTypeCB->setCurrentItem(typeBoxCount);
+ } else {
+ typeBoxCount++;
+ }
+ }
+
+ if (!foundType) {
+ insertType( m_pAttribute->getTypeName(), 0 );
+ m_pTypeCB->setCurrentItem(0);
+ }
+
+ m_pNameLE->setFocus();
+ connect( m_pNameLE, SIGNAL( textChanged ( const QString & ) ), SLOT( slotNameChanged( const QString & ) ) );
+ slotNameChanged(m_pNameLE->text() );
+}
+
+void UMLAttributeDialog::slotNameChanged( const QString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+bool UMLAttributeDialog::apply() {
+ QString name = m_pNameLE->text();
+ if (name.isEmpty()) {
+ KMessageBox::error(this, i18n("You have entered an invalid attribute name."),
+ i18n("Attribute Name Invalid"), false);
+ m_pNameLE->setText( m_pAttribute->getName() );
+ return false;
+ }
+ UMLClassifier * pConcept = dynamic_cast<UMLClassifier *>( m_pAttribute->parent() );
+ UMLObject *o = pConcept->findChildObject(name);
+ if (o && o != m_pAttribute) {
+ KMessageBox::error(this, i18n("The attribute name you have chosen is already being used in this operation."),
+ i18n("Attribute Name Not Unique"), false);
+ m_pNameLE->setText( m_pAttribute->getName() );
+ return false;
+ }
+ m_pAttribute->setName(name);
+ Uml::Visibility scope = Uml::Visibility::Protected;
+ if ( m_pPublicRB->isChecked() ) {
+ scope = Uml::Visibility::Public;
+ } else if ( m_pPrivateRB->isChecked() ) {
+ scope = Uml::Visibility::Private;
+ } else if ( m_pImplementationRB->isChecked() ) {
+ scope = Uml::Visibility::Implementation;
+ }
+ m_pAttribute->setVisibility(scope);
+ // Set the scope as the default in the option state
+ Settings::OptionState optionState = Settings::getOptionState();
+ optionState.classState.defaultAttributeScope = scope;
+ Settings::setOptionState(optionState);
+
+ m_pAttribute->setInitialValue( m_pInitialLE->text() );
+ m_pAttribute->setStereotype( m_pStereoTypeLE->text() );
+ m_pAttribute->setStatic( m_pStaticCB->isChecked() );
+
+ QString typeName = m_pTypeCB->currentText();
+ UMLTemplate *tmplParam = pConcept->findTemplate(typeName);
+ if (tmplParam) {
+ m_pAttribute->setType(tmplParam);
+ return true;
+ }
+ UMLDoc * pDoc = UMLApp::app()->getDocument();
+ UMLObject *obj = pDoc->findUMLObject(typeName);
+ UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(obj);
+ if (classifier == NULL) {
+ Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (pl == Uml::pl_Cpp || pl == Uml::pl_Java) {
+ // Import_Utils::createUMLObject works better for C++ namespace and java package than Object_Factory::createUMLObject
+
+ Import_Utils::setRelatedClassifier(pConcept);
+ obj = Import_Utils::createUMLObject(Uml::ot_UMLObject, typeName);
+ Import_Utils::setRelatedClassifier(NULL);
+ } else {
+ // If it's obviously a pointer type (C++) then create a datatype.
+ // Else we don't know what it is so as a compromise create a class.
+ Uml::Object_Type ot = (typeName.contains('*') ? Uml::ot_Datatype : Uml::ot_Class);
+ obj = Object_Factory::createUMLObject(ot, typeName);
+ }
+ if (obj == NULL)
+ return false;
+ classifier = static_cast<UMLClassifier*>(obj);
+ }
+ m_pAttribute->setType( classifier );
+ return true;
+}
+
+void UMLAttributeDialog::slotApply() {
+ apply();
+}
+
+void UMLAttributeDialog::slotOk() {
+ if ( apply() ) {
+ accept();
+ }
+}
+
+void UMLAttributeDialog::insertType( const QString& type, int index )
+{
+ m_pTypeCB->insertItem( type, index );
+ m_pTypeCB->completionObject()->addItem( type );
+}
+
+
+#include "umlattributedialog.moc"
diff --git a/umbrello/umbrello/dialogs/umlattributedialog.h b/umbrello/umbrello/dialogs/umlattributedialog.h
new file mode 100644
index 00000000..92305d61
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlattributedialog.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLATTRIBUTEDIALOG_H
+#define UMLATTRIBUTEDIALOG_H
+
+#include <kdialogbase.h>
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class QButtonGroup;
+class QCheckBox;
+class QGroupBox;
+class QRadioButton;
+class UMLAttribute;
+class KComboBox;
+class QLineEdit;
+
+class UMLAttributeDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ UMLAttributeDialog( QWidget * pParent, UMLAttribute * pAttribute );
+ ~UMLAttributeDialog();
+
+protected:
+ /**
+ * Sets up the dialog
+ */
+ void setupDialog();
+
+ /**
+ * Checks if changes are valid and applies them if they are,
+ * else returns false
+ */
+ bool apply();
+
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertType( const QString& type, int index = -1 );
+
+ /**
+ * The Attribute to represent
+ */
+ UMLAttribute * m_pAttribute;
+
+ //GUI Widgets
+ QGroupBox * m_pAttsGB, * m_pValuesGB;
+ QButtonGroup * m_pScopeBG;
+ QRadioButton * m_pPublicRB, * m_pPrivateRB, * m_pProtectedRB, * m_pImplementationRB;
+ QLabel * m_pTypeL, * m_pNameL, * m_pInitialL, * m_pStereoTypeL;
+ KComboBox * m_pTypeCB;
+ QLineEdit * m_pNameLE, * m_pInitialLE, * m_pStereoTypeLE;
+ QCheckBox* m_pStaticCB;
+
+public slots:
+ /**
+ * I don't think this is used, but if we had an apply button
+ * it would slot into here
+ */
+ void slotApply();
+
+ /**
+ * Used when the OK button is clicked. Calls apply()
+ */
+ void slotOk();
+ void slotNameChanged( const QString & );
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlentityattributedialog.cpp b/umbrello/umbrello/dialogs/umlentityattributedialog.cpp
new file mode 100644
index 00000000..ef6a5791
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlentityattributedialog.cpp
@@ -0,0 +1,262 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlentityattributedialog.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+
+// kde includes
+#include <kcombobox.h>
+#include <kcompletion.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kdebug.h>
+
+// app includes
+#include "../entityattribute.h"
+#include "../classifier.h"
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../codegenerator.h"
+#include "../dialog_utils.h"
+#include "../object_factory.h"
+#include "../umlclassifierlist.h"
+
+UMLEntityAttributeDialog::UMLEntityAttributeDialog( QWidget * pParent, UMLEntityAttribute * pEntityAttribute )
+ : KDialogBase( Plain, i18n("Entity Attribute Properties"), Help | Ok | Cancel , Ok, pParent, "_UMLENTITYATTRIBUTEDLG_", true, true) {
+ m_pEntityAttribute = pEntityAttribute;
+ setupDialog();
+}
+
+UMLEntityAttributeDialog::~UMLEntityAttributeDialog() {}
+
+void UMLEntityAttributeDialog::setupDialog() {
+ UMLDoc * pDoc = UMLApp::app()->getDocument();
+ int margin = fontMetrics().height();
+
+ QVBoxLayout * mainLayout = new QVBoxLayout( plainPage() );
+
+ m_pValuesGB = new QGroupBox(i18n("General Properties"), plainPage() );
+ QGridLayout * valuesLayout = new QGridLayout(m_pValuesGB, 5, 2);
+ valuesLayout -> setMargin(margin);
+ valuesLayout -> setSpacing(10);
+
+ m_pTypeL = new QLabel(i18n("&Type:"), m_pValuesGB);
+ valuesLayout -> addWidget(m_pTypeL, 0, 0);
+
+ m_pTypeCB = new KComboBox(true, m_pValuesGB);
+ valuesLayout -> addWidget(m_pTypeCB, 0, 1);
+ m_pTypeL->setBuddy(m_pTypeCB);
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 1,
+ m_pNameL, i18n("&Name:"),
+ m_pNameLE, m_pEntityAttribute->getName() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 2,
+ m_pInitialL, i18n("&Default value:"),
+ m_pInitialLE, m_pEntityAttribute->getInitialValue() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 3,
+ m_pStereoTypeL, i18n("Stereotype name:"),
+ m_pStereoTypeLE, m_pEntityAttribute->getStereotype() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 4,
+ m_pValuesL, i18n("Length/Values:"),
+ m_pValuesLE, m_pEntityAttribute->getValues() );
+
+ m_pAutoIncrementCB = new QCheckBox( i18n("&Auto increment"), m_pValuesGB );
+ m_pAutoIncrementCB->setChecked( m_pEntityAttribute->getAutoIncrement() );
+ valuesLayout->addWidget(m_pAutoIncrementCB, 5, 0);
+
+ m_pNullCB = new QCheckBox( i18n("Allow &null"), m_pValuesGB );
+ m_pNullCB->setChecked( m_pEntityAttribute->getNull() );
+ valuesLayout->addWidget(m_pNullCB, 6, 0);
+
+ m_pAttributesL = new QLabel(i18n("Attributes:"), m_pValuesGB);
+ valuesLayout->addWidget(m_pAttributesL, 7, 0);
+
+ m_pAttributesCB = new KComboBox(true, m_pValuesGB);
+ m_pAttributesCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ valuesLayout->addWidget(m_pAttributesCB, 7, 1);
+ m_pTypeL->setBuddy(m_pAttributesCB);
+
+ insertAttribute( m_pEntityAttribute->getAttributes() );
+ insertAttribute("");
+ insertAttribute("binary");
+ insertAttribute("unsigned");
+ insertAttribute("unsigned zerofill");
+
+ mainLayout -> addWidget(m_pValuesGB);
+
+ m_pScopeBG = new QButtonGroup(i18n("Indexing"), plainPage() );
+ QHBoxLayout* scopeLayout = new QHBoxLayout(m_pScopeBG);
+ scopeLayout->setMargin(margin);
+
+ m_pNoneRB = new QRadioButton(i18n("&None"), m_pScopeBG);
+ scopeLayout->addWidget(m_pNoneRB);
+
+ m_pPublicRB = new QRadioButton(i18n("&Primary"), m_pScopeBG);
+ scopeLayout->addWidget(m_pPublicRB);
+
+ m_pPrivateRB = new QRadioButton(i18n("&Index"), m_pScopeBG);
+ scopeLayout->addWidget(m_pPrivateRB);
+
+ m_pProtectedRB = new QRadioButton(i18n("&Unique"), m_pScopeBG);
+ scopeLayout->addWidget(m_pProtectedRB);
+
+ mainLayout->addWidget(m_pScopeBG);
+ Uml::DBIndex_Type scope = m_pEntityAttribute->getIndexType();
+ if ( scope == Uml::Primary )
+ m_pPublicRB->setChecked( true );
+ else if( scope == Uml::Index )
+ m_pPrivateRB -> setChecked( true );
+ else if( scope == Uml::Unique )
+ m_pProtectedRB -> setChecked( true );
+ else {
+ m_pNoneRB->setChecked(true);
+ }
+
+ m_pTypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+
+ // Add the data types.
+ UMLClassifierList dataTypes = pDoc->getDatatypes();
+ if (dataTypes.count() == 0) {
+ // Switch to SQL as the active language if no datatypes are set.
+ UMLApp::app()->setActiveLanguage("SQL");
+ pDoc->addDefaultDatatypes();
+ kapp->processEvents();
+ dataTypes = pDoc->getDatatypes();
+ }
+ UMLClassifier *dat;
+ for (UMLClassifierListIt dit(dataTypes); (dat = dit.current()) != NULL; ++dit) {
+ insertType(dat->getName());
+ }
+
+ //work out which one to select
+ int typeBoxCount = 0;
+ bool foundType = false;
+ while (typeBoxCount < m_pTypeCB->count() && foundType == false) {
+ QString typeBoxString = m_pTypeCB->text(typeBoxCount);
+ if ( typeBoxString == m_pEntityAttribute->getTypeName() ) {
+ foundType = true;
+ m_pTypeCB->setCurrentItem(typeBoxCount);
+ } else {
+ typeBoxCount++;
+ }
+ }
+
+ if (!foundType) {
+ insertType( m_pEntityAttribute->getTypeName(), 0 );
+ m_pTypeCB->setCurrentItem(0);
+ }
+
+ m_pNameLE->setFocus();
+ connect( m_pNameLE, SIGNAL( textChanged ( const QString & ) ), SLOT( slotNameChanged( const QString & ) ) );
+ slotNameChanged(m_pNameLE->text() );
+}
+
+void UMLEntityAttributeDialog::slotNameChanged( const QString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+bool UMLEntityAttributeDialog::apply() {
+ QString name = m_pNameLE->text();
+ if (name.isEmpty()) {
+ KMessageBox::error(this, i18n("You have entered an invalid entity attribute name."),
+ i18n("Entity Attribute Name Invalid"), false);
+ m_pNameLE->setText( m_pEntityAttribute->getName() );
+ return false;
+ }
+ UMLClassifier * pConcept = dynamic_cast<UMLClassifier *>( m_pEntityAttribute->parent() );
+ UMLObject *o = pConcept->findChildObject(name);
+ if (o && o != m_pEntityAttribute) {
+ KMessageBox::error(this, i18n("The entity attribute name you have chosen is already being used in this operation."),
+ i18n("Entity Attribute Name Not Unique"), false);
+ m_pNameLE->setText( m_pEntityAttribute->getName() );
+ return false;
+ }
+ m_pEntityAttribute->setName(name);
+ m_pEntityAttribute->setInitialValue( m_pInitialLE->text() );
+ m_pEntityAttribute->setStereotype( m_pStereoTypeLE->text() );
+ m_pEntityAttribute->setValues( m_pValuesLE->text() );
+ m_pEntityAttribute->setAttributes( m_pAttributesCB->currentText() );
+ m_pEntityAttribute->setAutoIncrement( m_pAutoIncrementCB->isChecked() );
+ m_pEntityAttribute->setNull( m_pNullCB->isChecked() );
+
+ if ( m_pPublicRB->isChecked() ) {
+ m_pEntityAttribute->setIndexType(Uml::Primary);
+ } else if ( m_pPrivateRB -> isChecked() ) {
+ m_pEntityAttribute->setIndexType(Uml::Index);
+ } else if ( m_pProtectedRB -> isChecked() ) {
+ m_pEntityAttribute->setIndexType(Uml::Unique);
+ } else {
+ m_pEntityAttribute->setIndexType(Uml::None);
+ }
+
+ QString typeName = m_pTypeCB->currentText();
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLClassifierList dataTypes = pDoc->getDatatypes();
+ UMLClassifier *dat;
+ for (UMLClassifierListIt dit(dataTypes); (dat = dit.current()) != NULL; ++dit) {
+ if (typeName == dat->getName()) {
+ m_pEntityAttribute->setType(dat);
+ return true;
+ }
+ }
+ UMLObject *obj = pDoc->findUMLObject(typeName);
+ UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(obj);
+ if (classifier == NULL) {
+ // If it's obviously a pointer type (C++) then create a datatype.
+ // Else we don't know what it is so as a compromise create a class.
+ Uml::Object_Type ot = (typeName.contains('*') ? Uml::ot_Datatype
+ : Uml::ot_Class);
+ obj = Object_Factory::createUMLObject(ot, typeName);
+ if (obj == NULL)
+ return false;
+ classifier = static_cast<UMLClassifier*>(obj);
+ }
+ m_pEntityAttribute->setType( classifier );
+ return true;
+}
+
+void UMLEntityAttributeDialog::slotApply() {
+ apply();
+}
+
+void UMLEntityAttributeDialog::slotOk() {
+ if ( apply() ) {
+ accept();
+ }
+}
+
+void UMLEntityAttributeDialog::insertType( const QString& type, int index ) {
+ m_pTypeCB->insertItem( type, index );
+ m_pTypeCB->completionObject()->addItem( type );
+}
+
+void UMLEntityAttributeDialog::insertAttribute( const QString& type, int index ) {
+ m_pAttributesCB->insertItem( type, index );
+ m_pAttributesCB->completionObject()->addItem( type );
+}
+
+
+#include "umlentityattributedialog.moc"
diff --git a/umbrello/umbrello/dialogs/umlentityattributedialog.h b/umbrello/umbrello/dialogs/umlentityattributedialog.h
new file mode 100644
index 00000000..0b81472e
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlentityattributedialog.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLENTITYATTRIBUTEDIALOG_H
+#define UMLENTITYATTRIBUTEDIALOG_H
+
+#include <kdialogbase.h>
+
+/**
+ * @author Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class QButtonGroup;
+class QCheckBox;
+class QGroupBox;
+class QRadioButton;
+class UMLEntityAttribute;
+class KComboBox;
+class QLineEdit;
+
+class UMLEntityAttributeDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ UMLEntityAttributeDialog( QWidget* pParent, UMLEntityAttribute* pEntityAttribute );
+ ~UMLEntityAttributeDialog();
+
+protected:
+ /**
+ * Sets up the dialog
+ */
+ void setupDialog();
+
+ /**
+ * Checks if changes are valid and applies them if they are,
+ * else returns false
+ */
+ bool apply();
+
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertType( const QString& type, int index = -1 );
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertAttribute( const QString& type, int index = -1 );
+
+ /**
+ * The EntityAttribute to represent
+ */
+ UMLEntityAttribute * m_pEntityAttribute;
+
+ //GUI Widgets
+ QGroupBox * m_pAttsGB, * m_pValuesGB;
+ QButtonGroup * m_pScopeBG;
+ QRadioButton * m_pPublicRB, * m_pPrivateRB, * m_pProtectedRB, * m_pNoneRB;
+ QLabel * m_pTypeL, * m_pNameL, * m_pInitialL, * m_pStereoTypeL, * m_pValuesL, * m_pAttributesL ;
+ KComboBox * m_pTypeCB;
+ KComboBox * m_pAttributesCB;
+ QLineEdit * m_pNameLE, * m_pInitialLE, * m_pStereoTypeLE, * m_pValuesLE;
+ QCheckBox* m_pAutoIncrementCB;
+ QCheckBox* m_pNullCB;
+
+public slots:
+ /**
+ * I don't think this is used, but if we had an apply button
+ * it would slot into here
+ */
+ void slotApply();
+
+ /**
+ * Used when the OK button is clicked. Calls apply()
+ */
+ void slotOk();
+ void slotNameChanged( const QString & );
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umloperationdialog.cpp b/umbrello/umbrello/dialogs/umloperationdialog.cpp
new file mode 100644
index 00000000..07c56d52
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umloperationdialog.cpp
@@ -0,0 +1,530 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umloperationdialog.h"
+
+//qt includes
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qbuttongroup.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+
+//kde includes
+#include <kcombobox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kbuttonbox.h>
+#include <karrowbutton.h>
+
+//app includes
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../operation.h"
+#include "../classifier.h"
+#include "../template.h"
+#include "../listpopupmenu.h"
+#include "../umlattributelist.h"
+#include "../classifierlistitem.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../dialog_utils.h"
+#include "parmpropdlg.h"
+#include "../stereotype.h"
+#include "../uniqueid.h"
+
+UMLOperationDialog::UMLOperationDialog( QWidget * parent, UMLOperation * pOperation )
+ : KDialogBase( Plain, i18n("Operation Properties"), Help | Ok | Cancel , Ok, parent, "_UMLOPERATIONDLG_", true, true) {
+ m_pOperation = pOperation;
+ m_doc = UMLApp::app()->getDocument();
+ m_pMenu = 0;
+ setupDialog();
+}
+
+UMLOperationDialog::~UMLOperationDialog() {}
+
+void UMLOperationDialog::setupDialog() {
+
+ int margin = fontMetrics().height();
+ QVBoxLayout * topLayout = new QVBoxLayout( plainPage() );
+
+ m_pGenGB = new QGroupBox(i18n("General Properties"), plainPage() );
+ QGridLayout * genLayout = new QGridLayout(m_pGenGB, 3, 4 );
+ genLayout -> setColStretch(1, 1);
+ genLayout -> setColStretch(3, 1);
+ genLayout -> addColSpacing(1, 200);
+ genLayout -> addColSpacing(3, 200);
+ genLayout -> setMargin(margin);
+ genLayout -> setSpacing(10);
+
+ Dialog_Utils::makeLabeledEditField( m_pGenGB, genLayout, 0,
+ m_pNameL, i18n("&Name:"),
+ m_pNameLE, m_pOperation->getName() );
+
+ m_pRtypeL = new QLabel(i18n("&Type:"), m_pGenGB );
+ genLayout -> addWidget(m_pRtypeL, 0, 2);
+
+ m_pRtypeCB = new KComboBox(true, m_pGenGB );
+ genLayout -> addWidget(m_pRtypeCB, 0, 3);
+ m_pRtypeL->setBuddy(m_pRtypeCB);
+
+ m_pStereoTypeL = new QLabel( i18n("Stereotype name:"), m_pGenGB );
+ genLayout -> addWidget(m_pStereoTypeL, 1, 0);
+ m_pStereoTypeCB = new KComboBox(true, m_pGenGB );
+ genLayout -> addWidget(m_pStereoTypeCB, 1, 1);
+
+ m_pAbstractCB = new QCheckBox( i18n("&Abstract operation"), m_pGenGB );
+ m_pAbstractCB -> setChecked( m_pOperation->getAbstract() );
+ genLayout -> addWidget( m_pAbstractCB, 2, 0 );
+ m_pStaticCB = new QCheckBox( i18n("Classifier &scope (\"static\")"), m_pGenGB );
+ m_pStaticCB -> setChecked( m_pOperation->getStatic() );
+ genLayout -> addWidget( m_pStaticCB, 2, 1 );
+ m_pQueryCB = new QCheckBox( i18n("&Query (\"const\")"), m_pGenGB );
+ m_pQueryCB -> setChecked( m_pOperation->getConst() );
+ genLayout -> addWidget( m_pQueryCB, 2, 2 );
+
+ topLayout -> addWidget( m_pGenGB );
+
+ m_pScopeBG = new QButtonGroup(i18n("Visibility"), plainPage() );
+
+ QHBoxLayout * scopeLayout = new QHBoxLayout(m_pScopeBG);
+ scopeLayout -> setMargin(margin);
+
+ m_pPublicRB = new QRadioButton(i18n("P&ublic"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pPublicRB);
+
+ m_pPrivateRB = new QRadioButton(i18n("P&rivate"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pPrivateRB);
+
+ m_pProtectedRB = new QRadioButton(i18n("Prot&ected"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pProtectedRB);
+
+ m_pImplementationRB = new QRadioButton(i18n("I&mplementation"), m_pScopeBG);
+ scopeLayout -> addWidget(m_pImplementationRB);
+
+ topLayout -> addWidget(m_pScopeBG);
+
+ m_pParmsGB = new QGroupBox(i18n("Parameters"), plainPage() );
+ QVBoxLayout* parmsLayout = new QVBoxLayout(m_pParmsGB);
+ parmsLayout->setMargin(margin);
+ parmsLayout->setSpacing(10);
+
+ //horizontal box contains the list box and the move up/down buttons
+ QHBoxLayout* parmsHBoxLayout = new QHBoxLayout(parmsLayout);
+ m_pParmsLB = new QListBox(m_pParmsGB);
+ parmsHBoxLayout->addWidget(m_pParmsLB);
+
+ //the move up/down buttons (another vertical box)
+ QVBoxLayout* buttonLayout = new QVBoxLayout( parmsHBoxLayout );
+ m_pUpButton = new KArrowButton( m_pParmsGB );
+ m_pUpButton->setEnabled( false );
+ buttonLayout->addWidget( m_pUpButton );
+
+ m_pDownButton = new KArrowButton( m_pParmsGB, Qt::DownArrow );
+ m_pDownButton->setEnabled( false );
+ buttonLayout->addWidget( m_pDownButton );
+
+ KButtonBox* buttonBox = new KButtonBox(m_pParmsGB);
+ buttonBox->addButton( i18n("Ne&w Parameter..."), this, SLOT(slotNewParameter()) );
+ m_pDeleteButton = buttonBox->addButton( i18n("&Delete"), this, SLOT(slotDeleteParameter()) );
+ m_pPropertiesButton = buttonBox->addButton( i18n("&Properties"), this,
+ SLOT(slotParameterProperties()) );
+ parmsLayout->addWidget(buttonBox);
+
+ topLayout -> addWidget(m_pParmsGB);
+
+ m_pDeleteButton->setEnabled(false);
+ m_pPropertiesButton->setEnabled(false);
+ m_pUpButton->setEnabled(false);
+ m_pDownButton->setEnabled(false);
+
+ // Add "void". We use this for denoting "no return type" independent
+ // of the programming language.
+ // For example, the Ada generator would interpret the return type
+ // "void" as an instruction to generate a procedure instead of a
+ // function.
+ insertType( "void" );
+
+ m_pRtypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pRtypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+
+ // add template parameters
+ UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(m_pOperation->parent());
+ if (classifier) {
+ UMLClassifierListItemList tmplParams( classifier->getFilteredList(Uml::ot_Template) );
+ for (UMLClassifierListItem *li = tmplParams.first(); li; li = tmplParams.next())
+ insertType( li->getName() );
+ }
+ //now add the Classes and Interfaces (both are Concepts)
+ UMLClassifierList namesList( m_doc->getConcepts() );
+ UMLClassifier* pConcept = 0;
+ for(pConcept=namesList.first(); pConcept!=0 ;pConcept=namesList.next()) {
+ insertType( pConcept->getFullyQualifiedName() );
+ }
+
+ //work out which one to select
+ int returnBoxCount = 0;
+ bool foundReturnType = false;
+ while (returnBoxCount < m_pRtypeCB->count() && foundReturnType == false) {
+ QString returnBoxString = m_pRtypeCB->text(returnBoxCount);
+ if ( returnBoxString == m_pOperation->getTypeName() ) {
+ foundReturnType = true;
+ m_pRtypeCB->setCurrentItem(returnBoxCount);
+ break;
+ }
+ returnBoxCount++;
+ }
+
+ if (!foundReturnType) {
+ insertType( m_pOperation->getTypeName(), 0 );
+ m_pRtypeCB->setCurrentItem(0);
+ }
+
+ //fill in parm list box
+ UMLAttributeList list = m_pOperation->getParmList();
+ UMLAttribute * pAtt = 0;
+ for (pAtt = list.first(); pAtt; pAtt = list.next())
+ m_pParmsLB->insertItem( pAtt->getName() );
+
+ //set scope
+ Uml::Visibility scope = m_pOperation -> getVisibility();
+ if( scope == Uml::Visibility::Public )
+ m_pPublicRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Private )
+ m_pPrivateRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Protected )
+ m_pProtectedRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Implementation )
+ m_pImplementationRB -> setChecked( true );
+
+ // manage stereotypes
+ m_pStereoTypeCB -> setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pStereoTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+ insertStereotype (QString("")); // an empty stereotype is the default
+ int defaultStereotype=0;
+ bool foundDefaultStereotype = false;
+ for (UMLStereotypeListIt it(m_doc->getStereotypes()); it.current(); ++it) {
+ if (!foundDefaultStereotype) {
+ if ( m_pOperation->getStereotype() == it.current()->getName()) {
+ foundDefaultStereotype = true;
+ }
+ defaultStereotype++;
+ }
+ insertStereotype (it.current()->getName());
+ }
+ // lookup for a default stereotype, if the operation doesn't have one
+ if (foundDefaultStereotype)
+ m_pStereoTypeCB->setCurrentItem(defaultStereotype);
+ else
+ m_pStereoTypeCB->setCurrentItem(-1);
+
+ //setup parm list box signals
+ connect( m_pUpButton, SIGNAL( clicked() ), this, SLOT( slotParameterUp() ) );
+ connect( m_pDownButton, SIGNAL( clicked() ), this, SLOT( slotParameterDown() ) );
+
+ connect(m_pParmsLB, SIGNAL(clicked(QListBoxItem*)),
+ this, SLOT(slotParamsBoxClicked(QListBoxItem*)));
+
+ connect(m_pParmsLB, SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotParmRightButtonPressed(QListBoxItem *, const QPoint &)));
+
+ connect(m_pParmsLB, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
+ this, SLOT(slotParmRightButtonClicked(QListBoxItem *, const QPoint &)));
+
+
+ connect(m_pParmsLB, SIGNAL(doubleClicked(QListBoxItem *)),
+ this, SLOT(slotParmDoubleClick(QListBoxItem *)));
+
+ m_pNameLE->setFocus();
+ connect( m_pNameLE, SIGNAL( textChanged ( const QString & ) ), SLOT( slotNameChanged( const QString & ) ) );
+ slotNameChanged(m_pNameLE->text() );
+
+}
+
+void UMLOperationDialog::slotNameChanged( const QString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+
+void UMLOperationDialog::slotParmRightButtonPressed(QListBoxItem *item, const QPoint &p) {
+ ListPopupMenu::Menu_Type type = ListPopupMenu::mt_Undefined;
+ if(item)//pressed on an item
+ {
+ type = ListPopupMenu::mt_Parameter_Selected;
+ } else//pressed into fresh air
+ {
+ type = ListPopupMenu::mt_New_Parameter;
+ }
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotParmPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ m_pMenu = new ListPopupMenu(this, type);
+ m_pMenu->popup(p);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotParmPopupMenuSel(int)));
+
+}
+
+void UMLOperationDialog::slotParmRightButtonClicked(QListBoxItem */*item*/, const QPoint &/*p*/) {
+ if(m_pMenu) {
+ m_pMenu -> hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotParmPopupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void UMLOperationDialog::slotParmDoubleClick(QListBoxItem *item) {
+ if(!item)
+ return;
+ slotParmPopupMenuSel(ListPopupMenu::mt_Properties);
+}
+
+void UMLOperationDialog::slotParmPopupMenuSel(int id) {
+ if( id == ListPopupMenu::mt_Rename || id == ListPopupMenu::mt_Properties ) {
+ slotParameterProperties();
+ } else if( id == ListPopupMenu::mt_New_Parameter ) {
+ slotNewParameter();
+ }
+ else if( id == ListPopupMenu::mt_Delete ) {
+ slotDeleteParameter();
+ }
+}
+
+void UMLOperationDialog::slotNewParameter() {
+ int result = 0;
+ UMLAttribute* pAtt = 0;
+
+ QString currentName = m_pOperation->getUniqueParameterName();
+ UMLAttribute* newAttribute = new UMLAttribute(m_pOperation, currentName, Uml::id_Reserved);
+
+ ParmPropDlg dlg(this, m_doc, newAttribute);
+ result = dlg.exec();
+ QString name = dlg.getName();
+ pAtt = m_pOperation -> findParm( name );
+ if( result ) {
+ if( name.length() == 0 ) {
+ KMessageBox::error(this, i18n("You have entered an invalid parameter name."),
+ i18n("Parameter Name Invalid"), false);
+ delete newAttribute;
+ return;
+ }
+ if( !pAtt ) {
+ newAttribute->setID( UniqueID::gen() );
+ newAttribute->setName( name );
+ newAttribute->setTypeName( dlg.getTypeName() );
+ newAttribute->setInitialValue( dlg.getInitialValue() );
+ newAttribute->setDoc( dlg.getDoc() );
+ newAttribute->setParmKind( dlg.getParmKind() );
+ m_pOperation->addParm( newAttribute );
+ m_pParmsLB -> insertItem( name );
+ m_doc -> setModified( true );
+ } else {
+ KMessageBox::sorry(this, i18n("The parameter name you have chosen\nis already being used in this operation."),
+ i18n("Parameter Name Not Unique"), false);
+ delete newAttribute;
+ }
+ } else {
+ delete newAttribute;
+ }
+}
+
+void UMLOperationDialog::slotDeleteParameter() {
+ UMLAttribute* pOldAtt = m_pOperation->findParm( m_pParmsLB->currentText() );
+
+ m_pOperation->removeParm( pOldAtt );
+ m_pParmsLB->removeItem( m_pParmsLB->currentItem() );
+ m_doc->setModified(true);
+
+ m_pDeleteButton->setEnabled(false);
+ m_pPropertiesButton->setEnabled(false);
+ m_pUpButton->setEnabled(false);
+ m_pDownButton->setEnabled(false);
+}
+
+void UMLOperationDialog::slotParameterProperties() {
+ int result = 0;
+ UMLAttribute* pAtt = 0, * pOldAtt = 0;
+ pOldAtt = m_pOperation->findParm( m_pParmsLB->currentText() );
+
+ if( !pOldAtt ) {
+ kDebug() << "THE impossible has occurred for:" << m_pParmsLB->currentText() << endl;
+ return;
+ }//should never occur
+ ParmPropDlg dlg(this, m_doc, pOldAtt);
+ result = dlg.exec();
+ QString name = dlg.getName();
+ pAtt = m_pOperation->findParm( name );
+ if( result ) {
+ if( name.length() == 0 ) {
+ KMessageBox::error(this, i18n("You have entered an invalid parameter name."),
+ i18n("Parameter Name Invalid"), false);
+ return;
+ }
+ if ( !pAtt || pOldAtt->getTypeName() != dlg.getTypeName() ||
+ pOldAtt->getDoc() != dlg.getDoc() ||
+ pOldAtt->getInitialValue() != dlg.getInitialValue() ) {
+ pOldAtt->setName( name );
+ QString typeName = dlg.getTypeName();
+ if (pOldAtt->getTypeName() != typeName) {
+ UMLClassifierList namesList( m_doc->getConcepts() );
+ UMLClassifier* obj = NULL;
+ for (obj=namesList.first(); obj!=0; obj=namesList.next()) {
+ if (typeName == obj->getFullyQualifiedName()) {
+ pOldAtt->setType( obj );
+ break;
+ }
+ }
+ if (obj == NULL) {
+ // Nothing found: set type name directly. Bad.
+ kDebug() << "UMLOperationDialog::slotParameterProperties: "
+ << typeName << " not found." << endl;
+ pOldAtt->setTypeName( typeName ); // Bad.
+ }
+ }
+ m_pParmsLB->changeItem( dlg.getName(), m_pParmsLB -> currentItem() );
+ pOldAtt->setDoc( dlg.getDoc() );
+ pOldAtt->setInitialValue( dlg.getInitialValue() );
+ m_doc->setModified( true );
+ } else if( pAtt != pOldAtt ) {
+ KMessageBox::error(this, i18n("The parameter name you have chosen is already being used in this operation."),
+ i18n("Parameter Name Not Unique"), false);
+ }
+ }
+}
+
+void UMLOperationDialog::slotParameterUp()
+{
+ kDebug() << k_funcinfo << endl;
+ UMLAttribute* pOldAtt = m_pOperation->findParm( m_pParmsLB->currentText() );
+
+ m_pOperation->moveParmLeft( pOldAtt );
+ QString tmp = m_pParmsLB->currentText();
+ m_pParmsLB->changeItem( m_pParmsLB->item( m_pParmsLB->currentItem() - 1 )->text(), m_pParmsLB->currentItem() );
+ m_pParmsLB->changeItem( tmp, m_pParmsLB->currentItem() - 1 );
+ m_doc->setModified(true);
+ slotParamsBoxClicked( m_pParmsLB->selectedItem() );
+}
+
+void UMLOperationDialog::slotParameterDown()
+{
+ UMLAttribute* pOldAtt = m_pOperation->findParm( m_pParmsLB->currentText() );
+
+ m_pOperation->moveParmRight( pOldAtt );
+ QString tmp = m_pParmsLB->currentText();
+ m_pParmsLB->changeItem( m_pParmsLB->item( m_pParmsLB->currentItem() + 1 )->text(), m_pParmsLB->currentItem() );
+ m_pParmsLB->changeItem( tmp, m_pParmsLB->currentItem() + 1 );
+
+ m_doc->setModified(true);
+ slotParamsBoxClicked( m_pParmsLB->selectedItem() );
+}
+
+void UMLOperationDialog::slotParamsBoxClicked(QListBoxItem* parameterItem) {
+ if (parameterItem) {
+ m_pDeleteButton->setEnabled(true);
+ m_pPropertiesButton->setEnabled(true);
+ m_pUpButton->setEnabled( parameterItem->prev() );
+ m_pDownButton->setEnabled( parameterItem->next() );
+ } else {
+ m_pDeleteButton->setEnabled(false);
+ m_pPropertiesButton->setEnabled(false);
+ m_pUpButton->setEnabled(false);
+ m_pDownButton->setEnabled(false);
+ }
+}
+
+bool UMLOperationDialog::apply()
+{
+ QString name = m_pNameLE -> text();
+ if( name.length() == 0 ) {
+ KMessageBox::error(this, i18n("You have entered an invalid operation name."),
+ i18n("Operation Name Invalid"), false);
+ m_pNameLE -> setText( m_pOperation -> getName() );
+ return false;
+ }
+
+ UMLClassifier *classifier = dynamic_cast<UMLClassifier*>( m_pOperation->parent() );
+ if( classifier != 0L &&
+ classifier->checkOperationSignature(name, m_pOperation->getParmList(), m_pOperation) )
+ {
+ QString msg = QString(i18n("An operation with that signature already exists in %1.\n")).arg(classifier->getName())
+ +
+ QString(i18n("Choose a different name or parameter list." ));
+ KMessageBox::error(this, msg, i18n("Operation Name Invalid"), false);
+ return false;
+ }
+ m_pOperation -> setName( name );
+
+ if( m_pPublicRB -> isChecked() )
+ m_pOperation -> setVisibility( Uml::Visibility::Public );
+ else if( m_pPrivateRB -> isChecked() )
+ m_pOperation -> setVisibility( Uml::Visibility::Private );
+ else if (m_pProtectedRB -> isChecked() )
+ m_pOperation -> setVisibility( Uml::Visibility::Protected );
+ else if (m_pImplementationRB -> isChecked() )
+ m_pOperation -> setVisibility( Uml::Visibility::Implementation );
+
+ QString typeName = m_pRtypeCB->currentText();
+ UMLTemplate *tmplParam = classifier->findTemplate(typeName);
+ if (tmplParam)
+ m_pOperation->setType(tmplParam);
+ else
+ m_pOperation->setTypeName(typeName);
+
+ m_pOperation->setStereotype( m_pStereoTypeCB->currentText() );
+
+ bool isAbstract = m_pAbstractCB->isChecked();
+ m_pOperation -> setAbstract( isAbstract );
+ if (isAbstract) {
+ /* If any operation is abstract then the owning class needs
+ to be made abstract.
+ The inverse is not true: The fact that no operation is
+ abstract does not mean that the class must be non-abstract.
+ */
+ classifier->setAbstract(true);
+ }
+ m_pOperation->setStatic( m_pStaticCB->isChecked() );
+ m_pOperation->setConst( m_pQueryCB->isChecked() );
+
+ return true;
+}
+
+void UMLOperationDialog::slotApply() {
+ apply();
+}
+
+void UMLOperationDialog::slotOk() {
+ if ( apply() ) {
+ accept();
+ }
+}
+
+void UMLOperationDialog::insertType( const QString& type, int index )
+{
+ m_pRtypeCB->insertItem( type, index );
+ m_pRtypeCB->completionObject()->addItem( type );
+}
+
+void UMLOperationDialog::insertStereotype( const QString& type, int index )
+{
+ m_pStereoTypeCB->insertItem( type, index );
+ m_pStereoTypeCB->completionObject()->addItem( type );
+}
+
+#include "umloperationdialog.moc"
diff --git a/umbrello/umbrello/dialogs/umloperationdialog.h b/umbrello/umbrello/dialogs/umloperationdialog.h
new file mode 100644
index 00000000..1dee99ab
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umloperationdialog.h
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef UMLOPERATIONDIALOG_H
+#define UMLOPERATIONDIALOG_H
+
+//kde includes
+#include <kdialogbase.h>
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLOperation;
+class ListPopupMenu;
+class QGroupBox;
+class QListBox;
+class QButtonGroup;
+class QRadioButton;
+class QPushButton;
+class QLabel;
+class QCheckBox;
+class KComboBox;
+class QLineEdit;
+class UMLDoc;
+class KArrowButton;
+
+class UMLOperationDialog : public KDialogBase {
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ UMLOperationDialog( QWidget * parent, UMLOperation * pOperation );
+
+ /**
+ * Deconstructor
+ */
+ ~UMLOperationDialog();
+
+protected:
+ /**
+ * Sets up the dialog
+ */
+ void setupDialog();
+
+ /**
+ * Checks if changes are valid and applies them if they are,
+ * else returns false
+ */
+ bool apply();
+
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertType( const QString& type, int index = -1 );
+
+ /**
+ * The operation to represent.
+ */
+ UMLOperation * m_pOperation;
+
+ /**
+ * The UMLDocument where all objects live
+ */
+ UMLDoc *m_doc;
+
+ /**
+ * Menu used in paramater list box.
+ */
+ ListPopupMenu * m_pMenu;
+
+ /**
+ * Inserts @p stereotype into the stereotype-combobox as well as its completion object.
+ */
+ void insertStereotype( const QString& type, int index = -1 );
+
+ //GUI widgets
+ QGroupBox * m_pParmsGB, * m_pGenGB;
+ QListBox * m_pParmsLB;
+ QButtonGroup * m_pScopeBG;
+ QRadioButton * m_pPublicRB, * m_pPrivateRB, * m_pProtectedRB, *m_pImplementationRB;
+ QLabel * m_pRtypeL, * m_pNameL, * m_pStereoTypeL;
+ KComboBox * m_pRtypeCB, * m_pStereoTypeCB;
+ QLineEdit * m_pNameLE;
+ QCheckBox * m_pAbstractCB;
+ QCheckBox * m_pStaticCB;
+ QCheckBox * m_pQueryCB;
+ QPushButton* m_pDeleteButton;
+ QPushButton* m_pPropertiesButton;
+ KArrowButton* m_pUpButton;
+ KArrowButton* m_pDownButton;
+
+public slots:
+ void slotParmRightButtonPressed(QListBoxItem *item, const QPoint &p);
+ void slotParmRightButtonClicked(QListBoxItem *item, const QPoint &p);
+ void slotParmDoubleClick(QListBoxItem *item);
+ void slotParmPopupMenuSel(int id);
+ void slotNewParameter();
+ void slotDeleteParameter();
+ void slotParameterProperties();
+ void slotParameterUp();
+ void slotParameterDown();
+
+ /**
+ * enables or disables buttons
+ */
+ void slotParamsBoxClicked(QListBoxItem* parameterItem);
+
+ /**
+ * I don't think this is used, but if we had an apply button
+ * it would slot into here
+ */
+ void slotApply();
+
+ /**
+ * Used when the OK button is clicked. Calls apply()
+ */
+ void slotOk();
+ void slotNameChanged( const QString & );
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlroledialog.cpp b/umbrello/umbrello/dialogs/umlroledialog.cpp
new file mode 100644
index 00000000..91ad5c65
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlroledialog.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlroledialog.h"
+
+// qt/kde includes
+#include <qlayout.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// app includes
+#include "../umlrole.h"
+#include "umlroleproperties.h"
+
+UMLRoleDialog::UMLRoleDialog( QWidget * parent, UMLRole * pRole )
+ : KDialogBase( Plain, i18n("Role Properties"), Help | Ok | Cancel , Ok, parent, "_UMLROLEDLG_", true, true)
+{
+ m_pRole = pRole;
+ setupDialog();
+}
+
+UMLRoleDialog::~UMLRoleDialog() {}
+
+void UMLRoleDialog::setupDialog() {
+ // UMLRoleDialogLayout = new QGridLayout( this, 1, 1, 11, 6, "UMLRoleLayout");
+ m_pRoleProps = new UMLRoleProperties(this, m_pRole);
+ setMainWidget( m_pRoleProps );
+
+ resize( QSize(425, 620).expandedTo(minimumSizeHint()) );
+
+ // topLayout -> addWidget( m_pParmsGB);
+
+}
+
+bool UMLRoleDialog::apply() {
+ if( m_pRoleProps ) {
+ m_pRoleProps->updateObject();
+ return true;
+ }
+ return false;
+}
+
+void UMLRoleDialog::slotApply() {
+ apply();
+}
+
+void UMLRoleDialog::slotOk() {
+ if ( apply() ) {
+ accept();
+ }
+}
+
+
+#include "umlroledialog.moc"
diff --git a/umbrello/umbrello/dialogs/umlroledialog.h b/umbrello/umbrello/dialogs/umlroledialog.h
new file mode 100644
index 00000000..09856d34
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlroledialog.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef UMLROLEDIALOG_H
+#define UMLROLEDIALOG_H
+
+//kde includes
+#include <kdialogbase.h>
+
+/**
+ * @author Paul Hensgen
+ */
+
+class UMLRole;
+class UMLRoleProperties;
+
+class UMLRoleDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ UMLRoleDialog( QWidget * parent, UMLRole * pRole );
+
+ /**
+ * Deconstructor
+ */
+ ~UMLRoleDialog();
+
+protected:
+
+ /**
+ * Sets up the dialog
+ */
+ void setupDialog();
+
+ /**
+ * Checks if changes are valid and applies them if they are,
+ * else returns false
+ */
+ bool apply();
+
+ /**
+ * The role to represent.
+ */
+ UMLRole * m_pRole;
+
+private:
+
+ UMLRoleProperties * m_pRoleProps;
+
+public slots:
+
+ /**
+ * I don't think this is used, but if we had an apply button
+ * it would slot into here
+ */
+ void slotApply();
+
+ /**
+ * Used when the OK button is clicked. Calls apply()
+ */
+ void slotOk();
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlroleproperties.cpp b/umbrello/umbrello/dialogs/umlroleproperties.cpp
new file mode 100644
index 00000000..275d98f1
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlroleproperties.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlroleproperties.h"
+
+// qt/kde includes
+#include <qradiobutton.h>
+#include <qtextedit.h>
+#include <qlineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+
+UMLRoleProperties::UMLRoleProperties ( QWidget *parent, UMLRole *role)
+ : UMLRolePropertiesBase (parent)
+{
+
+ m_pRole = role;
+ constructWidget();
+
+}
+
+UMLRoleProperties::~UMLRoleProperties() { }
+
+void UMLRoleProperties::constructWidget() {
+
+ // Use Parent Role to set starting Properties
+ //
+
+ // Rolename
+ m_pRoleLE -> setText(m_pRole->getName());
+
+ // Multiplicity
+ m_pMultiLE -> setText(m_pRole->getMultiplicity());
+
+ // Visibility
+ Uml::Visibility scope = m_pRole->getVisibility();
+ if( scope == Uml::Visibility::Public )
+ m_pPublicRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Private )
+ m_pPrivateRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Protected )
+ m_pProtectedRB -> setChecked( true );
+ else if( scope == Uml::Visibility::Implementation )
+ m_pImplementationRB -> setChecked( true );
+
+ // Changeability
+ Uml::Changeability_Type changeability = m_pRole->getChangeability();
+ if( changeability == Uml::chg_Changeable )
+ m_pChangeableRB -> setChecked( true );
+ else if( changeability == Uml::chg_Frozen )
+ m_pFrozenRB -> setChecked( true );
+ else
+ m_pAddOnlyRB -> setChecked( true );
+
+ // Documentation
+ //
+ m_pDocTE-> setText(m_pRole-> getDoc());
+ //m_pDocTE->setWordWrap(QMultiLineEdit::WidgetWidth);
+}
+
+void UMLRoleProperties::updateObject() {
+
+ if(m_pRole) {
+
+ // block signals to save work load..we only need to emit modified once,
+ // not each time we update an attribute of the association. I suppose
+ // we could check to see IF anything changed, but thats a lot more code,
+ // and not much gained. THis way is easier, if less 'beautiful'. -b.t.
+
+ m_pRole->blockSignals(true);
+
+ // set props
+ m_pRole->setName(m_pRoleLE->text());
+ m_pRole->setMultiplicity(m_pMultiLE->text());
+
+ if(m_pPrivateRB->isChecked())
+ m_pRole->setVisibility(Uml::Visibility::Private);
+ else if(m_pProtectedRB->isChecked())
+ m_pRole->setVisibility(Uml::Visibility::Protected);
+ else if(m_pPublicRB->isChecked())
+ m_pRole->setVisibility(Uml::Visibility::Public);
+ else if(m_pImplementationRB->isChecked())
+ m_pRole->setVisibility(Uml::Visibility::Implementation);
+
+ if(m_pFrozenRB->isChecked())
+ m_pRole->setChangeability(Uml::chg_Frozen);
+ else if(m_pAddOnlyRB->isChecked())
+ m_pRole->setChangeability(Uml::chg_AddOnly);
+ else
+ m_pRole->setChangeability(Uml::chg_Changeable);
+
+ m_pRole->setDoc(m_pDocTE->text());
+
+ m_pRole->blockSignals(false);
+
+ m_pRole->emitModified();
+
+ } //end if m_pRole
+
+}
+
+
+#include "umlroleproperties.moc"
diff --git a/umbrello/umbrello/dialogs/umlroleproperties.h b/umbrello/umbrello/dialogs/umlroleproperties.h
new file mode 100644
index 00000000..34f7d3e9
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlroleproperties.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLROLEPROPERTIES_H
+#define UMLROLEPROPERTIES_H
+
+//my class includes
+#include "umlrolepropertiesbase.h"
+#include "../umlrole.h"
+
+/**
+ * Displays properties of a UMLRole in a widget which may be used as
+ * a properties page or a stand-alone dialog.
+ *
+ * @author Brian Thomas <brian.thomas@gsfc.nasa.gov>
+ */
+class UMLRoleProperties : public UMLRolePropertiesBase {
+ Q_OBJECT
+public:
+
+ /**
+ * Sets up the UMLRoleProperties.
+ *
+ * @param parent The parent widget to the UMLRoleProperties.
+ * @param role The UMLRole to display the properties of.
+ */
+ UMLRoleProperties( QWidget *parent, UMLRole *role);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~UMLRoleProperties();
+
+ /**
+ * Will move information from the dialog into the object.
+ * Call when the ok or apply button is pressed.
+ */
+ void updateObject();
+
+protected:
+
+ // the parent role object
+ UMLRole * m_pRole;
+
+private:
+
+ void constructWidget();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlrolepropertiesbase.ui b/umbrello/umbrello/dialogs/umlrolepropertiesbase.ui
new file mode 100644
index 00000000..7c35a284
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlrolepropertiesbase.ui
@@ -0,0 +1,203 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>UMLRolePropertiesBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>UMLRolePropertiesBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>572</width>
+ <height>545</height>
+ </rect>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>400</width>
+ <height>520</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>propsGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Role Properties</string>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>360</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>roleNameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Rolename:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_pMultiLE</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_pRoleLE</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Multiplicity:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ <widget class="QGroupBox" row="3" column="0">
+ <property name="name">
+ <cstring>docGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Documentation</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTextEdit" row="0" column="0">
+ <property name="name">
+ <cstring>m_pDocTE</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QButtonGroup" row="2" column="0">
+ <property name="name">
+ <cstring>changeabilityButtonGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Role Changeability</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_pAddOnlyRB</cstring>
+ </property>
+ <property name="text">
+ <string>Add only</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="1">
+ <property name="name">
+ <cstring>m_pFrozenRB</cstring>
+ </property>
+ <property name="text">
+ <string>Frozen</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_pChangeableRB</cstring>
+ </property>
+ <property name="text">
+ <string>Changeable</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QButtonGroup" row="1" column="0">
+ <property name="name">
+ <cstring>visibilityButtonGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Role Visibility</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_pPublicRB</cstring>
+ </property>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="1">
+ <property name="name">
+ <cstring>m_pPrivateRB</cstring>
+ </property>
+ <property name="text">
+ <string>Private</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_pProtectedRB</cstring>
+ </property>
+ <property name="text">
+ <string>Protected</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="3">
+ <property name="name">
+ <cstring>m_pImplementationRB</cstring>
+ </property>
+ <property name="text">
+ <string>Implementation</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/umbrello/umbrello/dialogs/umltemplatedialog.cpp b/umbrello/umbrello/dialogs/umltemplatedialog.cpp
new file mode 100644
index 00000000..a183d95d
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umltemplatedialog.cpp
@@ -0,0 +1,161 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umltemplatedialog.h"
+
+// qt includes
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+
+// kde includes
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// app includes
+#include "../template.h"
+#include "../classifier.h"
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../dialog_utils.h"
+
+UMLTemplateDialog::UMLTemplateDialog(QWidget* pParent, UMLTemplate* pTemplate)
+ : KDialogBase( Plain, i18n("Template Properties"), Help | Ok | Cancel , Ok, pParent, "_UMLTemplateDLG_", true, true) {
+ m_pTemplate = pTemplate;
+ setupDialog();
+}
+
+UMLTemplateDialog::~UMLTemplateDialog() {}
+
+void UMLTemplateDialog::setupDialog() {
+ int margin = fontMetrics().height();
+
+ QVBoxLayout* mainLayout = new QVBoxLayout( plainPage() );
+
+ m_pValuesGB = new QGroupBox(i18n("General Properties"), plainPage() );
+ QGridLayout* valuesLayout = new QGridLayout(m_pValuesGB, 3, 2);
+ valuesLayout->setMargin(margin);
+ valuesLayout->setSpacing(10);
+
+ m_pTypeL = new QLabel(i18n("&Type:"), m_pValuesGB);
+ valuesLayout->addWidget(m_pTypeL, 0, 0);
+
+ m_pTypeCB = new KComboBox(m_pValuesGB);
+ valuesLayout->addWidget(m_pTypeCB, 0, 1);
+ m_pTypeL->setBuddy(m_pTypeCB);
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 1,
+ m_pNameL, i18n("&Name:"),
+ m_pNameLE, m_pTemplate->getName() );
+
+ Dialog_Utils::makeLabeledEditField( m_pValuesGB, valuesLayout, 2,
+ m_pStereoTypeL, i18n("&Stereotype name:"),
+ m_pStereoTypeLE, m_pTemplate->getStereotype() );
+
+ mainLayout->addWidget(m_pValuesGB);
+
+ // "class" is the nominal type of template parameter
+ insertType( "class" );
+ // Add the active data types to combo box
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLClassifierList namesList( pDoc->getConcepts() );
+ UMLClassifier* obj = 0;
+ for (obj = namesList.first(); obj; obj = namesList.next()) {
+ insertType( obj->getName() );
+ }
+
+ m_pTypeCB->setEditable(true);
+ m_pTypeCB->setDuplicatesEnabled(false);//only allow one of each type in box
+ m_pTypeCB->setCompletionMode( KGlobalSettings::CompletionPopup );
+// m_pTypeCB->setAutoCompletion(true);
+
+ //work out which one to select
+ int typeBoxCount = 0;
+ bool foundType = false;
+ while (typeBoxCount < m_pTypeCB->count() && foundType == false) {
+ QString typeBoxString = m_pTypeCB->text(typeBoxCount);
+ if ( typeBoxString == m_pTemplate->getTypeName() ) {
+ foundType = true;
+ m_pTypeCB->setCurrentItem(typeBoxCount);
+ } else {
+ typeBoxCount++;
+ }
+ }
+
+ if (!foundType) {
+ insertType( m_pTemplate->getTypeName(), 0 );
+ m_pTypeCB->setCurrentItem(0);
+ }
+
+ m_pNameLE->setFocus();
+}
+
+void UMLTemplateDialog::insertType( const QString& type, int index )
+{
+ m_pTypeCB->insertItem( type, index );
+ m_pTypeCB->completionObject()->addItem( type );
+}
+
+bool UMLTemplateDialog::apply() {
+ QString typeName = m_pTypeCB->currentText();
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLClassifierList namesList( pDoc->getConcepts() );
+ UMLClassifier* obj = 0;
+ for (obj = namesList.first(); obj; obj = namesList.next()) {
+ if (typeName == obj->getName()) {
+ m_pTemplate->setType( obj );
+ }
+ }
+ if (obj == NULL) { // not found.
+ // FIXME: This implementation is not good yet.
+ m_pTemplate->setTypeName( typeName );
+ }
+ QString name = m_pNameLE->text();
+ if( name.length() == 0 ) {
+ KMessageBox::error(this, i18n("You have entered an invalid template name."),
+ i18n("Template Name Invalid"), false);
+ m_pNameLE->setText( m_pTemplate->getName() );
+ return false;
+ }
+
+ UMLClassifier * pClass = dynamic_cast<UMLClassifier *>( m_pTemplate->parent() );
+ if (pClass) {
+ UMLObject *o = pClass->findChildObject(name);
+ if (o && o != m_pTemplate) {
+ KMessageBox::error(this, i18n("The template parameter name you have chosen is already being used in this operation."),
+ i18n("Template Name Not Unique"), false);
+ m_pNameLE->setText( m_pTemplate->getName() );
+ return false;
+ }
+ }
+ m_pTemplate->setName(name);
+
+ m_pTemplate->setStereotype( m_pStereoTypeLE->text() );
+
+ return true;
+}
+
+void UMLTemplateDialog::slotApply() {
+ apply();
+}
+
+void UMLTemplateDialog::slotOk() {
+ if ( apply() ) {
+ accept();
+ }
+}
+
+#include "umltemplatedialog.moc"
diff --git a/umbrello/umbrello/dialogs/umltemplatedialog.h b/umbrello/umbrello/dialogs/umltemplatedialog.h
new file mode 100644
index 00000000..3bdd321b
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umltemplatedialog.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLTEMPLATEDIALOG_H
+#define UMLTEMPLATEDIALOG_H
+
+#include <kdialogbase.h>
+
+class QButtonGroup;
+class QCheckBox;
+class KComboBox;
+class QGroupBox;
+class QLineEdit;
+class QRadioButton;
+class UMLTemplate;
+
+/**
+ * A dialog to edit the properties of a class template (paramaterised class)
+ *
+ * @author Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLTemplateDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ UMLTemplateDialog(QWidget* pParent, UMLTemplate* pAttribute);
+ ~UMLTemplateDialog();
+
+protected:
+ /**
+ * Sets up the dialog
+ */
+ void setupDialog();
+
+ /**
+ * Checks if changes are valid and applies them if they are,
+ * else returns false
+ */
+ bool apply();
+
+ /**
+ * The Attribute to represent
+ */
+ UMLTemplate* m_pTemplate;
+
+ //GUI Widgets
+ QGroupBox* m_pTemplateGB;
+ QGroupBox* m_pValuesGB;
+ QLabel *m_pTypeL, *m_pNameL, *m_pStereoTypeL;
+ KComboBox* m_pTypeCB;
+ QLineEdit *m_pNameLE, *m_pStereoTypeLE;
+
+public slots:
+ /**
+ * I don't think this is used, but if we had an apply button
+ * it would slot into here
+ */
+ void slotApply();
+
+ /**
+ * Used when the OK button is clicked. Calls apply()
+ */
+ void slotOk();
+protected:
+ /**
+ * Inserts @p type into the type-combobox as well as its completion object.
+ */
+ void insertType( const QString& type, int index = -1 );
+
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlviewdialog.cpp b/umbrello/umbrello/dialogs/umlviewdialog.cpp
new file mode 100644
index 00000000..94f44059
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlviewdialog.cpp
@@ -0,0 +1,184 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlviewdialog.h"
+
+// qt/kde includes
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qgroupbox.h>
+#include <qtextedit.h>
+#include <qspinbox.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kfontdialog.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+// local includes
+#include "../umlview.h"
+#include "../umldoc.h"
+#include "../uml.h"
+#include "diagrampropertiespage.h"
+
+
+UMLViewDialog::UMLViewDialog( QWidget * pParent, UMLView * pView ) : KDialogBase(IconList, i18n("Properties"), Ok | Apply | Cancel | Help,
+ Ok, pParent, "_VIEWDLG_", true, true) {
+ m_pView = pView;
+ m_options = m_pView -> getOptionState();
+ setupPages();
+}
+
+UMLViewDialog::~UMLViewDialog() {
+}
+
+void UMLViewDialog::slotOk() {
+ applyPage( General );
+ applyPage( Color );
+ applyPage( Font );
+ applyPage( Class );
+ accept();
+}
+
+void UMLViewDialog::slotApply() {
+ applyPage( (Page)activePageIndex() );
+}
+
+void UMLViewDialog::setupPages()
+{
+ setupDiagramPropertiesPage();
+ setupColorPage();
+ setupFontPage();
+ setupClassPage();
+}
+
+void UMLViewDialog::setupDiagramPropertiesPage()
+{
+ QVBox *page = addVBoxPage( i18n("General"), i18n("General Settings"), DesktopIcon( "misc") );
+ m_diagramProperties = new DiagramPropertiesPage(page);
+
+ m_diagramProperties->diagramName->setText( m_pView->getName() );
+ m_diagramProperties->zoom->setValue(m_pView->currentZoom());
+ m_diagramProperties->showOpSigs->setChecked( m_pView->getShowOpSig() );
+
+ m_diagramProperties->showGrid->setChecked(m_pView -> getShowSnapGrid());
+ m_diagramProperties->snapToGrid->setChecked(m_pView-> getSnapToGrid());
+ m_diagramProperties->snapComponentSizeToGrid->setChecked(m_pView-> getSnapComponentSizeToGrid());
+
+ m_diagramProperties->gridSpaceX->setValue( m_pView -> getSnapX());
+ m_diagramProperties->gridSpaceY->setValue( m_pView -> getSnapY());
+ m_diagramProperties->lineWidth->setValue( m_pView -> getLineWidth());
+ m_diagramProperties->documentation->setText(m_pView -> getDoc());
+
+}
+
+void UMLViewDialog::setupClassPage() {
+ if( m_pView -> getType() != Uml::dt_Class ) {
+ return;
+ }
+
+ QFrame * newPage = addPage( i18n("Display"), i18n("Classes Display Options"), DesktopIcon( "info") );
+ QHBoxLayout * m_pOptionsLayout = new QHBoxLayout( newPage );
+ m_pOptionsPage = new ClassOptionsPage( newPage, &m_options );
+ m_pOptionsLayout -> addWidget( m_pOptionsPage );
+}
+
+void UMLViewDialog::setupColorPage() {
+ QFrame * colorPage = addPage( i18n("Color"), i18n("Diagram Colors"), DesktopIcon( "colors") );
+ QHBoxLayout * m_pColorLayout = new QHBoxLayout(colorPage);
+ m_pColorPage = new UMLWidgetColorPage( colorPage, &m_options );
+ m_pColorLayout -> addWidget(m_pColorPage);
+}
+
+void UMLViewDialog::setupFontPage() {
+ QVBox * page = addVBoxPage( i18n("Font"), i18n("Font Settings"), DesktopIcon( "fonts") );
+ m_pChooser = new KFontChooser( (QWidget*)page, "font", false, QStringList(), false);
+ m_pChooser -> setFont( m_pView -> getOptionState().uiState.font );
+}
+
+void UMLViewDialog::applyPage( Page page ) {
+
+ switch (page) {
+ case General:
+ {
+ checkName();
+ m_pView->setZoom( m_diagramProperties->zoom->value() );
+ m_pView->setDoc( m_diagramProperties->documentation->text() );
+ m_pView->setSnapX( m_diagramProperties->gridSpaceX->value() );
+ m_pView->setSnapY( m_diagramProperties->gridSpaceY->value() );
+ m_pView->setLineWidth( m_diagramProperties->lineWidth->value() );
+ m_pView->setSnapToGrid( m_diagramProperties->snapToGrid->isChecked() );
+ m_pView->setSnapComponentSizeToGrid( m_diagramProperties->snapComponentSizeToGrid->isChecked() );
+ m_pView->setShowSnapGrid( m_diagramProperties->showGrid->isChecked() );
+ m_pView->setShowOpSig( m_diagramProperties->showOpSigs->isChecked() );
+ break;
+ }
+ case Color:
+ m_pColorPage->updateUMLWidget();
+ m_pView->setUseFillColor( m_options.uiState.useFillColor );
+ m_pView->setLineColor( m_options.uiState.lineColor );
+ m_pView->setFillColor( m_options.uiState.fillColor );
+ break;
+
+ case Font:
+ kDebug() << "UMLViewDialog::applyPage: setting font "
+ << m_pChooser->font().toString() << endl;
+ m_pView->setFont( m_pChooser->font(), true );
+ break;
+
+ case Class:
+ if( m_pView->getType() != Uml::dt_Class ) {
+ return;
+ }
+ m_pOptionsPage->updateUMLWidget();
+ m_pView->setClassWidgetOptions( m_pOptionsPage );
+ // sig = m_pTempWidget->getShowOpSigs();
+ // showSig = !( sig == Uml::st_NoSig || sig == Uml::st_NoSigNoVis );
+ // options.classState.showOpSig = showSig;
+ // sig = m_pTempWidget->getShowAttSigs();
+ // showSig = !( sig == Uml::st_NoSig || sig == Uml::st_NoSigNoVis );
+ // options.classState.showAttSig = showSig;
+ m_pView->setOptionState( m_options );
+ break;
+ }
+}
+
+void UMLViewDialog::checkName() {
+ QString name = m_diagramProperties->diagramName-> text();
+ UMLDoc * pDoc = UMLApp::app()-> getDocument();
+ UMLView * pView = pDoc -> findView( m_pView -> getType(), name );
+ if( name.length() == 0 ) {
+ KMessageBox::sorry(this, i18n("The name you have entered is invalid."),
+ i18n("Invalid Name"), false);
+ m_diagramProperties->diagramName->setText( m_pView->getName() );
+ return;
+ }
+ if( pView && pView != m_pView ) {
+ KMessageBox::sorry(this, i18n("The name you have entered is not unique."),
+ i18n("Name Not Unique"), false);
+ m_diagramProperties->diagramName->setText( m_pView->getName() );
+ return;
+ }
+ m_pView->setName( name );
+ pDoc->signalDiagramRenamed(m_pView);
+}
+
+
+
+
+
+
+#include "umlviewdialog.moc"
diff --git a/umbrello/umbrello/dialogs/umlviewdialog.h b/umbrello/umbrello/dialogs/umlviewdialog.h
new file mode 100644
index 00000000..b6fe4ebd
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlviewdialog.h
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEWDIALOG_H
+#define UMLVIEWDIALOG_H
+//kde includes
+#include <kdialogbase.h>
+//app includes
+#include "classoptionspage.h"
+#include "umlwidgetcolorpage.h"
+#include "../optionstate.h"
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLView;
+class ClassWidget;
+
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QGroupBox;
+class QTextEdit;
+class QSpinBox;
+class KFontChooser;
+class DiagramPropertiesPage;
+
+
+class UMLViewDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ UMLViewDialog( QWidget * pParent, UMLView * pView );
+
+ /**
+ * Deconstructor
+ */
+ ~UMLViewDialog();
+protected:
+ enum Page
+ {
+ General = 0,
+ Color,
+ Font,
+ Class
+ };
+
+ /**
+ * Sets up the dialog pages.
+ */
+ void setupPages();
+
+ /**
+ * Sets up the general Diagram Properties Page
+ */
+ void setupDiagramPropertiesPage();
+
+ /**
+ * Sets up the Class page
+ */
+ void setupClassPage();
+
+ /**
+ * Sets up the color page.
+ */
+ void setupColorPage();
+
+ /**
+ * Sets up font page.
+ */
+ void setupFontPage();
+
+ /**
+ * Applys the properties of the given page.
+ */
+ void applyPage( Page page );
+
+ /**
+ * Checks whether the name is unique and sets it if it is.
+ */
+ void checkName();
+
+ /**
+ * The view to represent.
+ */
+ UMLView * m_pView;
+
+ Settings::OptionState m_options;
+
+ KFontChooser * m_pChooser;
+ DiagramPropertiesPage *m_diagramProperties;
+ ClassOptionsPage * m_pOptionsPage;
+ UMLWidgetColorPage * m_pColorPage;
+
+ //GUI widgets
+ QLabel * m_pNameL, * m_pSpinXL, * m_pSpinYL;
+ QLineEdit * m_pNameLE;
+ QGroupBox * m_pDocGB, * m_pValuesGB;
+ QCheckBox * m_pSnapToGridCB, * m_pShowSnapCB;
+ QTextEdit * m_pDocTE;
+ QSpinBox * m_pSnapXSB, * m_pSnapYSB;
+ QSpinBox * m_pLineWidthSB;
+public slots:
+ void slotOk();
+ void slotApply();
+};
+
+#endif
diff --git a/umbrello/umbrello/dialogs/umlwidgetcolorpage.cpp b/umbrello/umbrello/dialogs/umlwidgetcolorpage.cpp
new file mode 100644
index 00000000..e234a8c2
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlwidgetcolorpage.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlwidgetcolorpage.h"
+#include "../optionstate.h"
+#include "../umlview.h"
+#include "../umlwidget.h"
+#include <klocale.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+
+#include <kcolorbutton.h>
+
+UMLWidgetColorPage::UMLWidgetColorPage( QWidget *pParent, UMLWidget *pWidget ) : QWidget( pParent )
+{
+ m_pUMLWidget = pWidget;
+ m_options = 0;
+ init();
+ m_pLineColorB->setColor( pWidget->getLineColor() );
+ m_pFillColorB->setColor( pWidget->getFillColour() );
+ m_pUseFillColorCB->setChecked( pWidget -> getUseFillColour() );
+}
+
+UMLWidgetColorPage::UMLWidgetColorPage( QWidget * pParent, Settings::OptionState *options ) : QWidget( pParent )
+{
+ m_options = options;
+ m_pUMLWidget = 0;
+ init();
+ m_pLineColorB->setColor( m_options->uiState.lineColor );
+ m_pFillColorB->setColor( m_options->uiState.fillColor );
+ m_pUseFillColorCB->setChecked( m_options->uiState.useFillColor );
+}
+
+void UMLWidgetColorPage::init()
+{
+ int margin = fontMetrics().height();
+
+ //setup GUI
+ QVBoxLayout * topLayout = new QVBoxLayout( this );
+ topLayout -> setSpacing( 6 );
+
+ m_pColorGB = new QGroupBox( i18n( "Color" ), this );
+ topLayout -> addWidget( m_pColorGB );
+ QGridLayout * colorLayout = new QGridLayout( m_pColorGB, 3, 3 );
+ colorLayout -> setMargin( margin );
+
+ m_pLineColorL = new QLabel( i18n( "&Line:" ), m_pColorGB );
+ colorLayout -> addWidget( m_pLineColorL, 0, 0 );
+
+ m_pLineColorB = new KColorButton( m_pColorGB );
+ colorLayout -> addWidget( m_pLineColorB, 0, 1 );
+ m_pLineColorL->setBuddy(m_pLineColorB);
+
+ m_pLineDefaultB = new QPushButton( i18n( "&Default" ), m_pColorGB) ;
+ colorLayout -> addWidget( m_pLineDefaultB, 0, 2 );
+
+ m_pFillColorL = new QLabel( i18n( "&Fill:" ), m_pColorGB );
+ colorLayout -> addWidget( m_pFillColorL, 1, 0 );
+
+ m_pFillColorB = new KColorButton( m_pColorGB );
+ colorLayout -> addWidget( m_pFillColorB, 1, 1 );
+ m_pFillColorL->setBuddy(m_pFillColorB);
+
+ m_pFillDefaultB = new QPushButton( i18n( "D&efault" ), m_pColorGB );
+ colorLayout -> addWidget( m_pFillDefaultB, 1, 2 );
+
+ m_pUseFillColorCB = new QCheckBox( i18n( "&Use fill" ), m_pColorGB );
+ colorLayout -> setRowStretch( 2, 2 );
+ colorLayout -> addWidget( m_pUseFillColorCB, 2, 0 );
+
+ //connect button signals up
+ connect( m_pLineDefaultB, SIGNAL( clicked() ), this, SLOT( slotLineButtonClicked() )) ;
+ connect( m_pFillDefaultB, SIGNAL( clicked() ), this, SLOT( slotFillButtonClicked() ) );
+}
+
+UMLWidgetColorPage::~UMLWidgetColorPage() {}
+
+void UMLWidgetColorPage::slotLineButtonClicked() {
+ // UMLView * pView = dynamic_cast<UMLView *>( m_pUMLWidget -> parent() );
+ m_pLineColorB -> setColor( Settings::getOptionState().uiState.lineColor );
+}
+
+void UMLWidgetColorPage::slotFillButtonClicked() {
+ // UMLView * pView = dynamic_cast<UMLView *>( m_pUMLWidget -> parent() );
+ m_pFillColorB -> setColor( Settings::getOptionState().uiState.fillColor );
+}
+
+void UMLWidgetColorPage::updateUMLWidget() {
+ if(m_pUMLWidget)
+ {
+ m_pUMLWidget->setUseFillColour( m_pUseFillColorCB -> isChecked() );
+ m_pUMLWidget->setLineColor( m_pLineColorB -> color() );
+ m_pUMLWidget->setFillColour( m_pFillColorB -> color() );
+ }
+ else if(m_options)
+ {
+ m_options->uiState.useFillColor = m_pUseFillColorCB -> isChecked();
+ m_options->uiState.lineColor = m_pLineColorB -> color();
+ m_options->uiState.fillColor = m_pFillColorB -> color();
+ }
+}
+
+#include "umlwidgetcolorpage.moc"
diff --git a/umbrello/umbrello/dialogs/umlwidgetcolorpage.h b/umbrello/umbrello/dialogs/umlwidgetcolorpage.h
new file mode 100644
index 00000000..45826338
--- /dev/null
+++ b/umbrello/umbrello/dialogs/umlwidgetcolorpage.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLWIDGETCOLORPAGE_H
+#define UMLWIDGETCOLORPAGE_H
+
+#include <qwidget.h>
+#include "../optionstate.h"
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLWidget;
+class UMLView;
+class KColorButton;
+class QLabel;
+class QPushButton;
+class QCheckBox;
+class QGroupBox;
+
+class UMLWidgetColorPage : public QWidget {
+ Q_OBJECT
+public:
+
+ /**
+ * Constructor - Observe a UMLWidget
+ */
+ UMLWidgetColorPage( QWidget * pParent, UMLWidget * pWidget );
+
+ /**
+ * Constructor - Observe an OptionState structure
+ */
+ UMLWidgetColorPage( QWidget * pParent, Settings::OptionState *options );
+
+ /**
+ * destructor
+ */
+ virtual ~UMLWidgetColorPage();
+
+ /**
+ * Updates the @ref UMLWidget with the dialog properties.
+ */
+ void updateUMLWidget();
+
+public slots:
+ /**
+ * Sets the default line color when default line button
+ * clicked.
+ */
+ void slotLineButtonClicked();
+
+ /**
+ * Sets the default fill color when default fill button
+ * clicked.
+ */
+ void slotFillButtonClicked();
+
+protected:
+ /**
+ * The widget to set the color for.
+ */
+ UMLWidget * m_pUMLWidget;
+
+ Settings::OptionState *m_options;
+
+ //GUI widgets
+ QGroupBox * m_pColorGB;
+ QLabel * m_pLineColorL, * m_pFillColorL;
+ QCheckBox * m_pUseFillColorCB;
+ QPushButton * m_pLineDefaultB, * m_pFillDefaultB;
+ KColorButton * m_pLineColorB, * m_pFillColorB;
+private:
+ void init();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/docgenerators/Makefile.am b/umbrello/umbrello/docgenerators/Makefile.am
new file mode 100644
index 00000000..47087c4c
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = -I$(srcdir)/.. -I$(top_srcdir)/umbrello/docgenerators -I../../../umbrello/umbrello $(LIBXML_CFLAGS) $(all_includes)
+METASOURCES = AUTO
+bin_PROGRAMS = umbodoc
+
+AM_LDFLAGS = $(all_libraries)
+umbodoc_COMPILE_FIRST = version.h
+umbodoc_SOURCES = main.cpp
+umbodoc_LDADD = $(LIB_KDECORE) $(LIBXSLT_LIBS) $(LIBXML_LIBS)
+noinst_LTLIBRARIES = libdocgenerators.la
+noinst_HEADERS = docbookgenerator.h version.h
+libdocgenerators_la_SOURCES = docbookgenerator.h docbookgenerator.cpp xhtmlgenerator.cpp
+libdocgenerators_la_LIBADD = $(LIB_KDECORE) $(LIBXSLT_LIBS) $(LIBXML_LIBS)
+
+appdir=$(kde_datadir)/umbrello
+app_DATA = xmi2docbook.xsl docbook2xhtml.xsl xmi.css common.ent
+
+version.h: $(top_srcdir)/umbrello/VERSION
+ printf "#undef UMBRELLO_VERSION\n#define UMBRELLO_VERSION \"`cat $(top_srcdir)/umbrello/VERSION`\"\n" > version.h
+
+CLEANFILES = version.h
+
diff --git a/umbrello/umbrello/docgenerators/common.ent b/umbrello/umbrello/docgenerators/common.ent
new file mode 100644
index 00000000..af88fd38
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/common.ent
@@ -0,0 +1,19 @@
+
+ <!ENTITY title1 "Software Specifications" >
+ <!ENTITY title2 "" >
+ <!ENTITY actor "Actor:">
+ <!ENTITY usecase "Use Cases:">
+ <!ENTITY classes "Classes:">
+ <!ENTITY back "Back">
+ <!ENTITY packagename "Package Name:">
+ <!ENTITY classname "Class Name:">
+ <!ENTITY yes "yes">
+ <!ENTITY no "no">
+ <!ENTITY attributes "Attributes:">
+ <!ENTITY metodes "Methods:">
+ <!ENTITY parameters "Parameters:">
+
+
+
+
+
diff --git a/umbrello/umbrello/docgenerators/docbook2xhtml.xsl b/umbrello/umbrello/docgenerators/docbook2xhtml.xsl
new file mode 100644
index 00000000..8b0e5b11
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/docbook2xhtml.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version='1.0'>
+ <!--xsl:import href="docbook-xsl-1.70.1/xhtml/docbook.xsl"/-->
+ <xsl:import href="http://docbook.sourceforge.net/release/xsl/snapshot/html/docbook.xsl"/>
+ <xsl:param name="html.stylesheet">xmi.css</xsl:param>
+</xsl:stylesheet>
+
diff --git a/umbrello/umbrello/docgenerators/docbookgenerator.cpp b/umbrello/umbrello/docgenerators/docbookgenerator.cpp
new file mode 100644
index 00000000..9907d6f9
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/docbookgenerator.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * docbookgenerator.cpp - description *
+ * ------------------- *
+ * copyright : (C) 2006 by Gael de Chalendar (aka Kleag) *
+ * (C) 2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "docbookgenerator.h"
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+#include <kstandarddirs.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "uml.h"
+#include "umldoc.h"
+#include "umlviewimageexportermodel.h"
+
+extern int xmlLoadExtDtdDefaultValue;
+
+DocbookGenerator::DocbookGenerator()
+{
+}
+
+DocbookGenerator::~DocbookGenerator() {}
+
+
+bool DocbookGenerator::generateDocbookForProject()
+{
+ UMLApp *app = UMLApp::app();
+ UMLDoc* umlDoc = app->getDocument();
+ KURL url = umlDoc->URL();
+ QString fileName = url.fileName();
+ fileName.replace(QRegExp(".xmi$"),"");
+ url.setFileName(fileName);
+ kDebug() << "Exporting to directory: " << url << endl;
+ generateDocbookForProjectInto(url);
+ return true;
+}
+
+KIO::Job* DocbookGenerator::generateDocbookForProjectInto(const KURL& destDir)
+{
+ UMLApp* app = UMLApp::app();
+ UMLDoc* umlDoc = app->getDocument();
+
+ // export all views
+ umlDoc->writeToStatusBar(i18n("Exporting all views..."));
+ QStringList errors = UMLViewImageExporterModel().exportAllViews(
+ UMLViewImageExporterModel::mimeTypeToImageType("image/png"),
+ destDir, false);
+ if (!errors.empty())
+ {
+#if KDE_IS_VERSION(3,4,0)
+ KMessageBox::errorList(app, i18n("Some errors happened when exporting the images:"), errors);
+#else
+ QString errorsCaption;
+ for (QStringList::Iterator it = errors.begin(); it != errors.end(); ++it) {
+ errorsCaption += "\n" + *it;
+ }
+ KMessageBox::error(app, i18n("Some errors happened when exporting the images:") + errorsCaption);
+#endif
+ return 0;
+ }
+
+ //write the XMI model in an in-memory char* string
+ QString xmi;
+ QTextOStream xmiStream(&xmi);
+
+ KTempFile tmpfile; // we need this tmp file if we are writing to a remote file
+
+ QFile file;
+ file.setName( tmpfile.name() );
+
+ // lets open the file for writing
+ if( !file.open( IO_WriteOnly ) ) {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(tmpfile.name()), i18n("Save Error"));
+ return false;
+ }
+ umlDoc->saveToXMI(file); // save the xmi stuff to it
+ file.close();
+ tmpfile.close();
+
+ xsltStylesheetPtr cur = NULL;
+ xmlDocPtr doc, res;
+
+ const char *params[16 + 1];
+ int nbparams = 0;
+ params[nbparams] = NULL;
+
+ QString xsltFile(KGlobal::dirs()->findResource("appdata","xmi2docbook.xsl"));
+
+ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = 1;
+ cur = xsltParseStylesheetFile((const xmlChar *)xsltFile.latin1());
+ doc = xmlParseFile((const char*)(tmpfile.name().utf8()));
+ res = xsltApplyStylesheet(cur, doc, params);
+
+ KTempFile tmpDocBook;
+ tmpDocBook.setAutoDelete(false);
+
+ xsltSaveResultToFile(tmpDocBook.fstream(), res, cur);
+ xsltFreeStylesheet(cur);
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+
+ KURL url = umlDoc->URL();
+ QString fileName = url.fileName();
+ fileName.replace(QRegExp(".xmi$"),".docbook");
+ url.setPath(destDir.path());
+ url.addPath(fileName);
+ kDebug() << "Copying result to: " << url << endl;
+ KIO::Job* job = KIO::file_copy(tmpDocBook.file()->name(),url,-1,true,false,false);
+ job->setAutoErrorHandlingEnabled(true);
+
+ return job;
+}
+
+
+#include "docbookgenerator.moc"
diff --git a/umbrello/umbrello/docgenerators/docbookgenerator.h b/umbrello/umbrello/docgenerators/docbookgenerator.h
new file mode 100644
index 00000000..775a7383
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/docbookgenerator.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ docbookgenerator.h - description
+ -------------------
+ begin : THu Jun 22 2006
+ copyright : (C) 2006 by Gael de Chalendar (aka Kleag)
+ email : kleag@free.fr
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOCBOOKGENERATOR_H
+#define DOCBOOKGENERATOR_H
+
+#include <kurl.h>
+#include <qobject.h>
+
+class UMLDoc;
+
+namespace KIO
+{
+ class Job;
+}
+
+/**
+ * class DocbookGenerator is a documentation generator for UML documents.
+ * It uses libxslt to convert the XMI generated by UMLDoc::saveToXMI through
+ * the XSLT file stored in resources.
+ *
+ * @todo Add configure checks for libxml2 and libxslt and use conditional
+ * compilation of this library and its callers
+ * @todo allow to specify the destination and ensure that it works with distant
+ * ones
+ */
+class DocbookGenerator : public QObject
+{
+ Q_OBJECT
+ public:
+
+ /**
+ * Constructor
+ */
+ DocbookGenerator();
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~DocbookGenerator();
+
+ /**
+ * Exports the current model to docbook in a directory named as the model
+ * with the .xmi suffix removed. The docbook file will have the same name
+ * with the .docbook suffix. Figures will be named as the corresponding
+ * diagrams in the GUI
+ * @todo change file naming to avoid paths with spaces or non-ASCII chars
+ * @todo better handling of error conditions
+ * @return true if saving is successful and false otherwise.
+ */
+ bool generateDocbookForProject();
+
+ /**
+ * Exports the current model to docbook in the given directory
+ * @param destDir the directory where the docbook file and the figures will
+ * be written
+ * @todo better handling of error conditions
+ * @return true if saving is successful and false otherwise.
+ */
+ KIO::Job* generateDocbookForProjectInto(const KURL& destDir);
+
+};
+
+#endif // DOCBOOKGENERATOR_H
diff --git a/umbrello/umbrello/docgenerators/main.cpp b/umbrello/umbrello/docgenerators/main.cpp
new file mode 100644
index 00000000..d4b6fc4e
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/main.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include <unistd.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/DOCBparser.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+// kde includes
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <ktip.h>
+#include <kdebug.h>
+#include <kwin.h>
+
+#include "version.h"
+
+extern int xmlLoadExtDtdDefaultValue;
+
+static const char description[] =
+ I18N_NOOP("Umbrello UML Modeller autonomous code generator");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+
+static KCmdLineOptions options[] =
+{
+ { "+[File]", I18N_NOOP("File to transform"), 0 },
+ { "xslt <url>", I18N_NOOP("The XSLT file to use"), 0},
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+ xsltStylesheetPtr cur = NULL;
+ xmlDocPtr doc, res;
+
+ const char *params[16 + 1];
+ int nbparams = 0;
+ params[nbparams] = NULL;
+
+ KAboutData aboutData( "umbodoc", I18N_NOOP("Umbrello UML Modeller autonomous code generator"),
+ UMBRELLO_VERSION, description, KAboutData::License_GPL,
+ I18N_NOOP("(c) 2006 Gael de Chalendar (aka Kleag), (c) 2002-2006 Umbrello UML Modeller Authors"), 0,
+ "http://uml.sf.net/");
+ aboutData.addAuthor("Gael de Chalendar (aka Kleag)",0, "kleag@free.fr");
+ aboutData.addAuthor(I18N_NOOP("Umbrello UML Modeller Authors"), 0, "uml-devel@lists.sourceforge.net");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ QCStringList xsltOpt = args->getOptionList("xslt");
+ if (xsltOpt.size() > 0)
+ {
+ QString xsltFile(xsltOpt.last());
+
+ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = 1;
+ cur = xsltParseStylesheetFile((const xmlChar *)xsltFile.latin1());
+ doc = xmlParseFile(args->url( 0 ).url().latin1());
+ res = xsltApplyStylesheet(cur, doc, params);
+ xsltSaveResultToFile(stdout, res, cur);
+
+ xsltFreeStylesheet(cur);
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ }
+ return(0);
+}
+
diff --git a/umbrello/umbrello/docgenerators/xhtmlgenerator.cpp b/umbrello/umbrello/docgenerators/xhtmlgenerator.cpp
new file mode 100644
index 00000000..5da1ae75
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/xhtmlgenerator.cpp
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * xhtmlgenerator.cpp - description *
+ * ------------------- *
+ * copyright : (C) 2006 by Gael de Chalendar (aka Kleag) *
+ * (C) 2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "xhtmlgenerator.h"
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+#include <kstandarddirs.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "uml.h"
+#include "umldoc.h"
+#include "umlviewimageexportermodel.h"
+#include "docbookgenerator.h"
+
+extern int xmlLoadExtDtdDefaultValue;
+
+XhtmlGenerator::XhtmlGenerator()
+{
+}
+
+XhtmlGenerator::~XhtmlGenerator() {}
+
+
+bool XhtmlGenerator::generateXhtmlForProject()
+{
+ UMLApp *app = UMLApp::app();
+ UMLDoc* umlDoc = app->getDocument();
+ KURL url = umlDoc->URL();
+ QString fileName = url.fileName();
+ fileName.replace(QRegExp(".xmi$"),"");
+ url.setFileName(fileName);
+ kDebug() << "Exporting to directory: " << url << endl;
+ return generateXhtmlForProjectInto(url);
+}
+
+bool XhtmlGenerator::generateXhtmlForProjectInto(const KURL& destDir)
+{
+ kDebug() << "First convert to docbook" << endl;
+ m_destDir = destDir;
+// KURL url(QString("file://")+m_tmpDir.name());
+ KIO::Job* docbookJob = DocbookGenerator().generateDocbookForProjectInto(destDir);
+ if (docbookJob == 0)
+ {
+ return false;
+ }
+ kDebug() << "Connecting..." << endl;
+ connect(docbookJob, SIGNAL(result( KIO::Job * )), this, SLOT(slotDocbookToXhtml( KIO::Job *)));
+ return true;
+}
+
+void XhtmlGenerator::slotDocbookToXhtml(KIO::Job * docbookJob)
+{
+ kDebug() << "Now convert docbook to html..." << endl;
+ if ( docbookJob->error() )
+ {
+ docbookJob->showErrorDialog( 0L );
+ return;
+ }
+
+ UMLApp* app = UMLApp::app();
+ UMLDoc* umlDoc = app->getDocument();
+
+ const KURL& url = umlDoc->URL();
+ QString docbookName = url.fileName();
+ docbookName.replace(QRegExp(".xmi$"),".docbook");
+// KURL docbookUrl(QString("file://")+m_tmpDir.name());
+ KURL docbookUrl = m_destDir;
+ docbookUrl.addPath(docbookName);
+
+ xsltStylesheetPtr cur = NULL;
+ xmlDocPtr doc, res;
+
+ const char *params[16 + 1];
+ int nbparams = 0;
+ params[nbparams] = NULL;
+
+ QString xsltFileName(KGlobal::dirs()->findResource("appdata","docbook2xhtml.xsl"));
+ kDebug() << "XSLT file is'"<<xsltFileName<<"'" << endl;
+ QFile xsltFile(xsltFileName);
+ xsltFile.open(IO_ReadOnly);
+ QString xslt = xsltFile.readAll();
+ kDebug() << "XSLT is'"<<xslt<<"'" << endl;
+ xsltFile.close();
+
+ QString localXsl = KGlobal::dirs()->findResource("data","ksgmltools2/docbook/xsl/html/docbook.xsl");
+ kDebug() << "Local xsl is'"<<localXsl<<"'" << endl;
+ if (!localXsl.isEmpty())
+ {
+ localXsl = QString("href=\"file://") + localXsl + "\"";
+ xslt.replace(QRegExp("href=\"http://[^\"]*\""),localXsl);
+ }
+ KTempFile tmpXsl;
+ *tmpXsl.textStream() << xslt;
+ tmpXsl.file()->close();
+
+
+ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = 1;
+ kDebug() << "Parsing stylesheet " << tmpXsl.name() << endl;
+ cur = xsltParseStylesheetFile((const xmlChar *)tmpXsl.name().latin1());
+ kDebug() << "Parsing file " << docbookUrl.path() << endl;
+ doc = xmlParseFile((const char*)(docbookUrl.path().utf8()));
+ kDebug() << "Applying stylesheet " << endl;
+ res = xsltApplyStylesheet(cur, doc, params);
+
+ KTempFile tmpXhtml;
+ tmpXhtml.setAutoDelete(false);
+
+ kDebug() << "Writing HTML result to temp file: " << tmpXhtml.file()->name() << endl;
+ xsltSaveResultToFile(tmpXhtml.fstream(), res, cur);
+
+ xsltFreeStylesheet(cur);
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+
+ QString xhtmlName = url.fileName();
+ xhtmlName.replace(QRegExp(".xmi$"),".html");
+ KURL xhtmlUrl = m_destDir;
+ xhtmlUrl.addPath(xhtmlName);
+
+ kDebug() << "Copying HTML result to: " << xhtmlUrl << endl;
+ KIO::Job* job = KIO::file_copy(tmpXhtml.file()->name(),xhtmlUrl,-1,true,false,false);
+ job->setAutoErrorHandlingEnabled(true);
+ connect (job, SIGNAL(result( KIO::Job* )), this, SLOT(slotHtmlCopyFinished( KIO::Job* )));
+
+ QString cssFileName(KGlobal::dirs()->findResource("appdata","xmi.css"));
+ kDebug() << "CSS file is'"<<cssFileName<<"'" << endl;
+ KURL cssUrl = m_destDir;
+ cssUrl.addPath("xmi.css");
+ KIO::Job* cssJob = KIO::file_copy(cssFileName,cssUrl,-1,true,false,false);
+ cssJob->setAutoErrorHandlingEnabled(true);
+}
+
+void XhtmlGenerator::slotHtmlCopyFinished( KIO::Job* )
+{
+ kDebug() << "HTML copy finished: emiting finished" << endl;
+ emit(finished());
+}
+
+#include "xhtmlgenerator.moc"
diff --git a/umbrello/umbrello/docgenerators/xhtmlgenerator.h b/umbrello/umbrello/docgenerators/xhtmlgenerator.h
new file mode 100644
index 00000000..46402382
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/xhtmlgenerator.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ xhtmlgenerator.h - description
+ -------------------
+ begin : Sat Jun 24 2006
+ copyright : (C) 2006 by Gael de Chalendar (aka Kleag)
+ email : kleag@free.fr
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef XHTMLGENERATOR_H
+#define XHTMLGENERATOR_H
+
+#include <kurl.h>
+#include <ktempdir.h>
+#include <qobject.h>
+
+namespace KIO
+{
+ class Job;
+}
+
+/**
+ * class XhtmlGenerator is a documentation generator for UML documents.
+ * It uses first @ref DocbookGenerator to convert the XMI generated by
+ * UMLDoc::saveToXMI to docbook and next libxslt through
+ * the XSLT file stored in resources to convert the docbook file to XHTML.
+ * The latter uses the XSLT available on the Web at
+ * http://docbook.sourceforge.net/release/xsl/snapshot/html/docbook.xsl
+ *
+ * @todo allow to specify the destination and ensure that it works with distant
+ * ones
+ */
+class XhtmlGenerator : public QObject
+{
+ Q_OBJECT
+ public:
+
+ /**
+ * Constructor
+ */
+ XhtmlGenerator();
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~XhtmlGenerator();
+
+ /**
+ * Exports the current model to XHTML in a directory named as the model
+ * with the .xmi suffix removed. The XHTML file will have the same name
+ * with the .html suffix. Figures will be named as the corresponding
+ * diagrams in the GUI
+ * @todo change file naming to avoid paths with spaces or non-ASCII chars
+ * @todo better handling of error conditions
+ * @return true if saving is successful and false otherwise.
+ */
+ bool generateXhtmlForProject();
+
+ /**
+ * Exports the current model to XHTML in the given directory
+ * @param destDir the directory where the XHTML file and the figures will
+ * be written
+ * @todo better handling of error conditions
+ * @return true if saving is successful and false otherwise.
+ */
+ bool generateXhtmlForProjectInto(const KURL& destDir);
+
+ signals:
+
+ /** Emited when the documentation generation is finished */
+ void finished();
+
+ protected slots:
+
+ /** This slot is triggerd when the first part, xmi to docbook, is
+ * finished
+ * @param docbookJob the job copying the docbook file to its destination.
+ * Used only for error reporting
+ */
+ void slotDocbookToXhtml(KIO::Job * docbookJob);
+
+ /** Triggered when the copying of the HTML result file is finished. Emits
+ * the signal finished().
+ */
+ void slotHtmlCopyFinished( KIO::Job* );
+
+ private:
+
+ /** The destination directory where the final documentation will be
+ * written.
+ */
+ KURL m_destDir;
+// KTempDir m_tmpDir;
+};
+
+#endif // XHTMLGENERATOR_H
diff --git a/umbrello/umbrello/docgenerators/xmi.css b/umbrello/umbrello/docgenerators/xmi.css
new file mode 100644
index 00000000..0cb67fea
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/xmi.css
@@ -0,0 +1,170 @@
+h1 {
+ font-family : Verdana, Arial, Helvetica;
+ font-size : 15pt;
+ font-weight : bold;
+ color : #333366;
+}
+
+.class-title {
+ background-color:#9999cc;
+ color : #ffffff;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+}
+
+.class-name {
+ background-color:#ffffe0;
+ color : #6633cc;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+}
+
+
+.interface-title {
+ background-color:#9999cc;
+ color : #ffffff;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+}
+
+.interface-name {
+ background-color:#ffffe0;
+ color : #6633cc;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+ font-style : italic;
+}
+
+.info-title {
+ background-color:#f0f0f0;
+ color : #888888;
+ font-family : Verdana, Helvetica;
+ font-size : 11pt;
+ font-weight : bold;
+ text-align : left;
+}
+
+.info {
+ background-color:#f0f0f0;
+ color : #000000;
+ font-family : Verdana, Helvetica;
+ font-size : 10pt;
+ text-align : left;
+}
+
+
+.class-feature {
+ background-color:#f0f0f0;
+ color : #848484;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+ text-align : left;
+}
+
+.feature-heading {
+ color : #000099;
+ background-color:#ffffe0;
+ font-family : Verdana, Helvetica;
+ font-weight : bold;
+ font-size : 10pt;
+}
+
+.feature-detail {
+ color : #000000;
+ background-color:#ffffff;
+ font-family : Verdana, Helvetica;
+ font-size : 10pt;
+ text-align : left;
+}
+
+.comment {
+ color : #555555;
+ background-color:#ffffff;
+ font-family : Verdana, Helvetica;
+ font-size : 10pt;
+ text-align : left;
+ font-style : italic;
+}
+
+
+.datatype {
+ color : blue;
+}
+
+a.classifier:link {
+ color : blue;
+}
+
+a.classifier:visited {
+ color : blue;
+}
+
+a.interface:link {
+ color : blue;
+ font-style : italic;
+}
+
+a.interface:visited {
+ color : blue;
+ font-style : italic;
+}
+
+a.index-class:link {
+ font-family : Helvetica;
+ color : blue;
+ text-decoration : none;
+}
+
+a.index-class:visited {
+ font-family : Helvetica;
+ color : blue;
+ text-decoration : none;
+}
+
+a.index-interface:link {
+ color : blue;
+ font-style : italic;
+ text-decoration : none;
+}
+
+a.index-interface:visited {
+ color : blue;
+ font-style : italic;
+ text-decoration : none;
+}
+
+.index-title {
+ color : #000080;
+ font-family : Verdana, Helvetica;
+ font-size : 12pt;
+ font-weight : bold;
+}
+
+.parameter-heading {
+ color : #000099;
+ background-color: #f0f0f0;
+ font-family : Verdana, Helvetica;
+ font-weight : bold;
+ font-size : 10pt;
+}
+
+.property-name {
+ font-family : Verdana, Arial, Helvetica;
+ font-size : 8pt;
+ font-weight : bold;
+ color : Black;
+}
+
+.toc {
+color : #000099;
+background-color: #f0f0f0;
+font-family : Verdana, Helvetica;
+font-weight : normal;
+font-size : 10pt;
+}
+
diff --git a/umbrello/umbrello/docgenerators/xmi2docbook.sh b/umbrello/umbrello/docgenerators/xmi2docbook.sh
new file mode 100644
index 00000000..32f46928
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/xmi2docbook.sh
@@ -0,0 +1,9 @@
+#! /bin/bash
+
+echo Converting from XMI to docbook...
+java -cp /usr/share/java/xalan-j2-2.6.0.jar org.apache.xalan.xslt.Process -xml -in $1.xmi -xsl /home/gael/Logiciels/kde3.5-svn/kdesdk/umbrello.withdocgen/umbrello/docgenerators/xmi2docbook.xsl -out $1.docbook
+
+echo Converting from docbook to XHTML...
+java -cp /usr/share/java/xalan-j2-2.6.0.jar org.apache.xalan.xslt.Process -in $1.docbook -xsl /home/gael/Logiciels/kde3.5-svn/kdesdk/umbrello.withdocgen/umbrello/docgenerators/docbook2xhtml.xsl -out $1.html -html
+
+echo done.
diff --git a/umbrello/umbrello/docgenerators/xmi2docbook.xsl b/umbrello/umbrello/docgenerators/xmi2docbook.xsl
new file mode 100644
index 00000000..ff10aac5
--- /dev/null
+++ b/umbrello/umbrello/docgenerators/xmi2docbook.xsl
@@ -0,0 +1,998 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+ "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd"
+ [ <!ENTITY % common SYSTEM "common.ent" > %common;] >
+
+<!--
+ Title: umbrello-xmi-to-html.xsl
+ Purpose: An XSL stylesheet for converting Umbrello 1.4 XMI to HTML.
+ Based on xmi-to-html.xsl from Objects by Design.
+
+ Copyright (C) 1999-2001, Objects by Design, Inc. All Rights Reserved.
+ Copyright (C) 2005, Oliver M. Kellogg <okellogg@users.sourceforge.net>
+ Copyright (C) 2006, Gaël de Chalendar (Kleag) <kleag@free.fr>
+
+ 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. A copy of the license may be found at
+ http://www.gnu.org/licenses/gpl.html
+
+ Version: June, 16 2006
+
+ xmlns="http://www.w3.org/1999/xhtml"
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0"
+ xmlns:UML="http://schema.omg.org/spec/UML/1.3"
+ exclude-result-prefixes="UML">
+
+<xsl:output method="xml" indent="yes"
+ doctype-system="http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd"
+ doctype-public="-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN" />
+
+<xsl:key
+ name="classifier"
+ match="//UML:Class"
+ use="@xmi.id"/>
+
+<xsl:key
+ name="generalization"
+ match="//UML:Generalization"
+ use="@xmi.id"/>
+
+<xsl:key
+ name="abstraction"
+ match="//UML:Abstraction"
+ use="@xmi.id"/>
+
+<xsl:key
+ name="multiplicity"
+ match="//UML:Multiplicity"
+ use="@xmi.id"/>
+
+
+<!-- Document Root -->
+<xsl:template match="/">
+ <article role="specification">
+ <xsl:apply-templates select="//UML:Model" mode="title"/>
+
+ <!-- Actors -->
+ <section id="actors">
+ <title>Actors</title>
+ <xsl:apply-templates select="//UML:Actor"/>
+ </section>
+
+ <!-- Use Cases -->
+ <section id="usecases">
+ <title>Use Cases</title>
+ <xsl:apply-templates select="//UML:UseCase"/>
+ </section>
+
+ <!-- Interfaces -->
+ <section id="interfaces">
+ <title>Interfaces</title>
+ <xsl:apply-templates select="//UML:Interface"/>
+ </section>
+
+ <!-- Classes -->
+ <section id="classes">
+ <title>Classes</title>
+ <xsl:apply-templates select="//UML:Class"/>
+ </section>
+ <!-- Diagrams -->
+ <section id="diagrams">
+ <title>Diagrams</title>
+ <xsl:apply-templates select="//diagrams/diagram"/>
+ </section>
+ </article>
+
+</xsl:template>
+
+
+<!-- Window Title -->
+<xsl:template match="UML:Model" mode="title">
+ <title>
+ <!-- Name of the model -->
+ <xsl:value-of select="@name"/>
+ </title>
+</xsl:template>
+
+
+<!-- Actor -->
+<xsl:template match="UML:Actor">
+ <xsl:variable name="element_name" select="@name"/>
+ <xsl:variable name="xmi_id" select="@xmi.id" />
+ <xsl:variable name="comment" select="@comment" />
+
+ <section>
+ <title><xsl:value-of select="$element_name"/></title>
+
+ <table frame='all'><title></title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1'/>
+ <colspec colname='c2'/>
+ <colspec colname='c3'/>
+ <thead>
+ <row>
+ <entry role="class-title" >Actor</entry>
+ <entry role="class-name" namest="c2" nameend="c3" ><xsl:value-of select="$element_name"/></entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:if test="count($comment) > 0">
+ <row>
+ <entry role="comment" namest="c1" nameend="c3" ><para><xsl:value-of select="$comment"/></para></entry>
+ </row>
+ </xsl:if>
+
+ <xsl:call-template name="specifications"/>
+
+ <xsl:call-template name="realizations"/>
+
+ <xsl:call-template name="supertypes"/>
+
+ <xsl:call-template name="subtypes"/>
+
+ <xsl:call-template name="associations">
+ <xsl:with-param name="source" select="$xmi_id"/>
+ </xsl:call-template>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+</xsl:template>
+
+<!-- Use Case -->
+<xsl:template match="UML:UseCase">
+ <xsl:variable name="element_name" select="@name"/>
+ <xsl:variable name="xmi_id" select="@xmi.id" />
+ <xsl:variable name="comment" select="@comment" />
+
+ <section>
+ <title><xsl:value-of select="$element_name"/></title>
+
+ <table frame='all'><title></title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1'/>
+ <colspec colname='c2'/>
+ <colspec colname='c3'/>
+ <thead>
+ <row>
+ <entry role="class-title" >Use Case</entry>
+ <entry role="class-name" namest="c2" nameend="c3" ><xsl:value-of select="$element_name"/></entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:if test="count($comment) > 0">
+ <row>
+ <entry role="comment" namest="c1" nameend="c3" ><para><xsl:value-of select="$comment"/></para></entry>
+ </row>
+ </xsl:if>
+
+ <xsl:call-template name="specifications"/>
+
+ <xsl:call-template name="realizations"/>
+
+ <xsl:call-template name="supertypes"/>
+
+ <xsl:call-template name="subtypes"/>
+
+ <xsl:call-template name="associations">
+ <xsl:with-param name="source" select="$xmi_id"/>
+ </xsl:call-template>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+</xsl:template>
+
+
+<!-- Interface -->
+<xsl:template match="UML:Interface">
+ <xsl:variable name="element_name" select="@name"/>
+ <xsl:variable name="comment" select="@comment" />
+ <xsl:variable name="realizations"
+ select="Foundation.Core.ModelElement.supplierDependency/
+ Foundation.Core.Abstraction"/>
+ <xsl:variable name="generalizations"
+ select="UML:Generalization"/>
+ <xsl:variable name="specializations"
+ select="Foundation.Core.GeneralizableElement.specialization/
+ Foundation.Core.Generalization"/>
+ <xsl:variable name="class_operations"
+ select="UML:Classifier.feature/UML:Operation" />
+ <section>
+ <title><xsl:value-of select="$element_name"/></title>
+ <table frame='all'><title></title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1'/>
+ <colspec colname='c2'/>
+ <colspec colname='c3'/>
+ <thead>
+ <row>
+ <entry role="class-title" >Interface</entry>
+ <entry role="class-name" namest="c2" nameend="c3" ><xsl:value-of select="$element_name"/></entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:if test="count($comment) > 0">
+ <row>
+ <entry role="comment" namest="c1" nameend="c3" ><para><xsl:value-of select="$comment"/></para></entry>
+ </row>
+ </xsl:if>
+ <xsl:if test="count($class_operations) = 0">
+ <row>
+ <entry namest="c1" nameend="c3" ><para/></entry>
+ </row>
+ </xsl:if>
+
+ <xsl:if test="count($realizations) = 0
+ and count($generalizations) = 0
+ and count($specializations) = 0
+ and count($class_operations) = 0">
+ </xsl:if>
+ <xsl:call-template name="realizations"/>
+ <xsl:call-template name="supertypes"/>
+ <xsl:call-template name="subtypes"/>
+ <xsl:call-template name="operations"/>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+</xsl:template>
+
+
+<!-- Class -->
+<xsl:template match="UML:Class">
+ <xsl:variable name="element_name" select="@name"/>
+ <xsl:variable name="xmi_id" select="@xmi.id" />
+ <xsl:variable name="comment" select="@comment" />
+ <xsl:variable name="class_attributes"
+ select="UML:Classifier.feature/UML:Attribute" />
+ <xsl:variable name="class_operations"
+ select="UML:Classifier.feature/UML:Operation" />
+
+ <section>
+ <title><xsl:value-of select="$element_name"/></title>
+
+ <table frame='all'><title></title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1'/>
+ <colspec colname='c2'/>
+ <colspec colname='c3'/>
+ <thead>
+ <row>
+ <entry role="class-title" >Class</entry>
+ <entry role="class-name" namest="c2" nameend="c3" ><xsl:value-of select="$element_name"/></entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:if test="count($comment) > 0">
+ <row>
+ <entry role="comment" namest="c1" nameend="c3" ><para><xsl:value-of select="$comment"/></para></entry>
+ </row>
+ </xsl:if>
+ <xsl:if test="count($class_attributes) = 0
+ and count($class_operations) = 0">
+ <row>
+ <entry namest="c1" nameend="c3" ><para/></entry>
+ </row>
+ </xsl:if>
+
+ <xsl:call-template name="specifications"/>
+
+ <xsl:call-template name="realizations"/>
+
+ <xsl:call-template name="supertypes"/>
+
+ <xsl:call-template name="subtypes"/>
+
+ <xsl:call-template name="associations">
+ <xsl:with-param name="source" select="$xmi_id"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="attributes"/>
+
+ <xsl:call-template name="operations"/>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+</xsl:template>
+
+
+<xsl:template match="diagrams/diagram">
+ <xsl:variable name="xmi_id" select="@xmi.id" />
+ <xsl:comment >diagrambegin<xsl:value-of select="position()"/>namebegin<xsl:value-of select="@name"/>nameend</xsl:comment>
+ <xsl:comment >diagram<xsl:value-of select="position()"/>documentationbegin<xsl:value-of select="@documentation"/>documentationend</xsl:comment>
+
+ <section>
+ <title><xsl:value-of select="@name"/></title>
+ <para>
+ <xsl:value-of select="@documentation"/>
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata format="PNG">
+ <xsl:attribute name="fileref"><xsl:value-of select="@name"/>
+ <xsl:text>.png</xsl:text>
+ </xsl:attribute>
+ </imagedata>
+ </imageobject>
+ </mediaobject>
+ </section>
+ <xsl:if test="widgets/actorwidget">
+ <section>
+ <title>&actor;</title>
+ <xsl:for-each select="widgets/actorwidget">
+ <xsl:call-template name="actor"/>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+
+ <xsl:if test="widgets/usecasewidget">
+ <section>
+ <title>&usecase;</title>
+ <xsl:for-each select="widgets/usecasewidget">
+ <xsl:call-template name="usecase"/>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+
+ <xsl:if test="widgets/classwidget">
+ <section>
+ <title>&classes;</title>
+ <para/>
+ <!--xsl:for-each select="widgets/classwidget">
+ <xsl:call-template name="class"/>
+ </xsl:for-each-->
+ </section>
+ </xsl:if>
+
+ <xsl:comment >diagramend<xsl:value-of select="position()"/></xsl:comment>
+</xsl:template>
+
+
+<!-- The following template is designed to be called for Abstractions with the "realize"
+ stereotype, i.e. Realization relationships. It formats the name of the supplier of the
+ Abstraction dependency, i.e. the class or interface specifying the behaviour of the
+ client in the dependency.
+-->
+<!-- Specifications (interface or class) -->
+<xsl:template name="specifications">
+
+ <!-- Abstractions identify specifications -->
+ <xsl:variable name="specifications"
+ select="Foundation.Core.ModelElement.clientDependency/
+ Foundation.Core.Abstraction"/>
+
+ <xsl:if test="count($specifications) > 0">
+ <section>
+ <title>Specifications:</title>
+ <xsl:for-each select="$specifications">
+ <!-- get the supplier in the abstraction -->
+ <xsl:variable name="abstraction"
+ select="key('abstraction', ./@xmi.idref)" />
+ <xsl:variable name="target"
+ select="$abstraction/
+ Foundation.Core.Dependency.supplier/
+ */@xmi.idref" />
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+
+</xsl:template>
+
+
+<!-- The following template is designed to be called for Abstractions with the "realize"
+ stereotype, i.e. Realization relationships. It formats the name of the client of the
+ Abstraction dependency, i.e. the class realizing the specification defined by the
+ supplier in the dependency.
+-->
+<!-- Realizations (of interface) -->
+<xsl:template name="realizations">
+
+ <!-- Abstractions identify realizations -->
+ <xsl:variable name="realizations"
+ select="Foundation.Core.ModelElement.supplierDependency/
+ Foundation.Core.Abstraction"/>
+
+ <xsl:if test="count($realizations) > 0">
+ <section>
+ <title>Realizations:</title>
+ <xsl:for-each select="$realizations">
+
+ <!-- get the client in the abstraction -->
+ <xsl:variable name="abstraction"
+ select="key('abstraction', ./@xmi.idref)" />
+ <xsl:variable name="target"
+ select="$abstraction/
+ Foundation.Core.Dependency.client/
+ */@xmi.idref" />
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+
+</xsl:template>
+
+
+
+<!-- Supertypes (inheritance) -->
+<xsl:template name="supertypes">
+
+ <!-- Generalizations identify supertypes -->
+ <xsl:variable name="generalizations"
+ select="UML:Generalization"/>
+
+ <xsl:if test="count($generalizations) > 0">
+ <section>
+ <title>Supertypes:</title>
+ <xsl:for-each select="$generalizations">
+
+ <!-- get the parent in the generalization -->
+ <xsl:variable name="generalization"
+ select="key('generalization', ./@xmi.idref)" />
+ <xsl:variable name="target"
+ select="$generalization/
+ Foundation.Core.Generalization.parent/
+ */@xmi.idref" />
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- Subtypes (inheritance) -->
+<xsl:template name="subtypes">
+
+ <!-- Specializations identify subtypes -->
+ <xsl:variable name="specializations"
+ select="Foundation.Core.GeneralizableElement.specialization/
+ Foundation.Core.Generalization"/>
+
+ <xsl:if test="count($specializations) > 0">
+ <section>
+ <title>Subtypes:</title>
+ <xsl:for-each select="$specializations">
+
+ <!-- get the child in the generalization -->
+ <xsl:variable name="generalization"
+ select="key('generalization', ./@xmi.idref)" />
+ <xsl:variable name="target"
+ select="$generalization/
+ Foundation.Core.Generalization.child/
+ */@xmi.idref" />
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- Associations -->
+<xsl:template name="associations">
+ <xsl:param name="source"/>
+
+ <xsl:variable name="association_ends"
+ select="//UML:AssociationEnd[@type=$source]" />
+
+ <xsl:if test="count($association_ends) > 0">
+ <section>
+ <title>Associations</title>
+ <para>visibility, type, properties.</para>
+
+ <xsl:for-each select="$association_ends">
+ <xsl:for-each select="preceding-sibling::UML:AssociationEnd |
+ following-sibling::UML:AssociationEnd">
+
+ <xsl:call-template name="association_end" />
+
+ </xsl:for-each>
+ </xsl:for-each>
+ </section>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- Association End -->
+<xsl:template name="association_end">
+ <!-- Visibility -->
+ <para>
+ <!--role="feature-detail"-->
+ <xsl:variable name="visibility"
+ select="@visibility" />
+ <xsl:choose>
+ <xsl:when test="string-length($visibility) > 0">
+ <xsl:value-of select="$visibility"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </para>
+
+ <!-- Type -->
+ <para>
+ <!--role="feature-detail"-->
+ <xsl:variable name="target"
+ select="Foundation.Core.AssociationEnd.type/*/@xmi.idref" />
+
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+ </para>
+
+ <!-- Properties -->
+ <para>
+ <!--role="feature-detail"-->
+ <!-- Rolename -->
+ <xsl:variable name="rolename" select="@name"/>
+
+ <!--role="property-name"-->
+ Rolename:
+ <xsl:choose>
+ <xsl:when test="string-length($rolename) > 0">
+ <xsl:value-of select="$rolename"/>
+ </xsl:when>
+ <xsl:otherwise>(none)</xsl:otherwise>
+ </xsl:choose>
+ </para>
+
+ <!-- Multiplicity -->
+ <xsl:apply-templates select=".//Foundation.Data_Types.Multiplicity" />
+
+ <!-- Navigable -->
+ <xsl:variable name="navigable"
+ select="Foundation.Core.AssociationEnd.isNavigable/@xmi.value"/>
+ <xsl:if test="string-length($navigable) > 0">
+
+ <para>
+ <!--role="property-name"-->
+ Navigable: <xsl:value-of select="$navigable"/>
+ </para>
+ </xsl:if>
+
+ <!-- Ordering -->
+ <xsl:variable name="ordering"
+ select="Foundation.Core.AssociationEnd.ordering/@xmi.value"/>
+ <xsl:if test="string-length($ordering) > 0">
+ <para>
+ <!--role="property-name"-->
+ Ordering: <xsl:value-of select="$ordering"/>
+ </para>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- Multiplicity (definition) -->
+<xsl:template match="Foundation.Data_Types.Multiplicity[@xmi.id]">
+
+ <para>
+ <!--role="property-name"-->
+ Multiplicity:
+
+ <xsl:variable name="lower"
+ select=".//Foundation.Data_Types.MultiplicityRange.lower"/>
+
+ <xsl:variable name="upper"
+ select=".//Foundation.Data_Types.MultiplicityRange.upper"/>
+
+ <xsl:value-of select="$lower" />
+ <xsl:if test="$upper != $lower">
+ <xsl:text>..</xsl:text>
+ <xsl:value-of select="$upper" />
+ </xsl:if>
+ </para>
+
+</xsl:template>
+
+<!-- Multiplicity (reference) -->
+<xsl:template match="Foundation.Data_Types.Multiplicity[@xmi.idref]">
+ <xsl:apply-templates select="key('multiplicity', @xmi.idref)" />
+</xsl:template>
+
+
+
+<!-- Attributes -->
+<xsl:template name="attributes">
+ <xsl:variable name="class_attributes"
+ select="UML:Classifier.feature/UML:Attribute" />
+ <xsl:if test="count($class_attributes) > 0">
+ <row>
+ <entry role="info-title" namest="c1" nameend="c3" >Attributes:</entry>
+ </row>
+ <row>
+ <entry role="feature-heading">visibility</entry>
+ <entry role="feature-heading">type</entry>
+ <entry role="feature-heading">name</entry>
+ </row>
+ <xsl:apply-templates select="UML:Classifier.feature/
+ UML:Attribute" />
+ </xsl:if>
+</xsl:template>
+
+
+<xsl:template match="UML:Attribute">
+ <xsl:variable name="target"
+ select='@type'/>
+
+
+ <row>
+ <entry role="feature-detail">
+ <xsl:value-of select="@visibility"/>
+ </entry>
+
+ <entry role="feature-detail">
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target" />
+ </xsl:call-template>
+ </entry>
+
+ <entry role="feature-detail">
+ <xsl:value-of select="@name"/>
+ </entry>
+ </row>
+
+ <row>
+ <entry role="comment"/>
+ <entry namest="c2" nameend="c3" role="comment"><xsl:value-of select="@comment"/></entry>
+ </row>
+
+</xsl:template>
+
+
+
+<!-- Operations -->
+<xsl:template name="operations">
+ <xsl:variable name="class_operations"
+ select="UML:Classifier.feature/UML:Operation" />
+ <xsl:if test="count($class_operations) > 0">
+ <row>
+ <entry role="info-title" namest="c1" nameend="c3" ><para>Operations:</para></entry>
+ </row>
+ <row>
+ <entry role="feature-heading" ><para>visibility</para></entry>
+ <entry role="feature-heading" ><para>return</para></entry>
+ <entry role="feature-heading" ><para>name</para></entry>
+ </row>
+
+ <xsl:apply-templates select="UML:Classifier.feature/
+ UML:Operation" />
+ </xsl:if>
+</xsl:template>
+
+
+<xsl:template match="UML:Operation">
+
+ <xsl:variable name="parameters"
+ select="UML:BehavioralFeature.parameter/
+ UML:Parameter[@kind!='return']" />
+
+ <xsl:variable name="return"
+ select="UML:BehavioralFeature.parameter/
+ UML:Parameter[@kind='return']" />
+
+ <xsl:variable name="target"
+ select="$return/@type" />
+
+ <row>
+ <entry role="feature-detail">
+ <xsl:value-of select="@visibility" />
+ </entry>
+
+ <entry role="feature-detail">
+
+ <xsl:choose>
+ <xsl:when test="string-length($target) = 0">
+ <para role="datatype"><xsl:text>void</xsl:text></para>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </entry>
+
+ <entry role="feature-detail">
+ <xsl:value-of select="@name"/>
+ </entry>
+
+
+ </row>
+
+ <row>
+ <entry role="comment"/>
+ <entry namest="c2" nameend="c3" role="comment"><xsl:value-of select="@comment"/></entry>
+ </row>
+
+ <xsl:variable name="parameter-count" select="count($parameters)" />
+
+ <xsl:if test="not(normalize-space($parameter-count)='0')">
+
+ <row>
+ <entry role="feature-detail" >
+ <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
+ </entry>
+
+ <entry role="parameter-heading" valign="top">parameters:</entry>
+ <entry bgcolor="#ffffff" align="right">
+ <!--table width="85%" align="right" cellpadding="0" cellspacing="0" border="0">
+ <xsl:apply-templates select="$parameters" />
+ </table-->
+ </entry>
+ </row>
+
+ </xsl:if >
+
+</xsl:template>
+
+
+
+<!-- Parameter -->
+<xsl:template match="UML:Parameter">
+ <xsl:variable name="target"
+ select="@type" />
+
+ <row>
+ <entry role="feature-detail" width="45%">
+ <xsl:call-template name="classify">
+ <xsl:with-param name="target" select="$target" />
+ </xsl:call-template>
+ </entry>
+
+ <entry role="feature-detail" width="55%">
+ <xsl:value-of select="@name"/>
+ </entry>
+ </row>
+</xsl:template>
+
+
+<!-- Classification -->
+<xsl:template name="classify">
+ <xsl:param name="target"/>
+
+ <xsl:variable name="classifier"
+ select="key('classifier', $target)" />
+
+ <xsl:variable name="classifier_name"
+ select="$classifier/@name" />
+
+ <xsl:variable name="type" select="name($classifier)" />
+
+ <!-- Get the type of the classifier (class, interface, datatype) -->
+ <xsl:variable name="classifier_type">
+ <xsl:choose>
+ <xsl:when test="$type='UML:Class'">classifier</xsl:when>
+ <xsl:when test="$type='UML:Interface'">interface</xsl:when>
+ <xsl:when test="$type='UML:DataType'">datatype</xsl:when>
+ <xsl:otherwise>classifier</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <!-- Datatypes don't have hyperlinks -->
+ <xsl:when test="$type='UML:DataType'">
+ <span role="datatype">
+ <xsl:value-of select="$classifier_name"/>
+ </span>
+ </xsl:when>
+
+ <!-- Classes and Interfaces have hyperlinks -->
+ <!-- The classifier type is used to style appropriately -->
+ <xsl:otherwise>
+ <xsl:if test="string-length($classifier) > 0">
+ <!--a role={$classifier_type}" href="#{$classifier_name}"-->
+ <xsl:value-of select="$classifier_name"/>
+ <!--/a-->
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+<!--xsl:template match="XMI.content">
+
+ <xsl:comment >maintitlebegin1&title1;maintitleend1</xsl:comment>
+ <xsl:comment >maintitlebegin2&title2;maintitleend2</xsl:comment>
+ <xsl:apply-templates select="diagrams/diagram"/>
+</xsl:template-->
+
+
+ <xsl:template name="actor">
+ <xsl:param name = "idvalue"><xsl:value-of select="@xmi.id"/></xsl:param>
+ <!--td valign="top"-->
+ <para>
+ <!--role="push"-->
+ <xsl:for-each select="//XMI.content/umlobjects/UML:Actor">
+ <xsl:if test="@xmi.id = $idvalue">
+ <emphasis><xsl:value-of select="@name"/>:</emphasis>
+ <xsl:value-of select="@documentation"/>
+ </xsl:if>
+ </xsl:for-each >
+ </para>
+ <!--/td-->
+ </xsl:template>
+
+ <xsl:template name="usecase">
+ <xsl:param name = "idvalue"><xsl:value-of select="@xmi.id"/></xsl:param>
+ <!--td valign="top"-->
+ <para>
+ <!--role="push"-->
+ <xsl:for-each select="//XMI.content/umlobjects/UML:UseCase">
+ <xsl:if test="@xmi.id = $idvalue">
+ <emphasis><xsl:value-of select="@name"/>:</emphasis>
+ <xsl:value-of select="@documentation"/>
+
+ </xsl:if>
+ </xsl:for-each >
+ </para>
+ <!--/td-->
+ </xsl:template>
+
+ <xsl:template name="class">
+ <xsl:param name = "idvalue"><xsl:value-of select="@xmi.id"/></xsl:param>
+ <!--td valign="top"-->
+ <div role="push">
+ <xsl:for-each select="//XMI.content/umlobjects/UML:Class">
+ <xsl:if test="@xmi.id = $idvalue">
+ <div role="boldtext">&packagename;<xsl:value-of select="@package"/></div>
+ <div role="boldtext">&classname;<xsl:value-of select="@name"/></div>
+ <xsl:value-of select="@documentation"/>
+ <div role="push">
+
+ Stereotype: <xsl:value-of select="@stereotype"/>
+
+ Abstarct:
+ <xsl:if test="@abstract='1'">
+ <xsl:text>&yes;</xsl:text>
+ </xsl:if>
+ <xsl:if test="@abstract='0'">
+ <xsl:text>&no;</xsl:text>
+ </xsl:if>
+
+ Visibility:
+ <xsl:if test="@scope='200'">
+ <xsl:text>public</xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='201'">
+ <xsl:text>private</xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='202'">
+ <xsl:text>protected</xsl:text>
+ </xsl:if>
+
+ <xsl:call-template name="attribute"/>
+ <xsl:call-template name="operation"/>
+ </div>
+ </xsl:if>
+ </xsl:for-each >
+ </div>
+ <!--/td-->
+ </xsl:template>
+
+
+ <xsl:template name="attribute">
+ <!--td valign="top"-->
+ <div role="boldtext">&attributes;</div>
+
+ <xsl:for-each select="UML:Attribute">
+ <xsl:value-of select="@name"/><xsl:text> - </xsl:text><xsl:value-of select="@type"/>
+ Static:
+ <xsl:if test="@static='1'">
+ <xsl:text>&yes;</xsl:text>
+ </xsl:if>
+ <xsl:if test="@static='0'">
+ <xsl:text>&no;</xsl:text>
+ </xsl:if>
+
+ Visibility:
+ <xsl:if test="@scope='200'">
+ <xsl:text>public</xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='201'">
+ <xsl:text>private</xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='202'">
+ <xsl:text>protected</xsl:text>
+ </xsl:if>
+
+ Default �t�: <xsl:value-of select="@value"/>
+
+ <xsl:value-of select="@documentation"/>
+
+ </xsl:for-each >
+ <!--/td-->
+ </xsl:template>
+
+ <xsl:template name="operation">
+ <entry valign="top">
+ <div role="boldtext">&metodes;</div>
+
+ <xsl:for-each select="UML:Operation">
+ <i>
+ <xsl:if test="@abstract='1'">
+ <xsl:text>abstract </xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='200'">
+ <xsl:text>public </xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='201'">
+ <xsl:text>private </xsl:text>
+ </xsl:if>
+ <xsl:if test="@scope='202'">
+ <xsl:text>protected </xsl:text>
+ </xsl:if>
+
+ <xsl:value-of select="@type"/><xsl:text> </xsl:text>
+
+ <xsl:value-of select="@name"/><xsl:text>(</xsl:text>
+
+ <xsl:apply-templates select="UML:Parameter" mode="diagram"/>
+ <xsl:text>)</xsl:text>
+
+ </i>
+ <xsl:value-of select="@documentation"/>
+ &parameters;
+ <xsl:for-each select="UML:Parameter">
+ <div role="push">
+ <xsl:value-of select="@type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+
+ <xsl:value-of select="@documentation"/>
+
+ </div>
+ </xsl:for-each>
+
+ </xsl:for-each >
+ </entry>
+ </xsl:template>
+
+ <xsl:template match="UML:Parameter" mode="diagram">
+
+ <xsl:value-of select="@type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:if test="position()!=last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/umbrello/umbrello/docwindow.cpp b/umbrello/umbrello/docwindow.cpp
new file mode 100644
index 00000000..d92c13f4
--- /dev/null
+++ b/umbrello/umbrello/docwindow.cpp
@@ -0,0 +1,223 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "docwindow.h"
+
+// qt/kde includes
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qmultilineedit.h>
+#include <klocale.h>
+
+// local includes
+#include "associationwidget.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlview.h"
+#include "umlwidget.h"
+
+
+DocWindow::DocWindow( UMLDoc * doc, QWidget *parent, const char *name ) : QWidget( parent, name ) {
+ //setup visual display
+ QHBoxLayout * mainLayout = new QHBoxLayout( this );
+
+ m_pDocGB = new QGroupBox( i18n( "Documentation" ), this );
+ mainLayout -> addWidget( m_pDocGB );
+
+ QHBoxLayout * docLayout = new QHBoxLayout( m_pDocGB );
+ m_pDocMLE = new QMultiLineEdit( m_pDocGB );
+ m_pDocMLE -> setText( "" );
+ docLayout -> setMargin( fontMetrics().height() );
+ docLayout -> addWidget( m_pDocMLE);
+ m_pDocMLE -> setWordWrap(QMultiLineEdit::WidgetWidth);
+
+ //setup the documentation variables
+ //show projects documentation to start
+ m_pUMLDoc = doc;
+ m_Showing = st_Project;
+ m_pUMLObject = 0;
+ m_pUMLView = 0;
+ m_pUMLWidget = 0;
+ m_pAssocWidget = 0;
+ updateDocumentation( true, true );
+}
+
+DocWindow::~DocWindow() {}
+
+void DocWindow::showDocumentation( UMLObject * object, bool overwrite ) {
+ if( object == m_pUMLObject && !overwrite )
+ return;
+ if( object != m_pUMLObject )
+ updateDocumentation( true );
+
+ m_Showing = st_UMLObject;
+ if( !object ) {
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+ m_pUMLObject = 0;
+ return;
+ }
+ m_pUMLObject = object;
+ m_pDocMLE -> setText( m_pUMLObject -> getDoc() );
+}
+
+void DocWindow::updateDocumentation( bool clear, bool startup ) {
+
+ bool mark_modified = false;
+ if( m_pUMLObject )
+ {
+ // the file is marked modified, if the documentation differs
+ // we don't do this on startup/load of a xmi file, because every time
+ // modified is set, we get another undo/redo backup point
+ if ( startup == false && m_pDocMLE -> text() != m_pUMLObject -> getDoc() )
+ {
+ mark_modified = true;
+ }
+ m_pUMLObject -> setDoc( m_pDocMLE -> text() );
+
+ } else if( m_pUMLView ) {
+ // the file is marked modified, if the documentation differs
+ // we don't do this on startup/load of a xmi file, because every time
+ // modified is set, we get another undo/redo backup point
+ if ( startup == false && m_pDocMLE -> text() != m_pUMLView -> getDoc() )
+ {
+ mark_modified = true;
+ }
+
+ m_pUMLView -> setDoc( m_pDocMLE -> text() );
+ } else if ( m_pUMLWidget ) {
+ // the file is marked modified, if the documentation differs
+ // we don't do this on startup/load of a xmi file, because every time
+ // modified is set, we get another undo/redo backup point
+ if ( startup == false && m_pDocMLE -> text() != m_pUMLWidget -> getDoc() )
+ {
+ mark_modified = true;
+ }
+
+ m_pUMLWidget -> setDoc( m_pDocMLE -> text() );
+ } else if( m_pAssocWidget ) {
+ // the file is marked modified, if the documentation differs
+ // we don't do this on startup/load of a xmi file, because every time
+ // modified is set, we get another undo/redo backup point
+ if ( startup == false && m_pDocMLE -> text() != m_pAssocWidget -> getDoc() )
+ {
+ mark_modified = true;
+ }
+
+ m_pAssocWidget -> setDoc( m_pDocMLE -> text() );
+ } else {
+ // the file is marked modified, if the documentation differs
+ // we don't do this on startup/load of a xmi file, because every time
+ // modified is set, we get another undo/redo backup point
+ if ( startup == false && m_pDocMLE -> text() != m_pUMLDoc->getDocumentation() )
+ {
+ mark_modified = true;
+ }
+
+ m_pUMLDoc->setDocumentation( m_pDocMLE->text() );
+ }
+
+ // now do the setModified call
+ if (mark_modified == true)
+ m_pUMLDoc -> setModified( true );
+
+ // we should show the documentation of the whole project
+ if( clear ) {
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+ m_pUMLObject = 0;
+ m_pUMLView = 0;
+ m_pUMLWidget = 0;
+ m_pAssocWidget = 0;
+ m_Showing = st_Project;
+ }
+
+ return;
+}
+
+void DocWindow::showDocumentation( UMLView * view, bool overwrite ) {
+ if( view == m_pUMLView && !overwrite )
+ return;
+ if( view != m_pUMLView )
+ updateDocumentation( true );
+ m_Showing = st_UMLView;
+ if( !view ) {
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+ m_pUMLView = 0;
+ return;
+ }
+ m_pUMLView = view;
+ m_pDocMLE -> setText( m_pUMLView -> getDoc() );
+}
+
+void DocWindow::showDocumentation( UMLWidget * widget, bool overwrite ) {
+ if( widget == m_pUMLWidget && !overwrite )
+ return;
+ if( widget != m_pUMLWidget )
+ updateDocumentation( true );
+ m_Showing = st_UMLWidget;
+ if( !widget ) {
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+ m_pUMLWidget = 0;
+ return;
+ }
+ m_pUMLWidget = widget;
+ m_pDocMLE -> setText( m_pUMLWidget -> getDoc() );
+}
+
+void DocWindow::showDocumentation( AssociationWidget * widget, bool overwrite ) {
+ if( widget == m_pAssocWidget && !overwrite )
+ return;
+ if( widget != m_pAssocWidget )
+ updateDocumentation( true );
+ m_Showing = st_Association;
+ if( !widget ) {
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+ m_pAssocWidget = 0;
+ return;
+ }
+ m_pAssocWidget = widget;
+ m_pDocMLE -> setText( m_pAssocWidget -> getDoc() );
+}
+
+void DocWindow::newDocumentation( ) {
+ m_pUMLView = 0;
+ m_pUMLObject = 0;
+ m_pUMLWidget = 0;
+ m_pAssocWidget = 0;
+ m_Showing = st_Project;
+ m_pDocMLE->setText( m_pUMLDoc->getDocumentation() );
+}
+
+bool DocWindow::isTyping()
+{
+ if (m_pDocMLE->hasFocus())
+ return true;
+ else
+ return false;
+}
+
+void DocWindow::slotAssociationRemoved(AssociationWidget* association) {
+ if (association == m_pAssocWidget || association->getUMLObject() == m_pUMLObject) {
+ // In old code, the below line crashed (bugs.kde.org/89860)
+ // A hotfix was made and detailed analysis was To Be Done:
+ // newDocumentation()
+ // However, it seems to have been fixed and the below line seems to work fine
+ updateDocumentation(true);
+ }
+}
+
+void DocWindow::slotWidgetRemoved(UMLWidget* widget) {
+ if (widget == m_pUMLWidget || widget->getUMLObject() == m_pUMLObject) {
+ updateDocumentation(true);
+ }
+}
+
+#include "docwindow.moc"
diff --git a/umbrello/umbrello/docwindow.h b/umbrello/umbrello/docwindow.h
new file mode 100644
index 00000000..fb488c5f
--- /dev/null
+++ b/umbrello/umbrello/docwindow.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef DOCWINDOW_H
+#define DOCWINDOW_H
+
+#include <qwidget.h>
+
+class AssociationWidget;
+class QGroupBox;
+class QMultiLineEdit;
+class UMLObject;
+class UMLDoc;
+class UMLView;
+class UMLWidget;
+
+/**
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class DocWindow : public QWidget {
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ explicit DocWindow( UMLDoc * doc, QWidget *parent = 0, const char *name = 0 );
+
+ /**
+ * Deconstructor
+ */
+ ~DocWindow();
+
+ /**
+ * Called when a widget wishes to display its documentation in the
+ * doc window. If there was already documentation there, that will
+ * be updated before being removed from the view.
+ *
+ * Also call this function if you update the documentation in another
+ * place, such as a properties dialog. Just set overwrite to true.
+ *
+ * Overwrite is used when you believe that the documentation window
+ * is already displaying documentation for the widget you wish to
+ * display.
+ * Overwrite just determines whose version is more up to date.
+ */
+ void showDocumentation( UMLObject * object, bool overwrite = false );
+
+ /**
+ * This method is the same as the one for UMLObjects except it
+ * displays documentation for a diagram.
+ */
+ void showDocumentation( UMLView * view, bool overwrite = false );
+
+ /**
+ * This method is the same as the one for UMLObjects except it
+ * displays documentation for an object instance (StateWidget/
+ * ObjectWidget).
+ */
+ void showDocumentation( UMLWidget * widget, bool overwrite = false );
+
+ /**
+ * This method is the same as the one for UMLObjects except it
+ * displays documentation for an association instance
+ * (AssociationWidget).
+ */
+ void showDocumentation( AssociationWidget * widget, bool overwrite = false );
+
+ /**
+ * Call when you wish move changes in the doc window back into the
+ * members documentation.
+ *
+ * If clear is true the doc window will display the documentation
+ * for the current project instead of the widget documentation.
+ *
+ * This is usually called before displaying a properties dialog.
+ *
+ * @param clear If true, show the documentation of current project
+ * @param startup If true, no setModified(true) calls will be done and nothing is pushed to the undo stack
+ */
+ void updateDocumentation( bool clear = false, bool startup = false );
+
+
+ /**
+ * Re-initializes the class for a new document.
+ */
+ void newDocumentation( );
+
+ /**
+ * Checks if the user is typing in the documentation edit window
+ */
+ bool isTyping();
+
+public slots:
+
+ /**
+ * An association was removed from the UMLView.
+ * If the association removed was the association which documentation is
+ * being shown, m_pAssocWidget is set to 0.
+ */
+ void slotAssociationRemoved(AssociationWidget* association);
+
+ /**
+ * A widget was removed from the UMLView.
+ * If the association removed was the association which documentation is
+ * being shown, m_pUMLWidget is set to 0.
+ */
+ void slotWidgetRemoved(UMLWidget* widget);
+
+private:
+ /**
+ * Used internally to know which type of object we are showing
+ * documentation for.
+ */
+ enum Showing_Type {
+ st_Project,
+ st_UMLView,
+ st_UMLObject,
+ st_UMLWidget,
+ st_Association
+ };
+
+ /**
+ * A pointer to the UMLObject we are going to show documentation.
+ */
+ UMLObject * m_pUMLObject;
+
+ /**
+ * A pointer to the UMLView we are going to show documentation.
+ */
+ UMLView * m_pUMLView;
+
+ /**
+ * A pointer to the Project we are going to show documentation.
+ */
+ UMLDoc * m_pUMLDoc;
+
+ /**
+ * A pointer to the UMLWidget we are going to show documentation.
+ */
+ UMLWidget * m_pUMLWidget;
+
+ /**
+ * A pointer to the association we are going to show documentation.
+ */
+ AssociationWidget * m_pAssocWidget;
+
+ /**
+ * Which type of documentation we are showing.
+ */
+ Showing_Type m_Showing;
+
+ //visual widgets
+ QMultiLineEdit * m_pDocMLE;
+ QGroupBox * m_pDocGB;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/entity.cpp b/umbrello/umbrello/entity.cpp
new file mode 100644
index 00000000..b3d842ac
--- /dev/null
+++ b/umbrello/umbrello/entity.cpp
@@ -0,0 +1,217 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "entity.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+// app includes
+#include "entityattribute.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "clipboard/idchangelog.h"
+#include "dialogs/umlentityattributedialog.h"
+
+UMLEntity::UMLEntity(const QString& name, Uml::IDType id) : UMLClassifier(name, id) {
+ init();
+}
+
+UMLEntity::~UMLEntity() {
+ m_List.clear();
+}
+
+bool UMLEntity::operator==( UMLEntity& rhs ) {
+ return UMLClassifier::operator==(rhs);
+}
+
+void UMLEntity::copyInto(UMLEntity *rhs) const
+{
+ UMLClassifier::copyInto(rhs);
+}
+
+UMLObject* UMLEntity::clone() const
+{
+ UMLEntity* clone = new UMLEntity();
+ copyInto(clone);
+
+ return clone;
+}
+
+void UMLEntity::init() {
+ m_BaseType = Uml::ot_Entity;
+}
+
+UMLAttribute* UMLEntity::createAttribute(const QString &name /*=null*/, UMLObject *type /*=NULL*/) {
+ Uml::IDType id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(Uml::ot_EntityAttribute);
+ } else {
+ currentName = name;
+ }
+ const Settings::OptionState optionState = Settings::getOptionState();
+ Uml::Visibility scope = optionState.classState.defaultAttributeScope;
+ UMLEntityAttribute* newAttribute = new UMLEntityAttribute(this, currentName, id, scope, type);
+
+ int button = QDialog::Accepted;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating attribute via list view
+ while (button==QDialog::Accepted && !goodName && name.isNull()) {
+ UMLEntityAttributeDialog attributedialog(0, newAttribute);
+ button = attributedialog.exec();
+ QString name = newAttribute->getName();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else if ( findChildObject(name) != NULL ) {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ } else {
+ goodName = true;
+ }
+ }
+
+ if (button != QDialog::Accepted) {
+ delete newAttribute;
+ return NULL;
+ }
+
+ addEntityAttribute(newAttribute);
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(newAttribute);
+ return newAttribute;
+}
+
+UMLObject* UMLEntity::addEntityAttribute(const QString& name, Uml::IDType id) {
+ UMLEntityAttribute* literal = new UMLEntityAttribute(this, name, id);
+ m_List.append(literal);
+ emit entityAttributeAdded(literal);
+ UMLObject::emitModified();
+ connect(literal,SIGNAL(modified()),this,SIGNAL(modified()));
+ return literal;
+}
+
+bool UMLEntity::addEntityAttribute(UMLEntityAttribute* attribute, IDChangeLog* Log /* = 0*/) {
+ QString name = (QString)attribute->getName();
+ if (findChildObject(name) == NULL) {
+ attribute->parent()->removeChild(attribute);
+ this->insertChild(attribute);
+ m_List.append(attribute);
+ emit entityAttributeAdded(attribute);
+ UMLObject::emitModified();
+ connect(attribute,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ } else if (Log) {
+ Log->removeChangeByNewID( attribute->getID() );
+ delete attribute;
+ }
+ return false;
+}
+
+bool UMLEntity::addEntityAttribute(UMLEntityAttribute* attribute, int position) {
+ QString name = (QString)attribute->getName();
+ if (findChildObject(name) == NULL) {
+ attribute->parent()->removeChild(attribute);
+ this->insertChild(attribute);
+ if ( position >= 0 && position <= (int)m_List.count() ) {
+ m_List.insert(position,attribute);
+ } else {
+ m_List.append(attribute);
+ }
+ emit entityAttributeAdded(attribute);
+ UMLObject::emitModified();
+ connect(attribute,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ }
+ return false;
+}
+
+int UMLEntity::removeEntityAttribute(UMLClassifierListItem* literal) {
+ if (!m_List.remove((UMLEntityAttribute*)literal)) {
+ kDebug() << "can't find att given in list" << endl;
+ return -1;
+ }
+ emit entityAttributeRemoved(literal);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ delete literal;
+ return m_List.count();
+}
+
+int UMLEntity::entityAttributes() {
+ UMLClassifierListItemList entityAttributes = getFilteredList(Uml::ot_EntityAttribute);
+ return entityAttributes.count();
+}
+
+void UMLEntity::signalEntityAttributeRemoved(UMLClassifierListItem *eattr) {
+ emit entityAttributeRemoved(eattr);
+}
+
+bool UMLEntity::resolveRef() {
+ bool success = UMLClassifier::resolveRef();
+ for (UMLObjectListIt oit(m_List); oit.current(); ++oit) {
+ UMLObject* obj = oit.current();
+ if (obj->resolveRef()) {
+ UMLClassifierListItem *cli = static_cast<UMLClassifierListItem*>(obj);
+ if (cli->getBaseType() == Uml::ot_EntityAttribute)
+ emit entityAttributeAdded(cli);
+ }
+ }
+ return success;
+}
+
+void UMLEntity::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement entityElement = UMLObject::save("UML:Entity", qDoc);
+ //save operations
+ UMLClassifierListItemList entityAttributes = getFilteredList(Uml::ot_EntityAttribute);
+ UMLClassifierListItem* pEntityAttribute = 0;
+ for (UMLClassifierListItemListIt it(entityAttributes);
+ (pEntityAttribute = it.current()) != NULL; ++it) {
+ pEntityAttribute->saveToXMI(qDoc, entityElement);
+ }
+ qElement.appendChild(entityElement);
+}
+
+bool UMLEntity::load(QDomElement& element) {
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Uml::tagEq(tag, "EntityAttribute")) { // for backward compatibility
+ UMLEntityAttribute* pEntityAttribute = new UMLEntityAttribute(this);
+ if( !pEntityAttribute->loadFromXMI(tempElement) ) {
+ return false;
+ }
+ m_List.append(pEntityAttribute);
+ } else if (tag == "stereotype") {
+ kDebug() << "UMLEntity::load(" << m_Name
+ << "): losing old-format stereotype." << endl;
+ } else {
+ kWarning() << "unknown child type in UMLEntity::load" << endl;
+ }
+ node = node.nextSibling();
+ }//end while
+ return true;
+}
+
+
+#include "entity.moc"
diff --git a/umbrello/umbrello/entity.h b/umbrello/umbrello/entity.h
new file mode 100644
index 00000000..7a4a2ce9
--- /dev/null
+++ b/umbrello/umbrello/entity.h
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENTITY_H
+#define ENTITY_H
+
+#include "classifier.h"
+
+class UMLEntityAttribute;
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Entity.
+ * This class inherits from @ref UMLClassifier which contains most of the
+ * information.
+ *
+ * @short Non-graphical Information for an Entity.
+ * @author Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLEntity : public UMLClassifier {
+ Q_OBJECT
+public:
+ /**
+ * Sets up an entity.
+ *
+ * @param name The name of the Entity.
+ * @param id The unique id of the Entity.
+ */
+ explicit UMLEntity(const QString& name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLEntity();
+
+ /**
+ * Overloaded '==' operator.
+ */
+ bool operator==(UMLEntity& rhs);
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLEntity* rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates an entity attribute for the parent concept.
+ * Reimplementation of method from UMLClassifier.
+ *
+ * @param name An optional name, used by when creating through UMLListView
+ * @param type An optional type, used by when creating through UMLListView
+ * @return The UMLEntityAttribute created
+ */
+ UMLAttribute* createAttribute(const QString &name = QString::null,
+ UMLObject *type = 0);
+
+ /**
+ * Adds an entityAttribute to the entity.
+ *
+ * @param name The name of the entityAttribute.
+ * @param id The id of the entityAttribute (optional.)
+ * If omitted a new ID is assigned internally.
+ * @return Pointer to the UMLEntityAttribute created.
+ */
+ UMLObject* addEntityAttribute(const QString &name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Adds an already created entityAttribute.
+ * The entityAttribute object must not belong to any other concept.
+ *
+ * @param att Pointer to the UMLEntityAttribute.
+ * @param Log Pointer to the IDChangeLog.
+ * @return True if the entityAttribute was successfully added.
+ */
+ bool addEntityAttribute(UMLEntityAttribute* att, IDChangeLog* Log = 0);
+
+ /**
+ * Adds an entityAttribute to the entity, at the given position.
+ * If position is negative or too large, the entityAttribute is added
+ * to the end of the list.
+ *
+ * @param att Pointer to the UMLEntityAttribute.
+ * @param position Position index for the insertion.
+ * @return True if the entityAttribute was successfully added.
+ */
+ //TODO: give default value -1 to position (append) - now it conflicts with the method above..
+ bool addEntityAttribute(UMLEntityAttribute* att, int position );
+
+ /**
+ * Removes an entityAttribute from the class.
+ *
+ * @param a The entityAttribute to remove.
+ * @return Count of the remaining entityAttributes after removal.
+ * Returns -1 if the given entityAttribute was not found.
+ */
+ int removeEntityAttribute(UMLClassifierListItem* a);
+
+ /**
+ * Emit the entityAttributeRemoved signal.
+ */
+ void signalEntityAttributeRemoved(UMLClassifierListItem *eattr);
+
+ /**
+ * Returns the number of entityAttributes for the class.
+ *
+ * @return The number of entityAttributes for the class.
+ */
+ int entityAttributes() ;
+
+ /**
+ * Resolve the types referenced by our UMLEntityAttributes.
+ * Reimplements the method from UMLClassifier.
+ */
+ virtual bool resolveRef();
+
+ /**
+ * Creates the <UML:Entity> element including its entityliterals.
+ */
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+signals:
+ void entityAttributeAdded(UMLClassifierListItem*);
+ void entityAttributeRemoved(UMLClassifierListItem*);
+
+protected:
+ /**
+ * Loads the <UML:Entity> element including its entityAttributes.
+ */
+ bool load(QDomElement& element);
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+};
+
+#endif // ENTITY_H
+
diff --git a/umbrello/umbrello/entityattribute.cpp b/umbrello/umbrello/entityattribute.cpp
new file mode 100644
index 00000000..8855efcb
--- /dev/null
+++ b/umbrello/umbrello/entityattribute.cpp
@@ -0,0 +1,178 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "entityattribute.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "umlcanvasobject.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "dialogs/umlentityattributedialog.h"
+#include "object_factory.h"
+
+UMLEntityAttribute::UMLEntityAttribute( const UMLObject *parent, const QString& name,
+ Uml::IDType id, Uml::Visibility s,
+ UMLObject *type, const QString& iv )
+ : UMLAttribute(parent, name, id, s, type, iv) {
+ init();
+ if (m_pSecondary) {
+ m_pSecondary->setBaseType(Uml::ot_Entity);
+ }
+}
+
+UMLEntityAttribute::UMLEntityAttribute(const UMLObject *parent) : UMLAttribute(parent) {
+ init();
+}
+
+UMLEntityAttribute::~UMLEntityAttribute() { }
+
+void UMLEntityAttribute::init() {
+ m_BaseType = Uml::ot_EntityAttribute;
+ m_indexType = Uml::None;
+ m_autoIncrement = false;
+ m_null = false;
+}
+
+QString UMLEntityAttribute::getAttributes() const{
+ return m_attributes;
+}
+
+void UMLEntityAttribute::setAttributes(const QString& attributes) {
+ m_attributes = attributes;
+}
+
+QString UMLEntityAttribute::getValues() const{
+ return m_values;
+}
+
+void UMLEntityAttribute::setValues(const QString& values) {
+ m_values = values;
+}
+
+bool UMLEntityAttribute::getAutoIncrement() const{
+ return m_autoIncrement;
+}
+
+void UMLEntityAttribute::setAutoIncrement(const bool autoIncrement) {
+ m_autoIncrement = autoIncrement;
+}
+
+Uml::DBIndex_Type UMLEntityAttribute::getIndexType() const{
+ return m_indexType;
+}
+
+void UMLEntityAttribute::setIndexType(const Uml::DBIndex_Type indexType) {
+ m_indexType = indexType;
+}
+
+bool UMLEntityAttribute::getNull() const{
+ return m_null;
+}
+
+void UMLEntityAttribute::setNull(const bool nullIn) {
+ m_null = nullIn;
+}
+
+QString UMLEntityAttribute::toString(Uml::Signature_Type sig) {
+ QString s;
+ //FIXME
+
+ if(sig == Uml::st_ShowSig || sig == Uml::st_NoSig) {
+ s=m_Vis.toString(true) + ' ';
+ } else
+ s = "";
+
+ if(sig == Uml::st_ShowSig || sig == Uml::st_SigNoVis) {
+ QString string = s + getName() + " : " + getTypeName();
+ if(m_InitialValue.length() > 0)
+ string += " = " + m_InitialValue;
+ return string;
+ } else
+ return s + getName();
+}
+
+bool UMLEntityAttribute::operator==( UMLEntityAttribute &rhs) {
+ if( this == &rhs )
+ return true;
+
+ if( !UMLObject::operator==( rhs ) )
+ return false;
+
+ // The type name is the only distinguishing criterion.
+ // (Some programming languages might support more, but others don't.)
+ if (m_pSecondary != rhs.m_pSecondary)
+ return false;
+
+ return true;
+}
+
+void UMLEntityAttribute::copyInto(UMLEntityAttribute *rhs) const
+{
+ // call the parent first.
+ UMLClassifierListItem::copyInto(rhs);
+
+ // Copy all datamembers
+ rhs->m_pSecondary = m_pSecondary;
+ rhs->m_SecondaryId = m_SecondaryId;
+ rhs->m_InitialValue = m_InitialValue;
+ rhs->m_ParmKind = m_ParmKind;
+}
+
+UMLObject* UMLEntityAttribute::clone() const
+{
+ UMLEntityAttribute* clone = new UMLEntityAttribute( (UMLEntityAttribute*)parent() );
+ copyInto(clone);
+
+ return clone;
+}
+
+
+void UMLEntityAttribute::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement entityattributeElement = UMLObject::save("UML:EntityAttribute", qDoc);
+ if (m_pSecondary == NULL) {
+ kDebug() << "UMLEntityAttribute::saveToXMI(" << m_Name
+ << "): m_pSecondary is NULL, using local name "
+ << m_SecondaryId << endl;
+ entityattributeElement.setAttribute( "type", m_SecondaryId );
+ } else {
+ entityattributeElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) );
+ }
+ entityattributeElement.setAttribute( "initialValue", m_InitialValue );
+ entityattributeElement.setAttribute( "dbindex_type", m_indexType );
+ entityattributeElement.setAttribute( "values", m_values );
+ entityattributeElement.setAttribute( "attributes", m_attributes );
+ entityattributeElement.setAttribute( "auto_increment", m_autoIncrement );
+ entityattributeElement.setAttribute( "allow_null", m_null );
+ qElement.appendChild( entityattributeElement );
+}
+
+bool UMLEntityAttribute::load( QDomElement & element ) {
+ if (! UMLAttribute::load(element))
+ return false;
+ int indexType = element.attribute( "dbindex_type", "1100" ).toInt();
+ m_indexType = ( Uml::DBIndex_Type )indexType;
+ m_values = element.attribute( "values", "" );
+ m_attributes = element.attribute( "attributes", "" );
+ m_autoIncrement = ( bool )element.attribute( "auto_increment", "" ).toInt();
+ m_null = ( bool )element.attribute( "allow_null", "" ).toInt();
+ return true;
+}
+
+bool UMLEntityAttribute::showPropertiesDialog(QWidget* parent) {
+ UMLEntityAttributeDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+#include "entityattribute.moc"
+
diff --git a/umbrello/umbrello/entityattribute.h b/umbrello/umbrello/entityattribute.h
new file mode 100644
index 00000000..76af37a7
--- /dev/null
+++ b/umbrello/umbrello/entityattribute.h
@@ -0,0 +1,183 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENTITYATTRIBUTE_H
+#define ENTITYATTRIBUTE_H
+
+#include "attribute.h"
+#include "umlnamespace.h"
+
+/**
+ * This class is used to set up information for an entityattribute. This is a database field
+ * It has a type, name, index type and default value.
+ *
+ * @short Sets up entityattribute information.
+ * @author Jonathan Riddell <jr @jriddell.org>
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLEntityAttribute : public UMLAttribute {
+ Q_OBJECT
+public:
+ /**
+ * Sets up an entityattribute.
+ *
+ * @param parent The parent of this UMLEntityAttribute.
+ * @param name The name of this UMLEntityAttribute.
+ * @param id The unique id given to this UMLEntityAttribute.
+ * @param s The visibility of the UMLEntityAttribute.
+ * @param type The type of this UMLEntityAttribute.
+ * @param iv The initial value of the entityattribute.
+ */
+ UMLEntityAttribute(const UMLObject* parent, const QString& name,
+ Uml::IDType id = Uml::id_None,
+ Uml::Visibility s = Uml::Visibility::Private,
+ UMLObject *type = 0, const QString& iv = 0);
+
+ /**
+ * Sets up an entityattribute.
+ *
+ * @param parent The parent of this UMLEntityAttribute.
+ */
+ UMLEntityAttribute(const UMLObject* parent);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==( UMLEntityAttribute& rhs);
+
+ /**
+ * destructor.
+ */
+ virtual ~UMLEntityAttribute();
+
+ /**
+ * Copy the internal presentation of this object into the UMLEntityAttribute
+ * object.
+ */
+ virtual void copyInto(UMLEntityAttribute* rhs) const;
+
+ /**
+ * Make a clone of the UMLEntityAttribute.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Returns The value of the UMLEntityAttribute's attributes property.
+ *
+ * @return The value of the UMLEntityAttribute's attributes property.
+ */
+ QString getAttributes() const;
+
+ /**
+ * Sets the UMLEntityAttribute's attributes property.
+ *
+ * @param attributes The new value for the attributes property.
+ */
+ void setAttributes(const QString& attributes);
+
+ /**
+ * Returns the UMLEntityAttribute's index type property.
+ *
+ * @return The value of the UMLEntityAttribute's index type property.
+ */
+ Uml::DBIndex_Type getIndexType() const;
+
+ /**
+ * Sets the UMLEntityAttribute's index type property.
+ *
+ * @param indexType The UMLEntityAttribute's index type property.
+ */
+ void setIndexType(const Uml::DBIndex_Type indexType);
+
+ /**
+ * Returns the UMLEntityAttribute's length/values property.
+ *
+ * @return The UMLEntityAttribute's length/values property.
+ */
+ QString getValues() const;
+
+ /**
+ * Sets the UMLEntityAttribute's length/values property.
+ *
+ * @param values The new value of the length/values property.
+ */
+ void setValues(const QString& values);
+
+ /**
+ * Returns the UMLEntityAttribute's auto_increment boolean
+ *
+ * @return The UMLEntityAttribute's auto_increment boolean
+ */
+ bool getAutoIncrement() const;
+
+ /**
+ * Sets the UMLEntityAttribute's auto_increment property
+ *
+ * @param autoIncrement The UMLEntityAttribute's auto_increment property
+ */
+ void setAutoIncrement(const bool autoIncrement);
+
+ /**
+ * Returns the UMLEntityAttribute's allow null value.
+ *
+ * @return The UMLEntityAttribute's allow null value.
+ */
+ bool getNull() const;
+
+ /**
+ * Sets the UMLEntityAttribute's allow null value.
+ *
+ * @param null The UMLEntityAttribute's allow null value.
+ */
+ void setNull(const bool null);
+
+ /**
+ * Returns a string representation of the UMLEntityAttribute.
+ *
+ * @param sig If true will show the entityattribute type and
+ * initial value.
+ * @return Returns a string representation of the UMLEntityAttribute.
+ */
+ QString toString(Uml::Signature_Type sig = Uml::st_NoSig);
+
+ /**
+ * Creates the <UML:EntityAttribute> XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Display the properties configuration dialog for the entityattribute.
+ */
+ bool showPropertiesDialog(QWidget* parent);
+
+protected:
+ /**
+ * Initialize members of this class.
+ * Auxiliary method used by constructors.
+ */
+ void init();
+
+ /**
+ * Loads the <UML:EntityAttribute> XMI element.
+ */
+ bool load(QDomElement& element);
+
+private:
+ Uml::DBIndex_Type m_indexType;
+ QString m_values;
+ QString m_attributes;
+ bool m_autoIncrement;
+ bool m_null;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/entitywidget.cpp b/umbrello/umbrello/entitywidget.cpp
new file mode 100644
index 00000000..942de360
--- /dev/null
+++ b/umbrello/umbrello/entitywidget.cpp
@@ -0,0 +1,203 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "entitywidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+
+// app includes
+#include "entity.h"
+#include "entityattribute.h"
+#include "classifier.h"
+#include "umlclassifierlistitemlist.h"
+#include "classifierlistitem.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "listpopupmenu.h"
+#include "object_factory.h"
+
+
+EntityWidget::EntityWidget(UMLView* view, UMLObject* o): UMLWidget(view, o) {
+ init();
+}
+
+void EntityWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Entity);
+ setSize(100, 30);
+ //set defaults from m_pView
+ if (m_pView) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ }
+ if (! UMLApp::app()->getDocument()->loading())
+ updateComponentSize();
+}
+
+EntityWidget::~EntityWidget() {}
+
+void EntityWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if(UMLWidget::getUseFillColour())
+ p.setBrush(UMLWidget::getFillColour());
+ else
+ p.setBrush(m_pView -> viewport() -> backgroundColor());
+
+ const int w = width();
+ const int h = height();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int fontHeight = fm.lineSpacing();
+ const QString name = this->getName();
+
+ p.drawRect(offsetX, offsetY, w, h);
+ p.setPen(QPen(Qt::black));
+
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ p.setFont(font);
+ int y = 0;
+ if ( !m_pObject->getStereotype().isEmpty() ) {
+ p.drawText(offsetX + ENTITY_MARGIN, offsetY,
+ w - ENTITY_MARGIN * 2,fontHeight,
+ Qt::AlignCenter, m_pObject->getStereotype(true));
+ font.setItalic( m_pObject -> getAbstract() );
+ p.setFont(font);
+ p.drawText(offsetX + ENTITY_MARGIN, offsetY + fontHeight,
+ w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ p.setFont(font);
+ y = fontHeight * 2;
+ } else {
+ font.setItalic( m_pObject -> getAbstract() );
+ p.setFont(font);
+ p.drawText(offsetX + ENTITY_MARGIN, offsetY,
+ w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ p.setFont(font);
+
+ y = fontHeight;
+ }
+
+ UMLWidget::setPen(p);
+
+ p.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y);
+
+ QFontMetrics fontMetrics(font);
+ UMLClassifier *classifier = (UMLClassifier*)m_pObject;
+ UMLClassifierListItem* entityattribute = 0;
+ UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EntityAttribute);
+ for (entityattribute = list.first(); entityattribute; entityattribute = list.next()) {
+ QString text = entityattribute->getName();
+ p.setPen( QPen(Qt::black) );
+ UMLEntityAttribute* casted = dynamic_cast<UMLEntityAttribute*>( entityattribute );
+ if( casted && casted->getIndexType() == Uml::Primary )
+ {
+ font.setUnderline( true );
+ p.setFont( font );
+ font.setUnderline( false );
+ }
+ p.drawText(offsetX + ENTITY_MARGIN, offsetY + y,
+ fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
+ p.setFont( font );
+ y+=fontHeight;
+ }
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize EntityWidget::calculateSize() {
+ if (!m_pObject) {
+ return UMLWidget::calculateSize();
+ }
+
+ int width, height;
+ QFont font = UMLWidget::getFont();
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setBold(false);
+ const QFontMetrics fm(font);
+
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ if ( !m_pObject->getStereotype().isEmpty() ) {
+ lines++;
+ }
+
+ const int numberOfEntityAttributes = ((UMLEntity*)m_pObject)->entityAttributes();
+
+ height = width = 0;
+ //set the height of the entity
+
+ lines += numberOfEntityAttributes;
+ if (numberOfEntityAttributes == 0) {
+ height += fontHeight / 2; //no entity literals, so just add a bit of space
+ }
+
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ // FIXME spaces to get round beastie with font width,
+ // investigate UMLWidget::getFontMetrics()
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(' ' + getName() + ' ').width();
+
+ const int w = getFontMetrics(FT_BOLD).boundingRect(m_pObject->getStereotype(true)).width();
+
+ width = w > width?w:width;
+
+ UMLClassifier* classifier = (UMLClassifier*)m_pObject;
+ UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EntityAttribute);
+ UMLClassifierListItem* listItem = 0;
+ for (listItem = list.first(); listItem; listItem = list.next()) {
+ int w = fm.width( listItem->getName() );
+ width = w > width?w:width;
+ }
+
+ //allow for width margin
+ width += ENTITY_MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void EntityWidget::slotMenuSelection(int sel) {
+ switch(sel) {
+ case ListPopupMenu::mt_EntityAttribute:
+ if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_pObject),
+ Uml::ot_EntityAttribute) ) {
+ UMLApp::app()->getDocument()->setModified();
+ }
+ break;
+ }
+ UMLWidget::slotMenuSelection(sel);
+}
+
+void EntityWidget::saveToXMI( QDomDocument& qDoc, QDomElement& qElement ) {
+ QDomElement conceptElement = qDoc.createElement("entitywidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
+bool EntityWidget::loadFromXMI( QDomElement & qElement ) {
+ if ( !UMLWidget::loadFromXMI(qElement) ) {
+ return false;
+ }
+ return true;
+}
+
diff --git a/umbrello/umbrello/entitywidget.h b/umbrello/umbrello/entitywidget.h
new file mode 100644
index 00000000..249f0984
--- /dev/null
+++ b/umbrello/umbrello/entitywidget.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENTITYWIDGET_H
+#define ENTITYWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLView;
+
+#define ENTITY_MARGIN 5
+
+/**
+ * Defines a graphical version of the entity. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an entity.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class EntityWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs an EntityWidget.
+ *
+ * @param view The parent of this EntityWidget.
+ * @param o The UMLObject this will be representing.
+ */
+ EntityWidget(UMLView* view, UMLObject* o);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~EntityWidget();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Draws the entity as a rectangle with a box underneith with a list of literals
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "entitywidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Loads from an "entitywidget" XMI element.
+ */
+ bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+public slots:
+ /**
+ * Will be called when a menu selection has been made from the
+ * popup menu.
+ *
+ * @param sel The selection id that has been selected.
+ */
+ void slotMenuSelection(int sel);
+};
+
+#endif
diff --git a/umbrello/umbrello/enum.cpp b/umbrello/umbrello/enum.cpp
new file mode 100644
index 00000000..ba3be7b4
--- /dev/null
+++ b/umbrello/umbrello/enum.cpp
@@ -0,0 +1,206 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "enum.h"
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+// app includes
+#include "enumliteral.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "clipboard/idchangelog.h"
+
+UMLEnum::UMLEnum(const QString& name, Uml::IDType id) : UMLClassifier(name, id) {
+ init();
+}
+
+UMLEnum::~UMLEnum() {
+ m_List.clear();
+}
+
+bool UMLEnum::operator==( UMLEnum & rhs ) {
+ return UMLClassifier::operator==(rhs);
+}
+
+void UMLEnum::copyInto(UMLEnum *rhs) const
+{
+ UMLClassifier::copyInto(rhs);
+}
+
+UMLObject* UMLEnum::clone() const
+{
+ UMLEnum *clone = new UMLEnum();
+ copyInto(clone);
+
+ return clone;
+}
+
+void UMLEnum::init() {
+ m_BaseType = Uml::ot_Enum;
+ setStereotype( "enum" );
+}
+
+UMLObject* UMLEnum::createEnumLiteral(const QString& name) {
+ Uml::IDType id = UniqueID::gen();
+ QString currentName;
+ if (name.isNull()) {
+ currentName = uniqChildName(Uml::ot_EnumLiteral);
+ } else {
+ currentName = name;
+ }
+
+ UMLEnumLiteral* newEnumLiteral = new UMLEnumLiteral(this, currentName);
+
+ bool ok = true;
+ bool goodName = false;
+
+ //check for name.isNull() stops dialog being shown
+ //when creating enum literal via list view
+ while (ok && !goodName && name.isNull()) {
+ ok = newEnumLiteral->showPropertiesDialog( UMLApp::app() );
+ QString name = newEnumLiteral->getName();
+
+ if(name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ } else {
+ goodName = true;
+ }
+ }
+
+ if (!ok) {
+ delete newEnumLiteral;
+ return NULL;
+ }
+
+ addEnumLiteral(newEnumLiteral);
+
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(newEnumLiteral);
+ return newEnumLiteral;
+}
+
+UMLObject* UMLEnum::addEnumLiteral(const QString &name, Uml::IDType id) {
+ UMLObject *el = UMLCanvasObject::findChildObject(name);
+ if (el != NULL) {
+ kDebug() << "UMLEnum::addEnumLiteral: " << name
+ << " is already present" << endl;
+ return el;
+ }
+ UMLEnumLiteral* literal = new UMLEnumLiteral(this, name, id);
+ m_List.append(literal);
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal,SIGNAL(modified()),this,SIGNAL(modified()));
+ return literal;
+}
+
+bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, IDChangeLog* Log /* = 0*/) {
+ QString name = (QString)literal->getName();
+ if (findChildObject(name) == NULL) {
+ literal->parent()->removeChild(literal);
+ this->insertChild(literal);
+ m_List.append(literal);
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ } else if (Log) {
+ Log->removeChangeByNewID( literal->getID() );
+ delete literal;
+ }
+ return false;
+}
+
+bool UMLEnum::addEnumLiteral(UMLEnumLiteral* literal, int position) {
+ QString name = (QString)literal->getName();
+ if (findChildObject(name) == NULL) {
+ literal->parent()->removeChild(literal);
+ this->insertChild(literal);
+ if ( position >= 0 && position <= (int)m_List.count() ) {
+ m_List.insert(position,literal);
+ } else {
+ m_List.append(literal);
+ }
+ UMLObject::emitModified();
+ emit enumLiteralAdded(literal);
+ connect(literal,SIGNAL(modified()),this,SIGNAL(modified()));
+ return true;
+ }
+ return false;
+}
+
+int UMLEnum::removeEnumLiteral(UMLEnumLiteral* literal) {
+ if (!m_List.remove(literal)) {
+ kDebug() << "can't find att given in list" << endl;
+ return -1;
+ }
+ emit enumLiteralRemoved(literal);
+ UMLObject::emitModified();
+ // If we are deleting the object, then we don't need to disconnect..this is done auto-magically
+ // for us by QObject. -b.t.
+ // disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ delete literal;
+ return m_List.count();
+}
+
+int UMLEnum::enumLiterals() {
+ return m_List.count();
+}
+
+void UMLEnum::signalEnumLiteralRemoved(UMLClassifierListItem *elit) {
+ emit enumLiteralRemoved(elit);
+}
+
+void UMLEnum::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement enumElement = UMLObject::save("UML:Enumeration", qDoc);
+ // save enum literals
+ UMLClassifierListItemList enumLiterals = getFilteredList(Uml::ot_EnumLiteral);
+ UMLClassifierListItem* pEnumLiteral = 0;
+ for (UMLClassifierListItemListIt it(enumLiterals);
+ (pEnumLiteral = it.current()) != NULL; ++it) {
+ pEnumLiteral->saveToXMI(qDoc, enumElement);
+ }
+ qElement.appendChild(enumElement);
+}
+
+bool UMLEnum::load(QDomElement& element) {
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Uml::tagEq(tag, "EnumerationLiteral") ||
+ Uml::tagEq(tag, "EnumLiteral")) { // for backward compatibility
+ UMLEnumLiteral* pEnumLiteral = new UMLEnumLiteral(this);
+ if( !pEnumLiteral->loadFromXMI(tempElement) ) {
+ return false;
+ }
+ m_List.append(pEnumLiteral);
+ } else if (tag == "stereotype") {
+ kDebug() << "UMLEnum::load(" << m_Name
+ << "): losing old-format stereotype." << endl;
+ } else {
+ kWarning() << "unknown child type in UMLEnum::load" << endl;
+ }
+ node = node.nextSibling();
+ }//end while
+ return true;
+}
+
+
+#include "enum.moc"
diff --git a/umbrello/umbrello/enum.h b/umbrello/umbrello/enum.h
new file mode 100644
index 00000000..1845eb88
--- /dev/null
+++ b/umbrello/umbrello/enum.h
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENUM_H
+#define ENUM_H
+
+#include "classifier.h"
+
+class UMLEnumLiteral;
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Enum.
+ * This class inherits from @ref UMLClassifier which contains most of the
+ * information.
+ *
+ * @short Non-graphical Information for an Enum.
+ * @author Jonathan Riddell
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLEnum : public UMLClassifier {
+ Q_OBJECT
+public:
+ /**
+ * Sets up an enum.
+ *
+ * @param name The name of the Enum.
+ * @param id The unique id of the Enum.
+ */
+ explicit UMLEnum(const QString& name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLEnum();
+
+ /**
+ * Overloaded '==' operator.
+ */
+ bool operator==(UMLEnum& rhs);
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLEnum *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates a literal for the enum.
+ *
+ * @return The UMLEnum created
+ */
+ UMLObject* createEnumLiteral(const QString& name = QString());
+
+ /**
+ * Adds an enumliteral to the enum.
+ *
+ * @param name The name of the enumliteral.
+ * @param id The id of the enumliteral (optional.)
+ * If omitted a new ID is assigned internally.
+ * @return Pointer to the UMLEnumliteral created.
+ */
+ UMLObject* addEnumLiteral(const QString &name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Adds an already created enumliteral.
+ * The enumliteral object must not belong to any other concept.
+ *
+ * @param Att Pointer to the UMLEnumLiteral.
+ * @param Log Pointer to the IDChangeLog.
+ * @return True if the enumliteral was successfully added.
+ */
+ bool addEnumLiteral(UMLEnumLiteral* Att, IDChangeLog* Log = 0);
+
+ /**
+ * Adds an enumliteral to the enum, at the given position.
+ * If position is negative or too large, the enumliteral is added
+ * to the end of the list.
+ *
+ * @param Att Pointer to the UMLEnumLiteral.
+ * @param position Position index for the insertion.
+ * @return True if the enumliteral was successfully added.
+ */
+ //TODO: give default value -1 to position (append) - now it conflicts with the method above..
+ bool addEnumLiteral(UMLEnumLiteral* Att, int position );
+
+ /**
+ * Removes an enumliteral from the class.
+ *
+ * @param a The enumliteral to remove.
+ * @return Count of the remaining enumliterals after removal.
+ * Returns -1 if the given enumliteral was not found.
+ */
+ int removeEnumLiteral(UMLEnumLiteral *a);
+
+ /**
+ * Returns the number of enumliterals for the class.
+ *
+ * @return The number of enumliterals for the class.
+ */
+ int enumLiterals();
+
+ /**
+ * Emit the enumLiteralRemoved signal.
+ */
+ void signalEnumLiteralRemoved(UMLClassifierListItem *elit);
+
+ /**
+ * Creates the <UML:Enum> element including its enumliterals.
+ */
+ virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+signals:
+ void enumLiteralAdded(UMLClassifierListItem*);
+ void enumLiteralRemoved(UMLClassifierListItem*);
+
+protected:
+ /**
+ * Loads the <UML:Enum> element including its enumliterals.
+ */
+ bool load( QDomElement & element );
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+};
+
+#endif // ENUM_H
+
diff --git a/umbrello/umbrello/enumliteral.cpp b/umbrello/umbrello/enumliteral.cpp
new file mode 100644
index 00000000..ea6eef49
--- /dev/null
+++ b/umbrello/umbrello/enumliteral.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "enumliteral.h"
+
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+UMLEnumLiteral::UMLEnumLiteral(const UMLObject *parent,
+ const QString& name, Uml::IDType id)
+ : UMLClassifierListItem(parent, name, id) {
+ m_BaseType = Uml::ot_EnumLiteral;
+}
+
+UMLEnumLiteral::UMLEnumLiteral(const UMLObject *parent) : UMLClassifierListItem(parent) {
+ m_BaseType = Uml::ot_EnumLiteral;
+}
+
+UMLEnumLiteral::~UMLEnumLiteral() { }
+
+bool UMLEnumLiteral::operator==(UMLEnumLiteral& rhs) {
+ if ( this == &rhs ) {
+ return true;
+ }
+ if ( !UMLObject::operator==( rhs ) ) {
+ return false;
+ }
+ return true;
+}
+
+void UMLEnumLiteral::copyInto(UMLEnumLiteral *rhs) const
+{
+ UMLClassifierListItem::copyInto(rhs);
+}
+
+UMLObject* UMLEnumLiteral::clone() const
+{
+ UMLEnumLiteral *clone = new UMLEnumLiteral((UMLObject *) parent());
+ copyInto(clone);
+
+ return clone;
+}
+
+
+void UMLEnumLiteral::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement attributeElement = UMLObject::save("UML:EnumerationLiteral", qDoc);
+ qElement.appendChild( attributeElement );
+}
+
+bool UMLEnumLiteral::load(QDomElement& ) {
+ return true;
+}
+
+bool UMLEnumLiteral::showPropertiesDialog(QWidget* parent) {
+ bool ok;
+ QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), getName(), &ok, parent);
+ if ( ok && !name.isEmpty() ) {
+ setName(name);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
diff --git a/umbrello/umbrello/enumliteral.h b/umbrello/umbrello/enumliteral.h
new file mode 100644
index 00000000..3484012e
--- /dev/null
+++ b/umbrello/umbrello/enumliteral.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENUMLITERAL_H
+#define ENUMLITERAL_H
+
+#include "classifierlistitem.h"
+
+/**
+ * This class is used to set up information for an enum literal. Enum
+ * literals are the values that enums can be set to.
+ *
+ * @short Sets up attribute information.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLEnumLiteral : public UMLClassifierListItem {
+public:
+ /**
+ * Sets up an enum literal.
+ *
+ * @param parent The parent of this UMLEnumLiteral.
+ * @param name The name of this UMLEnumLiteral.
+ * @param id The unique id given to this UMLEnumLiteral.
+ */
+ UMLEnumLiteral(const UMLObject* parent,
+ const QString& name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Sets up an enum literal.
+ *
+ * @param parent The parent of this UMLEnumLiteral.
+ */
+ UMLEnumLiteral(const UMLObject* parent);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==(UMLEnumLiteral &rhs);
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLEnumLiteral *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * destructor
+ */
+ virtual ~UMLEnumLiteral();
+
+ /**
+ * Creates the <UML:EnumLiteral> XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Display the properties configuration dialog for the enum literal.
+ */
+ bool showPropertiesDialog(QWidget* parent);
+
+protected:
+ /**
+ * Loads the <UML:EnumLiteral> XMI element (empty.)
+ */
+ bool load(QDomElement& element);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/enumwidget.cpp b/umbrello/umbrello/enumwidget.cpp
new file mode 100644
index 00000000..2d642b31
--- /dev/null
+++ b/umbrello/umbrello/enumwidget.cpp
@@ -0,0 +1,218 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "enumwidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+
+// app includes
+#include "enum.h"
+#include "enumliteral.h"
+#include "classifier.h"
+#include "umlclassifierlistitemlist.h"
+#include "classifierlistitem.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "listpopupmenu.h"
+#include "object_factory.h"
+
+
+EnumWidget::EnumWidget(UMLView* view, UMLObject* o) : UMLWidget(view, o) {
+ init();
+}
+
+void EnumWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Enum);
+ setSize(100, 30);
+ m_pMenu = 0;
+ //set defaults from m_pView
+ if (m_pView) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ m_bShowPackage = ops.classState.showPackage;
+ } else {
+ // For completeness only. Not supposed to happen.
+ m_bShowPackage = false;
+ }
+ if (! UMLApp::app()->getDocument()->loading())
+ updateComponentSize();
+}
+
+EnumWidget::~EnumWidget() {}
+
+void EnumWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if(UMLWidget::getUseFillColour())
+ p.setBrush(UMLWidget::getFillColour());
+ else
+ p.setBrush(m_pView -> viewport() -> backgroundColor());
+
+ const int w = width();
+ const int h = height();
+
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString name;
+ if ( m_bShowPackage ) {
+ name = m_pObject->getFullyQualifiedName();
+ } else {
+ name = this -> getName();
+ }
+
+ p.drawRect(offsetX, offsetY, w, h);
+ p.setPen(QPen(Qt::black));
+
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ p.setFont(font);
+ p.drawText(offsetX + ENUM_MARGIN, offsetY,
+ w - ENUM_MARGIN * 2,fontHeight,
+ Qt::AlignCenter, m_pObject->getStereotype(true));
+
+ font.setItalic( m_pObject -> getAbstract() );
+ p.setFont(font);
+ p.drawText(offsetX + ENUM_MARGIN, offsetY + fontHeight,
+ w - ENUM_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
+ font.setBold(false);
+ font.setItalic(false);
+ p.setFont(font);
+
+ int y = fontHeight * 2;
+
+ UMLWidget::setPen(p);
+
+ p.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y);
+
+ QFontMetrics fontMetrics(font);
+ UMLClassifier *classifier = (UMLClassifier*)m_pObject;
+ UMLClassifierListItem* enumLiteral = 0;
+ UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EnumLiteral);
+ for (enumLiteral = list.first(); enumLiteral; enumLiteral = list.next()) {
+ QString text = enumLiteral->getName();
+ p.setPen( QPen(Qt::black) );
+ p.drawText(offsetX + ENUM_MARGIN, offsetY + y,
+ fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
+ y+=fontHeight;
+ }
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize EnumWidget::calculateSize() {
+ if (!m_pObject) {
+ return UMLWidget::calculateSize();
+ }
+
+ int width, height;
+ QFont font = UMLWidget::getFont();
+ font.setItalic(false);
+ font.setUnderline(false);
+ font.setBold(false);
+ const QFontMetrics fm(font);
+
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;//always have one line - for name
+ lines++; //for the stereotype
+
+ const int numberOfEnumLiterals = ((UMLEnum*)m_pObject)->enumLiterals();
+
+ height = width = 0;
+ //set the height of the enum
+
+ lines += numberOfEnumLiterals;
+ if (numberOfEnumLiterals == 0) {
+ height += fontHeight / 2; //no enum literals, so just add a bit of space
+ }
+
+ height += lines * fontHeight;
+
+ //now set the width of the concept
+ //set width to name to start with
+ if (m_bShowPackage) {
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(m_pObject->getFullyQualifiedName()).width();
+ } else {
+ width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(getName()).width();
+ }
+ int w = getFontMetrics(FT_BOLD).boundingRect(m_pObject->getStereotype(true)).width();
+
+
+ width = w > width?w:width;
+
+ UMLClassifier *classifier = (UMLClassifier*)m_pObject;
+ UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EnumLiteral);
+ UMLClassifierListItem* listItem = 0;
+ for (listItem = list.first(); listItem; listItem = list.next()) {
+ int w = fm.width( listItem->getName() );
+ width = w > width?w:width;
+ }
+
+ //allow for width margin
+ width += ENUM_MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void EnumWidget::slotMenuSelection(int sel) {
+ switch(sel) {
+ case ListPopupMenu::mt_EnumLiteral:
+ if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(m_pObject),
+ Uml::ot_EnumLiteral) ) {
+ UMLApp::app()->getDocument()->setModified();
+ }
+ break;
+ }
+ UMLWidget::slotMenuSelection(sel);
+}
+
+void EnumWidget::setShowPackage(bool _status) {
+ m_bShowPackage = _status;
+ updateComponentSize();
+ update();
+}
+
+bool EnumWidget::getShowPackage() const {
+ return m_bShowPackage;
+}
+
+void EnumWidget::saveToXMI( QDomDocument& qDoc, QDomElement& qElement ) {
+ QDomElement conceptElement = qDoc.createElement("enumwidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+
+ conceptElement.setAttribute("showpackage", m_bShowPackage);
+ qElement.appendChild(conceptElement);
+}
+
+bool EnumWidget::loadFromXMI( QDomElement & qElement ) {
+ if ( !UMLWidget::loadFromXMI(qElement) ) {
+ return false;
+ }
+ QString showpackage = qElement.attribute("showpackage", "0");
+
+ m_bShowPackage = (bool)showpackage.toInt();
+
+ return true;
+}
+
+void EnumWidget::toggleShowPackage() {
+ m_bShowPackage = !m_bShowPackage;
+ updateComponentSize();
+ update();
+
+ return;
+}
+
diff --git a/umbrello/umbrello/enumwidget.h b/umbrello/umbrello/enumwidget.h
new file mode 100644
index 00000000..7022ac61
--- /dev/null
+++ b/umbrello/umbrello/enumwidget.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ENUMWIDGET_H
+#define ENUMWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLView;
+
+#define ENUM_MARGIN 5
+
+/**
+ * Defines a graphical version of the enum. Most of the functionality
+ * will come from the @ref UMLWidget class from which class inherits from.
+ *
+ * @short A graphical version of an enum.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class EnumWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs an EnumWidget.
+ *
+ * @param view The parent of this EnumWidget.
+ * @param o The UMLObject this will be representing.
+ */
+ EnumWidget(UMLView* view, UMLObject* o);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~EnumWidget();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Returns the status of whether to show Package.
+ *
+ * @return True if package is shown.
+ */
+ bool getShowPackage() const;
+
+ /**
+ * Toggles the status of whether to show package.
+ */
+ void toggleShowPackage();
+
+ /**
+ * Set the status of whether to show Package.
+ *
+ * @param _status True if package shall be shown.
+ */
+ void setShowPackage(bool _status);
+
+ /**
+ * Draws the enum as a rectangle with a box underneith with a list of literals
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "enumwidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Loads from an "enumwidget" XMI element.
+ */
+ bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+ bool m_bShowPackage;
+
+private:
+ /**
+ * The right mouse button menu.
+ */
+ ListPopupMenu* m_pMenu;
+
+public slots:
+ /**
+ * Will be called when a menu selection has been made from the
+ * popup menu.
+ *
+ * @param sel The selection id that has been selected.
+ */
+ void slotMenuSelection(int sel);
+};
+
+#endif
diff --git a/umbrello/umbrello/floatingtextwidget.cpp b/umbrello/umbrello/floatingtextwidget.cpp
new file mode 100644
index 00000000..44ea3373
--- /dev/null
+++ b/umbrello/umbrello/floatingtextwidget.cpp
@@ -0,0 +1,453 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "floatingtextwidget.h"
+
+// system includes
+#include <qregexp.h>
+#include <qpainter.h>
+#include <qevent.h>
+#include <qvalidator.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// local includes
+#include "floatingtextwidgetcontroller.h"
+#include "association.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "classifier.h"
+#include "listpopupmenu.h"
+#include "operation.h"
+#include "model_utils.h"
+#include "object_factory.h"
+#include "messagewidget.h"
+#include "dialogs/assocpropdlg.h"
+#include "dialogs/selectopdlg.h"
+
+
+FloatingTextWidget::FloatingTextWidget(UMLView * view, Uml::Text_Role role,
+ const QString& text, Uml::IDType id)
+ : UMLWidget(view, id, new FloatingTextWidgetController(this))
+{
+ init();
+ m_Text = text;
+ m_Role = role;
+ if ( ! UMLApp::app()->getDocument()->loading() ) {
+ updateComponentSize();
+ setZ( 10 );//make sure always on top.
+ update();
+ }
+}
+
+void FloatingTextWidget::init() {
+ // initialize loaded/saved (i.e. persistent) data
+ m_PreText = "";
+ m_Text = "";
+ m_PostText = "";
+ m_Role = Uml::tr_Floating;
+ m_Type = Uml::wt_Text;
+ // initialize non-saved (i.e. volatile) data
+ m_pLink = NULL;
+ UMLWidget::m_bResizable = false;
+}
+
+FloatingTextWidget::~FloatingTextWidget() {
+}
+
+void FloatingTextWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ int w = width();
+ int h = height();
+ p.setFont( UMLWidget::getFont() );
+ QColor textColor(50, 50, 50);
+ p.setPen(textColor);
+ p.drawText( offsetX , offsetY,w,h, Qt::AlignCenter, getDisplayText() );
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+void FloatingTextWidget::resizeEvent(QResizeEvent * /*re*/) {}
+
+QSize FloatingTextWidget::calculateSize() {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ int h = fm.lineSpacing();
+ int w = fm.width( getDisplayText() );
+ return QSize(w + 8, h + 4); // give a small margin
+}
+
+void FloatingTextWidget::slotMenuSelection(int sel) {
+ switch(sel) {
+ case ListPopupMenu::mt_Properties:
+ showProperties();
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ m_pView -> removeWidget(this);
+ break;
+
+ case ListPopupMenu::mt_Operation:
+ {
+ kDebug() << "FloatingTextWidget::slotMenuSelection(mt_Operation) is called."
+ << endl;
+ if (m_pLink == NULL) {
+ kDebug() << "FloatingTextWidget::slotMenuSelection(mt_Operation): "
+ << "m_pLink is NULL" << endl;
+ return;
+ }
+ UMLClassifier* c = m_pLink->getOperationOwner();
+ if (c == NULL) {
+ bool ok = false;
+ QString opText = KInputDialog::getText(i18n("Name"),
+ i18n("Enter operation name:"),
+ getText(), &ok, m_pView);
+ if (ok)
+ m_pLink->setCustomOpText(opText);
+ return;
+ }
+ UMLClassifierListItem* umlObj = Object_Factory::createChildObject(c, Uml::ot_Operation);
+ if (umlObj) {
+ UMLOperation* newOperation = static_cast<UMLOperation*>( umlObj );
+ m_pLink->setOperation(newOperation);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Select_Operation:
+ showOpDlg();
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ handleRename();
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ {
+ QFont font = getFont();
+ if( KFontDialog::getFont( font, false, m_pView ) ) {
+ if( m_Role == Uml::tr_Floating || m_Role == Uml::tr_Seq_Message ) {
+ setFont( font );
+ } else if (m_pLink) {
+ m_pLink->lwSetFont(font);
+ }
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_Reset_Label_Positions:
+ if (m_pLink)
+ m_pLink->resetTextPositions();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(sel);
+ break;
+ }//end switch
+}
+
+void FloatingTextWidget::handleRename() {
+ QRegExpValidator v(QRegExp(".*"), 0);
+ QString t;
+ if( m_Role == Uml::tr_RoleAName || m_Role == Uml::tr_RoleBName ) {
+ t = i18n("Enter role name:");
+ } else if (m_Role == Uml::tr_MultiA || m_Role == Uml::tr_MultiB) {
+ t = i18n("Enter multiplicity:");
+ /*
+ // NO! shouldn't be allowed
+ } else if( m_Role == Uml::tr_ChangeA || m_Role == Uml::tr_ChangeB ) {
+ t = i18n("Enter changeability");
+ */
+ } else if (m_Role == Uml::tr_Name) {
+ t = i18n("Enter association name:");
+ } else if (m_Role == Uml::tr_Floating) {
+ t = i18n("Enter new text:");
+ } else {
+ t = i18n("ERROR");
+ }
+ bool ok = false;
+ QString newText = KInputDialog::getText(i18n("Rename"), t, getText(), &ok,
+ m_pView, NULL, &v);
+ if (!ok || newText == getText())
+ return;
+}
+
+void FloatingTextWidget::changeName(const QString& newText)
+{
+
+ if (m_pLink && !isTextValid(newText)) {
+ AssociationWidget *assoc = dynamic_cast<AssociationWidget*>(m_pLink);
+ if (assoc) {
+ switch (m_Role) {
+ case Uml::tr_MultiA:
+ assoc->setMulti(QString(), Uml::A);
+ break;
+ case Uml::tr_MultiB:
+ assoc->setMulti(QString(), Uml::B);
+ break;
+ case Uml::tr_RoleAName:
+ assoc->setRoleName(QString(), Uml::A);
+ break;
+ case Uml::tr_RoleBName:
+ assoc->setRoleName(QString(), Uml::B);
+ break;
+ case Uml::tr_ChangeA:
+ assoc->setChangeability(Uml::chg_Changeable, Uml::A);
+ break;
+ case Uml::tr_ChangeB:
+ assoc->setChangeability(Uml::chg_Changeable, Uml::B);
+ break;
+ default:
+ assoc->setName(QString());
+ break;
+ }
+ } else {
+ MessageWidget *msg = dynamic_cast<MessageWidget*>(m_pLink);
+ if (msg) {
+ msg->setName(QString());
+ m_pView->removeWidget(this);
+ }
+ }
+ return;
+ }
+ if (m_pLink && m_Role != Uml::tr_Seq_Message && m_Role != Uml::tr_Seq_Message_Self) {
+ m_pLink->setText(this, newText);
+ } else {
+ setText( newText );
+ UMLApp::app()->getDocument()->setModified(true);
+ }
+ setVisible( true );
+ updateComponentSize();
+ update();
+}
+
+void FloatingTextWidget::setText(const QString &t) {
+ if (m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self) {
+ QString seqNum, op;
+ m_pLink->getSeqNumAndOp(seqNum, op);
+ if (seqNum.length() > 0 || op.length() > 0) {
+ if (! m_pView->getShowOpSig())
+ op.replace( QRegExp("\\(.*\\)"), "()" );
+ m_Text = seqNum.append(": ").append( op );
+ } else
+ m_Text = t;
+ } else
+ m_Text = t;
+ updateComponentSize();
+ update();
+}
+
+void FloatingTextWidget::setPreText (const QString &t)
+{
+ m_PreText = t;
+ updateComponentSize();
+ update();
+}
+
+void FloatingTextWidget::setPostText(const QString &t) {
+ m_PostText = t;
+ updateComponentSize();
+ update();
+}
+
+void FloatingTextWidget::changeTextDlg() {
+ bool ok = false;
+ QString newText = KInputDialog::getText(i18n("Change Text"), i18n("Enter new text:"), getText(), &ok, m_pView);
+
+ if(ok && newText != getText() && isTextValid(newText)) {
+ setText( newText );
+ setVisible( ( getText().length() > 0 ) );
+ updateComponentSize();
+ update();
+ }
+ if(!isTextValid(newText))
+ hide();
+}
+
+void FloatingTextWidget::showOpDlg() {
+ if (m_pLink == NULL) {
+ kError() << "FloatingTextWidget::showOpDlg: m_pLink is NULL" << endl;
+ return;
+ }
+ QString seqNum, opText;
+ UMLClassifier* c = m_pLink->getSeqNumAndOp(seqNum, opText);
+ if (c == NULL) {
+ kError() << "FloatingTextWidget::showOpDlg: "
+ << "m_pLink->getSeqNumAndOp() returns a NULL classifier"
+ << endl;
+ return;
+ }
+
+ SelectOpDlg selectDlg(m_pView, c);
+ selectDlg.setSeqNumber( seqNum );
+ if (m_pLink->getOperation() == NULL) {
+ selectDlg.setCustomOp( opText );
+ } else {
+ selectDlg.setClassOp( opText );
+ }
+ int result = selectDlg.exec();
+ if(!result) {
+ return;
+ }
+ seqNum = selectDlg.getSeqNumber();
+ opText = selectDlg.getOpText();
+ if (selectDlg.isClassOp()) {
+ Model_Utils::OpDescriptor od;
+ Model_Utils::Parse_Status st = Model_Utils::parseOperation(opText, od, c);
+ if (st == Model_Utils::PS_OK) {
+ UMLClassifierList selfAndAncestors = c->findSuperClassConcepts();
+ selfAndAncestors.prepend(c);
+ UMLOperation *op = NULL;
+ for (UMLClassifier *cl = selfAndAncestors.first(); cl; cl = selfAndAncestors.next()) {
+ op = cl->findOperation(od.m_name, od.m_args);
+ if (op != NULL)
+ break;
+ }
+ if (op == NULL) {
+ // The op does not yet exist. Create a new one.
+ UMLObject *o = c->createOperation(od.m_name, NULL, &od.m_args);
+ op = static_cast<UMLOperation*>(o);
+ }
+ if (od.m_pReturnType)
+ op->setType(od.m_pReturnType);
+ m_pLink->setOperation(op);
+ opText = QString();
+ } else {
+ m_pLink->setOperation(NULL);
+ }
+ } else {
+ m_pLink->setOperation(NULL);
+ }
+ m_pLink->setSeqNumAndOp(seqNum, opText);
+ setMessageText();
+}
+
+QString FloatingTextWidget::getPreText() const {
+ return m_PreText;
+}
+
+QString FloatingTextWidget::getPostText() const {
+ return m_PostText;
+}
+
+QString FloatingTextWidget::getText() const {
+ //test to make sure not just the ":" between the seq number
+ //and the actual message widget
+ // hmm. this section looks like it could have been avoided by using pre-, post- text
+ // instead of storing in the main body of the text -b.t.
+ if(m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self ||
+ m_Role == Uml::tr_Coll_Message || m_Role == Uml::tr_Coll_Message_Self) {
+ if( m_Text.length() <= 1 || m_Text == ": " )
+ return "";
+ }
+ return m_Text;
+}
+
+QString FloatingTextWidget::getDisplayText() const
+{
+ QString displayText = m_Text;
+ displayText.prepend(m_PreText);
+ displayText.append(m_PostText);
+ return displayText;
+}
+
+bool FloatingTextWidget::activate( IDChangeLog* ChangeLog /*= 0 */) {
+ if (! UMLWidget::activate(ChangeLog))
+ return false;
+ update();
+ return true;
+}
+
+void FloatingTextWidget::setLink(LinkWidget * l) {
+ m_pLink = l;
+}
+
+LinkWidget * FloatingTextWidget::getLink() {
+ return m_pLink;
+}
+
+void FloatingTextWidget::setRole(Uml::Text_Role role) {
+ m_Role = role;
+}
+
+Uml::Text_Role FloatingTextWidget::getRole() const {
+ return m_Role;
+}
+
+bool FloatingTextWidget::isTextValid( const QString &text ) {
+ int length = text.length();
+ if(length < 1)
+ return false;
+ for(int i=0;i<length;i++)
+ if(!text.at(i).isSpace())
+ return true;
+ return false;
+}
+
+void FloatingTextWidget::showProperties() {
+ if (m_Role == Uml::tr_Coll_Message || m_Role == Uml::tr_Coll_Message_Self ||
+ m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self) {
+ showOpDlg();
+ } else if (m_Role == Uml::tr_Floating) {
+ // double clicking on a text line opens the dialog to change the text
+ handleRename();
+ } else if (m_pLink) {
+ m_pLink->showDialog();
+ }
+}
+
+void FloatingTextWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement textElement = qDoc.createElement( "floatingtext" );
+ UMLWidget::saveToXMI( qDoc, textElement );
+ textElement.setAttribute( "text", m_Text );
+ textElement.setAttribute( "pretext", m_PreText );
+ textElement.setAttribute( "posttext", m_PostText );
+
+ /* No need to save these - the messagewidget already did it.
+ m_Operation = qElement.attribute( "operation", "" );
+ m_SeqNum = qElement.attribute( "seqnum", "" );
+ */
+
+ textElement.setAttribute( "role", m_Role );
+ qElement.appendChild( textElement );
+}
+
+bool FloatingTextWidget::loadFromXMI( QDomElement & qElement ) {
+ if( !UMLWidget::loadFromXMI( qElement ) )
+ return false;
+
+ QString role = qElement.attribute( "role", "" );
+ if( !role.isEmpty() )
+ m_Role = (Uml::Text_Role)role.toInt();
+
+ m_PreText = qElement.attribute( "pretext", "" );
+ m_PostText = qElement.attribute( "posttext", "" );
+ m_Text = qElement.attribute( "text", "" );
+ // If all texts are empty then this is a useless widget.
+ // In that case we return false.
+ // CAVEAT: The caller should not interpret the false return value
+ // as an indication of failure since previous umbrello versions
+ // saved lots of these empty FloatingTexts.
+ bool isDummy = (m_Text.isEmpty() && m_PreText.isEmpty() && m_PostText.isEmpty());
+ return !isDummy;
+}
+
+void FloatingTextWidget::setMessageText() {
+ if (m_pLink)
+ m_pLink->setMessageText(this);
+ setVisible(getText().length() > 0);
+ updateComponentSize();
+}
+
+
+#include "floatingtextwidget.moc"
+
diff --git a/umbrello/umbrello/floatingtextwidget.h b/umbrello/umbrello/floatingtextwidget.h
new file mode 100644
index 00000000..a8a1bfa8
--- /dev/null
+++ b/umbrello/umbrello/floatingtextwidget.h
@@ -0,0 +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) 2002-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef FLOATINGTEXTWIDGET_H
+#define FLOATINGTEXTWIDGET_H
+
+#include "umlwidget.h"
+#include "linkwidget.h"
+
+class UMLView;
+
+class FloatingTextWidgetController;
+
+/**
+ * This is a multipurpose class. In its simplest form it will display a
+ * line of text.
+ * It can also be setup to be the text for an operation with regard to the
+ * @ref MessageWidget on the sequence diagram.
+ * It is also used for the text required for an association.
+ *
+ * The differences between all these different uses will be the popup menu
+ * that is associated with it.
+ *
+ * @short Displays a line of text or an operation.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class FloatingTextWidget : public UMLWidget {
+ Q_OBJECT
+public:
+ friend class FloatingTextWidgetController;
+
+ /** sometimes the x/y values get numbers of <0 and >10000 - which is
+ probably due to a bug somewhere in calculating the position.
+ -> workaround till problem is found: define min and max limits
+ => if x or y is outside of interval, the position is reset
+ ( e.g. by AssociationWidget::resetTextPositions() )
+ */
+ static const int restrictPositionMin = 0;
+ static const int restrictPositionMax = 3000;
+
+
+ /**
+ * Constructs a FloatingTextWidget instance.
+ *
+ * @param view The parent of this FloatingTextWidget.
+ * @param role The role this FloatingTextWidget will take up.
+ * @param text The main text to display.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ explicit FloatingTextWidget(UMLView * view, Uml::Text_Role role = Uml::tr_Floating,
+ const QString& text = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * destructor
+ */
+ virtual ~FloatingTextWidget();
+
+ /**
+ * Set the main body of text to display.
+ *
+ * @param t The text to display.
+ */
+ void setText(const QString &t);
+
+ /**
+ * Set some text to be prepended to the main body of text.
+ * @param t The text to prepend to main body which is displayed.
+ */
+ void setPreText(const QString &t);
+
+ /**
+ * Set some text to be appended to the main body of text.
+ * @param t The text to append to main body which is displayed.
+ */
+ void setPostText(const QString &t);
+
+ /**
+ * Set the sequence number to display.
+ *
+ * @param sn The sequence number to display.
+ */
+ void setSeqNum(const QString &sn);
+
+ /**
+ * Return the sequence number.
+ *
+ * @return The sequence number.
+ */
+ QString getSeqNum() const;
+
+ /**
+ * Set the operation to display.
+ *
+ * @param op The operation to display.
+ */
+ void setOperation(const QString &op);
+
+ /**
+ * Return the operation that is displayed.
+ *
+ * @return The operation that is displayed.
+ *
+ QString getOperation() const;
+ */
+
+ /**
+ * Use to get the _main body_ of text (e.g. prepended and appended
+ * text is omitted) as currently displayed by the widget.
+ *
+ * @return The main text currently being displayed by the widget.
+ */
+ QString getText() const;
+
+ /**
+ * Use to get the pre-text which is prepended to the main body of
+ * text to be displayed.
+ *
+ * @return The pre-text currently displayed by the widget.
+ */
+ QString getPreText() const;
+
+ /**
+ * Use to get the post-text which is appended to the main body of
+ * text to be displayed.
+ *
+ * @return The post-text currently displayed by the widget.
+ */
+ QString getPostText() const;
+
+ /**
+ * Use to get the total text (prepended + main body + appended)
+ * currently displayed by the widget.
+ *
+ * @return The text currently being displayed by the widget.
+ */
+ QString getDisplayText() const;
+
+ /**
+ * Displays a dialog box to change the text.
+ */
+ void changeTextDlg();
+
+ /**
+ * Set the LinkWidget that this FloatingTextWidget is related to.
+ *
+ * @param l The related LinkWidget.
+ */
+ void setLink(LinkWidget * l);
+
+ /**
+ * Returns the LinkWidget this floating text is related to.
+ *
+ * @return The LinkWidget this floating text is related to.
+ */
+ LinkWidget * getLink();
+
+ /**
+ * Returns whether this is a line of text.
+ * Used for transparency in printing.
+ *
+ * @return Returns whether this is a line of text.
+ */
+ bool isText() {
+ return true;
+ }
+
+ /**
+ * Activate the FloatingTextWidget after the saved data has been loaded
+ *
+ * @param ChangeLog Pointer to the IDChangeLog.
+ * @return true for success
+ */
+ bool activate( IDChangeLog* ChangeLog = 0 );
+
+ /**
+ * Sets the role type of this FloatingTextWidget.
+ *
+ * @param role The Text_Role of this FloatingTextWidget.
+ */
+ void setRole(Uml::Text_Role role);
+
+ /**
+ * Return the role of the text widget
+ *
+ * @return The Text_Role of this FloatingTextWidget.
+ */
+ Uml::Text_Role getRole() const;
+
+ /**
+ * For a text to be valid it must be non-empty, i.e. have a length
+ * larger that zero, and have at least one non whitespace character.
+ *
+ * @param text The string to analyze.
+ * @return True if the given text is valid.
+ */
+ static bool isTextValid(const QString &text);
+
+ /**
+ * Overrides default method
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Handle the ListPopupMenu::mt_Rename case of the slotMenuSelection.
+ * Given an own method because it requires rather lengthy code.
+ */
+ void handleRename();
+
+ /**
+ * Change Name
+ */
+ void changeName(const QString& newText);
+
+ /**
+ * Shows an operation dialog box.
+ */
+ void showOpDlg();
+
+ /**
+ * Show the properties for a FloatingTextWidget.
+ * Depending on the role of the floating text wiget, the options dialog
+ * for the floating text widget, the rename dialog for floating text or
+ * the options dialog for the link widget are shown.
+ */
+ void showProperties();
+
+ /**
+ * Creates the "floatingtext" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads the "floatingtext" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+public slots:
+ /**
+ * Called when a menu selection has been made.
+ * This method is public due to called by @ref MessageWidget
+ * when this is text for a @ref MessageWidget.
+ *
+ * @param sel The selection that has been made.
+ */
+ void slotMenuSelection(int sel);
+
+ /**
+ * Sets the text for this label if it is acting as a sequence
+ * diagram message or a collaboration diagram message.
+ */
+ void setMessageText();
+
+protected:
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Override default method
+ */
+ void resizeEvent(QResizeEvent* /*re*/);
+
+ /**
+ * The association or message widget we may be linked to.
+ */
+ LinkWidget * m_pLink;
+
+ //////////////////// Data loaded/saved:
+
+ /// Prepended text (such as for scope of association Role or method)
+ QString m_PreText;
+ /**
+ * Ending text (such as bracket on changability notation for
+ * association Role)
+ */
+ QString m_PostText;
+
+ /**
+ * The role the text widget will enact.
+ */
+ Uml::Text_Role m_Role;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/floatingtextwidgetcontroller.cpp b/umbrello/umbrello/floatingtextwidgetcontroller.cpp
new file mode 100644
index 00000000..4c6a4aa8
--- /dev/null
+++ b/umbrello/umbrello/floatingtextwidgetcontroller.cpp
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "floatingtextwidgetcontroller.h"
+// qt/kde includes
+#include <kdebug.h>
+// app includes
+#include "floatingtextwidget.h"
+#include "messagewidget.h"
+#include "objectwidget.h"
+
+FloatingTextWidgetController::FloatingTextWidgetController(FloatingTextWidget *floatingTextWidget):
+ UMLWidgetController(floatingTextWidget) {
+ m_floatingTextWidget = floatingTextWidget;
+ m_unconstrainedPositionX = 0;
+ m_unconstrainedPositionY = 0;
+ m_movementDirectionX = 0;
+ m_movementDirectionY = 0;
+}
+
+FloatingTextWidgetController::~FloatingTextWidgetController() {
+}
+
+void FloatingTextWidgetController::saveWidgetValues(QMouseEvent *me) {
+ UMLWidgetController::saveWidgetValues(me);
+
+ m_unconstrainedPositionX = m_widget->getX();
+ m_unconstrainedPositionY = m_widget->getY();
+ m_movementDirectionX = 0;
+ m_movementDirectionY = 0;
+}
+
+bool FloatingTextWidgetController::isInResizeArea(QMouseEvent* /*me*/) {
+ return false;
+}
+
+void FloatingTextWidgetController::moveWidgetBy(int diffX, int diffY) {
+ if (m_floatingTextWidget->m_Role == Uml::tr_Seq_Message_Self)
+ return;
+
+ if (m_floatingTextWidget->m_Role == Uml::tr_Seq_Message
+ && ((MessageWidget*)m_floatingTextWidget->m_pLink)->getSelected()) {
+ return;
+ }
+
+ m_unconstrainedPositionX += diffX;
+ m_unconstrainedPositionY += diffY;
+ QPoint constrainedPosition = constrainPosition(diffX, diffY);
+
+ int newX = constrainedPosition.x();
+ int newY = constrainedPosition.y();
+
+ if (!m_movementDirectionX) {
+ if (m_unconstrainedPositionX != constrainedPosition.x()) {
+ m_movementDirectionX = (diffX > 0)? 1: -1;
+ }
+ } else if ((m_movementDirectionX < 0 && m_unconstrainedPositionX > m_floatingTextWidget->getX()) ||
+ (m_movementDirectionX > 0 && m_unconstrainedPositionX < m_floatingTextWidget->getX()) ) {
+ newX = m_unconstrainedPositionX;
+ m_movementDirectionX = 0;
+ }
+
+ if (!m_movementDirectionY) {
+ if (m_unconstrainedPositionY != constrainedPosition.y()) {
+ m_movementDirectionY = (diffY > 0)? 1: -1;
+ }
+ } else if ((m_movementDirectionY < 0 && m_unconstrainedPositionY > m_floatingTextWidget->getY()) ||
+ (m_movementDirectionY > 0 && m_unconstrainedPositionY < m_floatingTextWidget->getY()) ) {
+ newY = m_unconstrainedPositionY;
+ m_movementDirectionY = 0;
+ }
+
+ m_floatingTextWidget->setX(newX);
+ m_floatingTextWidget->setY(newY);
+
+ if (m_floatingTextWidget->m_pLink) {
+ m_floatingTextWidget->m_pLink->calculateNameTextSegment();
+ if (m_floatingTextWidget->m_Role == Uml::tr_Seq_Message) {
+ MessageWidget* messageWidget = (MessageWidget*)m_floatingTextWidget->m_pLink;
+ messageWidget->setY(newY + m_floatingTextWidget->getHeight());
+
+ //TODO This should be moved to somewhere in MessageWidget, refactor with messagewidgetcontroller.cpp:44
+ if (messageWidget->getSequenceMessageType() == Uml::sequence_message_creation) {
+ const int objWidgetHalfHeight = messageWidget->getWidget(Uml::B)->getHeight() / 2;
+ messageWidget->getWidget(Uml::B)->UMLWidget::setY(messageWidget->getY() - objWidgetHalfHeight);
+ }
+ }
+ }
+}
+
+void FloatingTextWidgetController::constrainMovementForAllWidgets(int &diffX, int &diffY) {
+ QPoint constrainedPosition = constrainPosition(diffX, diffY);
+
+ diffX = constrainedPosition.x() - m_floatingTextWidget->getX();
+ diffY = constrainedPosition.y() - m_floatingTextWidget->getY();
+}
+
+QPoint FloatingTextWidgetController::constrainPosition(int diffX, int diffY) {
+ int newX = m_floatingTextWidget->getX() + diffX;
+ int newY = m_floatingTextWidget->getY() + diffY;
+
+ if (m_floatingTextWidget->m_pLink) {
+ m_floatingTextWidget->m_pLink->constrainTextPos(newX, newY,
+ m_floatingTextWidget->width(), m_floatingTextWidget->height(),
+ m_floatingTextWidget->m_Role);
+ }
+
+ return QPoint(newX, newY);
+}
+
diff --git a/umbrello/umbrello/floatingtextwidgetcontroller.h b/umbrello/umbrello/floatingtextwidgetcontroller.h
new file mode 100644
index 00000000..f73b359a
--- /dev/null
+++ b/umbrello/umbrello/floatingtextwidgetcontroller.h
@@ -0,0 +1,152 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef FLOATINGTEXTWIDGETCONTROLLER_H
+#define FLOATINGTEXTWIDGETCONTROLLER_H
+
+#include "umlwidgetcontroller.h"
+
+class FloatingTextWidget;
+
+/**
+ * Controller for FloatingTextWidget.
+ *
+ * When moving a FloatingTextWidget, it is constrained using constrainTextPos
+ * method from the LinkWidget, if any.
+ * This applies both when moving as part of a selection and when constraining
+ * the move of the selection because it's the receiver of mouse move events.
+ * The only exception to this is that when moving the widget, if it's a sequence
+ * message and the message widget is selected, the floating text widget isn't
+ * moved itself, but automatically by the message widget.
+ * If the sequence message wasn't part of the selection, the floating text
+ * widget moves it.
+ * When moving the floating text as part of a selection, if the position of
+ * the floating text is constrained, it's kept at that position until it can
+ * be moved to another valid position.
+ * No resize is allowed for FloatingTextWidget.
+ *
+ * @author Umbrello UML Modeller Authors <uml-devel@lists.sourceforge.net>
+ */
+class FloatingTextWidgetController : public UMLWidgetController {
+public:
+
+ /**
+ * Constructor for FloatingTextWidgetController.
+ *
+ * @param floatingTextWidget The floating text widget which uses the controller.
+ */
+ FloatingTextWidgetController(FloatingTextWidget *floatingTextWidget);
+
+ /**
+ * Destructor for MessageWidgetController.
+ */
+ ~FloatingTextWidgetController();
+
+protected:
+
+ /**
+ * Overridden from UMLWidgetController.
+ * Saves the values of the widget needed for move/resize.
+ * Calls parent method and then saves the value of m_unconstrainedPositionX/Y
+ * and m_movementDirectionX/Y.
+ *
+ * @param me The QMouseEvent to get the offset from.
+ */
+ virtual void saveWidgetValues(QMouseEvent *me);
+
+ /**
+ * Overridden from UMLWidgetController.
+ * FloatingTextWidgets can't be resized, so this method always returns false.
+ * Cursor isn't changed.
+ *
+ * @param me The QMouseEVent to check.
+ * @return true if the mouse is in resize area, false otherwise.
+ */
+ virtual bool isInResizeArea(QMouseEvent *me);
+
+ /**
+ * Overridden from UMLWidgetController.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * If the floating text widget is part of a sequence message, and the
+ * message widget is selected, it does nothing: the message widget will
+ * update the text position when it's moved.
+ * In any other case, the floating text widget constrains its move using
+ * constrainPosition. When the position of the floating text is constrained,
+ * it's kept at that position until it can be moved to another valid
+ * position (m_unconstrainedPositionX/Y and m_movementDirectionX/Y are
+ * used for that).
+ * Moreover, if is part of a sequence message (and the message widget
+ * isn't selected), it updates the position of the message widget.
+ * @see constrainPosition
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void moveWidgetBy(int diffX, int diffY);
+
+ /**
+ * Overridden from UMLWidgetController.
+ * Modifies the value of the diffX and diffY variables used to move the
+ * widgets.
+ * The values are constrained using constrainPosition.
+ * @see constrainPosition
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void constrainMovementForAllWidgets(int &diffX, int &diffY);
+
+private:
+
+ /**
+ * Returns a constrained position for the widget after applying the position
+ * difference.
+ * If no link widget exists, the position returned is the current widget
+ * position with the difference applied. If there's a link, the position
+ * to be returned is constrained using constrainTextPos method from the
+ * LinkWidget, if any.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ * @return A QPoint with the constrained new position.
+ */
+ QPoint constrainPosition(int diffX, int diffY);
+
+ /**
+ * The floating text widget which uses the controller.
+ */
+ FloatingTextWidget *m_floatingTextWidget;
+
+ /**
+ * The horizontal position the widget would have if its move wasn't constrained.
+ */
+ int m_unconstrainedPositionX;
+
+ /**
+ * The vertical position the widget would have if its move wasn't constrained.
+ */
+ int m_unconstrainedPositionY;
+
+ /**
+ * The X direction the widget was moved when the constrain was applied.
+ * -1 means left, 1 means right.
+ */
+ int m_movementDirectionX;
+
+ /**
+ * The Y direction the widget was moved when the constrain was applied.
+ * -1 means up, 1 means down.
+ */
+ int m_movementDirectionY;
+};
+
+#endif
diff --git a/umbrello/umbrello/folder.cpp b/umbrello/umbrello/folder.cpp
new file mode 100644
index 00000000..8317bab1
--- /dev/null
+++ b/umbrello/umbrello/folder.cpp
@@ -0,0 +1,412 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "folder.h"
+// qt/kde includes
+#include <qfile.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umllistview.h"
+#include "optionstate.h"
+#include "object_factory.h"
+#include "model_utils.h"
+
+UMLFolder::UMLFolder(const QString & name, Uml::IDType id)
+ : UMLPackage(name, id) {
+ init();
+}
+
+UMLFolder::~UMLFolder() {
+}
+
+void UMLFolder::init() {
+ m_BaseType = Uml::ot_Folder;
+ m_diagrams.setAutoDelete(true);
+ UMLObject::setStereotype("folder");
+}
+
+UMLObject* UMLFolder::clone() const {
+ UMLFolder *clone = new UMLFolder();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLFolder::setLocalName(const QString& localName) {
+ m_localName = localName;
+}
+
+QString UMLFolder::getLocalName() {
+ return m_localName;
+}
+
+void UMLFolder::addView(UMLView *view) {
+ m_diagrams.append(view);
+}
+
+void UMLFolder::removeView(UMLView *view) {
+ // m_diagrams is set to autodelete!
+ m_diagrams.remove(view);
+}
+
+void UMLFolder::appendViews(UMLViewList& viewList, bool includeNested) {
+ if (includeNested) {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() == Uml::ot_Folder) {
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->appendViews(viewList);
+ }
+ }
+ }
+ UMLView *v;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
+ viewList.append(v);
+}
+
+void UMLFolder::activateViews() {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() == Uml::ot_Folder) {
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->activateViews();
+ }
+ }
+ UMLView *v;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
+ v->activateAfterLoad();
+ // Make sure we have a treeview item for each diagram.
+ // It may happen that we are missing them after switching off tabbed widgets.
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (optionState.generalState.tabdiagrams)
+ return;
+ UMLListView *lv = UMLApp::app()->getListView();
+ for (UMLViewListIt it(m_diagrams); (v = it.current()) != NULL; ++it) {
+ if (lv->findItem(v->getID()) != NULL)
+ continue;
+ lv->createDiagramItem(v);
+ }
+}
+
+UMLView *UMLFolder::findView(Uml::IDType id) {
+ UMLView *v = NULL;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
+ if (v->getID() == id)
+ return v;
+ }
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() != Uml::ot_Folder)
+ continue;
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ v = f->findView(id);
+ if (v)
+ break;
+ }
+ return v;
+}
+
+UMLView *UMLFolder::findView(Uml::Diagram_Type type, const QString &name, bool searchAllScopes) {
+ UMLView *v = NULL;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
+ if (v->getType() == type && v->getName() == name)
+ return v;
+ }
+ if (searchAllScopes) {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() != Uml::ot_Folder)
+ continue;
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ v = f->findView(type, name, searchAllScopes);
+ if (v)
+ break;
+ }
+ }
+ return v;
+}
+
+void UMLFolder::setViewOptions(const Settings::OptionState& optionState) {
+ // for each view update settings
+ UMLView *v;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit)
+ v->setOptionState(optionState);
+}
+
+void UMLFolder::removeAllViews() {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_objects); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() != Uml::ot_Folder)
+ continue;
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ f->removeAllViews();
+ }
+ UMLView *v = NULL;
+ for (UMLViewListIt vit(m_diagrams); (v = vit.current()) != NULL; ++vit) {
+ // TODO ------------------ check this code - bad: calling back to UMLDoc::removeView()
+ v->removeAllAssociations(); // note : It may not be apparent, but when we remove all associations
+ // from a view, it also causes any UMLAssociations that lack parent
+ // association widgets (but once had them) to remove themselves from
+ // this document.
+ UMLApp::app()->getDocument()->removeView(v, false);
+ }
+ m_diagrams.clear();
+}
+
+void UMLFolder::setFolderFile(const QString& fileName) {
+ m_folderFile = fileName;
+}
+
+QString UMLFolder::getFolderFile() {
+ return m_folderFile;
+}
+
+void UMLFolder::saveContents(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement ownedElement = qDoc.createElement("UML:Namespace.ownedElement");
+ UMLObject *obj;
+ // Save contained objects if any.
+ for (UMLObjectListIt oit(m_objects); (obj = oit.current()) != NULL; ++oit)
+ obj->saveToXMI (qDoc, ownedElement);
+ // Save asscociations if any.
+ for (UMLObjectListIt ait(m_List); (obj = ait.current()) != NULL; ++ait)
+ obj->saveToXMI (qDoc, ownedElement);
+ qElement.appendChild(ownedElement);
+ // Save diagrams to `extension'.
+ if (m_diagrams.count()) {
+ QDomElement diagramsElement = qDoc.createElement("diagrams");
+ UMLView *pView;
+ for (UMLViewListIt vit(m_diagrams); (pView = vit.current()) != NULL; ++vit) {
+ pView->saveToXMI(qDoc, diagramsElement);
+ }
+ QDomElement extension = qDoc.createElement("XMI.extension");
+ extension.setAttribute("xmi.extender", "umbrello");
+ extension.appendChild( diagramsElement );
+ qElement.appendChild(extension);
+ }
+}
+
+void UMLFolder::save(QDomDocument& qDoc, QDomElement& qElement) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ QString elementName("UML:Package");
+ const Uml::Model_Type mt = umldoc->rootFolderType(this);
+ if (mt != Uml::N_MODELTYPES)
+ elementName = "UML:Model";
+ QDomElement folderElement = UMLObject::save(elementName, qDoc);
+ saveContents(qDoc, folderElement);
+ qElement.appendChild(folderElement);
+}
+
+void UMLFolder::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ if (m_folderFile.isEmpty()) {
+ save(qDoc, qElement);
+ return;
+ }
+ // See if we can create the external file.
+ // If not then internalize the folder.
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ QString fileName = umldoc->URL().directory() + '/' + m_folderFile;
+ QFile file(fileName);
+ if (!file.open(IO_WriteOnly)) {
+ kError() << "UMLFolder::saveToXMI(" << m_folderFile << "): "
+ << "cannot create file, contents will be saved in main model file"
+ << endl;
+ m_folderFile = QString::null;
+ save(qDoc, qElement);
+ return;
+ }
+ // Okay, external file is writable. Wrap up main file.
+ QDomElement folderElement = UMLObject::save("UML:Package", qDoc);
+ QDomElement extension = qDoc.createElement("XMI.extension");
+ extension.setAttribute("xmi.extender", "umbrello");
+ QDomElement fileElement = qDoc.createElement("external_file");
+ fileElement.setAttribute("name", m_folderFile);
+ extension.appendChild(fileElement);
+ folderElement.appendChild(extension);
+ qElement.appendChild(folderElement);
+
+ // Save folder to external file.
+ QDomDocument folderDoc;
+ QDomElement folderRoot;
+ QDomProcessingInstruction xmlHeading =
+ folderDoc.createProcessingInstruction("xml",
+ "version=\"1.0\" encoding=\"UTF-8\"");
+ folderDoc.appendChild(xmlHeading);
+ folderRoot = folderDoc.createElement("external_file");
+ folderRoot.setAttribute("name", m_Name);
+ folderRoot.setAttribute("filename", m_folderFile);
+ folderRoot.setAttribute("mainModel", umldoc->URL().fileName());
+ folderRoot.setAttribute("parentId", ID2STR(m_pUMLPackage->getID()));
+ folderRoot.setAttribute("parent", m_pUMLPackage->getFullyQualifiedName("::", true));
+ saveContents(folderDoc, folderRoot);
+ folderDoc.appendChild(folderRoot);
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ stream << folderDoc.toString();
+ file.close();
+}
+
+bool UMLFolder::loadDiagramsFromXMI(QDomNode& diagrams) {
+ const Settings::OptionState optionState = Settings::getOptionState();
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ bool totalSuccess = true;
+ for (QDomElement diagram = diagrams.toElement(); !diagram.isNull();
+ diagrams = diagrams.nextSibling(), diagram = diagrams.toElement()) {
+ QString tag = diagram.tagName();
+ if (tag != "diagram") {
+ kDebug() << "UMLFolder::loadDiagramsFromXMI: ignoring "
+ << tag << " in <diagrams>" << endl;
+ continue;
+ }
+ UMLView * pView = new UMLView(this);
+ pView->setOptionState(optionState);
+ if (pView->loadFromXMI(diagram)) {
+ pView->hide();
+ umldoc->addView(pView);
+ } else {
+ delete pView;
+ totalSuccess = false;
+ }
+ }
+ return totalSuccess;
+}
+
+bool UMLFolder::loadFolderFile(const QString& path) {
+ QFile file(path);
+ if (!file.exists()) {
+ KMessageBox::error(0, i18n("The folderfile %1 does not exist.").arg(path), i18n("Load Error"));
+ return false;
+ }
+ if (!file.open(IO_ReadOnly)) {
+ KMessageBox::error(0, i18n("The folderfile %1 cannot be opened.").arg(path), i18n("Load Error"));
+ return false;
+ }
+ QTextStream stream(&file);
+ QString data = stream.read();
+ file.close();
+ QDomDocument doc;
+ QString error;
+ int line;
+ if (!doc.setContent( data, false, &error, &line)) {
+ kError() << "UMLFolder::loadFolderFile: Can't set content:"
+ << error << " line:" << line << endl;
+ return false;
+ }
+ QDomNode rootNode = doc.firstChild();
+ while (rootNode.isComment() || rootNode.isProcessingInstruction()) {
+ rootNode = rootNode.nextSibling();
+ }
+ if (rootNode.isNull()) {
+ kError() << "UMLFolder::loadFolderFile: Root node is Null" << endl;
+ return false;
+ }
+ QDomElement element = rootNode.toElement();
+ QString type = element.tagName();
+ if (type != "external_file") {
+ kError() << "UMLFolder::loadFolderFile: Root node has unknown type "
+ << type << endl;
+ return false;
+ }
+ return load(element);
+}
+
+bool UMLFolder::load(QDomElement& element) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ bool totalSuccess = true;
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (Uml::tagEq(type, "Namespace.ownedElement") ||
+ Uml::tagEq(type, "Namespace.contents")) {
+ //CHECK: Umbrello currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement)) {
+ kDebug() << "An error happened while loading the " << type
+ << " of the " << m_Name << endl;
+ totalSuccess = false;
+ }
+ continue;
+ } else if (type == "XMI.extension") {
+ for (QDomNode xtnode = node.firstChild(); !xtnode.isNull();
+ xtnode = xtnode.nextSibling()) {
+ QDomElement el = xtnode.toElement();
+ const QString xtag = el.tagName();
+ if (xtag == "diagrams") {
+ QDomNode diagramNode = xtnode.firstChild();
+ if (!loadDiagramsFromXMI(diagramNode))
+ totalSuccess = false;
+ } else if (xtag == "external_file") {
+ const QString rootDir(umldoc->URL().directory());
+ QString fileName = el.attribute("name", "");
+ const QString path(rootDir + '/' + fileName);
+ if (loadFolderFile(path))
+ m_folderFile = fileName;
+ } else {
+ kDebug() << "UMLFolder::load(" << m_Name
+ << "): ignoring XMI.extension " << xtag << endl;
+ continue;
+ }
+ }
+ continue;
+ }
+ // Do not re-create the predefined Datatypes folder in the Logical View,
+ // it already exists.
+ UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
+ if (this == logicalView && Uml::tagEq(type, "Package")) {
+ QString thisName = tempElement.attribute("name", "");
+ if (thisName == "Datatypes") {
+ UMLFolder *datatypeFolder = umldoc->getDatatypeFolder();
+ if (!datatypeFolder->loadFromXMI(tempElement))
+ totalSuccess = false;
+ continue;
+ }
+ }
+ UMLObject *pObject = NULL;
+ // Avoid duplicate creation of forward declared object
+ QString idStr = tempElement.attribute("xmi.id", "");
+ if (!idStr.isEmpty()) {
+ Uml::IDType id = STR2ID(idStr);
+ pObject = umldoc->findObjectById(id);
+ if (pObject) {
+ kDebug() << "UMLFolder::load: object " << idStr
+ << "already exists" << endl;
+ }
+ }
+ if (pObject == NULL) {
+ QString stereoID = tempElement.attribute("stereotype", "");
+ pObject = Object_Factory::makeObjectFromXMI(type, stereoID);
+ if (!pObject) {
+ kWarning() << "UMLFolder::load: "
+ << "Unknown type of umlobject to create: " << type << endl;
+ continue;
+ }
+ }
+ pObject->setUMLPackage(this);
+ if (!pObject->loadFromXMI(tempElement)) {
+ removeObject(pObject);
+ delete pObject;
+ totalSuccess = false;
+ }
+ }
+ return totalSuccess;
+}
+
+#include "folder.moc"
diff --git a/umbrello/umbrello/folder.h b/umbrello/umbrello/folder.h
new file mode 100644
index 00000000..2e4d23f6
--- /dev/null
+++ b/umbrello/umbrello/folder.h
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLFOLDER_H
+#define UMLFOLDER_H
+
+#include "package.h"
+#include "umlviewlist.h"
+#include "optionstate.h"
+
+/**
+ * This class manages the UMLObjects and UMLViews of a Folder.
+ * This class inherits from UMLPackage which contains most
+ * of the information.
+ *
+ * The UMLDoc class allocates a fixed instance of this class for
+ * each of the predefined Logical, UseCase, Component, Deployment, and
+ * Entity-Relationship folders. Further instances are created on demand
+ * for user folders.
+ *
+ * @short Non-graphical management of objects and diagrams of a Folder
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLFolder : public UMLPackage {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a Folder.
+ *
+ * @param name The name of the Folder.
+ * @param id The unique id of the Folder. A new ID will be generated
+ * if this argument is left away.
+ */
+ explicit UMLFolder(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Empty deconstructor.
+ */
+ virtual ~UMLFolder();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Set the localized name of this folder.
+ * This is set for the predefined root views (Logical,
+ * UseCase, Component, Deployment, EntityRelationship,
+ * and the Datatypes folder inside the Logical View.)
+ */
+ void setLocalName(const QString& localName);
+
+ /**
+ * Return the localized name of this folder.
+ * Only useful for the predefined root folders.
+ */
+ QString getLocalName();
+
+ /**
+ * Add a view to the diagram list.
+ */
+ void addView(UMLView *view);
+
+ /**
+ * Remove a view from the diagram list.
+ */
+ void removeView(UMLView *view);
+
+ /**
+ * Append the views in this folder to the given diagram list.
+ *
+ * @param viewList The UMLViewList to which to append the diagrams.
+ * @param includeNested Whether to include diagrams from nested folders
+ * (default: true.)
+ */
+ void appendViews(UMLViewList& viewList, bool includeNested = true);
+
+ /**
+ * Acivate the views in this folder.
+ * "Activation": Some widgets require adjustments after loading from file,
+ * those are done here.
+ */
+ void activateViews();
+
+ /**
+ * Seek a view of the given ID in this folder.
+ *
+ * @param id ID of the view to find.
+ * @return Pointer to the view if found, NULL if no view found.
+ */
+ UMLView *findView(Uml::IDType id);
+
+ /**
+ * Seek a view by the type and name given.
+ *
+ * @param type The type of view to find.
+ * @param name The name of the view to find.
+ * @param searchAllScopes Search in all subfolders (default: true.)
+ * @return Pointer to the view found, or NULL if not found.
+ */
+ UMLView * findView(Uml::Diagram_Type type, const QString &name, bool searchAllScopes = true);
+
+ /**
+ * Set the options for the views in this folder.
+ */
+ void setViewOptions(const Settings::OptionState& optionState);
+
+ /**
+ * Remove all views in this folder.
+ */
+ void removeAllViews();
+
+ /**
+ * Set the folder file name for a separate submodel.
+ */
+ void setFolderFile(const QString& fileName);
+
+ /**
+ * Get the folder file name for a separate submodel.
+ */
+ QString getFolderFile();
+
+ /**
+ * Creates a UML:Model or UML:Package element:
+ * UML:Model is created for the predefined fixed folders,
+ * UML:Package with stereotype "folder" is created for all else.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Auxiliary to saveToXMI(): Save the contained objects and diagrams.
+ * Can be used regardless of whether saving to the main model file
+ * or to an external folder file (see m_folderFile.)
+ */
+ void saveContents(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Auxiliary to saveToXMI(): Creates a <UML:Model> element when saving
+ * a predefined modelview, or a <UML:Package> element when saving a
+ * user created folder. Invokes saveContents() with the newly created
+ * element.
+ */
+ void save(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Auxiliary to load():
+ * Load the diagrams from the "diagrams" in the <XMI.extension>
+ */
+ bool loadDiagramsFromXMI(QDomNode& diagrams);
+
+ /**
+ * Folders in the listview can be marked such that their contents
+ * are saved to a separate file.
+ * This method loads the separate folder file.
+ * CAVEAT: This is not XMI standard compliant.
+ * If standard compliance is an issue then avoid folder files.
+ *
+ * @param path Fully qualified file name, i.e. absolute directory
+ * plus file name.
+ * @return True for success.
+ */
+ bool loadFolderFile(const QString& path);
+
+ /**
+ * Loads the UML:Component element.
+ */
+ bool load(QDomElement & element);
+
+private:
+ QString m_localName; ///< i18n name, only used for predefined root folders
+ /**
+ * If m_folderFile is not empty then it contains a file name to which
+ * this folder is saved.
+ * In this case the folder file acts as a physically separate submodel.
+ * What is saved in the main model is not the folder contents but a
+ * reference to the folder file.
+ */
+ QString m_folderFile;
+ UMLViewList m_diagrams;
+};
+
+#endif
diff --git a/umbrello/umbrello/forkjoinwidget.cpp b/umbrello/umbrello/forkjoinwidget.cpp
new file mode 100644
index 00000000..5a1ce3b8
--- /dev/null
+++ b/umbrello/umbrello/forkjoinwidget.cpp
@@ -0,0 +1,112 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "forkjoinwidget.h"
+//qt includes
+#include <qdom.h>
+//kde includes
+#include <kcursor.h>
+#include <kdebug.h>
+//app includes
+#include "umlview.h"
+#include "listpopupmenu.h"
+
+ForkJoinWidget::ForkJoinWidget(UMLView * view, bool drawVertical, Uml::IDType id)
+ : BoxWidget(view, id), m_drawVertical(drawVertical) {
+ init();
+}
+
+void ForkJoinWidget::init() {
+ WidgetBase::setBaseType( Uml::wt_ForkJoin );
+ UMLWidget::updateComponentSize();
+}
+
+ForkJoinWidget::~ForkJoinWidget() {
+}
+
+QSize ForkJoinWidget::calculateSize() {
+ if (m_drawVertical) {
+ return QSize(4, 40);
+ } else {
+ return QSize(40, 4);
+ }
+}
+
+void ForkJoinWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ p.fillRect( offsetX, offsetY, width(), height(), QBrush( Qt::black ));
+
+ if (m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void ForkJoinWidget::drawSelected(QPainter *, int /*offsetX*/, int /*offsetY*/) {
+}
+
+void ForkJoinWidget::constrain(int& width, int& height) {
+ if (m_drawVertical) {
+ if (width < 4)
+ width = 4;
+ else if (width > 10)
+ width = 10;
+ if (height < 40)
+ height = 40;
+ else if (height > 100)
+ height = 100;
+ } else {
+ if (height < 4)
+ height = 4;
+ else if (height > 10)
+ height = 10;
+ if (width < 40)
+ width = 40;
+ else if (width > 100)
+ width = 100;
+ }
+}
+
+void ForkJoinWidget::slotMenuSelection(int sel) {
+ switch (sel) {
+ case ListPopupMenu::mt_Flip:
+ setDrawVertical(!m_drawVertical);
+ break;
+ default:
+ break;
+ }
+}
+
+void ForkJoinWidget::setDrawVertical(bool to) {
+ m_drawVertical = to;
+ updateComponentSize();
+ UMLWidget::adjustAssocs( getX(), getY() );
+}
+
+bool ForkJoinWidget::getDrawVertical() const {
+ return m_drawVertical;
+}
+
+void ForkJoinWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement fjElement = qDoc.createElement("forkjoin");
+ UMLWidget::saveToXMI(qDoc, fjElement);
+ fjElement.setAttribute("drawvertical", m_drawVertical);
+ qElement.appendChild(fjElement);
+}
+
+bool ForkJoinWidget::loadFromXMI(QDomElement& qElement) {
+ if ( !UMLWidget::loadFromXMI(qElement) ) {
+ return false;
+ }
+ QString drawVertical = qElement.attribute("drawvertical", "0");
+ setDrawVertical( (bool)drawVertical.toInt() );
+ return true;
+}
+
diff --git a/umbrello/umbrello/forkjoinwidget.h b/umbrello/umbrello/forkjoinwidget.h
new file mode 100644
index 00000000..bf8c47c8
--- /dev/null
+++ b/umbrello/umbrello/forkjoinwidget.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+ * *
+ * 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) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef FORKJOINWIDGET_H
+#define FORKJOINWIDGET_H
+//qt includes
+#include <qpainter.h>
+//app includes
+#include "boxwidget.h"
+
+// fwd decl.
+class UMLView;
+
+/**
+ * @short Displays a fork/join plate in a state diagram.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ForkJoinWidget : public BoxWidget {
+public:
+
+ /**
+ * Constructs a ForkJoinWidget.
+ *
+ * @param view The parent to this widget.
+ * @param drawVertical Whether to draw the plate horizontally or vertically.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ explicit ForkJoinWidget(UMLView * view, bool drawVertical = false, Uml::IDType id = Uml::id_None);
+
+ /**
+ * destructor
+ */
+ virtual ~ForkJoinWidget();
+
+ /**
+ * Set whether to draw the plate vertically.
+ */
+ void setDrawVertical(bool to);
+ /**
+ * Get whether to draw the plate vertically.
+ */
+ bool getDrawVertical() const;
+
+ /**
+ * Overrides the function from UMLWidget.
+ *
+ * @param sel The command to be executed.
+ */
+ void slotMenuSelection(int sel);
+
+ /**
+ * Draws a slim solid black rectangle.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Saves the widget to the "forkjoinwidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Loads the widget from the "forkjoinwidget" XMI element.
+ */
+ bool loadFromXMI(QDomElement & qElement);
+
+protected:
+ /**
+ * Reimplement method from UMLWidget to suppress the resize corner.
+ * Although the ForkJoinWidget supports resizing, we suppress the
+ * resize corner because it is too large for this very slim widget.
+ */
+ void drawSelected(QPainter * p, int offsetX, int offsetY);
+
+ /**
+ * Overrides the function from UMLWidget.
+ */
+ QSize calculateSize();
+
+ /**
+ * Reimplement method from UMLWidget.
+ */
+ void constrain(int& width, int& height);
+
+private:
+ /**
+ * Initializes key variables for the class.
+ */
+ void init();
+
+ bool m_drawVertical; ///< whether to draw the plate horizontally or vertically
+};
+
+#endif
diff --git a/umbrello/umbrello/headings/Makefile.am b/umbrello/umbrello/headings/Makefile.am
new file mode 100644
index 00000000..334e9435
--- /dev/null
+++ b/umbrello/umbrello/headings/Makefile.am
@@ -0,0 +1,17 @@
+mydir = $(kde_datadir)/umbrello/headings
+my_DATA = heading.adb \
+heading.ads \
+heading.as \
+heading.cpp \
+heading.cs \
+heading.d \
+heading.h \
+heading.idl \
+heading.java \
+heading.js \
+heading.php \
+heading.pm \
+heading.py \
+heading.rb \
+heading.sql \
+heading.xsd
diff --git a/umbrello/umbrello/headings/heading.adb b/umbrello/umbrello/headings/heading.adb
new file mode 100644
index 00000000..87dc70a8
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.adb
@@ -0,0 +1,29 @@
+-- %filename% - Copyright %author%
+--
+-- Here you can write a license for your code, some comments or any other
+-- information you want to have in your generated code. To to this simply
+-- configure the "headings" directory in uml to point to a directory
+-- where you have your heading files.
+--
+-- or you can just replace the contents of this file with your own.
+-- If you want to do this, this file is located at
+--
+-- %headingpath%
+--
+-- -->Code Generators searches for heading files based on the file
+-- extension i.e. it will look for a file name ending in ".h" to
+-- include in C++ header files, and for a file name ending in
+-- ".java" to include in all generated java code. If you name
+-- the file "heading.<extension>", Code Generator will always
+-- choose this file even if there are other files with the same
+-- extension in the directory. If you name the file something
+-- else, it must be the only one with that extension in the
+-- directory to guarantee that Code Generator will choose it.
+--
+-- you can use variables in your heading files which are replaced at
+-- generation time. possible variables are : author, date, time,
+-- filename and filepath. Just write %variable_name%
+--
+-- This file was generated on %date% at %time%
+-- The original location of this file is %filepath%
+
diff --git a/umbrello/umbrello/headings/heading.ads b/umbrello/umbrello/headings/heading.ads
new file mode 100644
index 00000000..1e4a582c
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.ads
@@ -0,0 +1,30 @@
+-- %filename% - Copyright %author%
+--
+-- Here you can write a license for your code, some comments or any other
+-- information you want to have in your generated code. To to this simply
+-- configure the "headings" directory in uml to point to a directory
+-- where you have your heading files.
+--
+-- or you can just replace the contents of this file with your own.
+-- If you want to do this, this file is located at
+--
+-- %headingpath%
+--
+-- -->Code Generators searches for heading files based on the file
+-- extension i.e. it will look for a file name ending in ".h" to
+-- include in C++ header files, and for a file name ending in
+-- ".java" to include in all generated java code. If you name
+-- the file "heading.<extension>", Code Generator will always
+-- choose this file even if there are other files with the same
+-- extension in the directory. If you name the file something
+-- else, it must be the only one with that extension in the
+-- directory to guarantee that Code Generator will choose it.
+--
+-- you can use variables in your heading files which are replaced at
+-- generation time. possible variables are : author, date, time,
+-- filename and filepath. Just write %variable_name%
+--
+-- This file was generated on %date% at %time%
+-- The original location of this file is %filepath%
+
+
diff --git a/umbrello/umbrello/headings/heading.as b/umbrello/umbrello/headings/heading.as
new file mode 100644
index 00000000..6e3f61cd
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.as
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.cpp b/umbrello/umbrello/headings/heading.cpp
new file mode 100644
index 00000000..d33911bf
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.cpp
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.cs b/umbrello/umbrello/headings/heading.cs
new file mode 100644
index 00000000..6e3f61cd
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.cs
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.d b/umbrello/umbrello/headings/heading.d
new file mode 100644
index 00000000..d33911bf
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.d
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.h b/umbrello/umbrello/headings/heading.h
new file mode 100644
index 00000000..d33911bf
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.h
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.idl b/umbrello/umbrello/headings/heading.idl
new file mode 100644
index 00000000..6e3f61cd
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.idl
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.java b/umbrello/umbrello/headings/heading.java
new file mode 100644
index 00000000..6e3f61cd
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.java
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.js b/umbrello/umbrello/headings/heading.js
new file mode 100644
index 00000000..6e3f61cd
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.js
@@ -0,0 +1,29 @@
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.php b/umbrello/umbrello/headings/heading.php
new file mode 100644
index 00000000..7ff129ac
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.php
@@ -0,0 +1,30 @@
+<?php
+/************************************************************************
+ %filename% - Copyright %author%
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+%headingpath%
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is %filepath%
+**************************************************************************/
diff --git a/umbrello/umbrello/headings/heading.pm b/umbrello/umbrello/headings/heading.pm
new file mode 100644
index 00000000..cc02c171
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.pm
@@ -0,0 +1,29 @@
+#!/usr/bin/env perl
+# %filename% - Copyright %author%
+#
+# Here you can write a license for your code, some comments or any other
+# information you want to have in your generated code. To to this simply
+# configure the "headings" directory in uml to point to a directory
+# where you have your heading files.
+#
+# or you can just replace the contents of this file with your own.
+# If you want to do this, this file is located at
+#
+# %headingpath%
+#
+# -->Code Generators searches for heading files based on the file extension
+# i.e. it will look for a file name ending in ".h" to include in C++ header
+# files, and for a file name ending in ".java" to include in all generated
+# java code.
+# If you name the file "heading.<extension>", Code Generator will always
+# choose this file even if there are other files with the same extension in the
+# directory. If you name the file something else, it must be the only one with that
+# extension in the directory to guarantee that Code Generator will choose it.
+#
+# you can use variables in your heading files which are replaced at generation
+# time. possible variables are : author, date, time, filename and filepath.
+# just write %variable_name%
+#
+# This file was generated on %date% at %time%
+# The original location of this file is %filepath%
+
diff --git a/umbrello/umbrello/headings/heading.py b/umbrello/umbrello/headings/heading.py
new file mode 100644
index 00000000..61016aef
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# %filename% - Copyright %author%
+#
+# Here you can write a license for your code, some comments or any other
+# information you want to have in your generated code. To to this simply
+# configure the "headings" directory in uml to point to a directory
+# where you have your heading files.
+#
+# or you can just replace the contents of this file with your own.
+# If you want to do this, this file is located at
+#
+# %headingpath%
+#
+# -->Code Generators searches for heading files based on the file extension
+# i.e. it will look for a file name ending in ".h" to include in C++ header
+# files, and for a file name ending in ".java" to include in all generated
+# java code.
+# If you name the file "heading.<extension>", Code Generator will always
+# choose this file even if there are other files with the same extension in the
+# directory. If you name the file something else, it must be the only one with that
+# extension in the directory to guarantee that Code Generator will choose it.
+#
+# you can use variables in your heading files which are replaced at generation
+# time. possible variables are : author, date, time, filename and filepath.
+# just write %variable_name%
+#
+# This file was generated on %date% at %time%
+# The original location of this file is %filepath%
+
diff --git a/umbrello/umbrello/headings/heading.rb b/umbrello/umbrello/headings/heading.rb
new file mode 100644
index 00000000..b4bbc9b7
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+# %filename% - Copyright %author%
+#
+# Here you can write a license for your code, some comments or any other
+# information you want to have in your generated code. To to this simply
+# configure the "headings" directory in uml to point to a directory
+# where you have your heading files.
+#
+# or you can just replace the contents of this file with your own.
+# If you want to do this, this file is located at
+#
+# %headingpath%
+#
+# -->Code Generators searches for heading files based on the file extension
+# i.e. it will look for a file name ending in ".h" to include in C++ header
+# files, and for a file name ending in ".java" to include in all generated
+# java code.
+# If you name the file "heading.<extension>", Code Generator will always
+# choose this file even if there are other files with the same extension in the
+# directory. If you name the file something else, it must be the only one with that
+# extension in the directory to guarantee that Code Generator will choose it.
+#
+# you can use variables in your heading files which are replaced at generation
+# time. possible variables are : author, date, time, filename and filepath.
+# just write %variable_name%
+#
+# This file was generated on %date% at %time%
+# The original location of this file is %filepath%
+
diff --git a/umbrello/umbrello/headings/heading.sql b/umbrello/umbrello/headings/heading.sql
new file mode 100644
index 00000000..f4797f56
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.sql
@@ -0,0 +1,28 @@
+-- %filename% - Copyright %author%
+--
+-- Here you can write a license for your code, some comments or any other
+-- information you want to have in your generated code. To to this simply
+-- configure the "headings" directory in uml to point to a directory
+-- where you have your heading files.
+--
+-- or you can just replace the contents of this file with your own.
+-- If you want to do this, this file is located at
+--
+-- %headingpath%
+--
+-- -->Code Generators searches for heading files based on the file extension
+-- i.e. it will look for a file name ending in ".h" to include in C++ header
+-- files, and for a file name ending in ".java" to include in all generated
+-- java code.
+-- If you name the file "heading.<extension>", Code Generator will always
+-- choose this file even if there are other files with the same extension in the
+-- directory. If you name the file something else, it must be the only one with that
+-- extension in the directory to guarantee that Code Generator will choose it.
+--
+-- you can use variables in your heading files which are replaced at generation
+-- time. possible variables are : author, date, time, filename and filepath.
+-- just write %variable_name%
+--
+-- This file was generated on %date% at %time%
+-- The original location of this file is %filepath%
+
diff --git a/umbrello/umbrello/headings/heading.xsd b/umbrello/umbrello/headings/heading.xsd
new file mode 100644
index 00000000..cd50b9f5
--- /dev/null
+++ b/umbrello/umbrello/headings/heading.xsd
@@ -0,0 +1,4 @@
+<!--
+This heading is genearated using the file at
+%headingpath%
+-->
diff --git a/umbrello/umbrello/hi128-app-umbrello.png b/umbrello/umbrello/hi128-app-umbrello.png
new file mode 100644
index 00000000..ce14d9f7
--- /dev/null
+++ b/umbrello/umbrello/hi128-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hi16-app-umbrello.png b/umbrello/umbrello/hi16-app-umbrello.png
new file mode 100644
index 00000000..6005f241
--- /dev/null
+++ b/umbrello/umbrello/hi16-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hi16-mime-umbrellofile.png b/umbrello/umbrello/hi16-mime-umbrellofile.png
new file mode 100644
index 00000000..86b364ac
--- /dev/null
+++ b/umbrello/umbrello/hi16-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/hi22-app-umbrello.png b/umbrello/umbrello/hi22-app-umbrello.png
new file mode 100644
index 00000000..128317d4
--- /dev/null
+++ b/umbrello/umbrello/hi22-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hi32-app-umbrello.png b/umbrello/umbrello/hi32-app-umbrello.png
new file mode 100644
index 00000000..255e592c
--- /dev/null
+++ b/umbrello/umbrello/hi32-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hi32-mime-umbrellofile.png b/umbrello/umbrello/hi32-mime-umbrellofile.png
new file mode 100644
index 00000000..2a298ffc
--- /dev/null
+++ b/umbrello/umbrello/hi32-mime-umbrellofile.png
Binary files differ
diff --git a/umbrello/umbrello/hi48-app-umbrello.png b/umbrello/umbrello/hi48-app-umbrello.png
new file mode 100644
index 00000000..98777102
--- /dev/null
+++ b/umbrello/umbrello/hi48-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hi64-app-umbrello.png b/umbrello/umbrello/hi64-app-umbrello.png
new file mode 100644
index 00000000..cfc7062a
--- /dev/null
+++ b/umbrello/umbrello/hi64-app-umbrello.png
Binary files differ
diff --git a/umbrello/umbrello/hierarchicalcodeblock.cpp b/umbrello/umbrello/hierarchicalcodeblock.cpp
new file mode 100644
index 00000000..7c04a960
--- /dev/null
+++ b/umbrello/umbrello/hierarchicalcodeblock.cpp
@@ -0,0 +1,386 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+// own header
+#include "hierarchicalcodeblock.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "codedocument.h"
+#include "classifiercodedocument.h"
+#include "codeclassfield.h"
+#include "codegenerationpolicy.h"
+#include "codegenerators/codegenfactory.h"
+#include "uml.h"
+
+// Constructors/Destructors
+//
+
+HierarchicalCodeBlock::HierarchicalCodeBlock ( CodeDocument * doc , const QString &start, const QString &endString, const QString &comment )
+ : CodeBlockWithComments (doc, start, comment), CodeGenObjectWithTextBlocks(doc)
+{
+ setEndText(endString);
+ initAttributes();
+}
+
+HierarchicalCodeBlock::~HierarchicalCodeBlock ( ) { }
+
+//
+// Methods
+//
+
+// Accessor methods
+//
+
+/**
+ * Set the value of m_endText
+ * @param new_var the new value of m_endText
+ */
+void HierarchicalCodeBlock::setEndText ( const QString &new_var ) {
+ m_endText = new_var;
+}
+
+/**
+ * Get the value of m_endText
+ * @return the value of m_endText
+ */
+QString HierarchicalCodeBlock::getEndText ( ) {
+ return m_endText;
+}
+
+QString HierarchicalCodeBlock::getUniqueTag()
+{
+ return getUniqueTag("hblock_tag");
+}
+
+QString HierarchicalCodeBlock::getUniqueTag( const QString& prefix )
+{
+ return getParentDocument()->getUniqueTag(prefix);
+}
+
+// other methods
+
+CodeBlock * HierarchicalCodeBlock::newCodeBlock() {
+ return getParentDocument()->newCodeBlock();
+}
+
+CodeBlockWithComments * HierarchicalCodeBlock::newCodeBlockWithComments() {
+ return getParentDocument()->newCodeBlockWithComments();
+}
+
+HierarchicalCodeBlock * HierarchicalCodeBlock::newHierarchicalCodeBlock() {
+ HierarchicalCodeBlock *hb = new HierarchicalCodeBlock(getParentDocument());
+ //hb->update();
+ return hb;
+}
+
+/**
+ * Add a CodeBlock object to the m_textblockVector List
+ */
+bool HierarchicalCodeBlock::addTextBlock(TextBlock* add_object )
+{
+
+ if(CodeGenObjectWithTextBlocks::addTextBlock(add_object))
+ {
+ getParentDocument()->addChildTagToMap(add_object->getTag(), add_object);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Insert a new text block before the existing text block. Returns
+ * false if it cannot insert the textblock.
+ */
+bool HierarchicalCodeBlock::insertTextBlock(TextBlock * newBlock, TextBlock * existingBlock, bool after)
+{
+
+ if(!newBlock || !existingBlock)
+ return false;
+
+ QString tag = existingBlock->getTag();
+ // FIX: just do a quick check if the parent DOCUMENT has this.
+ // IF it does, then the lack of an index will force us into
+ // a search of any child hierarchical codeblocks we may have
+ // Its not efficient, but works. I don't think speed is a problem
+ // right now for the current implementation, but in the future
+ // when code import/roundtripping is done, it *may* be. -b.t.
+ if(!getParentDocument()->findTextBlockByTag(tag, true))
+ return false;
+
+ int index = m_textblockVector.findRef(existingBlock);
+ if(index < 0)
+ {
+ // may be hiding in child hierarchical codeblock
+ for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next())
+ {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
+ if(hb && hb->insertTextBlock(newBlock, existingBlock, after))
+ return true; // found, and inserted, otherwise keep going
+ }
+ kWarning()<<" Warning: couldnt insert text block (tag:"<<newBlock->getTag()<<"). Reference text block (tag:"<<existingBlock->getTag()<<") not found."<<endl;
+ return false;
+ }
+
+ // if we get here.. it was in this object so insert
+
+ // check for tag FIRST
+ QString new_tag = newBlock->getTag();
+
+ // assign a tag if one doesn't already exist
+ if(new_tag.isEmpty())
+ {
+ new_tag = getUniqueTag();
+ newBlock->setTag(new_tag);
+ }
+
+ if(m_textBlockTagMap.contains(new_tag))
+ return false; // return false, we already have some object with this tag in the list
+ else {
+ m_textBlockTagMap.insert(new_tag, newBlock);
+ getParentDocument()->addChildTagToMap(new_tag, newBlock);
+ }
+
+
+ if(after)
+ index++;
+
+ m_textblockVector.insert(index,newBlock);
+
+ return true;
+}
+
+/**
+ * Remove a CodeBlock object from m_textblockVector List
+ */
+bool HierarchicalCodeBlock::removeTextBlock ( TextBlock * remove_object ) {
+
+ // try to remove from the list in this object
+ if(!m_textblockVector.removeRef(remove_object))
+ {
+ // may be hiding in child hierarchical codeblock
+ for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next())
+ {
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
+ if(hb && hb->removeTextBlock(remove_object))
+ return true; // because we got in child hb;
+ }
+ return false;
+ }
+
+ // IF we get here, the text block was in THIS object (and not a child)..
+ QString tag = remove_object->getTag();
+ if(!(tag.isEmpty()))
+ {
+ m_textBlockTagMap.erase(tag);
+ getParentDocument()->removeChildTagFromMap(tag);
+ }
+ return true;
+
+}
+
+/**
+ * @param text
+ */
+void HierarchicalCodeBlock::setStartText ( const QString &text ) {
+ m_startText = text;
+}
+
+/**
+ * @return QString
+ */
+QString HierarchicalCodeBlock::getStartText ( ) {
+ return m_startText;
+}
+
+// Other methods
+//
+
+void HierarchicalCodeBlock::addCodeClassFieldMethods(CodeClassFieldList &list )
+{
+
+ for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
+ {
+ CodeClassField * field = ccflit.current();
+ CodeAccessorMethodList list = field->getMethodList();
+ CodeAccessorMethod * method;
+ for (CodeAccessorMethodListIt it(list); (method = it.current()) != NULL; ++it)
+ {
+ QString tag = method->getTag();
+ if(tag.isEmpty())
+ {
+ tag = getUniqueTag();
+ method->setTag(tag);
+ }
+
+ addTextBlock(method); // wont add if already exists in object;
+
+ }
+
+ }
+
+}
+
+/**
+ * Save the XMI representation of this object
+ */
+void HierarchicalCodeBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+ QDomElement blockElement = doc.createElement( "hierarchicalcodeblock" );
+
+ setAttributesOnNode(doc, blockElement);
+
+ root.appendChild( blockElement );
+}
+
+void HierarchicalCodeBlock::setAttributesOnNode (QDomDocument & doc, QDomElement & elem ) {
+
+ // set super-class attributes
+ CodeBlockWithComments::setAttributesOnNode(doc, elem);
+ CodeGenObjectWithTextBlocks::setAttributesOnNode(doc, elem);
+
+ // set local class attributes
+ if(getContentType() != CodeBlock::AutoGenerated)
+ {
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ elem.setAttribute("startText",encodeText(getStartText(),endLine));
+ elem.setAttribute("endText",encodeText(getEndText(),endLine));
+ }
+}
+
+/**
+ * load params from the appropriate XMI element node.
+ */
+void HierarchicalCodeBlock::loadFromXMI ( QDomElement & root ) {
+ setAttributesFromNode(root);
+}
+
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void HierarchicalCodeBlock::setAttributesFromNode ( QDomElement & root)
+{
+
+ // set attributes from the XMI
+ CodeBlockWithComments::setAttributesFromNode(root); // superclass load
+
+ if(getContentType() != CodeBlock::AutoGenerated)
+ {
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ setStartText(decodeText(root.attribute("startText",""),endLine));
+ setEndText(decodeText(root.attribute("endText",""),endLine));
+ }
+
+ // do this *after* all other attributes saved
+ CodeGenObjectWithTextBlocks::setAttributesFromNode(root);
+
+}
+
+/** set the class attributes from a passed object
+ */
+void HierarchicalCodeBlock::setAttributesFromObject (TextBlock * obj) {
+
+ CodeBlockWithComments::setAttributesFromObject(obj);
+
+ HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(obj);
+ if(hb)
+ {
+ setStartText(hb->getStartText());
+ setEndText(hb->getEndText());
+ CodeGenObjectWithTextBlocks *cgowtb = dynamic_cast<CodeGenObjectWithTextBlocks*>(obj);
+ CodeGenObjectWithTextBlocks::setAttributesFromObject(cgowtb);
+ }
+
+}
+
+
+/**
+ * @return QString
+ */
+QString HierarchicalCodeBlock::toString ( ) {
+
+ QString string = QString();
+
+ if(getWriteOutText()) {
+ QString indent = getIndentationString();
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ QString startText = "";
+ QString endText = "";
+ if (!getStartText().isEmpty())
+ startText = formatMultiLineText (getStartText(), indent, endLine);
+ if (!getEndText().isEmpty())
+ endText = formatMultiLineText (getEndText(), indent, endLine);
+
+ QString body = childTextBlocksToString();
+ QString comment = getComment()->toString();
+
+ // tack in text, if there is something there..
+ if(!comment.isEmpty() && getComment()->getWriteOutText())
+ string.append(comment);
+
+ if (!startText.isEmpty())
+ string.append(startText);
+
+ if (!body.isEmpty())
+ string.append(body);
+
+ if (!endText.isEmpty())
+ string.append(endText);
+ }
+
+ return string;
+}
+
+QString HierarchicalCodeBlock::childTextBlocksToString() {
+ TextBlockList* list = getTextBlockList();
+ QString retString = "";
+ for(TextBlock *block = list->first() ; block; block=list->next())
+ {
+ QString blockValue = block->toString();
+ if(!blockValue.isEmpty())
+ retString.append(blockValue);
+ }
+ return retString;
+}
+
+TextBlock * HierarchicalCodeBlock::findCodeClassFieldTextBlockByTag ( const QString &tag )
+{
+
+ ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
+ if(cdoc)
+ return cdoc->findCodeClassFieldTextBlockByTag(tag);
+ else
+ kError()<<" HierarchicalCodeBlock: findCodeClassFieldTextBlockByTag() finds NO parent document! Badly constructed textblock?!?"<<endl;
+
+ // if we get here, we failed.
+ return (TextBlock*) NULL;
+
+}
+
+void HierarchicalCodeBlock::initAttributes ( ) {
+ m_canDelete = false;
+ m_startText = "";
+ m_endText = "";
+}
+
+void HierarchicalCodeBlock::release () {
+ resetTextBlocks();
+ TextBlock::release();
+}
+
+#include "hierarchicalcodeblock.moc"
diff --git a/umbrello/umbrello/hierarchicalcodeblock.h b/umbrello/umbrello/hierarchicalcodeblock.h
new file mode 100644
index 00000000..3c0dcbc1
--- /dev/null
+++ b/umbrello/umbrello/hierarchicalcodeblock.h
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+#ifndef HIERARCHICALCODEBLOCK_H
+#define HIERARCHICALCODEBLOCK_H
+
+#include <qmap.h>
+#include <qstring.h>
+
+#include "codegenobjectwithtextblocks.h"
+#include "codeblockwithcomments.h"
+#include "codeclassfieldlist.h"
+
+class HierarchicalCodeBlock : public CodeBlockWithComments, public CodeGenObjectWithTextBlocks
+{
+ Q_OBJECT
+ friend class CodeGenObjectWithTextBlocks;
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ explicit HierarchicalCodeBlock ( CodeDocument * doc , const QString &startString = "", const QString &endString = "", const QString &comment = "");
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~HierarchicalCodeBlock ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_endText
+ * @param new_var the new value of m_endText
+ */
+ void setEndText ( const QString &new_var );
+
+ /**
+ * Get the value of m_endText
+ * @return the value of m_endText
+ */
+ QString getEndText ( );
+
+ /**
+ * Add a TextBlock object to the m_textblockVector List
+ */
+ bool addTextBlock ( TextBlock * add_object );
+
+ /**
+ * Insert a new text block before/after the existing text block. Returns
+ * false if it cannot insert the textblock.
+ */
+ bool insertTextBlock (TextBlock * newBlock, TextBlock * existingBlock, bool after = true);
+
+ /**
+ * Remove a TextBlock object from m_textblockVector List
+ * returns boolean - true if successful
+ */
+ bool removeTextBlock ( TextBlock * remove_object );
+
+ /**
+ * @param text
+ */
+ void setStartText ( const QString &text );
+
+ /**
+ * @return QString
+ */
+ QString getStartText ( );
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root );
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root );
+
+ /**
+ * @return QString
+ */
+ virtual QString toString ( );
+
+ // return a unique, and currently unallocated, text block tag for this hblock
+ QString getUniqueTag();
+ QString getUniqueTag( const QString& prefix );
+
+ /**
+ * Utility method to add accessormethods in this object
+ */
+ void addCodeClassFieldMethods ( CodeClassFieldList &list );
+
+ virtual CodeBlock * newCodeBlock();
+ virtual CodeBlockWithComments * newCodeBlockWithComments();
+ virtual HierarchicalCodeBlock * newHierarchicalCodeBlock();
+
+protected:
+
+ /** causes the text block to release all of its connections
+ * and any other text blocks that it 'owns'.
+ * needed to be called prior to deletion of the textblock.
+ */
+ virtual void release ();
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode (QDomDocument & doc, QDomElement & elem );
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+ // look for specific text blocks which belong to code classfields
+ TextBlock * findCodeClassFieldTextBlockByTag ( const QString &tag );
+
+private:
+
+ QString m_startText;
+ QString m_endText;
+
+ QString childTextBlocksToString();
+ void initAttributes ( ) ;
+
+};
+
+#endif // HIERARCHICALCODEBLOCK_H
diff --git a/umbrello/umbrello/hisc-app-umbrello.svgz b/umbrello/umbrello/hisc-app-umbrello.svgz
new file mode 100644
index 00000000..27b89716
--- /dev/null
+++ b/umbrello/umbrello/hisc-app-umbrello.svgz
Binary files differ
diff --git a/umbrello/umbrello/import_rose.cpp b/umbrello/umbrello/import_rose.cpp
new file mode 100644
index 00000000..aeaeb7fb
--- /dev/null
+++ b/umbrello/umbrello/import_rose.cpp
@@ -0,0 +1,391 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "import_rose.h"
+
+// qt includes
+#include <qstring.h>
+#include <qtextstream.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qmessagebox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kdebug.h>
+// app includes
+#include "petalnode.h"
+#include "petaltree2uml.h"
+#include "umlnamespace.h" // only for the KDE4 compatibility macros
+
+namespace Import_Rose {
+
+typedef QPtrList<PetalNode> PetalNodeList;
+
+uint nClosures; // Multiple closing parentheses may appear on a single
+ // line. The parsing is done line-by-line and using
+ // recursive descent. This means that we can only handle
+ // _one_ closing parenthesis at a time, i.e. the closing
+ // of the currently parsed node. Since we may see more
+ // closing parentheses than we can handle, we need a
+ // counter indicating how many additional node closings
+ // have been seen.
+
+uint linum; // line number
+QString g_methodName;
+void methodName(const QString& m) {
+ g_methodName = m;
+}
+/**
+ * Auxiliary function for diagnostics: Return current location.
+ */
+QString loc() {
+ return "Import_Rose::" + g_methodName + " line " + QString::number(linum) + ": ";
+}
+
+/**
+ * Split a line into lexemes.
+ */
+QStringList scan(const QString& lin) {
+ QStringList result;
+ QString line = lin.stripWhiteSpace();
+ if (line.isEmpty())
+ return result; // empty
+ QString lexeme;
+ const uint len = line.length();
+ bool inString = false;
+ for (uint i = 0; i < len; i++) {
+ QChar c = line[i];
+ if (c == '"') {
+ lexeme += c;
+ if (inString) {
+ result.append(lexeme);
+ lexeme = QString();
+ }
+ inString = !inString;
+ } else if (inString ||
+ c.isLetterOrNumber() || c == '_' || c == '@') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ result.append(lexeme);
+ lexeme = QString();
+ }
+ if (! c.isSpace()) {
+ result.append(QString(c));
+ }
+ }
+ }
+ if (!lexeme.isEmpty())
+ result.append(lexeme);
+ return result;
+}
+
+/**
+ * Emulate perl shift().
+ */
+QString shift(QStringList& l) {
+ QString first = l.first();
+ l.pop_front();
+ return first;
+}
+
+/**
+ * Check for closing of one or more scopes.
+ */
+bool checkClosing(QStringList& tokens) {
+ if (tokens.count() == 0)
+ return false;
+ if (tokens.last() == ")") {
+ // For a single closing parenthesis, we just return true.
+ // But if there are more closing parentheses, we need to increment
+ // nClosures for each scope.
+ tokens.pop_back();
+ while (tokens.count() && tokens.last() == ")") {
+ nClosures++;
+ tokens.pop_back();
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Immediate values are numbers or quoted strings.
+ * @return True if the given text is a natural or negative number
+ * or a quoted string.
+ */
+bool isImmediateValue(QString s) {
+ return s.contains(QRegExp("^[\\d\\-\"]"));
+}
+
+/**
+ * Extract immediate values out of `l'.
+ * Examples of immediate value lists:
+ * number list: ( 123 , 456 )
+ * string list: ( "SomeText" 888 )
+ * Any enclosing parentheses are removed.
+ * All extracted items are also removed from `l'.
+ * For the example given above the following is returned:
+ * "123 456"
+ * or
+ * "\"SomeText\" 888"
+ */
+QString extractImmediateValues(QStringList& l) {
+ if (l.count() == 0)
+ return QString();
+ if (l.first() == "(")
+ l.pop_front();
+ QString result;
+ bool start = true;
+ while (l.count() && isImmediateValue(l.first())) {
+ if (start)
+ start = false;
+ else
+ result += ' ';
+ result += shift(l);
+ if (l.first() == ",")
+ l.pop_front();
+ }
+ if (l.first() == ")")
+ l.pop_front();
+ while (l.count() && l.first() == ")") {
+ nClosures++;
+ l.pop_front();
+ }
+ return result;
+}
+
+QString collectVerbatimText(QTextStream& stream) {
+ QString result;
+ QString line;
+ methodName("collectVerbatimText");
+ while (!(line = stream.readLine()).isNull()) {
+ linum++;
+ line = line.stripWhiteSpace();
+ if (line.isEmpty() || line.startsWith(")"))
+ break;
+ if (line[0] != '|') {
+ kError() << loc() << "expecting '|' at start of verbatim text" << endl;
+ return QString();
+ } else {
+ result += line.mid(1) + '\n';
+ }
+ }
+ if (line.isNull()) {
+ kError() << loc() << "premature EOF" << endl;
+ return QString();
+ }
+ if (! line.isEmpty()) {
+ for (uint i = 0; i < line.length(); i++) {
+ const QChar& clParenth = line[i];
+ if (clParenth != ')') {
+ kError() << loc() << "expected ')', found: " << clParenth << endl;
+ return QString();
+ }
+ nClosures++;
+ }
+ }
+ return result;
+}
+
+/**
+ * Extract the stripped down value from a (value ...) element.
+ * Example: for the input
+ * (value Text "This is some text")
+ * the following is extracted:
+ * "This is some text"
+ * Extracted elements and syntactic sugar of the value element are
+ * removed from the input list.
+ * The stream is passed into this method because it may be necessary
+ * to read new lines - in the case of verbatim text.
+ * The format of verbatim text in petal files is as follows:
+ *
+ * (value Text
+ * |This is the first line of verbatim text.
+ * |This is another line of verbatim text.
+ * )
+ * (The '|' character is supposed to be in the first column of the line)
+ * In this case the two lines are extracted without the leading '|'.
+ * The line ending '\n' of each line is preserved.
+ */
+QString extractValue(QStringList& l, QTextStream& stream) {
+ methodName("extractValue");
+ if (l.count() == 0)
+ return QString();
+ if (l.first() == "(")
+ l.pop_front();
+ if (l.first() != "value")
+ return QString();
+ l.pop_front(); // remove "value"
+ l.pop_front(); // remove the value type: could be e.g. "Text" or "cardinality"
+ QString result;
+ if (l.count() == 0) { // expect verbatim text to follow on subsequent lines
+ QString text = collectVerbatimText(stream);
+ nClosures--; // expect own closure
+ return text;
+ } else {
+ result = shift(l);
+ if (l.first() != ")") {
+ kError() << loc() << "expecting closing parenthesis" << endl;
+ return result;
+ }
+ l.pop_front();
+ }
+ while (l.count() && l.first() == ")") {
+ nClosures++;
+ l.pop_front();
+ }
+ return result;
+}
+
+/**
+ * Read attributes of a node.
+ * @param initialArgs Tokens on the line of the opening "(" of the node
+ * but with leading whitespace and the opening "(" removed.
+ * @param stream The QTextStream from which to read following lines.
+ * @return Pointer to the created PetalNode or NULL on error.
+ */
+PetalNode *readAttributes(QStringList initialArgs, QTextStream& stream) {
+ methodName("readAttributes");
+ if (initialArgs.count() == 0) {
+ kError() << loc() << "initialArgs is empty" << endl;
+ return NULL;
+ }
+ PetalNode::NodeType nt;
+ QString type = shift(initialArgs);
+ if (type == "object")
+ nt = PetalNode::nt_object;
+ else if (type == "list")
+ nt = PetalNode::nt_list;
+ else {
+ kError() << loc() << "unknown node type " << type << endl;
+ return NULL;
+ }
+ PetalNode *node = new PetalNode(nt);
+ bool seenClosing = checkClosing(initialArgs);
+ node->setInitialArgs(initialArgs);
+ if (seenClosing)
+ return node;
+ PetalNode::NameValueList attrs;
+ QString line;
+ while (!(line = stream.readLine()).isNull()) {
+ linum++;
+ line = line.stripWhiteSpace();
+ if (line.isEmpty())
+ continue;
+ QStringList tokens = scan(line);
+ QString stringOrNodeOpener = shift(tokens);
+ QString name;
+ if (nt == PetalNode::nt_object && !stringOrNodeOpener.contains(QRegExp("^[A-Za-z]"))) {
+ kError() << loc() << "unexpected line " << line << endl;
+ return NULL;
+ }
+ PetalNode::StringOrNode value;
+ if (nt == PetalNode::nt_object) {
+ name = stringOrNodeOpener;
+ if (tokens.count() == 0) { // expect verbatim text to follow on subsequent lines
+ value.string = collectVerbatimText(stream);
+ PetalNode::NameValue attr(name, value);
+ attrs.append(attr);
+ if (nClosures) {
+ // Decrement nClosures exactly once, namely for the own scope.
+ // Each recursion of readAttributes() is only responsible for
+ // its own scope. I.e. each further scope closing is handled by
+ // an outer recursion in case of multiple closing parentheses.
+ nClosures--;
+ break;
+ }
+ continue;
+ }
+ stringOrNodeOpener = shift(tokens);
+ } else if (stringOrNodeOpener != "(") {
+ value.string = stringOrNodeOpener;
+ PetalNode::NameValue attr;
+ attr.second = value;
+ attrs.append(attr);
+ if (tokens.count() && tokens.first() != ")") {
+ kDebug() << loc()
+ << "NYI - immediate list entry with more than one item" << endl;
+ }
+ if (checkClosing(tokens))
+ break;
+ continue;
+ }
+ if (stringOrNodeOpener == "(") {
+ QString nxt = tokens.first();
+ if (isImmediateValue(nxt)) {
+ value.string = extractImmediateValues(tokens);
+ } else if (nxt == "value" || nxt.startsWith("\"")) {
+ value.string = extractValue(tokens, stream);
+ } else {
+ kapp->processEvents();
+ value.node = readAttributes(tokens, stream);
+ if (value.node == NULL)
+ return NULL;
+ }
+ PetalNode::NameValue attr(name, value);
+ attrs.append(attr);
+ if (nClosures) {
+ // Decrement nClosures exactly once, namely for the own scope.
+ // Each recursion of readAttributes() is only responsible for
+ // its own scope. I.e. each further scope closing is handled by
+ // an outer recursion in case of multiple closing parentheses.
+ nClosures--;
+ break;
+ }
+ } else {
+ value.string = stringOrNodeOpener;
+ bool seenClosing = checkClosing(tokens);
+ PetalNode::NameValue attr(name, value);
+ attrs.append(attr);
+ if (seenClosing) {
+ break;
+ }
+ }
+ }
+ node->setAttributes(attrs);
+ return node;
+}
+
+bool loadFromMDL(QIODevice& file) {
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::Latin1);
+ QString line;
+ PetalNode *root = NULL;
+ linum = 0;
+ while (!(line = stream.readLine()).isNull()) {
+ linum++;
+ if (line.contains( QRegExp("^\\s*\\(object Petal") )) {
+ while (!(line = stream.readLine()).isNull() && !line.contains(')')) {
+ linum++; // CHECK: do we need petal version info?
+ }
+ if (line.isNull())
+ break;
+ } else {
+ QRegExp objectRx("^\\s*\\(object ");
+ if (line.contains(objectRx)) {
+ nClosures = 0;
+ QStringList initialArgs = scan(line);
+ initialArgs.pop_front(); // remove opening parenthesis
+ root = readAttributes(initialArgs, stream);
+ }
+ }
+ }
+ file.close();
+ if (root == NULL)
+ return false;
+ return petalTree2Uml(root);
+}
+
+}
+
diff --git a/umbrello/umbrello/import_rose.h b/umbrello/umbrello/import_rose.h
new file mode 100644
index 00000000..b5090db3
--- /dev/null
+++ b/umbrello/umbrello/import_rose.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IMPORT_ROSE__H
+#define IMPORT_ROSE__H
+
+#include <qiodevice.h>
+
+/**
+ * Rose model import
+ *
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Import_Rose {
+
+ /**
+ * Parse a file into the PetalNode internal tree representation
+ * and then create Umbrello objects by traversing the tree.
+ *
+ * @return True for success, false in case of error.
+ */
+ bool loadFromMDL(QIODevice & file);
+
+}
+
+#endif
diff --git a/umbrello/umbrello/kplayerslideraction.cpp b/umbrello/umbrello/kplayerslideraction.cpp
new file mode 100644
index 00000000..ae5c3f97
--- /dev/null
+++ b/umbrello/umbrello/kplayerslideraction.cpp
@@ -0,0 +1,412 @@
+/***************************************************************************
+ begin : Sat Jan 11 2003
+ copyright : (C) 2003 by kiriuja
+ email : kplayer-dev@en-directo.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* Taken from kplayer CVS 2003-09-21 (kplayer > 0.3.1) by Jonathan Riddell
+ * Changes from kplayer original marked by CHANGED
+ */
+
+#include <kapplication.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <kdebug.h>
+
+//CHANGED #include "kplayersettings.h"
+#include "kplayerslideraction.h"
+#include "kplayerslideraction.moc"
+
+void KPlayerPopupFrame::keyPressEvent (QKeyEvent* ev)
+{
+ switch ( ev -> key() )
+ {
+ case Qt::Key_Alt:
+ case Qt::Key_Tab:
+ case Qt::Key_Escape:
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ close();
+ }
+}
+
+/*void KPlayerPopupFrame::closeEvent (QCloseEvent* ev)
+{
+ QFrame::closeEvent (ev);
+}
+
+void KPlayerPopupFrame::mousePressEvent (QMouseEvent* ev)
+{
+ QFrame::mousePressEvent (ev);
+//if ( ! rect().contains (ev -> pos()) )
+// m_outside_mouse_press = true;
+}
+
+void KPlayerPopupFrame::mouseReleaseEvent (QMouseEvent* ev)
+{
+ QFrame::mouseReleaseEvent (ev);
+ if ( m_outside_mouse_press )
+ {
+ m_outside_mouse_press = false;
+ if ( ! rect().contains (ev -> pos()) )
+ close();
+ }
+}*/
+
+KPlayerPopupSliderAction::KPlayerPopupSliderAction (const QString& text,
+ const QString& pix, const KShortcut& shortcut, const QObject* receiver,
+ const char* slot, QObject* parent, const char* name)
+ : KAction (text, pix, shortcut, parent, name)
+{
+ m_frame = new KPlayerPopupFrame;
+ m_frame -> setFrameStyle (QFrame::PopupPanel | QFrame::Raised);
+ m_frame -> setLineWidth (2);
+ m_slider = new KPlayerSlider (Qt::Vertical, m_frame);
+ m_frame -> resize (36, m_slider -> sizeHint().height() + 4);
+ m_slider -> setGeometry (m_frame -> contentsRect());
+ //CHANGED kdDebug() << "Popup slider size " << m_slider -> width() << "x" << m_slider -> height() << "\n";
+ connect (m_slider, SIGNAL (changed (int)), receiver, slot);
+}
+
+KPlayerPopupSliderAction::~KPlayerPopupSliderAction()
+{
+ delete m_frame;
+ m_frame = 0;
+}
+
+/*int KPlayerPopupSliderAction::plug (QWidget* widget, int index)
+{
+ Q_ASSERT (m_slider);
+ Q_ASSERT (widget);
+ Q_ASSERT (! isPlugged());
+ if ( ! m_slider || ! widget || isPlugged() )
+ return -1;
+ Q_ASSERT (widget -> inherits ("KToolBar"));
+ if ( ! widget -> inherits ("KToolBar") )
+ return -1;
+ int retval = KAction::plug (widget, index);
+// if ( retval >= 0 )
+// m_slider -> reparent (widget, QPoint());
+ return retval;
+}
+
+void KPlayerPopupSliderAction::unplug (QWidget* widget)
+{
+ Q_ASSERT (m_slider);
+ Q_ASSERT (widget);
+ Q_ASSERT (isPlugged());
+ Q_ASSERT (widget -> inherits ("KToolBar"));
+ if ( ! m_slider || ! widget || ! isPlugged() || ! widget -> inherits ("KToolBar") )
+ return;
+//m_slider -> reparent (0, QPoint());
+ KAction::unplug (widget);
+}*/
+
+void KPlayerPopupSliderAction::slotActivated (void)
+{
+ KAction::slotActivated();
+ QWidget* button = 0;
+ if ( sender() )
+ {
+ //CHANGED kdDebug() << "Sender class name: " << sender() -> className() << "\n";
+ if ( sender() -> inherits ("KToolBarButton") )
+ button = (QWidget*) sender();
+ else if ( sender() -> inherits ("KToolBar") )
+ {
+ KToolBar* toolbar = (KToolBar*) sender();
+ int index = findContainer (toolbar);
+ if ( index >= 0 )
+ button = toolbar -> getButton (itemId (index));
+ }
+ }
+ QPoint point;
+ if ( button )
+ point = button -> mapToGlobal (QPoint (0, button -> height()));
+ else
+ {
+ point = QCursor::pos() - QPoint (m_frame -> width() / 2, m_frame -> height() / 2);
+ if ( point.x() + m_frame -> width() > QApplication::desktop() -> width() )
+ point.setX (QApplication::desktop() -> width() - m_frame -> width());
+ if ( point.y() + m_frame -> height() > QApplication::desktop() -> height() )
+ point.setY (QApplication::desktop() -> height() - m_frame -> height());
+ if ( point.x() < 0 )
+ point.setX (0);
+ if ( point.y() < 0 )
+ point.setY (0);
+ }
+ //CHANGED kdDebug() << "Point: " << point.x() << "x" << point.y() << "\n";
+ m_frame -> move (point);
+ /*if ( kapp && kapp -> activeWindow() )
+ {
+ QMouseEvent me (QEvent::MouseButtonRelease, QPoint(0,0), QPoint(0,0), QMouseEvent::LeftButton, QMouseEvent::NoButton);
+ QApplication::sendEvent (kapp -> activeWindow(), &me);
+ }*/
+ m_frame -> show();
+ m_slider -> setFocus();
+}
+
+KPlayerSliderAction::KPlayerSliderAction (const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, KActionCollection* parent, const char* name)
+ : KWidgetAction (new KPlayerSlider (Qt::Horizontal, 0, name), text, cut, receiver, slot, parent, name)
+ //: KAction (text, 0, parent, name)
+{
+ setAutoSized (true);
+ connect (slider(), SIGNAL (changed (int)), receiver, slot);
+}
+
+KPlayerSliderAction::~KPlayerSliderAction()
+{
+}
+
+int KPlayerSliderAction::plug (QWidget* widget, int index)
+{
+ //Q_ASSERT (widget);
+ //Q_ASSERT (! isPlugged());
+ //Q_ASSERT (slider());
+ //if ( ! slider() || ! widget || isPlugged() )
+ // return -1;
+ //Q_ASSERT (widget -> inherits ("KToolBar"));
+ //if ( ! widget -> inherits ("KToolBar") )
+ // return -1;
+ //if ( kapp && ! kapp -> authorizeKAction (name()) )
+ // return -1;
+ int result = KWidgetAction::plug (widget, index);
+ if ( result < 0 )
+ return result;
+ KToolBar* toolbar = (KToolBar*) widget;
+ //int id = getToolButtonID();
+ //kdDebug() << "Orientation: " << toolbar -> orientation() << "\n";
+ //m_slider -> reparent (toolbar, QPoint());
+ //toolbar -> insertWidget (id, 0, m_slider, index);
+ //toolbar -> setItemAutoSized (id, true);
+ //QWhatsThis::remove (m_slider);
+ //if ( ! whatsThis().isEmpty() )
+ // QWhatsThis::add (m_slider, whatsThis());
+ //if ( ! text().isEmpty() )
+ // QToolTip::add (m_slider, text());
+ //addContainer (toolbar, id);
+ //setupToolbar (toolbar -> orientation(), toolbar);
+ orientationChanged (toolbar -> orientation());
+ connect (toolbar, SIGNAL (orientationChanged (Orientation)), this, SLOT (orientationChanged (Orientation)));
+ //connect (toolbar, SIGNAL (destroyed()), this, SLOT (toolbarDestroyed()));
+ //if ( parentCollection() )
+ // parentCollection() -> connectHighlight (toolbar, this);
+ //return containerCount() - 1;
+ return result;
+}
+
+void KPlayerSliderAction::unplug (QWidget* widget)
+{
+ //Q_ASSERT (m_slider);
+ //Q_ASSERT (isPlugged());
+ //Q_ASSERT (widget -> inherits ("KToolBar"));
+ KWidgetAction::unplug (widget);
+ if ( ! slider() || ! isPlugged() || widget != slider() -> parent() )
+ return;
+ //KToolBar* toolbar = (KToolBar*) widget;
+ disconnect (widget, SIGNAL (orientationChanged (Orientation)), this, SLOT (orientationChanged (Orientation)));
+ //disconnect (toolbar, SIGNAL (destroyed()), this, SLOT (toolbarDestroyed()));
+ //m_slider -> reparent (0, QPoint());
+ /*int index = findContainer (toolbar);
+ if ( index == -1 )
+ return;
+ bar -> removeItem (menuId (index));
+ removeContainer (index);*/
+}
+
+/*void KPlayerSliderAction::setupToolbar (Orientation orientation, KToolBar* toolbar)
+{
+ if ( orientation == Qt::Horizontal )
+ {
+// toolbar -> setMinimumWidth (300);
+// toolbar -> setMinimumHeight (0);
+ toolbar -> setFixedExtentWidth (300);
+ toolbar -> setFixedExtentHeight (-1);
+// toolbar -> setHorizontallyStretchable (true);
+// toolbar -> setVerticallyStretchable (false);
+ }
+ else
+ {
+// toolbar -> setMinimumWidth (0);
+// toolbar -> setMinimumHeight (300);
+ toolbar -> setFixedExtentWidth (-1);
+ toolbar -> setFixedExtentHeight (300);
+// toolbar -> setHorizontallyStretchable (false);
+// toolbar -> setVerticallyStretchable (true);
+ }
+}*/
+
+void KPlayerSliderAction::orientationChanged (Qt::Orientation orientation)
+{
+ //if ( sender() && sender() -> inherits ("KToolBar") )
+ // setupToolbar (orientation, (KToolBar*) sender());
+ //Q_ASSERT (m_slider);
+ //Q_ASSERT (isPlugged());
+ if ( slider() )
+ slider() -> setOrientation (orientation);
+}
+
+/*void KPlayerSliderAction::toolbarDestroyed (void)
+{
+ if ( m_slider )
+ m_slider -> reparent (0, QPoint());
+}*/
+
+KPlayerSlider::KPlayerSlider (Qt::Orientation orientation, QWidget* parent, const char* name)
+//CHANGED : QSlider (orientation, parent, name)
+ : QSlider (300, 2200, 400, 1000, orientation, parent, name)
+{
+ m_changing_orientation = false;
+ setTickmarks (QSlider::Both);
+ connect (this, SIGNAL (valueChanged (int)), this, SLOT (sliderValueChanged (int)));
+}
+
+KPlayerSlider::~KPlayerSlider()
+{
+ //CHANGED kdDebug() << "KPlayerSlider destroyed\n";
+}
+
+QSize KPlayerSlider::sizeHint() const
+{
+ QSize hint = QSlider::sizeHint();
+ //CHANGED int length = kPlayerSettings() -> preferredSliderLength();
+ int length = 200;
+ if ( orientation() == Qt::Horizontal )
+ {
+ if ( hint.width() < length )
+ hint.setWidth (length);
+ }
+ else
+ {
+ if ( hint.height() < length )
+ hint.setHeight (length);
+ }
+ return hint;
+}
+
+QSize KPlayerSlider::minimumSizeHint() const
+{
+ //kdDebug() << "KPlayerSlider minimum size hint\n";
+ QSize hint = QSlider::minimumSizeHint();
+ //CHANGED int length = kPlayerSettings() -> minimumSliderLength();
+ int length = 200;
+ if ( orientation() == Qt::Horizontal )
+ {
+ if ( hint.width() < length )
+ hint.setWidth (length);
+ }
+ else
+ {
+ if ( hint.height() < length )
+ hint.setHeight (length);
+ }
+ return hint;
+}
+
+void KPlayerSlider::setOrientation (Qt::Orientation o)
+{
+ if ( o == orientation() )
+ return;
+ m_changing_orientation = true;
+ int minValue = QSlider::minValue();
+ int maxValue = QSlider::maxValue();
+ int value = QSlider::value();
+ QSlider::setOrientation (o);
+ QSlider::setMinValue (- maxValue);
+ QSlider::setMaxValue (- minValue);
+ QSlider::setValue (- value);
+ m_changing_orientation = false;
+}
+
+int KPlayerSlider::minValue (void) const
+{
+ if ( orientation() == Qt::Horizontal )
+ return QSlider::minValue();
+ return - QSlider::maxValue();
+}
+
+void KPlayerSlider::setMinValue (int minValue)
+{
+ if ( orientation() == Qt::Horizontal )
+ QSlider::setMinValue (minValue);
+ else
+ QSlider::setMaxValue (- minValue);
+}
+
+int KPlayerSlider::maxValue (void) const
+{
+ if ( orientation() == Qt::Horizontal )
+ return QSlider::maxValue();
+ return - QSlider::minValue();
+}
+
+void KPlayerSlider::setMaxValue (int maxValue)
+{
+ if ( orientation() == Qt::Horizontal )
+ QSlider::setMaxValue (maxValue);
+ else
+ QSlider::setMinValue (- maxValue);
+}
+
+int KPlayerSlider::lineStep (void) const
+{
+ return QSlider::lineStep();
+}
+
+void KPlayerSlider::setLineStep (int lineStep)
+{
+ QSlider::setLineStep (lineStep);
+}
+
+int KPlayerSlider::pageStep (void) const
+{
+ return QSlider::pageStep();
+}
+
+void KPlayerSlider::setPageStep (int pageStep)
+{
+ QSlider::setPageStep (pageStep);
+ setTickInterval (pageStep);
+}
+
+int KPlayerSlider::value (void) const
+{
+ if ( orientation() == Qt::Horizontal )
+ return QSlider::value();
+ return - QSlider::value();
+}
+
+void KPlayerSlider::setValue (int value, int)
+{
+ if ( orientation() == Qt::Horizontal )
+ QSlider::setValue (value);
+ else
+ QSlider::setValue (- value);
+}
+
+void KPlayerSlider::setup (int minValue, int maxValue, int value, int pageStep, int lineStep)
+{
+ setMinValue (minValue);
+ setMaxValue (maxValue);
+ setLineStep (lineStep);
+ setPageStep (pageStep);
+ setValue (value);
+}
+
+void KPlayerSlider::sliderValueChanged (int)
+{
+ if ( ! m_changing_orientation )
+ emit changed (value());
+}
diff --git a/umbrello/umbrello/kplayerslideraction.h b/umbrello/umbrello/kplayerslideraction.h
new file mode 100644
index 00000000..e8bb6ff9
--- /dev/null
+++ b/umbrello/umbrello/kplayerslideraction.h
@@ -0,0 +1,202 @@
+/***************************************************************************
+ kplayerslideraction.h
+ ---------------------
+ begin : Sat Jan 11 2003
+ copyright : (C) 2003 by kiriuja
+ email : kplayer-dev@en-directo.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef KPLAYERSLIDERACTION_H
+#define KPLAYERSLIDERACTION_H
+
+#include <kaction.h>
+#include <qslider.h>
+
+/**KPlayer's slider widget. Works around the Qt upside-down slider bug.
+ * Taken from kplayer CVS 2003-09-21 (kplayer > 0.3.1) by Jonathan Riddell
+ *@author kiriuja
+ */
+class KPlayerSlider : public QSlider
+{
+ Q_OBJECT
+
+public:
+ /** The KPlayerSlider constructor. Parameters are passed on to QSlider.
+ */
+ explicit KPlayerSlider (Qt::Orientation, QWidget* parent = 0, const char* name = 0);
+ /** The KPlayerSlider destructor. Does nothing.
+ */
+ virtual ~KPlayerSlider();
+
+ /** The size hint.
+ */
+ virtual QSize sizeHint() const;
+ /** The minimum size hint.
+ */
+ virtual QSize minimumSizeHint() const;
+
+ /** The minimum value.
+ */
+ int minValue (void) const;
+ /** Sets the minimum value.
+ */
+ void setMinValue (int);
+ /** The maximum value.
+ */
+ int maxValue (void) const;
+ /** Sets the maximum value.
+ */
+ void setMaxValue (int);
+ /** The line step.
+ */
+ int lineStep (void) const;
+ /** Sets the line step.
+ */
+ void setLineStep (int);
+ /** The page step.
+ */
+ int pageStep (void) const;
+ /** Sets the page step.
+ */
+ void setPageStep (int);
+ /** The current value.
+ */
+ int value (void) const;
+ /** Sets the current value. The extra parameter prevents overriding of the virtual QSlider::setValue.
+ */
+ void setValue (int, int = 0); // do not override the virtual setValue
+
+ /** Sets up the slider by setting five options in one go.
+ */
+ void setup (int minValue, int maxValue, int value, int pageStep, int lineStep = 1);
+ /** Sets the slider orientation.
+ */
+ virtual void setOrientation (Qt::Orientation);
+
+signals:
+ /** Emitted when the slider value changes.
+ */
+ void changed (int);
+
+protected slots:
+ /** Receives the valueChanged signal from QSlider.
+ */
+ void sliderValueChanged (int);
+
+protected:
+ // Recursion prevention. Should be private.
+ bool m_changing_orientation;
+
+ friend class KPlayerSliderAction;
+ friend class KPlayerPopupSliderAction;
+};
+
+/**KPlayer popup frame.
+ *@author kiriuja
+ */
+class KPlayerPopupFrame : public QFrame
+{
+ Q_OBJECT
+
+public:
+ /** The KPlayerPopupFrame constructor. Parameters are passed on to QFrame.
+ */
+ KPlayerPopupFrame (QWidget* parent = 0, const char* name = 0)
+ : QFrame (parent, name, Qt::WType_Popup) { }
+ /** The KPlayerPopupFrame destructor. Does nothing.
+ */
+ virtual ~KPlayerPopupFrame() { }
+
+protected:
+ /** Closes the popup frame when Alt, Tab, Esc, Enter or Return is pressed.
+ */
+ virtual void keyPressEvent (QKeyEvent*);
+};
+
+/**Action representing a popup slider activated by a toolbar button.
+ *@author kiriuja
+ */
+class KPlayerPopupSliderAction : public KAction
+{
+ Q_OBJECT
+
+public:
+ /** The KPlayerPopupSliderAction constructor. Parameters are passed on to KAction.
+ */
+ KPlayerPopupSliderAction (const QString& text, const QString& pix, const KShortcut& shortcut,
+ const QObject* receiver, const char* slot, QObject* parent = 0, const char* name = 0);
+ /** The KPlayerPopupSliderAction destructor. Deletes the KPlayerPopupFrame.
+ */
+ virtual ~KPlayerPopupSliderAction();
+
+ /** Returns a pointer to the KPlayerSlider object.
+ */
+ KPlayerSlider* slider (void)
+ { return m_slider; }
+
+ /** Plugs the action into the toolbar. Reparents the slider into the toolbar. */
+ //virtual int plug (QWidget*, int = -1);
+ /** Unplugs the action from the toolbar. Reparents the slider out of the toolbar. */
+ //virtual void unplug (QWidget*);
+
+protected slots:
+ /** Pops up the slider.
+ */
+ virtual void slotActivated (void);
+
+protected:
+ /** The slider.
+ */
+ KPlayerSlider* m_slider;
+ /** The popup frame.
+ */
+ KPlayerPopupFrame* m_frame;
+};
+
+/**Slider action suitable for insertion into a toolbar.
+ *@author kiriuja
+ */
+class KPlayerSliderAction : public KWidgetAction
+{
+ Q_OBJECT
+
+public:
+ /** The KPlayerSliderAction constructor. Parameters are passed on to KAction.
+ */
+ KPlayerSliderAction (const QString& text, const KShortcut&, const QObject* receiver,
+ const char* slot, KActionCollection* parent = 0, const char* name = 0);
+ /** The KPlayerSliderAction destructor. Does nothing.
+ */
+ virtual ~KPlayerSliderAction();
+
+ /** Returns a pointer to the KPlayerSlider object.
+ */
+ KPlayerSlider* slider (void)
+ { return (KPlayerSlider*) widget(); }
+
+ /** Plugs the slider into the toolbar.
+ */
+ virtual int plug (QWidget* widget, int index = -1);
+ /** Unplugs the slider from the toolbar.
+ */
+ virtual void unplug (QWidget* widget);
+
+protected slots:
+ /** Changes the slider orientation when the toolbar orientation changes.
+ */
+ void orientationChanged (Qt::Orientation);
+
+protected:
+ /** The slider.
+ */
+ //KPlayerSlider* m_slider;
+};
+
+#endif
diff --git a/umbrello/umbrello/kstartuplogo.cpp b/umbrello/umbrello/kstartuplogo.cpp
new file mode 100644
index 00000000..5cefe463
--- /dev/null
+++ b/umbrello/umbrello/kstartuplogo.cpp
@@ -0,0 +1,55 @@
+/*
+ * copyright (C) 2000
+ * Michael Edwardes <mte @users.sourceforge.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "kstartuplogo.h"
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <qtimer.h>
+
+KStartupLogo::KStartupLogo(QWidget * parent, const char *name)
+ : QWidget(parent,name, Qt::WStyle_NoBorder | Qt::WStyle_Customize | Qt::WDestructiveClose )
+,m_bReadyToHide(false) {
+ //pm.load(locate("appdata", "pics/startlogo.png"));
+ KStandardDirs * dirs = KGlobal::dirs();
+ QString dataDir = dirs -> findResourceDir("data", "umbrello/pics/object.png");
+ dataDir += "/umbrello/pics/";
+ QPixmap pm(dataDir + "startlogo.png");
+ setBackgroundPixmap(pm);
+ setGeometry(QApplication::desktop()->width()/2-pm.width()/2,
+ QApplication::desktop()->height()/2-pm.height()/2,
+ pm.width(),pm.height());
+
+ timer = new QTimer(this);
+ connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
+ timer->start(2000, true);
+}
+
+KStartupLogo::~KStartupLogo() {
+ delete timer;
+}
+
+void KStartupLogo::mousePressEvent( QMouseEvent*) {
+ // for the haters of raising startlogos
+ if (m_bReadyToHide)
+ hide();
+}
+
+void KStartupLogo::timerDone() {
+ this->hide();
+}
+
+void KStartupLogo::setHideEnabled(bool bEnabled) {
+ m_bReadyToHide = bEnabled;
+}
+#include "kstartuplogo.moc"
diff --git a/umbrello/umbrello/kstartuplogo.h b/umbrello/umbrello/kstartuplogo.h
new file mode 100644
index 00000000..d8f4af7a
--- /dev/null
+++ b/umbrello/umbrello/kstartuplogo.h
@@ -0,0 +1,49 @@
+/*
+ * copyright (C) 2000
+ * Michael Edwardes <mte @users.sourceforge.net>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KSTARTUPLOGO_H
+#define KSTARTUPLOGO_H
+
+#include <qwidget.h>
+
+
+/**
+ * Displays a startup splash screen.
+ * This class is mostly borrowed from another project, probably KMyMoney2.
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class KStartupLogo : public QWidget {
+ Q_OBJECT
+public:
+ KStartupLogo(QWidget *parent=0, const char *name=0);
+ ~KStartupLogo();
+ void setHideEnabled(bool bEnabled);
+
+protected:
+ virtual void mousePressEvent( QMouseEvent*);
+ bool m_bReadyToHide;
+ QTimer* timer;
+
+public slots:
+ void timerDone();
+
+};
+
+#endif
+
+
+
+
+
diff --git a/umbrello/umbrello/linepath.cpp b/umbrello/umbrello/linepath.cpp
new file mode 100644
index 00000000..59cf105f
--- /dev/null
+++ b/umbrello/umbrello/linepath.cpp
@@ -0,0 +1,957 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "linepath.h"
+
+// system includes
+#include <cstdlib>
+#include <cmath>
+
+// qt includes
+#include <qcanvas.h>
+#include <qdatastream.h>
+#include <qdom.h>
+
+// kde includes
+#include <kdebug.h>
+
+// application includes
+#include "associationwidget.h"
+#include "activitywidget.h"
+#include "widget_utils.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+
+LinePath::Circle::Circle(QCanvas * canvas, int radius /* = 0 */)
+ : QCanvasEllipse(radius * 2, radius * 2, canvas) {
+}
+
+void LinePath::Circle::setX(int x) {
+ QCanvasItem::setX( (double) x );
+}
+
+void LinePath::Circle::setY(int y) {
+ QCanvasItem::setY( (double) y );
+}
+
+void LinePath::Circle::setRadius(int radius) {
+ QCanvasEllipse::setSize(radius * 2, radius * 2);
+}
+
+int LinePath::Circle::getRadius() const {
+ return (QCanvasEllipse::height() / 2);
+}
+
+void LinePath::Circle::drawShape(QPainter& p) {
+ int diameter = height();
+ int radius = diameter / 2;
+ p.drawEllipse( (int)x() - radius, (int)y() - radius, diameter, diameter);
+}
+
+LinePath::LinePath() {
+ m_RectList.setAutoDelete( true );
+ m_LineList.setAutoDelete( true );
+ m_HeadList.setAutoDelete( true );
+ m_ParallelList.setAutoDelete( true );
+ m_bSelected = false;
+ m_pClearPoly = 0;
+ m_pCircle = 0;
+ m_PointArray.resize( 4 );
+ m_ParallelLines.resize( 4 );
+ m_pAssociation = 0;
+ m_bHeadCreated = false;
+ m_bParallelLineCreated = false;
+ m_DockRegion = TopBottom;
+}
+
+LinePath::~LinePath() {}
+
+void LinePath::setAssociation(AssociationWidget * association ) {
+ if( !association )
+ return;
+ cleanup();
+ m_pAssociation = association;
+ createHeadLines();
+ if( getAssocType() == Uml::at_Coll_Message )
+ setupParallelLine();
+ UMLView * view = (UMLView *)m_pAssociation -> parent();
+ connect( view, SIGNAL( sigColorChanged( Uml::IDType ) ), this, SLOT( slotLineColorChanged( Uml::IDType ) ) );
+ connect( view, SIGNAL( sigLineWidthChanged( Uml::IDType ) ), this, SLOT( slotLineWidthChanged( Uml::IDType ) ) );
+}
+
+QPoint LinePath::getPoint( int pointIndex ) {
+ int count = m_LineList.count();
+ if( count == 0 || pointIndex > count || pointIndex < 0)
+ return QPoint( -1, -1 );
+
+ if( pointIndex == count ) {
+ QCanvasLine * line = m_LineList.last();
+ return line -> endPoint();
+ }
+ QCanvasLine * line = m_LineList.at( pointIndex );
+ return line -> startPoint();
+}
+
+bool LinePath::setPoint( int pointIndex, const QPoint &point ) {
+ int count = m_LineList.count();
+ if( count == 0 || pointIndex > count || pointIndex < 0)
+ return false;
+ if (point.x() == 0 && point.y() == 0) {
+ kError() << "LinePath::setPoint:ignoring request for (0,0)" << endl;
+ return false;
+ }
+
+ if( pointIndex == count) {
+ QCanvasLine * line = m_LineList.last();
+ QPoint p = line -> startPoint();
+ line -> setPoints( p.x(), p.y(), point.x(), point.y() );
+ moveSelected( pointIndex );
+ update();
+ return true;
+ }
+ if( pointIndex == 0 ) {
+ QCanvasLine * line = m_LineList.first();
+ QPoint p = line -> endPoint();
+ line -> setPoints( point.x(), point.y(), p.x(), p.y() );
+ moveSelected( pointIndex );
+ update();
+ return true;
+ }
+ QCanvasLine * line = m_LineList.at( pointIndex );
+ QPoint p = line -> endPoint();
+ line -> setPoints( point.x(), point.y(), p.x(), p.y() );
+ line = m_LineList.at( pointIndex - 1 );
+ p = line -> startPoint();
+ line -> setPoints( p.x(), p.y(), point.x(), point.y() );
+ moveSelected( pointIndex );
+ update();
+ return true;
+}
+
+bool LinePath::isPoint( int pointIndex, const QPoint &point, unsigned short delta) {
+ int count = m_LineList.count();
+ if ( pointIndex >= count )
+ return false;
+
+ QCanvasLine * line = m_LineList.at( pointIndex );
+
+ /* check if the given point is the start or end point of the line */
+ if ( (
+ abs( line -> endPoint().x() - point.x() ) <= delta
+ &&
+ abs( line -> endPoint().y() - point.y() ) <= delta
+ ) || (
+ abs( line -> startPoint().x() - point.x() ) <= delta
+ &&
+ abs( line -> startPoint().y() - point.y() ) <= delta
+ ) )
+ return true;
+
+ /* check if the given point is the start or end point of the line */
+ return false;
+}
+
+bool LinePath::insertPoint( int pointIndex, const QPoint &point ) {
+ int count = m_LineList.count();
+ if( count == 0 )
+ return false;
+ const bool bLoading = UMLApp::app()->getDocument()->loading();
+
+ if( count == 1 || pointIndex == 1) {
+ QCanvasLine * first = m_LineList.first();
+ QPoint sp = first -> startPoint();
+ QPoint ep = first -> endPoint();
+ first -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
+ QCanvasLine * line = new QCanvasLine( getCanvas() );
+ line -> setZ( -2 );
+ line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
+ line -> setPen( getPen() );
+ line -> setVisible( true );
+ m_LineList.insert( 1, line );
+ if (!bLoading)
+ setupSelected();
+ return true;
+ }
+ if( count + 1 == pointIndex ) {
+ QCanvasLine * before = m_LineList.last();
+ QPoint sp = before -> startPoint();
+ QPoint ep = before -> endPoint();
+ before -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
+ QCanvasLine * line = new QCanvasLine( getCanvas() );
+ line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
+ line -> setZ( -2 );
+ line -> setPen( getPen() );
+ line -> setVisible( true );
+ m_LineList.append( line );
+ if (!bLoading)
+ setupSelected();
+ return true;
+ }
+ QCanvasLine * before = m_LineList.at( pointIndex - 1 );
+ QPoint sp = before -> startPoint();
+ QPoint ep = before -> endPoint();
+ before -> setPoints( sp.x(), sp.y(), point.x(), point.y() );
+ QCanvasLine * line = new QCanvasLine(getCanvas() );
+ line -> setPoints( point.x(), point.y(), ep.x(), ep.y() );
+ line -> setZ( -2 );
+ line -> setPen( getPen() );
+ line -> setVisible( true );
+ m_LineList.insert( pointIndex, line );
+ if (!bLoading)
+ setupSelected();
+ return true;
+}
+
+bool LinePath::removePoint( int pointIndex, const QPoint &point, unsigned short delta )
+{
+ /* get the number of line segments */
+ int count = m_LineList.count();
+ if ( pointIndex >= count )
+ return false;
+
+ /* we don't know if the user clicked on the start- or endpoint of a
+ * line segment */
+ QCanvasLine * current_line = m_LineList.at( pointIndex );
+ if (abs( current_line -> endPoint().x() - point.x() ) <= delta
+ &&
+ abs( current_line -> endPoint().y() - point.y() ) <= delta)
+ {
+ /* the user clicked on the end point of the line;
+ * we have to make sure that this isn't the last line segment */
+ if (pointIndex >= count - 1)
+ return false;
+
+ /* the next segment will get the starting point from the current one,
+ * which is going to be removed */
+ QCanvasLine * next_line = m_LineList.at( pointIndex + 1 );
+ QPoint startPoint = current_line -> startPoint();
+ QPoint endPoint = next_line -> endPoint();
+ next_line -> setPoints(startPoint.x(), startPoint.y(),
+ endPoint.x(), endPoint.y());
+
+ } else
+ if (abs( current_line -> startPoint().x() - point.x() ) <= delta
+ &&
+ abs( current_line -> startPoint().y() - point.y() ) <= delta)
+ {
+ /* the user clicked on the start point of the line;
+ * we have to make sure that this isn't the first line segment */
+ if (pointIndex < 1)
+ return false;
+
+ /* the previous segment will get the end point from the current one,
+ * which is going to be removed */
+ QCanvasLine * previous_line = m_LineList.at( pointIndex - 1 );
+ QPoint startPoint = previous_line -> startPoint();
+ QPoint endPoint = current_line -> endPoint();
+ previous_line -> setPoints(startPoint.x(), startPoint.y(),
+ endPoint.x(), endPoint.y());
+ } else {
+ /* the user clicked neither on the start- nor on the end point of
+ * the line; this really shouldn't happen, but just make sure */
+ return false;
+ }
+
+
+ /* remove the segment from the list */
+ m_LineList.remove( pointIndex );
+
+ return true;
+}
+
+bool LinePath::setStartEndPoints( const QPoint &start, const QPoint &end ) {
+ int count = m_LineList.count();
+
+ if( count == 0 ) {
+ QCanvasLine * line = new QCanvasLine(getCanvas() );
+ line -> setPoints( start.x(), start.y(), end.x(), end.y() );
+ line -> setZ( -2 );
+ line -> setPen( getPen() );
+ line -> setVisible( true );
+ m_LineList.append( line );
+ return true;
+ }
+ bool status = setPoint( 0, start );
+ if( status)
+ return setPoint( count , end );
+ return false;
+}
+
+int LinePath::count() {
+ return m_LineList.count() + 1;
+}
+
+int LinePath::onLinePath( const QPoint &position ) {
+ QCanvasItemList list = getCanvas() -> collisions( position );
+ int index = -1;
+
+ QCanvasItemList::iterator end(list.end());
+ for(QCanvasItemList::iterator item_it(list.begin()); item_it != end; ++item_it ) {
+ if( ( index = m_LineList.findRef( (QCanvasLine*)*item_it ) ) != -1 )
+ break;
+ }//end for
+ return index;
+}
+
+void LinePath::setSelected( bool select ) {
+ if(select)
+ setupSelected();
+ else if( m_RectList.count() > 0 )
+ m_RectList.clear();
+}
+
+void LinePath::setAssocType( Uml::Association_Type type ) {
+ LineListIt it( m_LineList );
+ QCanvasLine * line = 0;
+ while( ( line = it.current() ) ) {
+ line -> setPen( getPen() );
+ ++it;
+ }
+ if( m_pClearPoly ) {
+ delete m_pClearPoly;
+ m_pClearPoly = 0;
+ }
+ if( type == Uml::at_Coll_Message )
+ setupParallelLine();
+ else
+ createHeadLines();
+ update();
+}
+
+void LinePath::update() {
+ if (getAssocType() == Uml::at_Coll_Message) {
+ if (m_bParallelLineCreated) {
+ calculateParallelLine();
+ updateParallelLine();
+ } else
+ setupParallelLine();
+ } else if (m_bHeadCreated) {
+ calculateHead();
+ updateHead();
+ } else {
+ createHeadLines();
+ }
+}
+
+void LinePath::slotLineColorChanged( Uml::IDType viewID ) {
+ if(m_pAssociation->getUMLView()->getID() != viewID) {
+ return;
+ }
+ setLineColor( m_pAssociation->getUMLView()->getLineColor() );
+}
+
+
+void LinePath::setLineColor( const QColor &color ) {
+ QCanvasLine * line = 0;
+ uint linewidth = 0;
+ LineListIt it( m_LineList );
+ while( ( line = it.current() ) ) {
+ linewidth = line->pen().width();
+ line -> setPen( QPen( color, linewidth ) );
+ ++it;
+ }
+ LineListIt hit( m_HeadList );
+ while( ( line = hit.current() ) ) {
+ linewidth = line->pen().width();
+ line -> setPen( QPen( color, linewidth ) );
+ ++hit;
+ }
+ LineListIt pit( m_ParallelList );
+ while( ( line = pit.current() ) ) {
+ linewidth = line->pen().width();
+ line -> setPen( QPen( color, linewidth ) );
+ ++pit;
+ }
+
+ if( getAssocType() == Uml::at_Aggregation )
+ if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( Qt::white ) );
+ else if( getAssocType() == Uml::at_Composition )
+ if (m_pClearPoly) m_pClearPoly -> setBrush( QBrush( color ) );
+
+ if( m_pCircle ) {
+ linewidth = m_pCircle->pen().width();
+ m_pCircle->setPen( QPen(color, linewidth) );
+ }
+}
+
+void LinePath::slotLineWidthChanged( Uml::IDType viewID ) {
+ if(m_pAssociation->getUMLView()->getID() != viewID) {
+ return;
+ }
+ setLineWidth( m_pAssociation->getUMLView()->getLineWidth() );
+}
+
+void LinePath::setLineWidth( uint width ) {
+ QCanvasLine * line = 0;
+ QColor linecolor;
+ LineListIt it( m_LineList );
+ while( ( line = it.current() ) ) {
+ linecolor = line->pen().color();
+ line -> setPen( QPen( linecolor, width ) );
+ ++it;
+ }
+ LineListIt hit( m_HeadList );
+ while( ( line = hit.current() ) ) {
+ linecolor = line->pen().color();
+ line -> setPen( QPen( linecolor, width ) );
+ ++hit;
+ }
+ LineListIt pit( m_ParallelList );
+ while( ( line = pit.current() ) ) {
+ linecolor = line->pen().color();
+ line -> setPen( QPen( linecolor, width ) );
+ ++pit;
+ }
+
+ if( m_pCircle ) {
+ linecolor = m_pCircle->pen().color();
+ m_pCircle->setPen( QPen(linecolor, width) );
+ }
+}
+
+void LinePath::moveSelected( int pointIndex ) {
+ int lineCount = m_LineList.count();
+ if( !m_bSelected ) {
+ m_RectList.clear();
+ return;
+ }
+ if( (int)m_RectList.count() + 1 != lineCount )
+ setupSelected();
+ QCanvasRectangle * rect = 0;
+ QCanvasLine * line = 0;
+ if( pointIndex == lineCount || lineCount == 1) {
+ line = m_LineList.last();
+ QPoint p = line -> endPoint();
+ rect = m_RectList.last();
+ rect -> setX( p.x() );
+ rect -> setY( p.y() );
+ rect -> setZ( 4 );
+ return;
+ }
+ line = m_LineList.at( pointIndex );
+ QPoint p = line -> startPoint();
+ rect = m_RectList.at( pointIndex );
+ rect -> setX( p.x() );
+ rect -> setY( p.y() );
+ rect -> setZ( 4 );
+}
+
+void LinePath::setupSelected() {
+ m_RectList.clear();
+ QCanvasLine * line = 0;
+ LineListIt it( m_LineList );
+ while( ( line = it.current() ) ) {
+ QPoint sp = line -> startPoint();
+ QCanvasRectangle *rect = Widget_Utils::decoratePoint(sp);
+ m_RectList.append( rect );
+ ++it;
+ }
+ //special case for last point
+ line = m_LineList.last();
+ QPoint p = line -> endPoint();
+ QCanvasRectangle *rect = Widget_Utils::decoratePoint(p);
+ m_RectList.append( rect );
+ update();
+}
+
+QPen LinePath::getPen() {
+ Uml::Association_Type type = getAssocType();
+ if( type == Uml::at_Dependency || type == Uml::at_Realization || type == Uml::at_Anchor )
+ return QPen( getLineColor(), getLineWidth(), Qt::DashLine );
+ return QPen( getLineColor(), getLineWidth() );
+}
+
+void LinePath::calculateHead() {
+ uint size = m_LineList.count();
+ QPoint farPoint;
+ int halfLength = 10;
+ double arrowAngle = 0.2618; // 0.5 * atan(sqrt(3.0) / 3.0) = 0.2618
+ Uml::Association_Type at = getAssocType();
+ bool diamond = (at == Uml::at_Aggregation || at == Uml::at_Composition);
+ if (diamond || at == Uml::at_Containment) {
+ farPoint = getPoint(1);
+ m_EgdePoint = getPoint(0);
+ if (diamond) {
+ arrowAngle *= 1.5; // wider
+ halfLength += 1; // longer
+ } else {
+ // Containment has a circle-plus symbol at the
+ // containing object. What we are tweaking here
+ // is the perpendicular line through the circle
+ // (i.e. the horizontal line of the plus sign if
+ // the objects are oriented north/south)
+ arrowAngle *= 2.5; // wider
+ halfLength -= 4; // shorter
+ }
+ } else {
+ farPoint = getPoint(size - 1);
+ m_EgdePoint = getPoint(size);
+ // We have an arrow.
+ arrowAngle *= 2.0; // wider
+ halfLength += 3; // longer
+ }
+ int xa = farPoint.x();
+ int ya = farPoint.y();
+ int xb = m_EgdePoint.x();
+ int yb = m_EgdePoint.y();
+ double deltaX = xb - xa;
+ double deltaY = yb - ya;
+ double hypotenuse = sqrt(deltaX*deltaX + deltaY*deltaY); // the length
+ double slope = atan2(deltaY, deltaX); //slope of line
+ double arrowSlope = slope + arrowAngle;
+ double cosx, siny;
+ if (hypotenuse < 1.0e-6) {
+ cosx = 1.0;
+ siny = 0.0;
+ } else {
+ cosx = halfLength * deltaX/hypotenuse;
+ siny = halfLength * deltaY/hypotenuse;
+ }
+
+ m_ArrowPointA.setX( (int)rint(xb - halfLength * cos(arrowSlope)) );
+ m_ArrowPointA.setY( (int)rint(yb - halfLength * sin(arrowSlope)) );
+ arrowSlope = slope - arrowAngle;
+ m_ArrowPointB.setX( (int)rint(xb - halfLength * cos(arrowSlope)) );
+ m_ArrowPointB.setY( (int)rint(yb - halfLength * sin(arrowSlope)) );
+
+ if(xa > xb)
+ cosx = cosx > 0 ? cosx : cosx * -1;
+ else
+ cosx = cosx > 0 ? cosx * -1: cosx;
+
+ if(ya > yb)
+ siny = siny > 0 ? siny : siny * -1;
+ else
+ siny = siny > 0 ? siny * -1 : siny;
+
+ m_MidPoint.setX( (int)rint(xb + cosx) );
+ m_MidPoint.setY( (int)rint(yb + siny) );
+
+ m_PointArray.setPoint(0, m_EgdePoint);
+ m_PointArray.setPoint(1, m_ArrowPointA);
+ if( getAssocType() == Uml::at_Realization ||
+ getAssocType() == Uml::at_Generalization ) {
+ m_PointArray.setPoint( 2, m_ArrowPointB );
+ m_PointArray.setPoint( 3, m_EgdePoint );
+ } else {
+ QPoint diamondFarPoint;
+ diamondFarPoint.setX( (int)rint(xb + cosx * 2) );
+ diamondFarPoint.setY( (int)rint(yb + siny * 2) );
+ m_PointArray.setPoint(2, diamondFarPoint);
+ m_PointArray.setPoint(3, m_ArrowPointB);
+ }
+
+}
+
+void LinePath::updateHead() {
+ int count = m_HeadList.count();
+ QCanvasLine * line = 0;
+
+ switch( getAssocType() ) {
+ case Uml::at_State:
+ case Uml::at_Activity:
+ case Uml::at_UniAssociation:
+ case Uml::at_Dependency:
+ if( count < 2)
+ return;
+ line = m_HeadList.at( 0 );
+ line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() );
+
+ line = m_HeadList.at( 1 );
+ line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
+ break;
+
+ case Uml::at_Relationship:
+ if (count < 2) {
+ return;
+ }
+ {
+ int xoffset = 0;
+ int yoffset = 0;
+ if( m_DockRegion == TopBottom )
+ xoffset = 8;
+ else
+ yoffset = 8;
+ line = m_HeadList.at( 0 );
+ line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(),
+ m_PointArray[0].x()-xoffset, m_PointArray[0].y()-yoffset );
+
+ line = m_HeadList.at( 1 );
+ line->setPoints( m_PointArray[2].x(), m_PointArray[2].y(),
+ m_PointArray[0].x()+xoffset, m_PointArray[0].y()+yoffset );
+ }
+
+ case Uml::at_Generalization:
+ case Uml::at_Realization:
+ if( count < 3)
+ return;
+ line = m_HeadList.at( 0 );
+ line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointA.x(), m_ArrowPointA.y() );
+
+ line = m_HeadList.at( 1 );
+ line -> setPoints( m_EgdePoint.x(), m_EgdePoint.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
+
+ line = m_HeadList.at( 2 );
+ line -> setPoints( m_ArrowPointA.x(), m_ArrowPointA.y(), m_ArrowPointB.x(), m_ArrowPointB.y() );
+ m_pClearPoly -> setPoints( m_PointArray );
+ break;
+
+ case Uml::at_Composition:
+ case Uml::at_Aggregation:
+ if( count < 4)
+ return;
+ line = m_HeadList.at( 0 );
+ line -> setPoints( m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y(), m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y() );
+
+ line = m_HeadList.at( 1 );
+ line -> setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(), m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y() );
+
+ line = m_HeadList.at( 2 );
+ line -> setPoints( m_PointArray[ 2 ].x(), m_PointArray[ 2 ].y(), m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() );
+
+ line = m_HeadList.at( 3 );
+ line -> setPoints( m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y(), m_PointArray[ 0 ].x(), m_PointArray[ 0 ].y() );
+ m_pClearPoly -> setPoints( m_PointArray );
+ break;
+
+ case Uml::at_Containment:
+ if (count < 1)
+ return;
+ line = m_HeadList.at( 0 );
+ line->setPoints( m_PointArray[ 1 ].x(), m_PointArray[ 1 ].y(),
+ m_PointArray[ 3 ].x(), m_PointArray[ 3 ].y() );
+ m_pCircle -> setX( m_MidPoint.x() );
+ m_pCircle -> setY( m_MidPoint.y() );
+ break;
+ default:
+ break;
+ }
+}
+
+void LinePath::growList(LineList &list, int by) {
+ QPen pen( getLineColor(), getLineWidth() );
+ for (int i = 0; i < by; i++) {
+ QCanvasLine * line = new QCanvasLine( getCanvas() );
+ line -> setZ( 0 );
+ line -> setPen( pen );
+ line -> setVisible( true );
+ list.append( line );
+ }
+}
+
+void LinePath::createHeadLines() {
+ m_HeadList.clear();
+ QCanvas * canvas = getCanvas();
+ switch( getAssocType() ) {
+ case Uml::at_Activity:
+ case Uml::at_State:
+ case Uml::at_Dependency:
+ case Uml::at_UniAssociation:
+ case Uml::at_Relationship:
+ growList(m_HeadList, 2);
+ break;
+
+ case Uml::at_Generalization:
+ case Uml::at_Realization:
+ growList(m_HeadList, 3);
+ m_pClearPoly = new QCanvasPolygon( canvas );
+ m_pClearPoly -> setVisible( true );
+ m_pClearPoly -> setBrush( QBrush( Qt::white ) );
+ m_pClearPoly -> setZ( -1 );
+ break;
+
+ case Uml::at_Composition:
+ case Uml::at_Aggregation:
+ growList(m_HeadList, 4);
+ m_pClearPoly = new QCanvasPolygon( canvas );
+ m_pClearPoly -> setVisible( true );
+ if( getAssocType() == Uml::at_Aggregation )
+ m_pClearPoly -> setBrush( QBrush( Qt::white ) );
+ else
+ m_pClearPoly -> setBrush( QBrush( getLineColor() ) );
+ m_pClearPoly -> setZ( -1 );
+ break;
+
+ case Uml::at_Containment:
+ growList(m_HeadList, 1);
+ if (!m_pCircle) {
+ m_pCircle = new Circle( canvas, 6 );
+ m_pCircle->show();
+ m_pCircle->setPen( QPen( getLineColor(), getLineWidth() ) );
+ }
+ break;
+ default:
+ break;
+ }
+ m_bHeadCreated = true;
+}
+
+void LinePath::calculateParallelLine() {
+ int midCount = count() / 2;
+ double ATAN = atan(1.0);
+ int lineDist = 10;
+ //get 1/8(M) and 7/8(T) point
+ QPoint a = getPoint( midCount - 1 );
+ QPoint b = getPoint( midCount );
+ int mx = ( a.x() + b.x() ) / 2;
+ int my = ( a.y() + b.y() ) / 2;
+ int tx = ( mx + b.x() ) / 2;
+ int ty = ( my + b.y() ) / 2;
+ //find dist between M and T points
+ int distX = ( mx - tx );
+ distX *= distX;
+ int distY = ( my - ty );
+ distY *= distY;
+ double dist = sqrt( double(distX + distY) );
+ double angle = atan2( double(ty - my), double(tx - mx) ) + ( ATAN * 2 );
+ //find point from M to start line from.
+ double cosx = cos( angle ) * lineDist;
+ double siny = sin( angle ) * lineDist;
+ QPoint pointM( mx + (int)cosx, my + (int)siny );
+ //find dist between P(xb, yb)
+ distX = ( tx - b.x() );
+ distX *= distX;
+ distY = ( ty - b.y() );
+ distY *= distY;
+ dist = sqrt( double(distX + distY) );
+ //find point from T to end line
+ cosx = cos( angle ) * lineDist;
+ siny = sin( angle ) * lineDist;
+ QPoint pointT( tx + (int)cosx, ty + (int)siny );
+ m_ParallelLines[ 1 ] = pointM;
+ m_ParallelLines[ 0 ] = pointT;
+
+ int arrowDist = 5;
+ angle = atan2( double(pointT.y() - pointM.y()),
+ double(pointT.x() - pointM.x()) );
+ double arrowSlope = angle + ATAN;
+ cosx = ( cos( arrowSlope ) ) * arrowDist;
+ siny = ( sin( arrowSlope ) ) * arrowDist;
+ m_ParallelLines[ 2 ] = QPoint( pointT.x() - (int)cosx, pointT.y() - (int)siny );
+ arrowSlope = angle - ATAN;
+ cosx = ( cos( arrowSlope ) ) * arrowDist;
+ siny = ( sin( arrowSlope ) ) * arrowDist;
+ m_ParallelLines[ 3 ] = QPoint( pointT.x() - (int)cosx, pointT.y() - (int)siny );
+}
+
+void LinePath::setupParallelLine() {
+ m_ParallelList.clear();
+ growList(m_ParallelList, 3);
+ m_bParallelLineCreated = true;
+}
+
+void LinePath::updateParallelLine() {
+ if( !m_bParallelLineCreated )
+ return;
+ QCanvasLine * line = 0;
+ QPoint common = m_ParallelLines.at( 0 );
+ QPoint p = m_ParallelLines.at( 1 );
+ line = m_ParallelList.at( 0 );
+ line -> setPoints( common.x(), common.y(), p.x(), p.y() );
+
+ p = m_ParallelLines.at( 2 );
+ line = m_ParallelList.at( 1 );
+ line -> setPoints( common.x(), common.y(), p.x(), p.y() );
+
+ p = m_ParallelLines.at( 3 );
+ line = m_ParallelList.at( 2 );
+ line -> setPoints( common.x(), common.y(), p.x(), p.y() );
+}
+
+bool LinePath::operator==( LinePath & rhs ) {
+ if( this -> m_LineList.count() != rhs.m_LineList.count() )
+ return false;
+
+ //Check to see if all points at the same position
+ for( int i = 0; i< rhs.count() ; i++ ) {
+ if( this -> getPoint( i ) != rhs.getPoint( i ) )
+ return false;
+ }
+ return true;
+}
+
+LinePath & LinePath::operator=( LinePath & rhs ) {
+ if( this == &rhs )
+ return *this;
+ //clear out the old canvas objects
+ this -> m_LineList.clear();
+ this -> m_ParallelList.clear();
+ this -> m_RectList.clear();
+ this -> m_HeadList.clear();
+ int count = rhs.m_LineList.count();
+ //setup start end points
+ this -> setStartEndPoints( rhs.getPoint( 0 ), rhs.getPoint( count) );
+ //now insert the rest
+ for( int i = 1; i < count ; i++ ) {
+ this -> insertPoint( i, rhs.getPoint ( i ) );
+ }
+ this -> setAssocType( rhs.getAssocType() );
+
+ return *this;
+}
+
+QCanvas * LinePath::getCanvas() {
+ if( !m_pAssociation )
+ return 0;
+ const UMLView * view = m_pAssociation->getUMLView();
+ return view -> canvas();
+}
+
+Uml::Association_Type LinePath::getAssocType() {
+ if( m_pAssociation )
+ return m_pAssociation -> getAssocType();
+ return Uml::at_Association;
+}
+
+QColor LinePath::getLineColor() {
+ if( !m_pAssociation )
+ return Qt::black;
+ return m_pAssociation -> getLineColor();
+}
+
+uint LinePath::getLineWidth() {
+ if( !m_pAssociation )
+ return 0;
+ int viewLineWidth = m_pAssociation -> getLineWidth();
+ if ( viewLineWidth >= 0 && viewLineWidth <= 10 )
+ return viewLineWidth;
+ else {
+ kWarning() << "Ignore wrong LineWidth of " << viewLineWidth
+ << " in LinePath::getLineWidth" << endl;
+ return 0;
+ }
+}
+
+void LinePath::cleanup() {
+ if (m_pAssociation)
+ m_LineList.clear();
+ m_HeadList.clear();
+ m_RectList.clear();
+ m_ParallelList.clear();
+
+ if( m_pClearPoly )
+ delete m_pClearPoly;
+ if( m_pCircle )
+ delete m_pCircle;
+ m_pCircle = 0;
+ m_pClearPoly = 0;
+ m_bHeadCreated = m_bParallelLineCreated = false;
+ if( m_pAssociation ) {
+ UMLView * view = (UMLView *)m_pAssociation -> parent();
+ if(view) {
+ disconnect( view, SIGNAL( sigColorChanged( Uml::IDType ) ), this, SLOT( slotLineColorChanged( Uml::IDType ) ) );
+ disconnect( view, SIGNAL( sigLineWidthChanged( Uml::IDType ) ), this, SLOT( slotLineWidthChanged( Uml::IDType ) ) );
+ }
+ m_pAssociation = NULL;
+ }
+}
+
+void LinePath::setDockRegion( Region region ) {
+ m_DockRegion = region;
+}
+
+bool LinePath::hasPoints () {
+ int count = m_LineList.count();
+ if (count>1)
+ return true;
+ return false;
+}
+void LinePath::dumpPoints () {
+ int count = m_LineList.count();
+ for( int i = 1; i < count; i++ ) {
+ QPoint point = getPoint( i );
+ kDebug()<<" * point x:"<<point.x()<<" y:"<<point.y()<<endl;
+ }
+}
+
+void LinePath::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ int count = m_LineList.count();
+ QPoint point = getPoint( 0 );
+ QDomElement lineElement = qDoc.createElement( "linepath" );
+ QDomElement startElement = qDoc.createElement( "startpoint" );
+ startElement.setAttribute( "startx", point.x() );
+ startElement.setAttribute( "starty", point.y() );
+ lineElement.appendChild( startElement );
+ QDomElement endElement = qDoc.createElement( "endpoint" );
+ point = getPoint( count );
+ endElement.setAttribute( "endx", point.x() );
+ endElement.setAttribute( "endy", point.y() );
+ lineElement.appendChild( endElement );
+ for( int i = 1; i < count; i++ ) {
+ QDomElement pointElement = qDoc.createElement( "point" );
+ point = getPoint( i );
+ pointElement.setAttribute( "x", point.x() );
+ pointElement.setAttribute( "y", point.y() );
+ lineElement.appendChild( pointElement );
+ }
+ qElement.appendChild( lineElement );
+}
+
+bool LinePath::loadFromXMI( QDomElement & qElement ) {
+ QDomNode node = qElement.firstChild();
+ QDomElement startElement = node.toElement();
+ if( startElement.isNull() || startElement.tagName() != "startpoint" )
+ return false;
+ QString x = startElement.attribute( "startx", "0" );
+ int nX = x.toInt();
+ QString y = startElement.attribute( "starty", "0" );
+ int nY = y.toInt();
+ QPoint startPoint( nX, nY );
+
+ node = startElement.nextSibling();
+ QDomElement endElement = node.toElement();
+ if( endElement.isNull() || endElement.tagName() != "endpoint" )
+ return false;
+ x = endElement.attribute( "endx", "0" );
+ nX = x.toInt();
+ y = endElement.attribute( "endy", "0" );
+ nY = y.toInt();
+ QPoint endPoint( nX, nY );
+ setStartEndPoints( startPoint, endPoint );
+ QPoint point;
+ node = endElement.nextSibling();
+ QDomElement element = node.toElement();
+ int i = 1;
+ while( !element.isNull() ) {
+ if( element.tagName() == "point" ) {
+ x = element.attribute( "x", "0" );
+ y = element.attribute( "y", "0" );
+ point.setX( x.toInt() );
+ point.setY( y.toInt() );
+ insertPoint( i++, point );
+ }
+ node = element.nextSibling();
+ element = node.toElement();
+ }
+
+ return true;
+}
+
+
+void LinePath::activate() {
+ int count = m_LineList.count();
+ if (count == 0)
+ return;
+ QCanvas * canvas = getCanvas();
+ if (canvas == NULL)
+ return;
+ for (int i = 0; i < count ; i++) {
+ QCanvasLine *line = m_LineList.at(i);
+ line -> setCanvas( canvas );
+ line -> setPen( getPen() );
+ }
+}
+
+
+
+#include "linepath.moc"
diff --git a/umbrello/umbrello/linepath.h b/umbrello/umbrello/linepath.h
new file mode 100644
index 00000000..434749e3
--- /dev/null
+++ b/umbrello/umbrello/linepath.h
@@ -0,0 +1,383 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef LINEPATH_H
+#define LINEPATH_H
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qpoint.h>
+#include <qpointarray.h>
+#include <qcanvas.h>
+#include <qpainter.h>
+#include "umlnamespace.h"
+
+/* how many pixels a user could click around a point */
+#define POINT_DELTA 5
+
+class AssociationWidget;
+class UMLView;
+
+// Qt forward declarations
+class QDataStream;
+class QDomDocument;
+class QDomElement;
+
+// typedefs
+typedef QPtrList<QCanvasLine> LineList;
+typedef QPtrListIterator<QCanvasLine> LineListIt;
+
+typedef QPtrList<QCanvasRectangle> RectList;
+typedef QPtrListIterator<QCanvasRectangle> RectListIt;
+
+
+/**
+ *@author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class LinePath : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ LinePath();
+
+ /**
+ * Deconstructor
+ */
+ ~LinePath();
+
+ /**
+ * equal to (==) operator
+ */
+ bool operator==( LinePath & rhs );
+
+ /**
+ * copy ( = ) operator
+ */
+ LinePath & operator=( LinePath & rhs );
+
+ /**
+ * Enum to tell whether the line docks top/bottom or left/right
+ */
+ enum Region {
+ TopBottom, LeftRight
+ };
+
+ /**
+ * Tell the line where the line docks
+ */
+ void setDockRegion( Region region );
+
+ bool hasPoints ();
+ void dumpPoints ();
+
+ /**
+ * Returns the point at the point index.
+ */
+ QPoint getPoint( int pointIndex );
+
+ /**
+ * Sets the position of an already set point.
+ */
+ bool setPoint( int pointIndex, const QPoint &point );
+
+ /**
+ * Checks, if we are at an end of the segment or somewhere in the middle.
+ * We use the delta, because with the mouse it is hard to find the
+ * exactly point.
+ */
+ bool isPoint( int pointIndex, const QPoint &point, unsigned short delta = 0 );
+
+ /**
+ * Inserts a point at the given index.
+ */
+ bool insertPoint( int pointIndex, const QPoint &point );
+
+ /**
+ * Removes the point on the line given by the index, at the coordinates
+ * given by point with a fuzzy of delta
+ */
+ bool removePoint( int pointIndex, const QPoint &point, unsigned short delta = 0 );
+
+ /**
+ * Sets the start and end points.
+ */
+ bool setStartEndPoints( const QPoint &start, const QPoint &end );
+
+ /**
+ * Returns the amount of POINTS on the line.
+ * Includes start and end points.
+ */
+ int count();
+
+ /**
+ * Returns -1 if the given point is not on the line.
+ * else returns the line segment the point is on.
+ * Use the value to insert points at the point position.
+ */
+ int onLinePath( const QPoint &position );
+
+ /**
+ * Sets the canvas to be used.
+ */
+ void setCanvas( QCanvas * canvas );
+
+ /**
+ * Sets the Association type.
+ */
+ void setAssocType( Uml::Association_Type type );
+
+ /**
+ * Calls a group of methods to update the line. Used to save you calling multiple methods.
+ */
+ void update();
+
+ /**
+ * This will setup the class ready to display the line correctly.
+ * This MUST be called before you can use this class.
+ */
+ void setAssociation( AssociationWidget * association );
+
+ /**
+ * Returns the Association this class is linked to.
+ */
+ AssociationWidget * getAssociation() {
+ return m_pAssociation;
+ }
+
+ /**
+ * Sets the status of whether the line is selected or not.
+ */
+ void setSelected( bool select );
+
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ bool loadFromXMI( QDomElement & qElement );
+
+ /**
+ * Activates the line list.
+ * This is needed because the m_pAssociation does not yet
+ * exist at the time of the LinePath::loadFromXMI call.
+ * However, this means that the points in the m_LineList
+ * do not have a parent when they are loaded.
+ * They need to be reparented by calling LinePath::activate()
+ * once the m_pAssociation exists.
+ */
+ void activate();
+
+ /**
+ * Removes and item created that are no longer needed.
+ */
+ void cleanup();
+
+ /**
+ * Returns the type of pen to use depending on the type of Association.
+ */
+ QPen getPen();
+
+ /**
+ * Sets the line color used by the line.
+ */
+ void setLineColor( const QColor &color );
+ /**
+ * Sets the line width used by the line.
+ */
+ void setLineWidth( uint width );
+
+protected:
+
+ /**
+ * Draw a (hollow) circle.
+ * We can't use QCanvasEllipse directly for this because it doesn't
+ * use the pen, i.e. QCanvasEllipse only draws filled ellipses.
+ */
+ class Circle : public QCanvasEllipse {
+ public:
+ explicit Circle(QCanvas * canvas, int radius = 0);
+ void setRadius(int radius);
+ int getRadius() const;
+ void setX(int x);
+ void setY(int y);
+ /**
+ * The beef: Override method from QCanvasEllipse.
+ */
+ void drawShape(QPainter& p);
+ };
+
+ /**
+ * Returns the canvas being used.
+ * Will return zero if the Association hasn't been set.
+ *
+ * This class doesn't hold this information but is a wrapper
+ * method to stop calls to undefined variable like m_pAssociation.
+ */
+ QCanvas * getCanvas();
+
+ /**
+ * Returns the Association type.
+ * Returns Uml::at_Association if association hasn't been set.
+ *
+ * This class doesn't hold this information but is a wrapper
+ * method to stop calls to undefined variable like m_pAssociation.
+ */
+ Uml::Association_Type getAssocType();
+
+ /**
+ * Returns the Line Color to use.
+ * Returns black if association not set.
+ *
+ * This class doesn't hold this information but is a wrapper
+ * method to stop calls to undefined variable like m_pAssociation.
+ */
+ QColor getLineColor();
+ /**
+ * Returns the Line Width to use.
+ * Returns 0 if association not set.
+ *
+ * This class doesn't hold this information but is a wrapper
+ * method to stop calls to undefined variable like m_pAssociation.
+ */
+ uint getLineWidth();
+
+ /**
+ * Moves the selected canvas widgets.
+ */
+ void moveSelected( int pointIndex );
+
+ /**
+ * Sets up the selected canvases needed.
+ */
+ void setupSelected();
+
+ /**
+ * Calculates the head points.
+ */
+ void calculateHead();
+
+ /**
+ * Creates the head lines to display the head.
+ */
+ void createHeadLines();
+
+ /**
+ * Create a number of new lines and append them to the given list.
+ *
+ * @param list The list into which to append lines.
+ * @param by The number of lines to insert into the given list.
+ */
+ void growList(LineList &list, int by);
+
+ /**
+ * Updates the head lines. Call after calculating the new points.
+ */
+ void updateHead();
+
+ /**
+ * Creates the line objects to display the parallel line.
+ */
+ void setupParallelLine();
+
+ /**
+ * Calculates the position of the parallel line.
+ */
+ void calculateParallelLine();
+
+ /**
+ * Updates the parallel line.
+ * Call after calculating the new position.
+ */
+ void updateParallelLine();
+
+ /********Attributes*************/
+
+ /**
+ * The association we are representing.
+ */
+ AssociationWidget * m_pAssociation;
+
+ /**
+ * Contains all the lines of the association.
+ */
+ LineList m_LineList;
+
+ /**
+ * Selected boxes list.
+ */
+ RectList m_RectList;
+
+ /**
+ * Head lines.
+ */
+ LineList m_HeadList;
+
+ /**
+ * The parallel line.
+ */
+ LineList m_ParallelList;
+
+ /**
+ * Selected status.
+ */
+ bool m_bSelected;
+
+ /**
+ * Contains calculated points used to draw the line head.
+ */
+ QPointArray m_PointArray;
+
+ /**
+ * Contains calculated points used to draw the line head.
+ */
+ QPoint m_ArrowPointA, m_ArrowPointB, m_MidPoint, m_EgdePoint;
+
+ /**
+ * A polygon object to blank out any lines we don't want to see.
+ */
+ QCanvasPolygon * m_pClearPoly;
+
+ /**
+ * The transparent circle required by containment associations.
+ */
+ Circle * m_pCircle;
+
+ /**
+ * Contains the calculated points for the parallel line
+ * on a collaboration message to use.
+ */
+ QPointArray m_ParallelLines;
+
+ /**
+ * Region where the line docks
+ */
+ Region m_DockRegion;
+
+ bool m_bHeadCreated;
+
+ bool m_bParallelLineCreated;
+
+public slots:
+
+ /**
+ * Sets the line color used by the line.
+ *
+ * @param viewID The id of the object behind the widget.
+ */
+ void slotLineColorChanged( Uml::IDType viewID );
+ /**
+ * Sets the line width used by the line.
+ *
+ * @param viewID The id of the object behind the widget.
+ */
+ void slotLineWidthChanged( Uml::IDType viewID );
+};
+
+#endif
diff --git a/umbrello/umbrello/linkwidget.cpp b/umbrello/umbrello/linkwidget.cpp
new file mode 100644
index 00000000..b1b176de
--- /dev/null
+++ b/umbrello/umbrello/linkwidget.cpp
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "linkwidget.h"
+// qt/kde includes
+#include <kdebug.h>
+// app includes
+#include "umlview.h"
+#include "umlobject.h"
+#include "classifier.h"
+#include "operation.h"
+#include "uml.h"
+
+LinkWidget::LinkWidget() {
+}
+
+LinkWidget::~LinkWidget() {
+}
+
+UMLClassifier *LinkWidget::getOperationOwner() {
+ UMLOperation *op = getOperation();
+ if (op == NULL)
+ return NULL;
+ return static_cast<UMLClassifier*>(op->parent());
+}
+
+QString LinkWidget::getOperationText(UMLView *view /* = NULL */) {
+ UMLOperation *op = getOperation();
+ if (op == NULL)
+ return getCustomOpText();
+ if (view == NULL)
+ view = UMLApp::app()->getCurrentView();
+ Uml::Signature_Type sigType;
+ if (view && view->getShowOpSig())
+ sigType = Uml::st_SigNoVis;
+ else
+ sigType = Uml::st_NoSigNoVis;
+ QString opText = op->toString(sigType);
+ return opText;
+}
+
+void LinkWidget::resetTextPositions() {
+}
+
+bool LinkWidget::showDialog() {
+ return true;
+}
+
+void LinkWidget::calculateNameTextSegment() {
+}
+
+
diff --git a/umbrello/umbrello/linkwidget.h b/umbrello/umbrello/linkwidget.h
new file mode 100644
index 00000000..0e85d615
--- /dev/null
+++ b/umbrello/umbrello/linkwidget.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef LINKWIDGET_H
+#define LINKWIDGET_H
+
+#include <qfont.h>
+
+#include "umlnamespace.h"
+
+// forward declarations
+class UMLClassifier;
+class UMLOperation;
+class FloatingTextWidget;
+class UMLView;
+
+/**
+ * This is an interface realized by AssociationWidget and MessageWidget.
+ * The design of this interface was driven by the requirements of
+ * class FloatingTextWidget. As the architecture of Umbrello evolves (for
+ * example, if the class FloatingTextWidget is redesigned), it can be
+ * cleaned up.
+ *
+ * @short Interface to FloatingTextWidget for AssociationWidget and MessageWidget.
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class LinkWidget {
+public:
+ LinkWidget();
+ virtual ~LinkWidget();
+
+ /**
+ * Sets the font the widget is to use.
+ * Abstract operation implemented by inheriting classes.
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ *
+ * @param font Font to be set.
+ */
+ virtual void lwSetFont(QFont font) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual UMLClassifier *getOperationOwner();
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual UMLOperation *getOperation() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual void setOperation(UMLOperation *op) = 0;
+
+ /**
+ * Motivated by getOperationText()
+ */
+ virtual QString getCustomOpText() = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Operation)
+ */
+ virtual void setCustomOpText(const QString &opText) = 0;
+
+ /**
+ * Uses getOperation() if set, else calls getCustomOpText().
+ */
+ QString getOperationText(UMLView *view = NULL);
+
+ /**
+ * Motivated by FloatingTextWidget::slotMenuSelection(mt_Reset_Label_Positions)
+ * Only applies to AssociationWidget.
+ */
+ virtual void resetTextPositions();
+
+ /**
+ * Motivated by FloatingTextWidget::setMessageText()
+ */
+ virtual void setMessageText(FloatingTextWidget *ft) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::handleRename()
+ */
+ virtual void setText(FloatingTextWidget *ft, const QString &newText) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::mouseDoubleClickEvent()
+ * Only applies to AssociationWidget.
+ */
+ virtual bool showDialog();
+
+ /**
+ * Motivated by FloatingTextWidget::showOpDlg()
+ */
+ virtual UMLClassifier *getSeqNumAndOp(QString& seqNum, QString& op) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::showOpDlg()
+ */
+ virtual void setSeqNumAndOp(const QString &seqNum, const QString &op) = 0;
+
+ /**
+ * Abstract operation implemented by inheriting classes.
+ * Motivated by FloatingTextWidget::mouseMoveEvent()
+ */
+ virtual void constrainTextPos(int &textX, int &textY,
+ int textWidth, int textHeight,
+ Uml::Text_Role tr) = 0;
+
+ /**
+ * Motivated by FloatingTextWidget::setLink().
+ * Only applies to AssociationWidget.
+ */
+ virtual void calculateNameTextSegment();
+
+};
+
+#endif
diff --git a/umbrello/umbrello/listpopupmenu.cpp b/umbrello/umbrello/listpopupmenu.cpp
new file mode 100644
index 00000000..816d661b
--- /dev/null
+++ b/umbrello/umbrello/listpopupmenu.cpp
@@ -0,0 +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) 2002-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "listpopupmenu.h"
+
+// qt/kde includes
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// app includes
+#include "umlwidget.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+#include "classifierwidget.h"
+#include "classifier.h"
+#include "floatingtextwidget.h"
+#include "uml.h"
+#include "model_utils.h"
+#include "widget_utils.h"
+#include "folder.h"
+#include "umlview.h"
+#include "statewidget.h"
+#include "activitywidget.h"
+#include "forkjoinwidget.h"
+#include "objectwidget.h"
+
+//ListPopupMenu for a UMLView (diagram)
+ListPopupMenu::ListPopupMenu(QWidget *parent, Menu_Type type, UMLView * view)
+ : KPopupMenu(parent) {
+ init();
+ setupMenu(type, view);
+}
+
+//ListPopupMenu for the tree list view
+ListPopupMenu::ListPopupMenu(QWidget *parent, Uml::ListView_Type type)
+ : KPopupMenu(parent) {
+ init();
+ Menu_Type mt = mt_Undefined;
+ switch(type)
+ {
+ case Uml::lvt_Logical_View:
+ mt = mt_Logical_View;
+ break;
+
+ case Uml::lvt_UseCase_View:
+ mt = mt_UseCase_View;
+ break;
+
+ case Uml::lvt_Component_View:
+ mt = mt_Component_View;
+ break;
+
+ case Uml::lvt_EntityRelationship_Model:
+ mt = mt_EntityRelationship_Model;
+ break;
+
+ case Uml::lvt_Deployment_View:
+ mt = mt_Deployment_View;
+ break;
+
+ case Uml::lvt_Logical_Folder:
+ mt = mt_Logical_Folder;
+ break;
+
+ case Uml::lvt_UseCase_Folder:
+ mt = mt_UseCase_Folder;
+ break;
+
+ case Uml::lvt_Component_Folder:
+ mt = mt_Component_Folder;
+ break;
+
+ case Uml::lvt_Deployment_Folder:
+ mt = mt_Deployment_Folder;
+ break;
+
+ case Uml::lvt_EntityRelationship_Folder:
+ mt = mt_EntityRelationship_Folder;
+ break;
+
+ case Uml::lvt_UseCase_Diagram:
+ mt = mt_UseCase_Diagram;
+ break;
+
+ case Uml::lvt_Class_Diagram:
+ mt = mt_Class_Diagram;
+ break;
+
+ case Uml::lvt_Collaboration_Diagram:
+ mt = mt_Collaboration_Diagram;
+ break;
+
+ case Uml::lvt_Sequence_Diagram:
+ mt = mt_Sequence_Diagram;
+ break;
+
+ case Uml::lvt_State_Diagram:
+ mt = mt_State_Diagram;
+ break;
+
+ case Uml::lvt_Activity_Diagram:
+ mt = mt_Activity_Diagram;
+ break;
+
+ case Uml::lvt_Component_Diagram:
+ mt = mt_Component_Diagram;
+ break;
+
+ case Uml::lvt_Deployment_Diagram:
+ mt = mt_Deployment_Diagram;
+ break;
+
+ case Uml::lvt_EntityRelationship_Diagram:
+ mt = mt_EntityRelationship_Diagram;
+ break;
+
+ case Uml::lvt_Actor:
+ mt = mt_Actor;
+ break;
+
+ case Uml::lvt_UseCase:
+ mt = mt_UseCase;
+ break;
+
+ case Uml::lvt_Class:
+ mt = mt_Class;
+ break;
+
+ case Uml::lvt_Package:
+ mt = mt_Package;
+ break;
+
+ case Uml::lvt_Subsystem:
+ mt = mt_Subsystem;
+ break;
+
+ case Uml::lvt_Component:
+ mt = mt_Component;
+ break;
+
+ case Uml::lvt_Node:
+ mt = mt_Node;
+ break;
+
+ case Uml::lvt_Artifact:
+ mt = mt_Artifact;
+ break;
+
+ case Uml::lvt_Interface:
+ mt = mt_Interface;
+ break;
+
+ case Uml::lvt_Enum:
+ mt = mt_Enum;
+ break;
+
+ case Uml::lvt_EnumLiteral:
+ mt = mt_EnumLiteral;
+ break;
+
+ case Uml::lvt_Datatype:
+ mt = mt_Datatype;
+ break;
+
+ case Uml::lvt_Attribute:
+ mt = mt_Attribute;
+ break;
+
+ case Uml::lvt_Operation:
+ mt = mt_Operation;
+ break;
+
+ case Uml::lvt_Template:
+ mt = mt_Template;
+ break;
+
+ case Uml::lvt_Entity:
+ mt = mt_Entity;
+ break;
+
+ case Uml::lvt_EntityAttribute:
+ mt = mt_EntityAttribute;
+ break;
+
+ case Uml::lvt_Model:
+ mt = mt_Model;
+ break;
+
+ default: ;
+ //break;
+ }
+ setupMenu(mt);
+}
+
+//ListPopupMenu for a canvas widget
+ListPopupMenu::ListPopupMenu(QWidget * parent, UMLWidget * object,
+ bool multi, bool unique)
+ : KPopupMenu(parent)
+{
+ init();
+ //make the right menu for the type
+ //make menu for logical view
+ if(!object)
+ return;
+ Uml::Widget_Type type = object -> getBaseType();
+
+ if(multi) {
+ ClassifierWidget *c = NULL;
+ if (unique && (type == Uml::wt_Class || type == Uml::wt_Interface)) {
+ c = static_cast<ClassifierWidget *>( object );
+ makeMultiClassifierPopup(c);
+ }
+ setupColorSelection(object -> getUseFillColour());
+ insertSeparator();
+ insertStdItem(mt_Cut);
+ insertStdItem(mt_Copy);
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertItem(SmallIcon( "fonts" ), i18n( "Change Font..." ),
+ mt_Change_Font_Selection );
+ insertItem(SmallIcon( "editdelete" ), i18n("Delete Selected Items"),
+ mt_Delete_Selection);
+
+ // add this here and not above with the other stuff of the interface
+ // user might expect it at this position of the context menu
+ if (unique) {
+ if (type == Uml::wt_Interface) {
+ insertItem(i18n("Draw as Circle"), mt_DrawAsCircle_Selection);
+ setItemChecked( mt_DrawAsCircle_Selection,
+ c->getDrawAsCircle() );
+ insertItem(i18n("Change into Class"), mt_ChangeToClass_Selection);
+ } else if (type == Uml::wt_Class) {
+ UMLClassifier *umlc = c->getClassifier();
+ if (umlc->getAbstract() && umlc->attributes() == 0)
+ insertItem(i18n("Change into Interface"), mt_ChangeToInterface_Selection);
+ }
+ }
+
+ if(m_pInsert)
+ connect(m_pInsert, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pShow)
+ connect(m_pShow, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pColor)
+ connect(m_pColor, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ return;
+ }
+
+ StateWidget *pState;
+ ActivityWidget *pActivity;
+ UMLView * pView = static_cast<UMLView *>( parent );
+
+ switch(type) {
+ case Uml::wt_Actor:
+ case Uml::wt_UseCase:
+ setupColor(object -> getUseFillColour());
+ insertStdItems(true, type);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::wt_Class:
+ case Uml::wt_Interface:
+ makeClassifierPopup(static_cast<ClassifierWidget*>(object));
+ break;
+
+ case Uml::wt_Enum:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(SmallIcon("source"), i18n("Enum Literal..."), mt_EnumLiteral);
+ insertFileNew();
+ setupColor(object->getUseFillColour());
+ insertStdItems(true, type);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::wt_Entity:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(SmallIcon("source"), i18n("Entity Attribute..."), mt_EntityAttribute);
+ insertFileNew();
+ setupColor(object->getUseFillColour());
+ insertStdItems(true, type);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::wt_Datatype:
+ case Uml::wt_Package:
+ case Uml::wt_Component:
+ case Uml::wt_Node:
+ case Uml::wt_Artifact:
+ setupColor(object->getUseFillColour());
+ insertStdItems(false, type);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::wt_Object:
+ //Used for sequence diagram and collaboration diagram widgets
+ setupColor( object->getUseFillColour() );
+ if( pView->getType() == Uml::dt_Sequence ) {
+ insertSeparator();
+ int tabUp = insertItem( SmallIcon( "1uparrow"), i18n("Move Up"), mt_Up);
+ insertItem( SmallIcon( "1downarrow"), i18n("Move Down"), mt_Down);
+ if ( !(static_cast<ObjectWidget*>(object))->canTabUp() ) {
+ setItemEnabled(tabUp, false);
+ }
+ }
+ insertStdItems(true, type);
+ insertItem(i18n("Rename Class..."), mt_Rename);
+ insertItem(i18n("Rename Object..."), mt_Rename_Object);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::wt_Message:
+ insertStdItems(false, type);
+ insertStdItem(mt_Change_Font);
+ insertItem(SmallIcon( "filenew"), i18n("New Operation..."), mt_Operation);
+ insertItem(i18n("Select Operation..."), mt_Select_Operation);
+ break;
+
+ case Uml::wt_Note:
+ setupColor(object -> getUseFillColour());
+ insertSeparator();
+ insertStdItem(mt_Cut);
+ insertStdItem(mt_Copy);
+ insertStdItem(mt_Paste);
+ insertItem(SmallIcon( "editdelete"), i18n("Clear"), mt_Clear);
+ insertSeparator();
+ insertItem(i18n("Change Text..."), mt_Rename);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Change_Font);
+ break;
+
+ case Uml::wt_Box:
+ insertStdItems(false, type);
+ insertStdItem(mt_Line_Color);
+ break;
+
+ case Uml::wt_State:
+ pState = static_cast< StateWidget *>( object );
+ if( pState -> getStateType() == StateWidget::Normal ) {
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert -> insertItem(SmallIcon( "filenew"), i18n("Activity..."), mt_New_Activity);
+ insertFileNew();
+ }
+ setupColor( object -> getUseFillColour() );
+ insertStdItems(false, type);
+ if( pState -> getStateType() == StateWidget::Normal ) {
+ insertItem(i18n("Change State Name..."), mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ }
+ break;
+
+ case Uml::wt_ForkJoin:
+ {
+ ForkJoinWidget *pForkJoin = static_cast<ForkJoinWidget*>(object);
+ if (pForkJoin->getDrawVertical())
+ insertItem(i18n("Flip Horizontal"), mt_Flip);
+ else
+ insertItem(i18n("Flip Vertical"), mt_Flip);
+ }
+ break;
+
+ case Uml::wt_Activity:
+ pActivity = static_cast<ActivityWidget *>( object );
+ if( pActivity -> getActivityType() == ActivityWidget::Normal )
+ setupColor( object -> getUseFillColour() );
+ insertStdItems(false, type);
+ if( pActivity -> getActivityType() == ActivityWidget::Normal ) {
+ insertItem(i18n("Change Activity Name..."), mt_Rename);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Properties);
+ }
+ break;
+
+ case Uml::wt_Text:
+ switch( (static_cast<FloatingTextWidget*>(object))->getRole() ) {
+ case Uml::tr_MultiB:
+ insertAssocItem(i18n("Change Multiplicity..."), mt_Rename_MultiB);
+ break;
+ case Uml::tr_MultiA:
+ insertAssocItem(i18n("Change Multiplicity..."), mt_Rename_MultiA);
+ break;
+ case Uml::tr_Name:
+ insertAssocItem(i18n("Change Name"), mt_Rename_Name);
+ break;
+ case Uml::tr_RoleAName:
+ insertAssocItem(i18n("Change Role A Name..."), mt_Rename_RoleAName);
+ break;
+ case Uml::tr_RoleBName:
+ insertAssocItem(i18n("Change Role B Name..."), mt_Rename_RoleBName);
+ break;
+ case Uml::tr_ChangeA:
+ case Uml::tr_ChangeB:
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Reset_Label_Positions);
+ insertStdItem(mt_Properties);
+ break;
+
+ case Uml::tr_Coll_Message_Self:
+ case Uml::tr_Coll_Message:
+ case Uml::tr_Seq_Message_Self:
+ case Uml::tr_Seq_Message:
+ insertStdItem(mt_Change_Font);
+ insertItem(SmallIcon( "filenew"), i18n("New Operation..."), mt_Operation);
+ insertItem(i18n("Select Operation..."), mt_Select_Operation);
+ break;
+
+ case Uml::tr_Floating:
+ default:
+ insertStdItems(false, type);
+ insertItem(i18n("Change Text..."), mt_Rename);
+ insertStdItem(mt_Change_Font);
+ break;
+ }
+ break;
+ default:
+ break;
+ }//end switch
+
+ if(m_pInsert)
+ connect(m_pInsert, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pShow)
+ connect(m_pShow, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pColor)
+ connect(m_pColor, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+
+ bool bCutState = UMLApp::app() -> getCutCopyState();
+ setItemEnabled( mt_Cut, bCutState );
+ setItemEnabled( mt_Copy, bCutState );
+ setItemEnabled( mt_Paste, false );
+}
+
+ListPopupMenu::~ListPopupMenu() {}
+
+void ListPopupMenu::init() {
+ m_pInsert = 0;
+ m_pShow = 0;
+ m_pColor = 0;
+}
+
+void ListPopupMenu::insertFileNew() {
+ insertItem(SmallIcon("filenew"), i18n("New"), m_pInsert);
+}
+
+void ListPopupMenu::insertStdItem(Menu_Type m)
+{
+ switch (m) {
+ case mt_Properties:
+ insertItem(SmallIcon("info"), i18n("Properties"), mt_Properties);
+ break;
+ case mt_Rename:
+ insertItem(i18n("Rename..."), mt_Rename);
+ break;
+ case mt_Delete:
+ insertItem(SmallIcon("editdelete"), i18n("Delete"), mt_Delete);
+ break;
+ case mt_Cut:
+ insertItem(SmallIcon("editcut"), i18n("Cut"), mt_Cut);
+ break;
+ case mt_Copy:
+ insertItem(SmallIcon("editcopy"), i18n("Copy"), mt_Copy);
+ break;
+ case mt_Paste:
+ insertItem(SmallIcon("editpaste"), i18n("Paste"), mt_Paste);
+ break;
+ case mt_Change_Font:
+ insertItem(SmallIcon("fonts"), i18n("Change Font..."), mt_Change_Font);
+ break;
+ case mt_Line_Color:
+ insertItem(SmallIcon("color_line"), i18n("Line Color..."), mt_Line_Color);
+ break;
+ case mt_Expand_All:
+ insertItem(i18n("Expand All"), mt_Expand_All);
+ break;
+ case mt_Collapse_All:
+ insertItem(i18n("Collapse All"), mt_Collapse_All);
+ break;
+ case mt_Clone:
+ insertItem(i18n("Duplicate"), mt_Clone);
+ break;
+ case mt_Externalize_Folder:
+ insertItem(i18n("Externalize Folder..."), mt_Externalize_Folder);
+ break;
+ case mt_Internalize_Folder:
+ insertItem(i18n("Internalize Folder"), mt_Internalize_Folder);
+ break;
+ case mt_Import_Classes:
+ insertItem(BarIcon("source_cpp"), i18n("Import Classes..."), mt_Import_Classes);
+ break;
+ case mt_Package:
+ m_pInsert->insertItem(m_pixmap[pm_Package], i18n("Package"), mt_Package);
+ case mt_Subsystem:
+ m_pInsert->insertItem(m_pixmap[pm_Subsystem], i18n("Subsystem"), mt_Subsystem);
+ break;
+ case mt_Component:
+ m_pInsert->insertItem(m_pixmap[pm_Component], i18n("Component"), mt_Component);
+ break;
+ case mt_Artifact:
+ m_pInsert->insertItem(m_pixmap[pm_Artifact], i18n("Artifact"), mt_Artifact);
+ break;
+ case mt_Component_Diagram:
+ m_pInsert->insertItem(BarIcon("umbrello_diagram_component"), i18n("Component Diagram..."),
+ mt_Component_Diagram);
+ break;
+ case mt_Node:
+ m_pInsert->insertItem(m_pixmap[pm_Node], i18n("Node"), mt_Node);
+ break;
+ case mt_Deployment_Diagram:
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_Deployment), i18n("Deployment Diagram..."),
+ mt_Deployment_Diagram);
+ break;
+ case mt_Deployment_Folder:
+ case mt_Component_Folder:
+ case mt_UseCase_Folder:
+ case mt_EntityRelationship_Folder:
+ m_pInsert->insertItem(BarIcon("folder_new"), i18n("Folder"), m);
+ break;
+ case mt_Entity:
+ m_pInsert->insertItem(m_pixmap[pm_Entity], i18n("Entity"), mt_Entity);
+ break;
+ case mt_EntityRelationship_Diagram:
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_EntityRelationship), i18n("Entity Relationship Diagram..."),
+ mt_EntityRelationship_Diagram);
+ break;
+ case mt_Actor:
+ m_pInsert->insertItem(m_pixmap[pm_Actor], i18n("Actor"), mt_Actor);
+ break;
+ case mt_UseCase:
+ m_pInsert->insertItem(m_pixmap[pm_Usecase], i18n("Use Case"), mt_UseCase);
+ break;
+ case mt_UseCase_Diagram:
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_UseCase), i18n("Use Case Diagram..."),
+ mt_UseCase_Diagram);
+ break;
+ case mt_FloatText:
+ m_pInsert->insertItem(m_pixmap[pm_Text], i18n("Text Line..." ), mt_FloatText);
+ break;
+ case mt_Reset_Label_Positions:
+ insertItem(i18n("Reset Label Positions"), mt_Reset_Label_Positions);
+ break;
+ case mt_New_Parameter:
+ insertItem(SmallIcon("source"), i18n("New Parameter..."), mt_New_Parameter);
+ break;
+ case mt_New_Operation:
+ insertItem(SmallIcon("CVpublic_meth"),i18n("New Operation..."), mt_New_Operation);
+ break;
+ case mt_New_Attribute:
+ insertItem(SmallIcon("CVpublic_var"), i18n("New Attribute..."), mt_New_Attribute);
+ break;
+ case mt_New_Template:
+ insertItem(SmallIcon("source"), i18n("New Template..."), mt_New_Template);
+ break;
+ case mt_New_EnumLiteral:
+ insertItem(SmallIcon("source"), i18n("New Literal..."), mt_New_EnumLiteral);
+ break;
+ case mt_New_EntityAttribute:
+ insertItem(SmallIcon("source"), i18n("New Entity Attribute..."), mt_New_EntityAttribute);
+ break;
+ case mt_New_Activity:
+ m_pInsert->insertItem(SmallIcon("source"), i18n("Activity..."), mt_New_Activity);
+ break;
+ case mt_Export_Image:
+ insertItem(SmallIcon("image"), i18n("Export as Picture..."), mt_Export_Image);
+ break;
+ default:
+ kWarning() << "ListPopupMenu::insertStdItem called on unimplemented Menu_Type " << m << endl;
+ break;
+ }
+}
+
+void ListPopupMenu::insertStdItems(bool insertLeadingSeparator /* = true */,
+ Uml::Widget_Type type /* = wt_UMLWidget */)
+{
+ if (insertLeadingSeparator)
+ insertSeparator();
+ insertStdItem(mt_Cut);
+ insertStdItem(mt_Copy);
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ if (type == Uml::wt_UMLWidget)
+ insertStdItem(mt_Rename);
+ else if (Model_Utils::isCloneable(type))
+ insertStdItem(mt_Clone);
+ insertStdItem(mt_Delete);
+}
+
+void ListPopupMenu::insertContainerItems(bool folderAndDiagrams) {
+ if (folderAndDiagrams)
+ m_pInsert -> insertItem(BarIcon("folder_new"), i18n("Folder"), mt_Logical_Folder);
+ m_pInsert -> insertItem(m_pixmap[pm_Class], i18n("Class"), mt_Class);
+ m_pInsert -> insertItem(m_pixmap[pm_Interface], i18n("Interface"), mt_Interface);
+ m_pInsert -> insertItem(m_pixmap[pm_Datatype], i18n("Datatype"), mt_Datatype);
+ m_pInsert -> insertItem(m_pixmap[pm_Enum], i18n("Enum"), mt_Enum);
+ insertStdItem(mt_Package);
+ if (folderAndDiagrams) {
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_Class), i18n("Class Diagram..."), mt_Class_Diagram);
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_State), i18n("State Diagram..."), mt_State_Diagram);
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_Activity), i18n("Activity Diagram..."), mt_Activity_Diagram);
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_Sequence), i18n("Sequence Diagram..."), mt_Sequence_Diagram);
+ m_pInsert->insertItem(Widget_Utils::iconSet(Uml::dt_Collaboration), i18n("Collaboration Diagram..."), mt_Collaboration_Diagram);
+ }
+ insertFileNew();
+}
+
+void ListPopupMenu::insertAssocItem(const QString &label, Menu_Type mt) {
+ insertItem(label, mt);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Reset_Label_Positions);
+ insertStdItem(mt_Properties);
+}
+
+void ListPopupMenu::insertSubmodelAction() {
+ const Settings::OptionState& ostat = Settings::getOptionState();
+ if (ostat.generalState.tabdiagrams) {
+ // Umbrello currently does not support External Folders
+ // in combination with Tabbed Diagrams.
+ // If you need external folders then disable the tabbed diagrams
+ // in the General Settings.
+ return;
+ }
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *current = static_cast<UMLListViewItem*>(listView->currentItem());
+ UMLObject *o = current->getUMLObject();
+ if (o == NULL) {
+ kError() << "ListPopupMenu::insertSubmodelAction: "
+ << current->getText() << " getUMLObject() returns NULL" << endl;
+ return;
+ }
+ UMLFolder *f = dynamic_cast<UMLFolder*>(o);
+ if (f == NULL) {
+ kError() << "ListPopupMenu::insertSubmodelAction: "
+ << "current->getUMLObject (" << o->getName() << ") is not a Folder" << endl;
+ return;
+ }
+ QString submodelFile = f->getFolderFile();
+ if (submodelFile.isEmpty())
+ insertStdItem(mt_Externalize_Folder);
+ else
+ insertStdItem(mt_Internalize_Folder);
+}
+
+void ListPopupMenu::makeMultiClassifierPopup(ClassifierWidget *c)
+{
+ Uml::Widget_Type type = c->getBaseType();
+ ClassifierWidget *cls = NULL;
+
+ m_pShow = new KPopupMenu(this);
+ m_pShow->setCheckable(true);
+ if (type == Uml::wt_Class) {
+ cls = static_cast<ClassifierWidget*>(c);
+ m_pShow->insertItem( i18n("Attributes"), mt_Show_Attributes_Selection);
+ m_pShow->setItemChecked(mt_Show_Attributes_Selection,
+ cls->getShowAtts());
+ }
+ m_pShow->insertItem(i18n("Operations"), mt_Show_Operations_Selection);
+ m_pShow->setItemChecked(mt_Show_Operations_Selection, c->getShowOps());
+ m_pShow->insertItem(i18n("Public Only"), mt_Show_Public_Only_Selection);
+ m_pShow->setItemChecked(mt_Show_Public_Only_Selection, c->getShowPublicOnly());
+ m_pShow->insertItem(i18n("Visibility"), mt_Visibility_Selection);
+ m_pShow->setItemChecked(mt_Visibility_Selection, c->getShowVisibility());
+ m_pShow->insertItem(i18n("Operation Signature"),
+ mt_Show_Operation_Signature_Selection);
+ bool sig = (c->getShowOpSigs() == Uml::st_SigNoVis ||
+ c->getShowOpSigs() == Uml::st_ShowSig);
+ m_pShow->setItemChecked(mt_Show_Operation_Signature_Selection, sig);
+ if (type == Uml::wt_Class) {
+ m_pShow->insertItem(i18n("Attribute Signature"),
+ mt_Show_Attribute_Signature_Selection);
+ sig = (cls->getShowAttSigs() == Uml::st_SigNoVis ||
+ cls->getShowAttSigs() == Uml::st_ShowSig);
+ m_pShow->setItemChecked(mt_Show_Attribute_Signature_Selection, sig);
+ }
+ m_pShow->insertItem(i18n("Package"), mt_Show_Packages_Selection);
+ m_pShow->setItemChecked(mt_Show_Packages_Selection, c->getShowPackage());
+ if (type == Uml::wt_Class) {
+ m_pShow->insertItem(i18n("Stereotype"), mt_Show_Stereotypes_Selection);
+ m_pShow->setItemChecked(mt_Show_Stereotypes_Selection,
+ cls->getShowStereotype());
+ }
+ insertItem(i18n("Show"), m_pShow);
+}
+
+void ListPopupMenu::makeClassifierPopup(ClassifierWidget *c)
+{
+ Uml::Widget_Type type = c->getBaseType();
+ m_pInsert = new KPopupMenu(this);
+ if (type == Uml::wt_Class)
+ m_pInsert->insertItem(SmallIcon( "CVpublic_var" ), i18n("Attribute..."), mt_Attribute);
+ m_pInsert->insertItem( SmallIcon( "CVpublic_meth"), i18n("Operation..."), mt_Operation);
+ insertFileNew();
+
+ makeMultiClassifierPopup(c);
+
+ setupColor(c->getUseFillColour());
+ insertStdItems(true, type);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Change_Font);
+ if (type == Uml::wt_Interface) {
+ insertItem(i18n("Draw as Circle"), mt_DrawAsCircle);
+ setItemChecked( mt_DrawAsCircle, c->getDrawAsCircle() );
+ insertItem(i18n("Change into Class"), mt_ChangeToClass);
+ } else {
+ insertItem(i18n("Refactor"), mt_Refactoring);
+ insertItem(i18n("View Code"), mt_ViewCode);
+ UMLClassifier *umlc = c->getClassifier();
+ if (umlc->getAbstract() && umlc->attributes() == 0)
+ insertItem(i18n("Change into Interface"), mt_ChangeToInterface);
+ }
+ insertStdItem(mt_Properties);
+}
+
+void ListPopupMenu::setupColor(bool fc)
+{
+ m_pColor = new KPopupMenu(this);
+ m_pColor -> insertItem(SmallIcon( "color_line"), i18n("Line Color..."), mt_Line_Color);
+ m_pColor -> insertItem(SmallIcon( "color_fill"), i18n("Fill Color..."), mt_Fill_Color);
+ m_pColor -> insertItem( i18n("Use Fill Color"), mt_Use_Fill_Color);
+
+ m_pColor -> setItemChecked(mt_Use_Fill_Color, fc);
+ insertItem(SmallIcon( "colorize"), i18n("Color"), m_pColor);
+}
+
+void ListPopupMenu::setupColorSelection(bool fc)
+{
+ m_pColor = new KPopupMenu(this);
+ m_pColor -> insertItem(SmallIcon( "color_line"), i18n("Line Color..."), mt_Line_Color_Selection);
+ m_pColor -> insertItem(SmallIcon( "color_fill"), i18n("Fill Color..."), mt_Fill_Color_Selection);
+ m_pColor -> insertItem( i18n("Use Fill Color"), mt_Use_Fill_Color);
+
+ m_pColor -> setItemChecked(mt_Use_Fill_Color, fc);
+ insertItem(SmallIcon( "colorize"), i18n("Color"), m_pColor);
+}
+
+Uml::Diagram_Type ListPopupMenu::convert_MT_DT(Menu_Type mt) {
+ Uml::Diagram_Type type = Uml::dt_Undefined;
+
+ switch(mt) {
+ case mt_UseCase_Diagram:
+ type = Uml::dt_UseCase;
+ break;
+ case mt_Class_Diagram:
+ type = Uml::dt_Class;
+ break;
+ case mt_Sequence_Diagram:
+ type = Uml::dt_Sequence;
+ break;
+ case mt_Collaboration_Diagram:
+ type = Uml::dt_Collaboration;
+ break;
+ case mt_State_Diagram:
+ type = Uml::dt_State;
+ break;
+ case mt_Activity_Diagram:
+ type = Uml::dt_Activity;
+ break;
+ case mt_Component_Diagram:
+ type = Uml::dt_Component;
+ break;
+ case mt_Deployment_Diagram:
+ type = Uml::dt_Deployment;
+ break;
+ case mt_EntityRelationship_Diagram:
+ type = Uml::dt_EntityRelationship;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+Uml::Object_Type ListPopupMenu::convert_MT_OT(Menu_Type mt) {
+ Uml::Object_Type type = Uml::ot_UMLObject;
+
+ switch(mt) {
+ case mt_UseCase:
+ type = Uml::ot_UseCase;
+ break;
+ case mt_Actor:
+ type = Uml::ot_Actor;
+ break;
+ case mt_Class:
+ type = Uml::ot_Class;
+ break;
+ case mt_Attribute:
+ type = Uml::ot_Attribute;
+ break;
+ case mt_EnumLiteral:
+ type = Uml::ot_EnumLiteral;
+ break;
+ case mt_EntityAttribute:
+ type = Uml::ot_EntityAttribute;
+ break;
+ case mt_Operation:
+ type = Uml::ot_Operation;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+void ListPopupMenu::setupMenu(Menu_Type type, UMLView* view) {
+ //make the right menu for the type
+ //make menu for logical view
+ m_pInsert = 0;
+
+ m_pShow = 0;
+ m_pColor = 0;
+
+ KStandardDirs* dirs = KGlobal::dirs();
+ QString dataDir = dirs->findResourceDir("data", "umbrello/pics/object.png");
+ dataDir += "/umbrello/pics/";
+ m_pixmap[pm_Class] .load(dataDir+"class.png", "PNG");
+ m_pixmap[pm_Package] .load(dataDir+"package.png", "PNG");
+ m_pixmap[pm_Interface] .load(dataDir+"interface.png", "PNG");
+ m_pixmap[pm_Datatype] .load(dataDir+"datatype.png", "PNG");
+ m_pixmap[pm_Enum] .load(dataDir+"enum.png", "PNG");
+ m_pixmap[pm_Actor] .load(dataDir+"actor.png", "PNG");
+ m_pixmap[pm_Usecase] .load(dataDir+"usecase.png", "PNG");
+ m_pixmap[pm_InitialState].load(dataDir+"initial_state.png", "PNG");
+ m_pixmap[pm_EndState] .load(dataDir+"end_state.png", "PNG");
+ m_pixmap[pm_Branch] .load(dataDir+"branch.png", "PNG");
+ m_pixmap[pm_Object] .load(dataDir+"object.png", "PNG");
+ m_pixmap[pm_Component] .load(dataDir+"component.png", "PNG");
+ m_pixmap[pm_Node] .load(dataDir+"node.png", "PNG");
+ m_pixmap[pm_Entity] .load(dataDir+"entity.png", "PNG");
+ m_pixmap[pm_Artifact] .load(dataDir+"artifact.png", "PNG");
+ m_pixmap[pm_Text] .load(dataDir+"text.png", "PNG");
+ m_pixmap[pm_Subsystem] .load(dataDir+"subsystem.png", "PNG");
+
+ switch(type) {
+ case mt_Logical_View:
+ m_pInsert = new KPopupMenu(this);
+ insertContainerItems(true);
+ insertSeparator();
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertStdItem(mt_Import_Classes);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Component_View:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Component_Folder);
+ insertStdItem(mt_Subsystem);
+ insertStdItem(mt_Component);
+ insertStdItem(mt_Artifact);
+ insertStdItem(mt_Component_Diagram);
+ insertFileNew();
+ insertSeparator();
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Deployment_View:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Deployment_Folder);
+ insertStdItem(mt_Node);
+ insertStdItem(mt_Deployment_Diagram);
+ insertFileNew();
+ insertSeparator();
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_EntityRelationship_Model:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_EntityRelationship_Folder);
+ insertStdItem(mt_Entity);
+ insertStdItem(mt_EntityRelationship_Diagram);
+ insertFileNew();
+ insertSeparator();
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_UseCase_View:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_UseCase_Folder);
+ insertStdItem(mt_Actor);
+ insertStdItem(mt_UseCase);
+ insertStdItem(mt_UseCase_Diagram);
+ insertFileNew();
+ insertSeparator();
+ // insertStdItem(mt_Cut);
+ // insertStdItem(mt_Copy);
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Logical_Folder:
+ m_pInsert = new KPopupMenu(this);
+ insertContainerItems(true);
+ insertStdItems();
+ insertStdItem(mt_Import_Classes);
+ insertSubmodelAction();
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Component_Folder:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Component_Folder);
+ insertStdItem(mt_Subsystem);
+ insertStdItem(mt_Component);
+ insertStdItem(mt_Artifact);
+ insertStdItem(mt_Component_Diagram);
+ insertFileNew();
+ insertStdItems();
+ insertSubmodelAction();
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Deployment_Folder:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Deployment_Folder);
+ insertStdItem(mt_Node);
+ insertStdItem(mt_Deployment_Diagram);
+ insertFileNew();
+ insertStdItems();
+ insertSubmodelAction();
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_UseCase_Folder:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_UseCase_Folder);
+ insertStdItem(mt_Actor);
+ insertStdItem(mt_UseCase);
+ insertStdItem(mt_UseCase_Diagram);
+ insertFileNew();
+ insertStdItems();
+ insertSubmodelAction();
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_EntityRelationship_Folder:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_EntityRelationship_Folder);
+ insertStdItem(mt_Entity);
+ insertStdItem(mt_EntityRelationship_Diagram);
+ insertFileNew();
+ insertStdItems();
+ insertSubmodelAction();
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_UseCase_Diagram:
+ case mt_Sequence_Diagram:
+ case mt_Class_Diagram:
+ case mt_Collaboration_Diagram:
+ case mt_State_Diagram:
+ case mt_Activity_Diagram:
+ case mt_Component_Diagram:
+ case mt_Deployment_Diagram:
+ case mt_EntityRelationship_Diagram:
+ //don't insert standard items because cut/copy not currently
+ // possible with tabbed diagrams (it didn't work anyway)
+ //insertStdItems(false);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Export_Image);
+ insertStdItem(mt_Properties);
+ break;
+
+ //FIXME a lot of these insertItem()s could be insertStandardItem()s
+ case mt_On_UseCase_Diagram:
+ m_pInsert = new KPopupMenu( this );
+ m_pInsert -> insertItem(m_pixmap[pm_Actor], i18n( "Actor..." ), mt_Actor );
+ m_pInsert -> insertItem(m_pixmap[pm_Usecase], i18n( "Use Case..."), mt_UseCase );
+ insertStdItem(mt_FloatText );
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_Class_Diagram:
+ m_pInsert = new KPopupMenu( this );
+ m_pInsert -> insertItem(m_pixmap[pm_Class], i18n("Class..."), mt_Class);
+ m_pInsert->insertItem(m_pixmap[pm_Interface], i18n("Interface..."), mt_Interface);
+ m_pInsert->insertItem(m_pixmap[pm_Datatype], i18n("Datatype..."), mt_Datatype);
+ m_pInsert->insertItem(m_pixmap[pm_Enum], i18n("Enum..."), mt_Enum);
+ m_pInsert -> insertItem(m_pixmap[pm_Package], i18n("Package..."), mt_Package);
+ insertStdItem(mt_FloatText);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_State_Diagram:
+ m_pInsert = new KPopupMenu( this );
+ m_pInsert -> insertItem(m_pixmap[pm_InitialState], i18n("Initial State"), mt_Initial_State );
+ m_pInsert -> insertItem(m_pixmap[pm_EndState], i18n("End State"), mt_End_State );
+ m_pInsert -> insertItem(m_pixmap[pm_Usecase], i18n("State..."), mt_State );
+ insertStdItem(mt_FloatText);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_Activity_Diagram:
+ m_pInsert = new KPopupMenu( this );
+ m_pInsert -> insertItem(m_pixmap[pm_InitialState], i18n("Initial Activity"), mt_Initial_Activity );
+ m_pInsert -> insertItem(m_pixmap[pm_EndState], i18n("End Activity"), mt_End_Activity );
+ m_pInsert -> insertItem(m_pixmap[pm_Usecase], i18n("Activity..."), mt_Activity );
+ m_pInsert -> insertItem(m_pixmap[pm_Branch], i18n("Branch/Merge"), mt_Branch );
+ insertStdItem(mt_FloatText);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_Component_Diagram:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(m_pixmap[pm_Subsystem], i18n("Subsystem..."), mt_Subsystem);
+ m_pInsert->insertItem(m_pixmap[pm_Component], i18n("Component..."), mt_Component);
+ m_pInsert->insertItem(m_pixmap[pm_Artifact], i18n("Artifact..."), mt_Artifact);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_Deployment_Diagram:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(m_pixmap[pm_Node], i18n("Node..."), mt_Node);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_EntityRelationship_Diagram:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(m_pixmap[pm_Entity], i18n("Entity..."), mt_Entity);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_On_Sequence_Diagram:
+ case mt_On_Collaboration_Diagram:
+ m_pInsert = new KPopupMenu( this );
+ m_pInsert -> insertItem(m_pixmap[pm_Object], i18n("Object..."), mt_Object);
+ insertStdItem(mt_FloatText);
+ insertFileNew();
+ insertSeparator();
+ setupDiagramMenu(view);
+ break;
+
+ case mt_Class:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert -> insertItem(SmallIcon( "CVpublic_var"), i18n("Attribute"), mt_Attribute);
+ m_pInsert -> insertItem(SmallIcon( "CVpublic_meth"), i18n("Operation"), mt_Operation);
+ m_pInsert -> insertItem(SmallIcon("source"), i18n("Template"), mt_Template);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Interface:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(SmallIcon("CVpublic_meth"), i18n("Operation"), mt_Operation);
+ m_pInsert -> insertItem(SmallIcon("source"), i18n("Template"), mt_Template);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Package:
+ m_pInsert = new KPopupMenu(this);
+ insertContainerItems(false);
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Subsystem:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Subsystem);
+ insertStdItem(mt_Component);
+ insertStdItem(mt_Artifact);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Component:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_Component);
+ insertStdItem(mt_Artifact);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ insertSeparator();
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+
+ case mt_Entity:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(SmallIcon("source"), i18n("Entity Attribute..."), mt_EntityAttribute);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_EnumLiteral:
+ insertStdItems(false);
+ break;
+
+ case mt_Enum:
+ m_pInsert = new KPopupMenu(this);
+ m_pInsert->insertItem(SmallIcon("source"), i18n("Enum Literal..."), mt_EnumLiteral);
+ insertFileNew();
+ insertStdItems();
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Datatype:
+ case mt_Node:
+ case mt_Artifact:
+ case mt_Actor:
+ case mt_UseCase:
+ case mt_Attribute:
+ case mt_EntityAttribute:
+ case mt_Operation:
+ case mt_Template:
+ insertStdItems(false);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_New_Parameter:
+ insertStdItem(mt_New_Parameter);
+ break;
+
+ case mt_New_Operation:
+ insertStdItem(mt_New_Operation);
+ break;
+
+ case mt_New_Attribute:
+ insertStdItem(mt_New_Attribute);
+ break;
+
+ case mt_New_Template:
+ insertStdItem(mt_New_Template);
+ break;
+
+ case mt_New_EnumLiteral:
+ insertStdItem(mt_New_EnumLiteral);
+ break;
+
+ case mt_New_EntityAttribute:
+ insertStdItem(mt_New_EntityAttribute);
+ break;
+
+ case mt_New_Activity:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_New_Activity);
+ insertFileNew();
+ break;
+
+ case mt_Activity_Selected:
+ m_pInsert = new KPopupMenu(this);
+ insertStdItem(mt_New_Activity);
+ insertFileNew();
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Delete);
+ break;
+
+ case mt_Parameter_Selected:
+ insertStdItem(mt_New_Parameter);
+ insertStdItem(mt_Rename);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Operation_Selected:
+ insertStdItem(mt_New_Operation);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Attribute_Selected:
+ insertStdItem(mt_New_Attribute);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Template_Selected:
+ insertItem(SmallIcon("source"),i18n("New Template..."), mt_New_Attribute);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_EnumLiteral_Selected:
+ insertStdItem(mt_New_EnumLiteral);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_EntityAttribute_Selected:
+ insertStdItem(mt_New_EntityAttribute);
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Association_Selected:
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Line_Color);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_Anchor:
+ insertItem(SmallIcon( "editdelete"),i18n("Delete Anchor"), mt_Delete);
+ break;
+
+ case mt_RoleNameA:
+ insertAssocItem(i18n("Change Role A Name..."), mt_Rename_RoleAName);
+ break;
+
+ case mt_RoleNameB:
+ insertAssocItem(i18n("Change Role B Name..."), mt_Rename_RoleBName);
+ break;
+
+ case mt_MultiB:
+ insertAssocItem(i18n("Change Multiplicity..."), mt_Rename_MultiB);
+ break;
+
+ case mt_MultiA:
+ insertAssocItem(i18n("Change Multiplicity..."), mt_Rename_MultiA);
+ break;
+
+ case mt_Name:
+ insertAssocItem(i18n("Change Name"), mt_Rename_Name);
+ break;
+
+ case mt_FullAssociation:
+ insertStdItem(mt_Delete);
+ insertItem(i18n("Change Association Name..."), mt_Rename_Name);
+ insertItem(i18n("Change Role A Name..."), mt_Rename_RoleAName);
+ insertItem(i18n("Change Role B Name..."), mt_Rename_RoleBName);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_Reset_Label_Positions);
+ insertStdItem(mt_Line_Color);
+ insertStdItem(mt_Properties);
+ break;
+
+ case mt_AttributeAssociation:
+ insertStdItem(mt_Delete); // @todo add more items
+ break;
+
+ case mt_Collaboration_Message:
+ // insertStdItem(mt_Cut);
+ // insertStdItem(mt_Copy);
+ // insertStdItem(mt_Paste);
+ // insertSeparator();
+ insertStdItem(mt_Delete);
+ insertStdItem(mt_Change_Font);
+ insertStdItem(mt_New_Operation);
+ insertItem(i18n("Select Operation..."), mt_Select_Operation);
+ break;
+
+ case mt_Model:
+ insertItem(i18n("Rename..."), mt_Model);
+ break;
+
+ default:
+ insertStdItem(mt_Expand_All);
+ insertStdItem(mt_Collapse_All);
+ break;
+ }//end switch
+
+ if( view ) {
+ bool bCutState = UMLApp::app() -> getCutCopyState();
+ setItemEnabled( mt_Undo, UMLApp::app()->getUndoEnabled() );
+ setItemEnabled( mt_Redo, UMLApp::app()->getRedoEnabled() );
+ setItemEnabled( mt_Cut, bCutState );
+ setItemEnabled( mt_Copy, bCutState );
+ setItemEnabled( mt_Paste, UMLApp::app() -> getPasteState() );
+ }
+ if(m_pInsert)
+ connect(m_pInsert, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pShow)
+ connect(m_pShow, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+ if(m_pColor)
+ connect(m_pColor, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
+}
+
+void ListPopupMenu::setupDiagramMenu(UMLView* view) {
+ insertItem(SmallIcon("undo"), i18n("Undo"), mt_Undo);
+ insertItem(SmallIcon("redo"), i18n("Redo"), mt_Redo);
+ insertSeparator();
+ insertStdItem(mt_Cut);
+ insertStdItem(mt_Copy);
+ insertStdItem(mt_Paste);
+ insertSeparator();
+ insertItem(SmallIcon("editclear"), i18n("Clear Diagram"), mt_Clear);
+ insertStdItem(mt_Export_Image);
+ insertSeparator();
+ insertItem(i18n("Snap to Grid"), mt_SnapToGrid);
+ setItemChecked(mt_SnapToGrid, view->getSnapToGrid() );
+ insertItem(i18n("Show Grid"), mt_ShowSnapGrid );
+ setItemChecked(mt_ShowSnapGrid, view->getShowSnapGrid() );
+ insertStdItem(mt_Properties);
+}
+
diff --git a/umbrello/umbrello/listpopupmenu.h b/umbrello/umbrello/listpopupmenu.h
new file mode 100644
index 00000000..58d779ab
--- /dev/null
+++ b/umbrello/umbrello/listpopupmenu.h
@@ -0,0 +1,330 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef LISTPOPUPMENU_H
+#define LISTPOPUPMENU_H
+
+#include <kpopupmenu.h>
+#include "umlnamespace.h"
+
+class UMLView;
+class UMLWidget;
+class ClassifierWidget;
+
+/**
+ * A popup menu that depending on what type it is set to will
+ * display a different menu.
+ *
+ * @short Displays a popup menu.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class ListPopupMenu : public KPopupMenu {
+public:
+
+ /// This type hosts all possible menu types.
+ enum Menu_Type
+ {
+ mt_Model,
+ mt_Logical_View,
+ mt_UseCase_View,
+ mt_Component_View,
+ mt_Deployment_View,
+ mt_EntityRelationship_Model,
+ mt_UseCase_Diagram,
+ mt_Sequence_Diagram,
+ mt_Class_Diagram,
+ mt_Collaboration_Diagram,
+ mt_State_Diagram,
+ mt_Activity_Diagram,
+ mt_Component_Diagram,
+ mt_Deployment_Diagram,
+ mt_EntityRelationship_Diagram,
+ mt_On_UseCase_Diagram,
+ mt_On_Sequence_Diagram,
+ mt_On_Class_Diagram,
+ mt_On_Collaboration_Diagram,
+ mt_On_State_Diagram,
+ mt_On_Activity_Diagram,
+ mt_On_Component_Diagram,
+ mt_On_Deployment_Diagram,
+ mt_On_EntityRelationship_Diagram,
+ mt_Logical_Folder,
+ mt_UseCase_Folder,
+ mt_Component_Folder,
+ mt_Deployment_Folder,
+ mt_EntityRelationship_Folder,
+ mt_Class,
+ mt_Package,
+ mt_Subsystem,
+ mt_Component,
+ mt_Node,
+ mt_Artifact,
+ mt_Interface,
+ mt_Enum,
+ mt_Entity,
+ mt_Datatype,
+ mt_Actor,
+ mt_UseCase,
+ mt_Attribute,
+ mt_EntityAttribute,
+ mt_EnumLiteral,
+ mt_Object,
+ mt_Initial_State,
+ mt_End_State,
+ mt_State,
+ mt_Activity,
+ mt_Initial_Activity,
+ mt_End_Activity,
+ mt_Operation,
+ mt_Template,
+ mt_New_Parameter,
+ mt_New_Operation,
+ mt_New_Attribute,
+ mt_New_Template,
+ mt_New_EnumLiteral,
+ mt_New_EntityAttribute,
+ mt_Parameter_Selected,
+ mt_Operation_Selected,
+ mt_Attribute_Selected,
+ mt_Template_Selected,
+ mt_EnumLiteral_Selected,
+ mt_EntityAttribute_Selected,
+ mt_Association_Selected, // Association without role names
+ mt_Show_Attributes,
+ mt_Show_Attributes_Selection, //SHOWATTS, multiple items
+ mt_Show_Operations,
+ mt_Show_Operations_Selection, //SHOWOPS, multiple items
+ mt_Show_Packages,
+ mt_Show_Packages_Selection, //SHOWPACKAGE, multiple items
+ mt_Show_Stereotypes,
+ mt_Show_Stereotypes_Selection, //SHOWSTEREOTYPE, multiple items
+ mt_Visibility,
+ mt_Visibility_Selection, //SCOPE, multiple items
+ mt_DrawAsCircle,
+ mt_DrawAsCircle_Selection, //DRAWASCIRCLE, multiple items
+ mt_ChangeToClass,
+ mt_ChangeToClass_Selection,
+ mt_ChangeToInterface,
+ mt_ChangeToInterface_Selection,
+ mt_Rename_Object,
+ mt_Select_Operation,
+ mt_Anchor,
+ mt_Properties,
+ mt_Rename,
+ mt_Delete,
+ mt_Export_Image,
+ mt_Import_Classes,
+ mt_Sequence_Number,
+ mt_Cut,
+ mt_Copy,
+ mt_Paste,
+ mt_Clear,
+ mt_Redo,
+ mt_Undo,
+ mt_Link_Docs,
+ mt_Show_Operation_Signature,
+ mt_Show_Operation_Signature_Selection, //SHOWOPSIG, multiple items
+ mt_Show_Attribute_Signature,
+ mt_Show_Attribute_Signature_Selection, //SHOWATTSIG, multiple items
+ mt_Message_Text,
+ mt_Collaboration_Message,
+ mt_FloatText,
+ mt_MultiA,
+ mt_MultiB,
+ mt_Name, //Association name
+ mt_FullAssociation, // Association with role names
+ mt_AttributeAssociation, // Rendering of an attribute as an association
+ mt_RoleNameA,
+ mt_RoleNameB,
+ mt_Delete_Selection,
+ mt_Reset_Label_Positions,
+ mt_Line_Color,
+ mt_Line_Color_Selection, //LINECOLOR, multiple items
+ mt_Fill_Color,
+ mt_Fill_Color_Selection, //FILLCOLOR, multiple items
+ mt_Use_Fill_Color,
+ mt_Default_Properties,
+ mt_Rename_MultiA,
+ mt_Rename_MultiB,
+ mt_Rename_Name,
+ mt_Rename_RoleAName,
+ mt_Rename_RoleBName,
+ mt_Change_Font,
+ mt_Change_Font_Selection,
+ mt_SnapToGrid,
+ mt_ShowSnapGrid,
+ mt_Activity_Selected,
+ mt_New_Activity,
+ mt_Up,
+ mt_Down,
+ mt_Branch,
+ mt_Flip,
+
+ mt_Expand_All, //Expand all items in the list
+ mt_Collapse_All, //Collapse all items in the list
+
+ mt_Refactoring,
+ mt_ViewCode, // view code document contents
+ mt_Clone, // Create a deep copy of the object.
+ mt_Show_Public_Only, // (not currently used)
+ mt_Show_Public_Only_Selection, // Show public operations/attributes only.
+ mt_Externalize_Folder, // Mark folder for saving as separate submodel
+ mt_Internalize_Folder, // Reintegrate separate submodel into main model
+
+ mt_Undefined = - 1
+ };
+
+ /**
+ * Constructs the popup menu for a diagram
+ *
+ * @param parent The parent to ListPopupMenu.
+ * @param type The type of menu to display.
+ * @param view The UMLView in which this ListPopupMenu is going to be displayed
+ */
+ explicit ListPopupMenu(QWidget* parent, Menu_Type type = mt_Undefined, UMLView* view = 0);
+
+ /**
+ * Constructs the popup menu for a list view item.
+ *
+ * @param parent The parent to ListPopupMenu.
+ * @param type The type of menu to display.
+ */
+ ListPopupMenu(QWidget* parent, Uml::ListView_Type type);
+
+ /**
+ * Constructs the popup menu for a canvas widget.
+ *
+ * @param parent The parent to ListPopupMenu.
+ * @param object The UMLWidget to represent a menu for.
+ * @param multi True if multiple items are selected.
+ * @param unique True if multiple selected items all have
+ * the same type (e.g. Class, Interface)
+ */
+ ListPopupMenu(QWidget* parent, UMLWidget* object, bool multi = false, bool unique = false);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~ListPopupMenu();
+
+ /**
+ * Utility: Convert a Menu_Type value to an Object_Type value.
+ */
+ static Uml::Object_Type convert_MT_OT(Menu_Type mt);
+
+ /**
+ * Utility: Convert a Menu_Type value to a Diagram_Type value.
+ */
+ static Uml::Diagram_Type convert_MT_DT(Menu_Type mt);
+
+private:
+ /**
+ * Basic initialization - common to all constructors.
+ */
+ void init();
+
+ /**
+ * Shortcut for inserting a "File->New" choice.
+ */
+ void insertFileNew();
+
+ /**
+ * Shortcut for the most frequently used insertItem() calls.
+ *
+ * @param m The Menu_Type for which to insert a menu item.
+ */
+ void insertStdItem(Menu_Type m);
+
+ /**
+ * Shortcut for the most frequently used insertStdItem() calls.
+ *
+ * @param insertLeadingSeparator Set this true if the group shall
+ * start with a separator.
+ * @param type The Widget_Type for which to insert the menu items.
+ * If no argument is supplied then a Rename item will be
+ * included.
+ */
+ void insertStdItems(bool insertLeadingSeparator = true,
+ Uml::Widget_Type type = Uml::wt_UMLWidget);
+
+ /**
+ * Shortcut for inserting standard model items (Class, Interface,
+ * Datatype, Enum, Package) as well as diagram choices.
+ *
+ * @param folderAndDiagrams Set this true if folders and diagram
+ * types shall be included as choices.
+ */
+ void insertContainerItems(bool folderAndDiagrams);
+
+ /**
+ * Inserts a menu item for an association related text
+ * (such as name, role, multiplicity etc.)
+ *
+ * @param label The menu text.
+ * @param mt The menu type.
+ */
+ void insertAssocItem(const QString &label, Menu_Type mt);
+
+ /**
+ * Inserts a menu item for externalization/de-externalization
+ * of a folder.
+ */
+ void insertSubmodelAction();
+
+ /**
+ * Creates a popup menu for a multiple selection of class and
+ * interface widgets.
+ */
+ void makeMultiClassifierPopup(ClassifierWidget *c);
+
+ /**
+ * Creates a popup menu for a single class or interface widgets.
+ */
+ void makeClassifierPopup(ClassifierWidget *c);
+
+ /**
+ * Shortcut for commonly used menu initializations.
+ *
+ * @param type The Menu_Type for which to set up the menu.
+ * @param view The UMLView parent of the menu.
+ */
+ void setupMenu(Menu_Type type, UMLView * view = 0);
+
+ enum PixMap_Type {
+ pm_Class,
+ pm_Package,
+ pm_Interface,
+ pm_Datatype,
+ pm_Enum,
+ pm_Actor,
+ pm_Usecase,
+ pm_InitialState,
+ pm_EndState,
+ pm_Branch,
+ pm_Object,
+ pm_Component,
+ pm_Node,
+ pm_Artifact,
+ pm_Text,
+ pm_Entity,
+ pm_Subsystem,
+ pm_NUMBER_OF_PIXMAPS
+ };
+ QPixmap m_pixmap[pm_NUMBER_OF_PIXMAPS];
+ KPopupMenu * m_pInsert, * m_pShow, * m_pColor;
+ void setupColor(bool fc);
+ void setupColorSelection(bool fc);
+ void setupDiagramMenu(UMLView* view);
+};
+
+#endif
diff --git a/umbrello/umbrello/main.cpp b/umbrello/umbrello/main.cpp
new file mode 100644
index 00000000..faba82d3
--- /dev/null
+++ b/umbrello/umbrello/main.cpp
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include <unistd.h>
+
+// kde includes
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <ktip.h>
+#include <kdebug.h>
+#include <kwin.h>
+
+// app includes
+#include "uml.h"
+#include "version.h"
+#include "umldoc.h"
+#include "cmdlineexportallviewsevent.h"
+#include "kstartuplogo.h"
+
+static const char description[] =
+ I18N_NOOP("Umbrello UML Modeller");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+/**
+ * @todo Add options to use the documentation generators from command line.
+ */
+static KCmdLineOptions options[] =
+ {
+ { "+[File]", I18N_NOOP("File to open"), 0 },
+ { "export <extension>", I18N_NOOP("export diagrams to extension and exit"), 0},
+ { "directory <url>", I18N_NOOP("the local directory to save the exported diagrams in"), I18N_NOOP("the directory of the file")},
+ { "use-folders", I18N_NOOP("keep the tree structure used to store the views in the document in the target directory"), 0},
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+ KCmdLineLastOption
+ };
+
+/**
+ * Determines if the application GUI should be shown based on command line arguments.
+ *
+ * @param args The command line arguments given.
+ * @return True if the GUI should be shown, false otherwise.
+ */
+bool getShowGUI(KCmdLineArgs *args);
+
+/**
+ * Creates, shows and returns the startup logo for the application if it should be shown,
+ * else returns null pointer.
+ * The startup logo is shown if it is configured to be shown and also the GUI must be shown.
+ *
+ * @param cfg The application configuration.
+ * @param showGUI If the GUI should be shown.
+ * @return The startup logo for the application, or a null pointer if it shouldn't be shown.
+ */
+KStartupLogo* showStartupLogo(KConfig* cfg, bool showGUI);
+
+/**
+ * Initializes the document used by the application.
+ * If a file was specified in command line arguments, opens that file. Else, it
+ * opens the last opened file, or a new file if there isn't any "last file used"
+ * in the configuration.
+ *
+ * @param args The command line arguments given.
+ * @param cfg The application configuration.
+ */
+void initDocument(KCmdLineArgs *args, KConfig* cfg);
+
+/**
+ * Export all the views in the document using the command line args set by the user.
+ * Errors that occurred while exporting, if any, are shown using kError().
+ *
+ * @param args The command line arguments given.
+ * @param exportOpt A list containing all the "export" arguments given.
+ */
+void exportAllViews(KCmdLineArgs *args, const QCStringList &exportOpt);
+
+extern "C" int flushEvents() {
+ kapp->processEvents();
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ KAboutData aboutData( "umbrello", I18N_NOOP("Umbrello UML Modeller"),
+ UMBRELLO_VERSION, description, KAboutData::License_GPL,
+ I18N_NOOP("(c) 2001 Paul Hensgen, (c) 2002-2006 Umbrello UML Modeller Authors"), 0,
+ "http://uml.sf.net/");
+ aboutData.addAuthor("Paul Hensgen",0, "phensgen@users.sourceforge.net");
+ aboutData.addAuthor(I18N_NOOP("Umbrello UML Modeller Authors"), 0, "uml-devel@lists.sourceforge.net");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ KApplication app;
+ if( app.isRestored() ) {
+ RESTORE( UMLApp );
+ } else {
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ bool showGUI = getShowGUI(args);
+
+ UMLApp *uml = new UMLApp();
+ flushEvents();
+ KConfig * cfg = app.config();
+
+ KStartupLogo* startLogo = showStartupLogo(cfg, showGUI);
+
+ if (showGUI) {
+ uml->show();
+ }
+ uml->initGenerator();
+
+ //show tips if wanted
+ if (showGUI) {
+ KTipDialog::showTip();
+ }
+
+ initDocument(args, cfg);
+
+ // export option
+ QCStringList exportOpt = args->getOptionList("export");
+ if (exportOpt.size() > 0) {
+ exportAllViews(args, exportOpt);
+ }
+
+ if ( showGUI && (startLogo != 0L) && !startLogo->isHidden() ) {
+ startLogo->raise();
+ }
+ }
+ return app.exec();
+}
+
+bool getShowGUI(KCmdLineArgs *args) {
+ if (args->getOptionList("export").size() > 0) {
+ return false;
+ }
+
+ return true;
+}
+
+KStartupLogo* showStartupLogo(KConfig* cfg, bool showGUI) {
+ KStartupLogo* startLogo = 0L;
+
+ cfg->setGroup( "General Options" );
+ bool showLogo = cfg->readBoolEntry( "logo", true );
+ if (showGUI && showLogo) {
+#if KDE_IS_VERSION(3,3,90)
+ startLogo = new KStartupLogo(0);
+ startLogo->setHideEnabled(true);
+ KWin::setMainWindow(startLogo, UMLApp::app()->winId());
+#else
+ startLogo = new KStartupLogo(UMLApp::app());
+ startLogo->setHideEnabled(true);
+#endif
+ KWin::setState(startLogo->winId(), NET::KeepAbove);
+ startLogo->show();
+ QApplication::flushX();
+ }
+
+ return startLogo;
+}
+
+void initDocument(KCmdLineArgs *args, KConfig* cfg) {
+ if ( args -> count() ) {
+ UMLApp::app()->openDocumentFile( args->url( 0 ) );
+ } else {
+ cfg->setGroup( "General Options" );
+ bool last = cfg->readBoolEntry( "loadlast", false );
+ QString file = cfg->readPathEntry( "lastFile" );
+ if( last && !file.isEmpty() ) {
+ UMLApp::app()->openDocumentFile( KURL( file ) );
+ } else {
+ UMLApp::app()->newDocument();
+ }
+ }
+}
+
+void exportAllViews(KCmdLineArgs *args, const QCStringList &exportOpt) {
+ QString extension(exportOpt.last());
+ kDebug() << "extension: " << extension << endl;
+
+ // export to the specified directory, or the directory where the file is saved
+ // if no directory was specified
+ KURL directory;
+ QCStringList directoryOpt = args->getOptionList("directory");
+ if (directoryOpt.size() > 0) {
+ directory = KCmdLineArgs::makeURL(directoryOpt.last());
+ } else {
+ directory = KURL(UMLApp::app()->getDocument()->URL().directory());
+ }
+
+ bool useFolders = args->isSet("use-folders");
+
+ kDebug() << "directory: " << directory.prettyURL() << endl;
+
+ // the event is posted so when the QT loop begins it's processed. UMLApp process this event executing
+ // the method it provides for exporting the views. Once all the views were exported, a quit event
+ // is sent and the app finishes without user interaction
+ kapp->postEvent(UMLApp::app(), new CmdLineExportAllViewsEvent(extension, directory, useFolders));
+}
+
diff --git a/umbrello/umbrello/messagewidget.cpp b/umbrello/umbrello/messagewidget.cpp
new file mode 100644
index 00000000..3cefc99d
--- /dev/null
+++ b/umbrello/umbrello/messagewidget.cpp
@@ -0,0 +1,792 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// onw header
+#include "messagewidget.h"
+
+//qt includes
+#include <qpainter.h>
+//kde includes
+#include <kdebug.h>
+#include <kcursor.h>
+//app includes
+#include "messagewidgetcontroller.h"
+#include "floatingtextwidget.h"
+#include "objectwidget.h"
+#include "classifier.h"
+#include "operation.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "uniqueid.h"
+#include "listpopupmenu.h"
+
+MessageWidget::MessageWidget(UMLView * view, ObjectWidget* a, ObjectWidget* b,
+ int y, Uml::Sequence_Message_Type sequenceMessageType,
+ Uml::IDType id /* = Uml::id_None */)
+ : UMLWidget(view, id, new MessageWidgetController(this)) {
+ init();
+ m_pOw[Uml::A] = a;
+ m_pOw[Uml::B] = b;
+ m_nY = y;
+ m_sequenceMessageType = sequenceMessageType;
+ if (m_sequenceMessageType == Uml::sequence_message_creation) {
+ y -= m_pOw[Uml::B]->getHeight() / 2;
+ m_pOw[Uml::B]->setY(y);
+ }
+ updateResizability();
+ calculateWidget();
+ y = y < getMinY() ? getMinY() : y;
+ y = y > getMaxY() ? getMaxY() : y;
+ m_nY = y;
+
+ this->activate();
+}
+
+MessageWidget::MessageWidget(UMLView * view, Uml::Sequence_Message_Type seqMsgType, Uml::IDType id)
+ : UMLWidget(view, id, new MessageWidgetController(this)) {
+ init();
+ m_sequenceMessageType = seqMsgType;
+}
+
+void MessageWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Message);
+ m_bIgnoreSnapToGrid = true;
+ m_bIgnoreSnapComponentSizeToGrid = true;
+ m_pOw[Uml::A] = m_pOw[Uml::B] = NULL;
+ m_pFText = NULL;
+ m_nY = 0;
+ setVisible(true);
+}
+
+MessageWidget::~MessageWidget() {
+}
+
+void MessageWidget::updateResizability() {
+ if (m_sequenceMessageType == Uml::sequence_message_synchronous ||
+ m_pOw[Uml::A] == m_pOw[Uml::B])
+ UMLWidget::m_bResizable = true;
+ else
+ UMLWidget::m_bResizable = false;
+}
+
+void MessageWidget::draw(QPainter& p, int offsetX, int offsetY) {
+ if(!m_pOw[Uml::A] || !m_pOw[Uml::B]) {
+ return;
+ }
+ UMLWidget::setPen(p);
+ if (m_sequenceMessageType == Uml::sequence_message_synchronous) {
+ drawSynchronous(p, offsetX, offsetY);
+ } else if (m_sequenceMessageType == Uml::sequence_message_asynchronous) {
+ drawAsynchronous(p, offsetX, offsetY);
+ } else if (m_sequenceMessageType == Uml::sequence_message_creation) {
+ drawCreation(p, offsetX, offsetY);
+ } else {
+ kWarning() << "Unknown message type" << endl;
+ }
+}
+
+void MessageWidget::drawSolidArrowhead(QPainter& p, int x, int y, Qt::ArrowType direction) {
+ int arrowheadExtentX = 4;
+ if (direction == Qt::RightArrow) {
+ arrowheadExtentX = -arrowheadExtentX;
+ }
+ QPointArray points;
+ points.putPoints(0, 3, x, y, x + arrowheadExtentX, y - 3, x + arrowheadExtentX, y + 3);
+ p.setBrush( QBrush(p.pen().color()) );
+ p.drawPolygon(points);
+}
+
+void MessageWidget::drawArrow(QPainter& p, int x, int y, int w,
+ Qt::ArrowType direction, bool useDottedLine /* = false */) {
+ int arrowheadStartX = x;
+ int arrowheadExtentX = 4;
+ if (direction == Qt::RightArrow) {
+ arrowheadStartX += w;
+ arrowheadExtentX = -arrowheadExtentX;
+ }
+ // draw upper half of arrowhead
+ p.drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y - 3);
+ // draw lower half of arrowhead
+ p.drawLine(arrowheadStartX, y, arrowheadStartX + arrowheadExtentX, y + 3);
+ // draw arrow line
+ if (useDottedLine) {
+ QPen pen = p.pen();
+ pen.setStyle(Qt::DotLine);
+ p.setPen(pen);
+ }
+ p.drawLine(x, y, x + w, y);
+}
+
+void MessageWidget::drawSynchronous(QPainter& p, int offsetX, int offsetY) {
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w = getWidth() - 1;
+ int h = getHeight();
+
+ bool messageOverlaps = m_pOw[Uml::A] -> messageOverlap( getY(), this );
+
+ if(m_pOw[Uml::A] == m_pOw[Uml::B]) {
+ p.fillRect( offsetX, offsetY, 17, h, QBrush(Qt::white) ); //box
+ p.drawRect(offsetX, offsetY, 17, h); //box
+ offsetX += 17;
+ w -= 17;
+ offsetY += 3;
+ const int lowerLineY = offsetY + h - 6;
+ // draw upper line segment (leaving the life line)
+ p.drawLine(offsetX, offsetY, offsetX + w, offsetY);
+ // draw line segment parallel to (and at the right of) the life line
+ p.drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
+ // draw lower line segment (back to the life line)
+ drawArrow(p, offsetX, lowerLineY, w, Qt::LeftArrow);
+ offsetX -= 17;
+ offsetY -= 3;
+ } else if(x1 < x2) {
+ if (messageOverlaps) {
+ offsetX += 8;
+ w -= 8;
+ }
+ QPen pen = p.pen();
+ int startX = offsetX + w - 16;
+ p.fillRect(startX, offsetY, 17, h, QBrush(Qt::white)); //box
+ p.drawRect(startX, offsetY, 17, h); //box
+ p.drawLine(offsetX, offsetY + 4, startX, offsetY + 4); //arrow line
+ drawSolidArrowhead(p, startX - 1, offsetY + 4, Qt::RightArrow);
+ drawArrow(p, offsetX, offsetY + h - 3, w - 16, Qt::LeftArrow, true); // return arrow
+ if (messageOverlaps) {
+ offsetX -= 8; //reset for drawSelected()
+ }
+ } else {
+ if (messageOverlaps) {
+ w -=8;
+ }
+ QPen pen = p.pen();
+ p.fillRect( offsetX, offsetY, 17, h, QBrush(Qt::white) ); //box
+ p.drawRect(offsetX, offsetY, 17, h); //box
+ p.drawLine(offsetX + 18, offsetY + 4, offsetX + w, offsetY + 4); //arrow line
+ drawSolidArrowhead(p, offsetX + 17, offsetY + 4, Qt::LeftArrow);
+ drawArrow(p, offsetX + 18, offsetY + h - 3, w - 18, Qt::RightArrow, true); // return arrow
+ }
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+void MessageWidget::drawAsynchronous(QPainter& p, int offsetX, int offsetY) {
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w = getWidth() - 1;
+ int h = getHeight() - 1;
+ bool messageOverlapsA = m_pOw[Uml::A] -> messageOverlap( getY(), this );
+ //bool messageOverlapsB = m_pOw[Uml::B] -> messageOverlap( getY(), this );
+
+ if(m_pOw[Uml::A] == m_pOw[Uml::B]) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ const int lowerLineY = offsetY + h - 3;
+ // draw upper line segment (leaving the life line)
+ p.drawLine(offsetX, offsetY, offsetX + w, offsetY);
+ // draw line segment parallel to (and at the right of) the life line
+ p.drawLine(offsetX + w, offsetY, offsetX + w, lowerLineY);
+ // draw lower line segment (back to the life line)
+ drawArrow(p, offsetX, lowerLineY, w, Qt::LeftArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7; //reset for drawSelected()
+ }
+ } else if(x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ drawArrow(p, offsetX, offsetY + 4, w, Qt::RightArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ if (messageOverlapsA) {
+ w -= 7;
+ }
+ drawArrow(p, offsetX, offsetY + 4, w, Qt::LeftArrow);
+ }
+
+ if (m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+void MessageWidget::drawCreation(QPainter& p, int offsetX, int offsetY) {
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w = getWidth() - 1;
+ //int h = getHeight() - 1;
+ bool messageOverlapsA = m_pOw[Uml::A] -> messageOverlap( getY(), this );
+ //bool messageOverlapsB = m_pOw[Uml::B] -> messageOverlap( getY(), this );
+
+ const int lineY = offsetY + 4;
+ if (x1 < x2) {
+ if (messageOverlapsA) {
+ offsetX += 7;
+ w -= 7;
+ }
+ drawArrow(p, offsetX, lineY, w, Qt::RightArrow);
+ if (messageOverlapsA) {
+ offsetX -= 7;
+ }
+ } else {
+ if (messageOverlapsA) {
+ w -= 7;
+ }
+ drawArrow(p, offsetX, lineY, w, Qt::LeftArrow);
+ }
+
+ if (m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+int MessageWidget::onWidget(const QPoint & p) {
+ if (m_sequenceMessageType != Uml::sequence_message_synchronous) {
+ return UMLWidget::onWidget(p);
+ }
+ // Synchronous message:
+ // Consists of top arrow (call) and bottom arrow (return.)
+ if (p.x() < getX() || p.x() > getX() + getWidth())
+ return 0;
+ const int tolerance = 5; // pixels
+ const int pY = p.y();
+ const int topArrowY = getY() + 3;
+ const int bottomArrowY = getY() + getHeight() - 3;
+ if (pY < topArrowY - tolerance || pY > bottomArrowY + tolerance)
+ return 0;
+ if (getHeight() <= 2 * tolerance)
+ return 1;
+ if (pY > topArrowY + tolerance && pY < bottomArrowY - tolerance)
+ return 0;
+ return 1;
+}
+
+void MessageWidget::setTextPosition() {
+ if (m_pFText == NULL) {
+ kDebug() << "MessageWidget::setTextPosition: m_pFText is NULL"
+ << endl;
+ return;
+ }
+ if (m_pFText->getDisplayText().isEmpty()) {
+ return;
+ }
+ m_pFText->updateComponentSize();
+ int ftX = constrainX(m_pFText->getX(), m_pFText->getWidth(), m_pFText->getRole());
+ int ftY = getY() - m_pFText->getHeight();
+ m_pFText->setX( ftX );
+ m_pFText->setY( ftY );
+}
+
+int MessageWidget::constrainX(int textX, int textWidth, Uml::Text_Role tr) {
+ int result = textX;
+ const int minTextX = getX() + 5;
+ if (textX < minTextX || tr == Uml::tr_Seq_Message_Self) {
+ result = minTextX;
+ } else {
+ ObjectWidget *objectAtRight = NULL;
+ if (m_pOw[Uml::B]->getX() > m_pOw[Uml::A]->getX())
+ objectAtRight = m_pOw[Uml::B];
+ else
+ objectAtRight = m_pOw[Uml::A];
+ const int objRight_seqLineX = objectAtRight->getX() + objectAtRight->getWidth() / 2;
+ const int maxTextX = objRight_seqLineX - textWidth - 5;
+ if (maxTextX <= minTextX)
+ result = minTextX;
+ else if (textX > maxTextX)
+ result = maxTextX;
+ }
+ return result;
+}
+
+void MessageWidget::constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
+ Uml::Text_Role tr) {
+ textX = constrainX(textX, textWidth, tr);
+ // Constrain Y.
+ const int minTextY = getMinY();
+ const int maxTextY = getMaxY() - textHeight - 5;
+ if (textY < minTextY)
+ textY = minTextY;
+ else if (textY > maxTextY)
+ textY = maxTextY;
+// setY( textY + textHeight ); // NB: side effect
+}
+
+void MessageWidget::setLinkAndTextPos() {
+ if (m_pFText == NULL)
+ return;
+ m_pFText->setLink(this);
+ setTextPosition();
+}
+
+void MessageWidget::moveEvent(QMoveEvent* /*m*/) {
+ //kDebug() << "MessageWidget::moveEvent: m_pFText is " << m_pFText << endl;
+ if (!m_pFText) {
+ return;
+ }
+ //TODO why this condition?
+/* if (m_pView->getSelectCount() > 2) {
+ return;
+ }*/
+
+ setTextPosition();
+
+ emit sigMessageMoved();
+}
+
+void MessageWidget::resizeEvent(QResizeEvent* /*re*/) {
+}
+
+void MessageWidget::calculateWidget() {
+ setMessageText(m_pFText);
+ calculateDimensions();
+
+ setVisible(true);
+
+ setX(m_nPosX);
+ setY(m_nY);
+}
+
+void MessageWidget::slotWidgetMoved(Uml::IDType id) {
+ const Uml::IDType idA = m_pOw[Uml::A]->getLocalID();
+ const Uml::IDType idB = m_pOw[Uml::B]->getLocalID();
+ if (idA != id && idB != id) {
+ kDebug() << "MessageWidget::slotWidgetMoved(" << ID2STR(id)
+ << "): ignoring for idA=" << ID2STR(idA)
+ << ", idB=" << ID2STR(idB) << endl;
+ return;
+ }
+ m_nY = getY();
+ if (m_nY < getMinY())
+ m_nY = getMinY();
+ if (m_nY > getMaxY())
+ m_nY = getMaxY();
+ calculateWidget();
+ if( !m_pFText )
+ return;
+ if (m_pView->getSelectCount(true) > 1)
+ return;
+ setTextPosition();
+}
+
+bool MessageWidget::contains(ObjectWidget * w) {
+ if(m_pOw[Uml::A] == w || m_pOw[Uml::B] == w)
+ return true;
+ else
+ return false;
+}
+
+void MessageWidget::slotMenuSelection(int sel) {
+ if(sel == ListPopupMenu::mt_Delete) {
+ // This will clean up this widget and the text widget:
+ m_pView -> removeWidget(this);
+ } else {
+ if (m_pFText == NULL) {
+ Uml::Text_Role tr = Uml::tr_Seq_Message;
+ if (m_pOw[Uml::A] == m_pOw[Uml::B])
+ tr = Uml::tr_Seq_Message_Self;
+ m_pFText = new FloatingTextWidget( m_pView, tr );
+ m_pFText->setFont(UMLWidget::getFont());
+ setLinkAndTextPos();
+ m_pView->getWidgetList().append(m_pFText);
+ }
+ m_pFText -> slotMenuSelection(sel);
+ }
+}
+
+bool MessageWidget::activate(IDChangeLog * Log /*= 0*/) {
+ m_pView->resetPastePoint();
+ // UMLWidget::activate(Log); CHECK: I don't think we need this ?
+ if (m_pOw[Uml::A] == NULL) {
+ UMLWidget *pWA = m_pView->findWidget(m_widgetAId);
+ if (pWA == NULL) {
+ kDebug() << "MessageWidget::activate: role A object "
+ << ID2STR(m_widgetAId) << " not found" << endl;
+ return false;
+ }
+ m_pOw[Uml::A] = dynamic_cast<ObjectWidget*>(pWA);
+ if (m_pOw[Uml::A] == NULL) {
+ kDebug() << "MessageWidget::activate: role A widget "
+ << ID2STR(m_widgetAId) << " is not an ObjectWidget" << endl;
+ return false;
+ }
+ }
+ if (m_pOw[Uml::B] == NULL) {
+ UMLWidget *pWB = m_pView->findWidget(m_widgetBId);
+ if (pWB == NULL) {
+ kDebug() << "MessageWidget::activate: role B object "
+ << ID2STR(m_widgetBId) << " not found" << endl;
+ return false;
+ }
+ m_pOw[Uml::B] = dynamic_cast<ObjectWidget*>(pWB);
+ if (m_pOw[Uml::B] == NULL) {
+ kDebug() << "MessageWidget::activate: role B widget "
+ << ID2STR(m_widgetBId) << " is not an ObjectWidget" << endl;
+ return false;
+ }
+ }
+ updateResizability();
+
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(m_pOw[Uml::B]->getUMLObject());
+ UMLOperation *op = NULL;
+ if (c && !m_CustomOp.isEmpty()) {
+ Uml::IDType opId = STR2ID(m_CustomOp);
+ op = dynamic_cast<UMLOperation*>( c->findChildObjectById(opId, true) );
+ if (op) {
+ // If the UMLOperation is set, m_CustomOp isn't used anyway.
+ // Just setting it empty for the sake of sanity.
+ m_CustomOp = QString::null;
+ }
+ }
+
+ if( !m_pFText ) {
+ Uml::Text_Role tr = Uml::tr_Seq_Message;
+ if (m_pOw[Uml::A] == m_pOw[Uml::B])
+ tr = Uml::tr_Seq_Message_Self;
+ m_pFText = new FloatingTextWidget( m_pView, tr, "" );
+ m_pFText->setFont(UMLWidget::getFont());
+ }
+ if (op)
+ setOperation(op); // This requires a valid m_pFText.
+ setLinkAndTextPos();
+ m_pFText -> setText("");
+ m_pFText->setActivated();
+ QString messageText = m_pFText->getText();
+ m_pFText->setVisible( messageText.length() > 1 );
+
+ connect(m_pOw[Uml::A], SIGNAL(sigWidgetMoved(Uml::IDType)), this, SLOT(slotWidgetMoved(Uml::IDType)));
+ connect(m_pOw[Uml::B], SIGNAL(sigWidgetMoved(Uml::IDType)), this, SLOT(slotWidgetMoved(Uml::IDType)));
+
+ connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::A], SLOT(slotMessageMoved()) );
+ connect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::B], SLOT(slotMessageMoved()) );
+ m_pOw[Uml::A] -> messageAdded(this);
+ m_pOw[Uml::B] -> messageAdded(this);
+ calculateDimensions();
+
+ emit sigMessageMoved();
+ return true;
+}
+
+void MessageWidget::setMessageText(FloatingTextWidget *ft) {
+ if (ft == NULL)
+ return;
+ QString displayText = m_SequenceNumber + ": " + getOperationText(m_pView);
+ ft->setText(displayText);
+ setTextPosition();
+}
+
+void MessageWidget::setText(FloatingTextWidget *ft, const QString &newText) {
+ ft->setText(newText);
+ UMLApp::app()->getDocument()->setModified(true);
+}
+
+void MessageWidget::setSeqNumAndOp(const QString &seqNum, const QString &op) {
+ setSequenceNumber( seqNum );
+ m_CustomOp = op; ///FIXME m_pOperation
+}
+
+void MessageWidget::setSequenceNumber( const QString &sequenceNumber ) {
+ m_SequenceNumber = sequenceNumber;
+}
+
+QString MessageWidget::getSequenceNumber() const {
+ return m_SequenceNumber;
+}
+
+void MessageWidget::lwSetFont (QFont font) {
+ UMLWidget::setFont( font );
+}
+
+UMLClassifier *MessageWidget::getOperationOwner() {
+ UMLObject *pObject = m_pOw[Uml::B]->getUMLObject();
+ if (pObject == NULL)
+ return NULL;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(pObject);
+ return c;
+}
+
+UMLOperation *MessageWidget::getOperation() {
+ return static_cast<UMLOperation*>(m_pObject);
+}
+
+void MessageWidget::setOperation(UMLOperation *op) {
+ if (m_pObject && m_pFText)
+ disconnect(m_pObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
+ m_pObject = op;
+ if (m_pObject && m_pFText)
+ connect(m_pObject, SIGNAL(modified()), m_pFText, SLOT(setMessageText()));
+}
+
+QString MessageWidget::getCustomOpText() {
+ return m_CustomOp;
+}
+
+void MessageWidget::setCustomOpText(const QString &opText) {
+ m_CustomOp = opText;
+ m_pFText->setMessageText();
+}
+
+UMLClassifier * MessageWidget::getSeqNumAndOp(QString& seqNum, QString& op) {
+ seqNum = m_SequenceNumber;
+ UMLOperation *pOperation = getOperation();
+ if (pOperation != NULL) {
+ op = pOperation->toString(Uml::st_SigNoVis);
+ } else {
+ op = m_CustomOp;
+ }
+ UMLObject *o = m_pOw[Uml::B]->getUMLObject();
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(o);
+ return c;
+}
+
+void MessageWidget::calculateDimensions() {
+ if (m_sequenceMessageType == Uml::sequence_message_synchronous) {
+ calculateDimensionsSynchronous();
+ } else if (m_sequenceMessageType == Uml::sequence_message_asynchronous) {
+ calculateDimensionsAsynchronous();
+ } else if (m_sequenceMessageType == Uml::sequence_message_creation) {
+ calculateDimensionsCreation();
+ } else {
+ kWarning() << "Unknown message type" << endl;
+ }
+ if (! UMLApp::app()->getDocument()->loading()) {
+ adjustAssocs( getX(), getY() ); // adjust assoc lines
+ }
+}
+
+void MessageWidget::calculateDimensionsSynchronous() {
+ int x = 0;
+
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w1 = m_pOw[Uml::A]->getWidth() / 2;
+ int w2 = m_pOw[Uml::B]->getWidth() / 2;
+ x1 += w1;
+ x2 += w2;
+
+ int widgetWidth = 0;
+ int widgetHeight = 0;
+ if( m_pOw[Uml::A] == m_pOw[Uml::B] ) {
+ widgetWidth = 50;
+ x = x1 - 2;
+ } else if( x1 < x2 ) {
+ x = x1;
+ widgetWidth = x2 - x1 + 8;
+ } else {
+ x = x2 - 8;
+ widgetWidth = x1 - x2 + 8;
+ }
+
+ if ( height() < 20 ) {
+ widgetHeight = 20;
+ } else {
+ widgetHeight = height();
+ }
+
+ m_nPosX = x;
+ setSize(widgetWidth, widgetHeight);
+}
+
+void MessageWidget::calculateDimensionsAsynchronous() {
+ int x = 0;
+
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w1 = m_pOw[Uml::A]->getWidth() / 2;
+ int w2 = m_pOw[Uml::B]->getWidth() / 2;
+ x1 += w1;
+ x2 += w2;
+
+ int widgetWidth = 0;
+ int widgetHeight = 8;
+ if( m_pOw[Uml::A] == m_pOw[Uml::B] ) {
+ widgetWidth = 50;
+ x = x1;
+ if( height() < 20 ) {
+ widgetHeight = 20;
+ } else {
+ widgetHeight = height();
+ }
+ } else if( x1 < x2 ) {
+ x = x1;
+ widgetWidth = x2 - x1;
+ } else {
+ x = x2;
+ widgetWidth = x1 - x2;
+ }
+ x += 1;
+ widgetWidth -= 2;
+ m_nPosX = x;
+ setSize(widgetWidth, widgetHeight);
+}
+
+void MessageWidget::calculateDimensionsCreation() {
+ int x = 0;
+
+ int x1 = m_pOw[Uml::A]->getX();
+ int x2 = m_pOw[Uml::B]->getX();
+ int w1 = m_pOw[Uml::A]->getWidth() / 2;
+ int w2 = m_pOw[Uml::B]->getWidth();
+ x1 += w1;
+ if (x1 > x2)
+ x2 += w2;
+
+ int widgetWidth = 0;
+ int widgetHeight = 8;
+ if ( x1 < x2 ) {
+ x = x1;
+ widgetWidth = x2 - x1;
+ } else {
+ x = x2;
+ widgetWidth = x1 - x2;
+ }
+ x += 1;
+ widgetWidth -= 2;
+ m_nPosX = x;
+ m_nY = m_pOw[Uml::B]->getY() + m_pOw[Uml::B]->getHeight() / 2;
+ setSize(widgetWidth, widgetHeight);
+}
+
+void MessageWidget::cleanup() {
+ if (m_pOw[Uml::A]) {
+ disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::A], SLOT(slotMessageMoved()) );
+ m_pOw[Uml::A]->messageRemoved(this);
+ }
+ if (m_pOw[Uml::B]) {
+ disconnect(this, SIGNAL(sigMessageMoved()), m_pOw[Uml::B], SLOT(slotMessageMoved()) );
+ m_pOw[Uml::B]->messageRemoved(this);
+ }
+
+ UMLWidget::cleanup();
+ if (m_pFText) {
+ m_pView->removeWidget(m_pFText);
+ m_pFText = NULL;
+ }
+}
+
+void MessageWidget::setSelected(bool _select) {
+ UMLWidget::setSelected( _select );
+ if( !m_pFText || m_pFText->getDisplayText().isEmpty())
+ return;
+ if( m_bSelected && m_pFText -> getSelected() )
+ return;
+ if( !m_bSelected && !m_pFText -> getSelected() )
+ return;
+
+ m_pView -> setSelected( m_pFText, 0 );
+ m_pFText -> setSelected( m_bSelected );
+}
+
+int MessageWidget::getMinY() {
+ if (!m_pOw[Uml::A] || !m_pOw[Uml::B]) {
+ return 0;
+ }
+ if (m_sequenceMessageType == Uml::sequence_message_creation) {
+ return m_pOw[Uml::A]->getY() + m_pOw[Uml::A]->getHeight();
+ }
+ int heightA = m_pOw[Uml::A]->getY() + m_pOw[Uml::A]->getHeight();
+ int heightB = m_pOw[Uml::B]->getY() + m_pOw[Uml::B]->getHeight();
+ int height = heightA;
+ if( heightA < heightB ) {
+ height = heightB;
+ }
+ return height;
+}
+
+int MessageWidget::getMaxY() {
+ if( !m_pOw[Uml::A] || !m_pOw[Uml::B] ) {
+ return 0;
+ }
+ int heightA = (int)((ObjectWidget*)m_pOw[Uml::A])->getEndLineY();
+ int heightB = (int)((ObjectWidget*)m_pOw[Uml::B])->getEndLineY();
+ int height = heightA;
+ if( heightA > heightB ) {
+ height = heightB;
+ }
+ return (height - this->height());
+}
+
+void MessageWidget::setWidget(ObjectWidget * ow, Uml::Role_Type role) {
+ m_pOw[role] = ow;
+ updateResizability();
+}
+
+ObjectWidget* MessageWidget::getWidget(Uml::Role_Type role) {
+ return m_pOw[role];
+}
+
+void MessageWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement messageElement = qDoc.createElement( "messagewidget" );
+ UMLWidget::saveToXMI( qDoc, messageElement );
+ messageElement.setAttribute( "widgetaid", ID2STR(m_pOw[Uml::A]->getLocalID()) );
+ messageElement.setAttribute( "widgetbid", ID2STR(m_pOw[Uml::B]->getLocalID()) );
+ UMLOperation *pOperation = getOperation();
+ if (pOperation)
+ messageElement.setAttribute( "operation", ID2STR(pOperation->getID()) );
+ else
+ messageElement.setAttribute( "operation", m_CustomOp );
+ messageElement.setAttribute( "seqnum", m_SequenceNumber );
+ messageElement.setAttribute( "sequencemessagetype", m_sequenceMessageType );
+
+ // save the corresponding message text
+ if (m_pFText && !m_pFText->getText().isEmpty()) {
+ messageElement.setAttribute( "textid", ID2STR(m_pFText->getID()) );
+ m_pFText -> saveToXMI( qDoc, messageElement );
+ }
+
+ qElement.appendChild( messageElement );
+}
+
+bool MessageWidget::loadFromXMI(QDomElement& qElement) {
+ if ( !UMLWidget::loadFromXMI(qElement) ) {
+ return false;
+ }
+ QString textid = qElement.attribute( "textid", "-1" );
+ QString widgetaid = qElement.attribute( "widgetaid", "-1" );
+ QString widgetbid = qElement.attribute( "widgetbid", "-1" );
+ m_CustomOp = qElement.attribute( "operation", "" );
+ m_SequenceNumber = qElement.attribute( "seqnum", "" );
+ QString sequenceMessageType = qElement.attribute( "sequencemessagetype", "1001" );
+ m_sequenceMessageType = (Uml::Sequence_Message_Type)sequenceMessageType.toInt();
+
+ m_widgetAId = STR2ID(widgetaid);
+ m_widgetBId = STR2ID(widgetbid);
+ m_textId = STR2ID(textid);
+
+ Uml::Text_Role tr = Uml::tr_Seq_Message;
+ if (m_widgetAId == m_widgetBId)
+ tr = Uml::tr_Seq_Message_Self;
+
+ //now load child elements
+ QDomNode node = qElement.firstChild();
+ QDomElement element = node.toElement();
+ if ( !element.isNull() ) {
+ QString tag = element.tagName();
+ if (tag == "floatingtext") {
+ m_pFText = new FloatingTextWidget( m_pView, tr, getOperationText(m_pView), m_textId );
+ if( ! m_pFText->loadFromXMI(element) ) {
+ // Most likely cause: The FloatingTextWidget is empty.
+ delete m_pFText;
+ m_pFText = NULL;
+ }
+ } else {
+ kError() << "MessageWidget::loadFromXMI: unknown tag "
+ << tag << endl;
+ }
+ }
+ return true;
+}
+
+#include "messagewidget.moc"
diff --git a/umbrello/umbrello/messagewidget.h b/umbrello/umbrello/messagewidget.h
new file mode 100644
index 00000000..66f2f639
--- /dev/null
+++ b/umbrello/umbrello/messagewidget.h
@@ -0,0 +1,401 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef MESSAGEWIDGET_H
+#define MESSAGEWIDGET_H
+
+#include "umlwidget.h"
+#include "linkwidget.h"
+
+// forward declarations
+class FloatingTextWidget;
+class ObjectWidget;
+class UMLOperation;
+class MessageWidgetController;
+
+/**
+ * Used to display a message on a sequence diagram. The message
+ * could be between two objects or a message that calls itself on
+ * an object. This class will only display the line that is
+ * required and the text will be setup by the @ref FloatingTextWidget
+ * widget that is passed in the constructor. A message can be
+ * synchronous (calls a method and gains control back on return,
+ * as happens in most programming languages) or asynchronous
+ * (calls a method and gains back control immediately).
+ *
+ * @short Displays a message.
+ * @author Paul Hensgen
+ * @see UMLWidget
+ * @see ObjectWidget
+ * @see FloatingTextWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class MessageWidget : public UMLWidget, public LinkWidget {
+ Q_OBJECT
+public:
+ friend class MessageWidgetController;
+
+ /**
+ * Constructs a MessageWidget.
+ *
+ * @param view The parent to this class.
+ * @param a The role A widget for this message.
+ * @param b The role B widget for this message.
+ * @param y The vertical position to display this message.
+ * @param sequenceMessageType Whether synchronous or asynchronous
+ * @param id A unique id used for deleting this object cleanly.
+ * The default (-1) will prompt generation of a new ID.
+ */
+ MessageWidget(UMLView * view, ObjectWidget* a, ObjectWidget* b,
+ int y, Uml::Sequence_Message_Type sequenceMessageType,
+ Uml::IDType id = Uml::id_None);
+
+ /**
+ * Constructs a MessageWidget.
+ *
+ * @param view The parent to this class.
+ * @param sequenceMessageType The Uml::Sequence_Message_Type of this message widget
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ MessageWidget(UMLView * view, Uml::Sequence_Message_Type sequenceMessageType, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~MessageWidget();
+
+ /**
+ * Write property of QString m_SequenceNumber.
+ */
+ void setSequenceNumber( const QString &sequenceNumber );
+
+ /**
+ * Read property of QString m_SequenceNumber.
+ */
+ QString getSequenceNumber() const;
+
+ /**
+ * Returns whether the message is synchronous or asynchronous
+ */
+ Uml::Sequence_Message_Type getSequenceMessageType() const {
+ return m_sequenceMessageType;
+ }
+
+ /**
+ * Check to see if the given ObjectWidget is involved in the message.
+ *
+ * @param w The ObjectWidget to check for.
+ * @return true - if is contained, false - not contained.
+ */
+ bool contains(ObjectWidget * w);
+
+ /**
+ * Returns the related widget on the given side.
+ *
+ * @return The ObjectWidget we are related to.
+ */
+ ObjectWidget* getWidget(Uml::Role_Type role);
+
+ /**
+ * Sets the related widget on the given side.
+ *
+ * @param ow The ObjectWidget we are related to.
+ * @param role The Uml::Role_Type to be set for the ObjectWidget
+ */
+ void setWidget(ObjectWidget * ow, Uml::Role_Type role) ;
+
+ /**
+ * Returns the text widget it is related to.
+ *
+ * @return The text widget we are related to.
+ */
+ FloatingTextWidget * getFloatingTextWidget() {
+ return m_pFText;
+ }
+
+ /**
+ * Sets the text widget it is related to.
+ *
+ * @param f The text widget we are related to.
+ */
+ void setFloatingTextWidget(FloatingTextWidget * f) {
+ m_pFText = f;
+ }
+
+ /**
+ * Implements operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ void lwSetFont (QFont font);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ * @todo Move to LinkWidget.
+ */
+ UMLClassifier *getOperationOwner();
+
+ /**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+ UMLOperation *getOperation();
+
+ /**
+ * Implements operation from LinkWidget.
+ * Motivated by FloatingTextWidget.
+ */
+ void setOperation(UMLOperation *op);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ QString getCustomOpText();
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ */
+ void setCustomOpText(const QString &opText);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ */
+ void setMessageText(FloatingTextWidget *ft);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param ft The text widget which to update.
+ * @param newText The new text to set.
+ */
+ void setText(FloatingTextWidget *ft, const QString &newText);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param seqNum The new sequence number string to set.
+ * @param op The new operation string to set.
+ */
+ void setSeqNumAndOp(const QString &seqNum, const QString &op);
+
+ /**
+ * Overrides operation from LinkWidget.
+ * Required by FloatingTextWidget.
+ *
+ * @param seqNum Return this MessageWidget's sequence number string.
+ * @param op Return this MessageWidget's operation string.
+ */
+ UMLClassifier * getSeqNumAndOp(QString& seqNum, QString& op);
+
+ /**
+ * Calculate the geometry of the widget.
+ */
+ void calculateWidget();
+
+ /**
+ * Activates a MessageWidget. Connects its m_pOw[] pointers
+ * to UMLObjects and also send signals about its FloatingTextWidget.
+ */
+ bool activate(IDChangeLog * Log = 0);
+
+ /**
+ * Calculates the size of the widget by calling
+ * calculateDimenstionsSynchronous(),
+ * calculateDimenstionsAsynchronous(), or
+ * calculateDimensionsCreation()
+ */
+ void calculateDimensions();
+
+ /**
+ * Calculates and sets the size of the widget for a synchronous message
+ */
+ void calculateDimensionsSynchronous();
+
+ /**
+ * Calculates and sets the size of the widget for an asynchronous message
+ */
+ void calculateDimensionsAsynchronous();
+
+ /**
+ * Calculates and sets the size of the widget for a creation message
+ */
+ void calculateDimensionsCreation();
+
+ /**
+ * Calls drawSynchronous() or drawAsynchronous()
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Draws the calling arrow with filled in arrowhead, the
+ * timeline box and the returning arrow with a dashed line and
+ * stick arrowhead.
+ */
+ void drawSynchronous(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Draws a solid arrow line and a stick arrow head.
+ */
+ void drawAsynchronous(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Draws a solid arrow line and a stick arrow head to the
+ * edge of the target object widget instead of to the
+ * sequence line.
+ */
+ void drawCreation(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Sets the text position relative to the sequence message.
+ */
+ void setTextPosition();
+
+ /**
+ * Constrains the FloatingTextWidget X and Y values supplied.
+ * Overrides operation from LinkWidget.
+ *
+ * @param textX Candidate X value (may be modified by the constraint.)
+ * @param textY Candidate Y value (may be modified by the constraint.)
+ * @param textWidth Width of the text.
+ * @param textHeight Height of the text.
+ * @param tr Uml::Text_Role of the text.
+ */
+ void constrainTextPos(int &textX, int &textY, int textWidth, int textHeight,
+ Uml::Text_Role tr);
+
+ /**
+ * Used to cleanup any other widget it may need to delete.
+ */
+ void cleanup();
+
+ /**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select True if the widget is selected.
+ */
+ void setSelected(bool _select);
+
+ /**
+ * Returns the minimum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+ int getMinY();
+
+ /**
+ * Returns the maximum height this widget should be set at on
+ * a sequence diagrams. Takes into account the widget positions
+ * it is related to.
+ */
+ int getMaxY();
+
+ /**
+ * Overrides operation from UMLWidget.
+ *
+ * @param p Point to be checked.
+ *
+ * @return Non-zero if the point is on a part of the MessageWidget.
+ * NB In case of a synchronous message, the empty space
+ * between call line and return line does not count, i.e. if
+ * the point is located in that space the function returns 0.
+ */
+ int onWidget(const QPoint & p);
+
+ /**
+ * Saves to the "messagewidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads from the "messagewidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+protected:
+ /**
+ * Shortcut for calling m_pFText->setLink() followed by
+ * this->setTextPosition().
+ */
+ void setLinkAndTextPos();
+
+ /**
+ * Returns the textX arg with constraints applied.
+ * Auxiliary to setTextPosition() and constrainTextPos().
+ */
+ int constrainX(int textX, int textWidth, Uml::Text_Role tr);
+
+ /**
+ * Draw an arrow pointing in the given direction.
+ * The arrow head is not solid, i.e. it is made up of two lines
+ * like so: --->
+ * The direction can be either Qt::LeftArrow or Qt::RightArrow.
+ */
+ static void drawArrow( QPainter& p, int x, int y, int w,
+ Qt::ArrowType direction, bool useDottedLine = false );
+
+ /**
+ * Draw a solid (triangular) arrowhead pointing in the given direction.
+ * The direction can be either Qt::LeftArrow or Qt::RightArrow.
+ */
+ static void drawSolidArrowhead(QPainter& p, int x, int y, Qt::ArrowType direction);
+
+ /**
+ * Update the UMLWidget::m_bResizable flag according to the
+ * charactersitics of this message.
+ */
+ void updateResizability();
+
+ // Data loaded/saved
+ QString m_SequenceNumber;
+ QString m_CustomOp;
+ /**
+ * Whether the message is synchronous or asynchronous
+ */
+ Uml::Sequence_Message_Type m_sequenceMessageType;
+
+private:
+ void moveEvent(QMoveEvent */*m*/);
+ void resizeEvent(QResizeEvent */*re*/);
+
+ ObjectWidget * m_pOw[2];
+ FloatingTextWidget * m_pFText;
+ int m_nY;
+ /**
+ * The following variables are used by loadFromXMI() as an intermediate
+ * store. activate() resolves the IDs, i.e. after activate() the variables
+ * m_pOw[] and m_pFText can be used.
+ */
+ Uml::IDType m_widgetAId, m_widgetBId, m_textId;
+
+public slots:
+ void slotWidgetMoved(Uml::IDType id);
+ void slotMenuSelection(int sel);
+signals:
+ /**
+ * emitted when the message widget is moved up or down
+ * slots into ObjectWidget::slotMessageMoved()
+ */
+ void sigMessageMoved();
+};
+
+#endif
diff --git a/umbrello/umbrello/messagewidgetcontroller.cpp b/umbrello/umbrello/messagewidgetcontroller.cpp
new file mode 100644
index 00000000..8ffac822
--- /dev/null
+++ b/umbrello/umbrello/messagewidgetcontroller.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "messagewidgetcontroller.h"
+
+// kde includes
+#include <kcursor.h>
+#include <kdebug.h>
+
+// app includes
+#include "messagewidget.h"
+#include "floatingtextwidget.h"
+#include "objectwidget.h"
+#include "listpopupmenu.h"
+
+MessageWidgetController::MessageWidgetController(MessageWidget* messageWidget):
+ UMLWidgetController(messageWidget) {
+ m_messageWidget = messageWidget;
+ m_unconstrainedPositionY = 0;
+}
+
+MessageWidgetController::~MessageWidgetController() {
+}
+
+void MessageWidgetController::saveWidgetValues(QMouseEvent *me) {
+ UMLWidgetController::saveWidgetValues(me);
+
+ m_unconstrainedPositionY = m_widget->getY();
+}
+
+QCursor MessageWidgetController::getResizeCursor() {
+ return KCursor::sizeVerCursor();
+}
+
+void MessageWidgetController::resizeWidget(int newW, int newH) {
+ m_messageWidget->setSize(m_messageWidget->width(), newH);
+ emit m_messageWidget->sigMessageMoved();
+}
+
+void MessageWidgetController::moveWidgetBy(int diffX, int diffY) {
+ m_unconstrainedPositionY += diffY;
+ int newY = constrainPositionY(diffY);
+
+ if (m_unconstrainedPositionY != newY) {
+ if (m_unconstrainedPositionY > m_messageWidget->getY()) {
+ newY = m_unconstrainedPositionY;
+ } else {
+ return;
+ }
+ }
+
+ m_messageWidget->setY(newY);
+
+ if (m_messageWidget->m_sequenceMessageType == Uml::sequence_message_creation) {
+ const int objWidgetHalfHeight = m_messageWidget->m_pOw[Uml::B]->getHeight() / 2;
+ m_messageWidget->m_pOw[Uml::B]->UMLWidget::setY(newY - objWidgetHalfHeight);
+ }
+
+ m_messageWidget->moveEvent(0);
+}
+
+void MessageWidgetController::constrainMovementForAllWidgets(int &diffX, int &diffY) {
+ diffX = 0;
+ diffY = constrainPositionY(diffY) - m_widget->getY();
+}
+
+void MessageWidgetController::doMouseDoubleClick(QMouseEvent *me) {
+ if (m_messageWidget->m_pFText != NULL) {
+ m_messageWidget->m_pFText->slotMenuSelection(ListPopupMenu::mt_Select_Operation);
+ }
+}
+
+int MessageWidgetController::constrainPositionY(int diffY) {
+ int newY = m_widget->getY() + diffY;
+
+ int minY = m_messageWidget->getMinY();
+ if (m_messageWidget->m_pFText && !m_messageWidget->m_pFText->getDisplayText().isEmpty()) {
+ minY += m_messageWidget->m_pFText->getHeight();
+ }
+
+ if (newY < minY) {
+ newY = minY;
+ }
+
+ return newY;
+}
+
diff --git a/umbrello/umbrello/messagewidgetcontroller.h b/umbrello/umbrello/messagewidgetcontroller.h
new file mode 100644
index 00000000..921fd2bf
--- /dev/null
+++ b/umbrello/umbrello/messagewidgetcontroller.h
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef MESSAGEWIDGETCONTROLLER_H
+#define MESSAGEWIDGETCONTROLLER_H
+
+#include "umlwidgetcontroller.h"
+
+class MessageWidget;
+
+/**
+ * Controller for MessageWidget.
+ *
+ * When moving a MessageWidget, it is only moved along Y axis. X axis movement
+ * is always ignored.
+ * So, if the MessageWidget is being moved as part of a selection and that
+ * selection is moved in X and/or Y axis, the MessageWidget will only move in
+ * Y axis. Another constrain is applied in Y axis, so the message doesn't pass
+ * over the related object widgets. Due to this constrain, the vertical
+ * position the message would have if it wasn't constrained is calculated, so
+ * when the widget lowers the position where it was constrained it begins to
+ * move again.
+ * Also, when constraining the move of the selection because the receiver of
+ * mouse move events is a MessageWidget, all the widgets are moved only in Y
+ * axis. Another constrain is applied in Y axis, so the message doesn't pass
+ * over the related object widgets. The unconstrained position isn't need here,
+ * because the message widget is the receiver of the events, so when the cursor
+ * goes lower than where it was constrained it begins to lower automatically.
+ *
+ * Creation messages take care of moving the object created when they're moved.
+ *
+ * Only vertical resize is allowed for MessageWidget. Cursor is set to reflect
+ * this.
+ *
+ * Double click shows the dialog to select the operation of the message.
+ *
+ * @author Umbrello UML Modeller Authors <uml-devel@lists.sourceforge.net>
+ */
+class MessageWidgetController : public UMLWidgetController {
+public:
+
+ /**
+ * Constructor for MessageWidgetController.
+ *
+ * @param messageWidget The message widget which uses the controller.
+ */
+ MessageWidgetController(MessageWidget* messageWidget);
+
+ /**
+ * Destructor for MessageWidgetController.
+ */
+ ~MessageWidgetController();
+
+protected:
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Saves the values of the widget needed for move/resize.
+ * Calls parent method and then saves the value of m_unconstrainedPositionY
+ *
+ * @param me The QMouseEvent to get the offset from.
+ */
+ virtual void saveWidgetValues(QMouseEvent *me);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Returns the cursor to be shown when resizing the widget.
+ * The cursor shown is KCursor::sizeVerCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+ virtual QCursor getResizeCursor();
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Resizes the height of the message widget and emits the message moved signal.
+ * Message widgets can only be resized vertically, so width isn't modified.
+ *
+ * @param newW The new width for the widget (isn't used).
+ * @param newH The new height for the widget.
+ */
+ virtual void resizeWidget(int newW, int newH);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position. X position is ignored, and widget
+ * is only moved along Y axis. If message goes upper than the object, it's
+ * kept at this position until it should be lowered again (the unconstrained
+ * Y position is saved to know when it's the time to lower it again).
+ * If the message is a creation message, the object created is also moved to
+ * the new vertical position.
+ * @see constrainPositionY
+ *
+ * @param diffX The difference between current X position and new X position
+ * (isn't used).
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void moveWidgetBy(int diffX, int diffY);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ * All the widgets are constrained to be moved only in Y axis (diffX is set to 0).
+ * @see constrainPositionY
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void constrainMovementForAllWidgets(int &diffX, int &diffY);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Executes the action for double click in the widget.
+ * Shows the dialog to select the operation of the message.
+ *
+ * @param me The QMouseEvent which triggered the double click event.
+ */
+ virtual void doMouseDoubleClick(QMouseEvent *me);
+
+private:
+
+ /**
+ * Constrains the vertical position of the message widget so it doesn't go
+ * upper than the bottom side of the lower object.
+ * The height of the floating text widget in the message is taken in account
+ * if there is any and isn't empty.
+ *
+ * @param diffY The difference between current Y position and new Y position.
+ * @return The new Y position, constrained.
+ */
+ int constrainPositionY(int diffY);
+
+ /**
+ * The message widget which uses the controller.
+ */
+ MessageWidget *m_messageWidget;
+
+ /**
+ * The vertical position the widget would have if its move wasn't constrained.
+ */
+ int m_unconstrainedPositionY;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/messagewidgetlist.h b/umbrello/umbrello/messagewidgetlist.h
new file mode 100644
index 00000000..559a4cf7
--- /dev/null
+++ b/umbrello/umbrello/messagewidgetlist.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef MESSAGEWIDGETLIST_H
+#define MESSAGEWIDGETLIST_H
+
+#include <qptrlist.h>
+
+class MessageWidget;
+
+typedef QPtrList<MessageWidget> MessageWidgetList;
+typedef QPtrListIterator<MessageWidget> MessageWidgetListIt;
+
+#endif
diff --git a/umbrello/umbrello/model_utils.cpp b/umbrello/umbrello/model_utils.cpp
new file mode 100644
index 00000000..89e1cf33
--- /dev/null
+++ b/umbrello/umbrello/model_utils.cpp
@@ -0,0 +1,1221 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "model_utils.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <qstringlist.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "umlobject.h"
+#include "umlpackagelist.h"
+#include "package.h"
+#include "folder.h"
+#include "classifier.h"
+#include "enum.h"
+#include "entity.h"
+#include "template.h"
+#include "operation.h"
+#include "attribute.h"
+#include "association.h"
+#include "umlrole.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "codegenerator.h"
+
+namespace Model_Utils {
+
+bool isCloneable(Uml::Widget_Type type) {
+ switch (type) {
+ case Uml::wt_Actor:
+ case Uml::wt_UseCase:
+ case Uml::wt_Class:
+ case Uml::wt_Interface:
+ case Uml::wt_Enum:
+ case Uml::wt_Datatype:
+ case Uml::wt_Package:
+ case Uml::wt_Component:
+ case Uml::wt_Node:
+ case Uml::wt_Artifact:
+ return true;
+ default:
+ return false;
+ }
+}
+
+UMLObject * findObjectInList(Uml::IDType id, const UMLObjectList& inList) {
+ for (UMLObjectListIt oit(inList); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (obj->getID() == id)
+ return obj;
+ UMLObject *o;
+ Uml::Object_Type t = obj->getBaseType();
+ switch (t) {
+ case Uml::ot_Folder:
+ case Uml::ot_Package:
+ case Uml::ot_Component:
+ o = static_cast<UMLPackage*>(obj)->findObjectById(id);
+ if (o)
+ return o;
+ break;
+ case Uml::ot_Interface:
+ case Uml::ot_Class:
+ case Uml::ot_Enum:
+ case Uml::ot_Entity:
+ o = static_cast<UMLClassifier*>(obj)->findChildObjectById(id);
+ if (o == NULL &&
+ (t == Uml::ot_Interface || t == Uml::ot_Class))
+ o = ((UMLPackage*)obj)->findObjectById(id);
+ if (o)
+ return o;
+ break;
+ case Uml::ot_Association:
+ {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(obj);
+ UMLRole *rA = assoc->getUMLRole(Uml::A);
+ if (rA->getID() == id)
+ return rA;
+ UMLRole *rB = assoc->getUMLRole(Uml::B);
+ if (rB->getID() == id)
+ return rB;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+UMLObject* findUMLObject(const UMLObjectList& inList,
+ const QString& inName,
+ Uml::Object_Type type /* = ot_UMLObject */,
+ UMLObject *currentObj /* = NULL */) {
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ QString name = inName;
+ QStringList components;
+#ifdef TRY_BUGFIX_120682
+ // If we have a pointer or a reference in cpp we need to remove
+ // the asterisks and ampersands in order to find the appropriate object
+ if (UMLApp::app()->getActiveLanguage() == Uml::pl_Cpp) {
+ if (name.endsWith("*"))
+ name.remove("*");
+ else if (name.contains("&"))
+ name.remove("&");
+ }
+#endif
+ QString nameWithoutFirstPrefix;
+ if (name.contains("::"))
+ components = QStringList::split("::", name);
+ else if (name.contains("."))
+ components = QStringList::split(".", name);
+ if (components.size() > 1) {
+ name = components.front();
+ components.pop_front();
+ nameWithoutFirstPrefix = components.join("::");
+ }
+ if (currentObj) {
+ UMLPackage *pkg = NULL;
+ if (dynamic_cast<UMLClassifierListItem*>(currentObj)) {
+ currentObj = static_cast<UMLObject*>(currentObj->parent());
+ }
+ pkg = dynamic_cast<UMLPackage*>(currentObj);
+ if (pkg == NULL)
+ pkg = currentObj->getUMLPackage();
+ // Remember packages that we've seen - for avoiding cycles.
+ UMLPackageList seenPkgs;
+ for (; pkg; pkg = currentObj->getUMLPackage()) {
+ if (nameWithoutFirstPrefix.isEmpty()) {
+ if (caseSensitive) {
+ if (pkg->getName() == name)
+ return pkg;
+ } else if (pkg->getName().lower() == name.lower()) {
+ return pkg;
+ }
+ }
+ if (seenPkgs.findRef(pkg) != -1) {
+ kError() << "findUMLObject(" << name << "): "
+ << "breaking out of cycle involving "
+ << pkg->getName() << endl;
+ break;
+ }
+ seenPkgs.append(pkg);
+ UMLObjectList objectsInCurrentScope = pkg->containedObjects();
+ for (UMLObjectListIt oit(objectsInCurrentScope); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (caseSensitive) {
+ if (obj->getName() != name)
+ continue;
+ } else if (obj->getName().lower() != name.lower()) {
+ continue;
+ }
+ Uml::Object_Type foundType = obj->getBaseType();
+ if (nameWithoutFirstPrefix.isEmpty()) {
+ if (type != Uml::ot_UMLObject && type != foundType) {
+ kDebug() << "findUMLObject: type mismatch for "
+ << name << " (seeking type: "
+ << type << ", found type: "
+ << foundType << ")" << endl;
+ // Class, Interface, and Datatype are all Classifiers
+ // and are considered equivalent.
+ // The caller must be prepared to handle possible mismatches.
+ if ((type == Uml::ot_Class ||
+ type == Uml::ot_Interface ||
+ type == Uml::ot_Datatype) &&
+ (foundType == Uml::ot_Class ||
+ foundType == Uml::ot_Interface ||
+ foundType == Uml::ot_Datatype)) {
+ return obj;
+ }
+ continue;
+ }
+ return obj;
+ }
+ if (foundType != Uml::ot_Package &&
+ foundType != Uml::ot_Folder &&
+ foundType != Uml::ot_Class &&
+ foundType != Uml::ot_Interface &&
+ foundType != Uml::ot_Component) {
+ kDebug() << "findUMLObject: found \"" << name
+ << "\" is not a package (?)" << endl;
+ continue;
+ }
+ UMLPackage *pkg = static_cast<UMLPackage*>(obj);
+ return findUMLObject( pkg->containedObjects(),
+ nameWithoutFirstPrefix, type );
+ }
+ currentObj = pkg;
+ }
+ }
+ for (UMLObjectListIt oit(inList); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (caseSensitive) {
+ if (obj->getName() != name)
+ continue;
+ } else if (obj->getName().lower() != name.lower()) {
+ continue;
+ }
+ Uml::Object_Type foundType = obj->getBaseType();
+ if (nameWithoutFirstPrefix.isEmpty()) {
+ if (type != Uml::ot_UMLObject && type != foundType) {
+ kDebug() << "findUMLObject: type mismatch for "
+ << name << " (seeking type: "
+ << type << ", found type: "
+ << foundType << ")" << endl;
+ continue;
+ }
+ return obj;
+ }
+ if (foundType != Uml::ot_Package &&
+ foundType != Uml::ot_Folder &&
+ foundType != Uml::ot_Class &&
+ foundType != Uml::ot_Interface &&
+ foundType != Uml::ot_Component) {
+ kDebug() << "findUMLObject: found \"" << name
+ << "\" is not a package (?)" << endl;
+ continue;
+ }
+ UMLPackage *pkg = static_cast<UMLPackage*>(obj);
+ return findUMLObject( pkg->containedObjects(),
+ nameWithoutFirstPrefix, type );
+ }
+ return NULL;
+}
+
+QString uniqObjectName(Uml::Object_Type type, UMLPackage *parentPkg, QString prefix) {
+ QString currentName = prefix;
+ if (currentName.isEmpty()) {
+ if(type == Uml::ot_Class)
+ currentName = i18n("new_class");
+ else if(type == Uml::ot_Actor)
+ currentName = i18n("new_actor");
+ else if(type == Uml::ot_UseCase)
+ currentName = i18n("new_usecase");
+ else if(type == Uml::ot_Package)
+ currentName = i18n("new_package");
+ else if(type == Uml::ot_Component)
+ currentName = i18n("new_component");
+ else if(type == Uml::ot_Node)
+ currentName = i18n("new_node");
+ else if(type == Uml::ot_Artifact)
+ currentName = i18n("new_artifact");
+ else if(type == Uml::ot_Interface)
+ currentName = i18n("new_interface");
+ else if(type == Uml::ot_Datatype)
+ currentName = i18n("new_datatype");
+ else if(type == Uml::ot_Enum)
+ currentName = i18n("new_enum");
+ else if(type == Uml::ot_Entity)
+ currentName = i18n("new_entity");
+ else if(type == Uml::ot_Folder)
+ currentName = i18n("new_folder");
+ else if(type == Uml::ot_Association)
+ currentName = i18n("new_association");
+ else {
+ currentName = i18n("new_object");
+ kWarning() << "unknown object type in umldoc::uniqObjectName()" << endl;
+ }
+ }
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ QString name = currentName;
+ for (int number = 1; !doc->isUnique(name, parentPkg); number++) {
+ name = currentName + '_' + QString::number(number);
+ }
+ return name;
+}
+
+bool isCommonXMIAttribute( const QString &tag ) {
+ bool retval = (Uml::tagEq(tag, "name") ||
+ Uml::tagEq(tag, "visibility") ||
+ Uml::tagEq(tag, "isRoot") ||
+ Uml::tagEq(tag, "isLeaf") ||
+ Uml::tagEq(tag, "isAbstract") ||
+ Uml::tagEq(tag, "isSpecification") ||
+ Uml::tagEq(tag, "isActive") ||
+ Uml::tagEq(tag, "namespace") ||
+ Uml::tagEq(tag, "ownerScope") ||
+ Uml::tagEq(tag, "ModelElement.stereotype") ||
+ Uml::tagEq(tag, "GeneralizableElement.generalization") ||
+ Uml::tagEq(tag, "specialization") || //NYI
+ Uml::tagEq(tag, "clientDependency") || //NYI
+ Uml::tagEq(tag, "supplierDependency") //NYI
+ );
+ return retval;
+}
+
+bool isCommonDataType(QString type) {
+ CodeGenerator *gen = UMLApp::app()->getGenerator();
+ if (gen == NULL)
+ return false;
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ QStringList dataTypes = gen->defaultDatatypes();
+ QStringList::Iterator end(dataTypes.end());
+ for (QStringList::Iterator it = dataTypes.begin(); it != end; ++it) {
+ if (caseSensitive) {
+ if (type == *it)
+ return true;
+ } else if (type.lower() == (*it).lower()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool isClassifierListitem(Uml::Object_Type type) {
+ if (type == Uml::ot_Attribute ||
+ type == Uml::ot_Operation ||
+ type == Uml::ot_Template ||
+ type == Uml::ot_EntityAttribute ||
+ type == Uml::ot_EnumLiteral) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Uml::Model_Type guessContainer(UMLObject *o) {
+ Uml::Object_Type ot = o->getBaseType();
+ if (ot == Uml::ot_Package && o->getStereotype() == "subsystem")
+ return Uml::mt_Component;
+ Uml::Model_Type mt = Uml::N_MODELTYPES;
+ switch (ot) {
+ case Uml::ot_Package: // CHECK: packages may appear in other views?
+ case Uml::ot_Interface:
+ case Uml::ot_Datatype:
+ case Uml::ot_Enum:
+ case Uml::ot_Class:
+ case Uml::ot_Attribute:
+ case Uml::ot_Operation:
+ case Uml::ot_EnumLiteral:
+ case Uml::ot_Template:
+ mt = Uml::mt_Logical;
+ break;
+ case Uml::ot_Actor:
+ case Uml::ot_UseCase:
+ mt = Uml::mt_UseCase;
+ break;
+ case Uml::ot_Component:
+ case Uml::ot_Artifact: // trouble: artifact can also appear at Deployment
+ mt = Uml::mt_Component;
+ break;
+ case Uml::ot_Node:
+ mt = Uml::mt_Deployment;
+ break;
+ case Uml::ot_Entity:
+ case Uml::ot_EntityAttribute:
+ mt = Uml::mt_EntityRelationship;
+ break;
+ case Uml::ot_Association:
+ {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ for (int r = Uml::A; r <= Uml::B; r++) {
+ UMLObject *roleObj = assoc->getObject((Uml::Role_Type)r);
+ if (roleObj == NULL) {
+ // Ouch! we have been called while types are not yet resolved
+ return Uml::N_MODELTYPES;
+ }
+ UMLPackage *pkg = roleObj->getUMLPackage();
+ if (pkg) {
+ while (pkg->getUMLPackage()) { // wind back to root
+ pkg = pkg->getUMLPackage();
+ }
+ const Uml::Model_Type m = umldoc->rootFolderType(pkg);
+ if (m != Uml::N_MODELTYPES)
+ return m;
+ }
+ mt = guessContainer(roleObj);
+ if (mt != Uml::mt_Logical)
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return mt;
+}
+
+int stringToDirection(QString input, Uml::Parameter_Direction & result) {
+ QRegExp dirx("^(in|out|inout)");
+ int pos = dirx.search(input);
+ if (pos == -1)
+ return 0;
+ const QString& dirStr = dirx.capturedTexts().first();
+ uint dirLen = dirStr.length();
+ if (input.length() > dirLen && !input[dirLen].isSpace())
+ return 0; // no match after all.
+ if (dirStr == "out")
+ result = Uml::pd_Out;
+ else if (dirStr == "inout")
+ result = Uml::pd_InOut;
+ else
+ result = Uml::pd_In;
+ return dirLen;
+}
+
+Parse_Status parseTemplate(QString t, NameAndType& nmTp, UMLClassifier *owningScope) {
+
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+
+ t = t.stripWhiteSpace();
+ if (t.isEmpty())
+ return PS_Empty;
+
+ QStringList nameAndType = QStringList::split( QRegExp("\\s*:\\s*"), t);
+ if (nameAndType.count() == 2) {
+ UMLObject *pType = NULL;
+ if (nameAndType[1] != "class") {
+ pType = pDoc->findUMLObject(nameAndType[1], Uml::ot_UMLObject, owningScope);
+ if (pType == NULL)
+ return PS_Unknown_ArgType;
+ }
+ nmTp = NameAndType(nameAndType[0], pType);
+ } else {
+ nmTp = NameAndType(t, NULL);
+ }
+ return PS_OK;
+}
+
+Parse_Status parseAttribute(QString a, NameAndType& nmTp, UMLClassifier *owningScope,
+ Uml::Visibility *vis /* = 0 */) {
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+
+ a = a.simplifyWhiteSpace();
+ if (a.isEmpty())
+ return PS_Empty;
+
+ int colonPos = a.find(':');
+ if (colonPos < 0) {
+ nmTp = NameAndType(a, NULL);
+ return PS_OK;
+ }
+ QString name = a.left(colonPos).stripWhiteSpace();
+ if (vis) {
+ QRegExp mnemonicVis("^([\\+\\#\\-\\~] *)");
+ int pos = mnemonicVis.search(name);
+ if (pos == -1) {
+ *vis = Uml::Visibility::Private; // default value
+ } else {
+ QString caption = mnemonicVis.cap(1);
+ QString strVis = caption.left(1);
+ if (strVis == "+")
+ *vis = Uml::Visibility::Public;
+ else if (strVis == "#")
+ *vis = Uml::Visibility::Protected;
+ else if (strVis == "-")
+ *vis = Uml::Visibility::Private;
+ else
+ *vis = Uml::Visibility::Implementation;
+ }
+ name.remove(mnemonicVis);
+ }
+ Uml::Parameter_Direction pd = Uml::pd_In;
+ if (name.startsWith("in ")) {
+ pd = Uml::pd_In;
+ name = name.mid(3);
+ } else if (name.startsWith("inout ")) {
+ pd = Uml::pd_InOut;
+ name = name.mid(6);
+ } else if (name.startsWith("out ")) {
+ pd = Uml::pd_Out;
+ name = name.mid(4);
+ }
+ a = a.mid(colonPos + 1).stripWhiteSpace();
+ if (a.isEmpty()) {
+ nmTp = NameAndType(name, NULL, pd);
+ return PS_OK;
+ }
+ QStringList typeAndInitialValue = QStringList::split( QRegExp("\\s*=\\s*"), a );
+ const QString &type = typeAndInitialValue[0];
+ UMLObject *pType = pDoc->findUMLObject(type, Uml::ot_UMLObject, owningScope);
+ if (pType == NULL) {
+ nmTp = NameAndType(name, NULL, pd);
+ return PS_Unknown_ArgType;
+ }
+ QString initialValue;
+ if (typeAndInitialValue.count() == 2) {
+ initialValue = typeAndInitialValue[1];
+ }
+ nmTp = NameAndType(name, pType, pd, initialValue);
+ return PS_OK;
+}
+
+Parse_Status parseOperation(QString m, OpDescriptor& desc, UMLClassifier *owningScope) {
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+
+ m = m.simplifyWhiteSpace();
+ if (m.isEmpty())
+ return PS_Empty;
+ if (m.contains(QRegExp("operator *()"))) {
+ // C++ special case: two sets of parentheses
+ desc.m_name = "operator()";
+ m.remove(QRegExp("operator *()"));
+ } else {
+ /**
+ * The search pattern includes everything up to the opening parenthesis
+ * because UML also permits non programming-language oriented designs
+ * using narrative names, for example "check water temperature".
+ */
+ QRegExp beginningUpToOpenParenth( "^([^\\(]+)" );
+ int pos = beginningUpToOpenParenth.search(m);
+ if (pos == -1)
+ return PS_Illegal_MethodName;
+ desc.m_name = beginningUpToOpenParenth.cap(1);
+ }
+ desc.m_pReturnType = NULL;
+ QRegExp pat = QRegExp("\\) *:(.*)$");
+ int pos = pat.search(m);
+ if (pos != -1) { // return type is optional
+ QString retType = pat.cap(1);
+ retType = retType.stripWhiteSpace();
+ if (retType != "void") {
+ UMLObject *pRetType = owningScope->findTemplate(retType);
+ if (pRetType == NULL) {
+ pRetType = pDoc->findUMLObject(retType, Uml::ot_UMLObject, owningScope);
+ if (pRetType == NULL)
+ return PS_Unknown_ReturnType;
+ }
+ desc.m_pReturnType = pRetType;
+ }
+ }
+ // Remove possible empty parentheses ()
+ m.remove( QRegExp("\\s*\\(\\s*\\)") );
+ desc.m_args.clear();
+ pat = QRegExp( "\\((.*)\\)" );
+ pos = pat.search(m);
+ if (pos == -1) // argument list is optional
+ return PS_OK;
+ QString arglist = pat.cap(1);
+ arglist = arglist.stripWhiteSpace();
+ if (arglist.isEmpty())
+ return PS_OK;
+ QStringList args = QStringList::split( QRegExp("\\s*,\\s*"), arglist);
+ for (QStringList::Iterator lit = args.begin(); lit != args.end(); ++lit) {
+ NameAndType nmTp;
+ Parse_Status ps = parseAttribute(*lit, nmTp, owningScope);
+ if (ps)
+ return ps;
+ desc.m_args.append(nmTp);
+ }
+ return PS_OK;
+}
+
+QString psText(Parse_Status value) {
+ const QString text[] = {
+ i18n("OK"), i18n("Empty"), i18n("Malformed argument"),
+ i18n("Unknown argument type"), i18n("Illegal method name"),
+ i18n("Unknown return type"), i18n("Unspecified error")
+ };
+ return text[(unsigned) value];
+}
+
+QString progLangToString(Uml::Programming_Language pl) {
+ switch (pl) {
+ case Uml::pl_ActionScript:
+ return "ActionScript";
+ case Uml::pl_Ada:
+ return "Ada";
+ case Uml::pl_Cpp:
+ return "C++";
+ case Uml::pl_CSharp:
+ return "C#";
+ case Uml::pl_D:
+ return "D";
+ case Uml::pl_IDL:
+ return "IDL";
+ case Uml::pl_Java:
+ return "Java";
+ case Uml::pl_JavaScript:
+ return "JavaScript";
+ case Uml::pl_Pascal:
+ return "Pascal";
+ case Uml::pl_Perl:
+ return "Perl";
+ case Uml::pl_PHP:
+ return "PHP";
+ case Uml::pl_PHP5:
+ return "PHP5";
+ case Uml::pl_Python:
+ return "Python";
+ case Uml::pl_Ruby:
+ return "Ruby";
+ case Uml::pl_SQL:
+ return "SQL";
+ case Uml::pl_Tcl:
+ return "Tcl";
+ case Uml::pl_XMLSchema:
+ return "XMLSchema";
+ default:
+ break;
+ }
+ return QString::null;
+}
+
+Uml::Programming_Language stringToProgLang(QString str) {
+ if (str == "ActionScript")
+ return Uml::pl_ActionScript;
+ if (str == "Ada")
+ return Uml::pl_Ada;
+ if (str == "C++" || str == "Cpp") // "Cpp" only for bkwd compatibility
+ return Uml::pl_Cpp;
+ if (str == "C#")
+ return Uml::pl_CSharp;
+ if (str == "D")
+ return Uml::pl_D;
+ if (str == "IDL")
+ return Uml::pl_IDL;
+ if (str == "Java")
+ return Uml::pl_Java;
+ if (str == "JavaScript")
+ return Uml::pl_JavaScript;
+ if (str == "Pascal")
+ return Uml::pl_Pascal;
+ if (str == "Perl")
+ return Uml::pl_Perl;
+ if (str == "PHP")
+ return Uml::pl_PHP;
+ if (str == "PHP5")
+ return Uml::pl_PHP5;
+ if (str == "Python")
+ return Uml::pl_Python;
+ if (str == "Ruby")
+ return Uml::pl_Ruby;
+ if (str == "SQL")
+ return Uml::pl_SQL;
+ if (str == "Tcl")
+ return Uml::pl_Tcl;
+ if (str == "XMLSchema")
+ return Uml::pl_XMLSchema;
+ return Uml::pl_Reserved;
+}
+
+bool typeIsRootView(Uml::ListView_Type type) {
+ switch (type) {
+ case Uml::lvt_View:
+ case Uml::lvt_Logical_View:
+ case Uml::lvt_UseCase_View:
+ case Uml::lvt_Component_View:
+ case Uml::lvt_Deployment_View:
+ case Uml::lvt_EntityRelationship_Model:
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool typeIsCanvasWidget(Uml::ListView_Type type) {
+ switch (type) {
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Component:
+ case Uml::lvt_Node:
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Entity:
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool typeIsFolder(Uml::ListView_Type type) {
+ if (typeIsRootView(type) ||
+ type == Uml::lvt_Datatype_Folder ||
+ type == Uml::lvt_Logical_Folder ||
+ type == Uml::lvt_UseCase_Folder ||
+ type == Uml::lvt_Component_Folder ||
+ type == Uml::lvt_Deployment_Folder ||
+ type == Uml::lvt_EntityRelationship_Folder) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool typeIsContainer(Uml::ListView_Type type) {
+ if (typeIsFolder(type))
+ return true;
+ return (type == Uml::lvt_Package ||
+ type == Uml::lvt_Subsystem ||
+ type == Uml::lvt_Component);
+}
+
+bool typeIsClassifierList(Uml::ListView_Type type) {
+ if (type == Uml::lvt_Attribute ||
+ type == Uml::lvt_Operation ||
+ type == Uml::lvt_Template ||
+ type == Uml::lvt_EntityAttribute ||
+ type == Uml::lvt_EnumLiteral) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool typeIsDiagram(Uml::ListView_Type type) {
+ if (type == Uml::lvt_Class_Diagram ||
+ type == Uml::lvt_Collaboration_Diagram ||
+ type == Uml::lvt_State_Diagram ||
+ type == Uml::lvt_Activity_Diagram ||
+ type == Uml::lvt_Sequence_Diagram ||
+ type == Uml::lvt_UseCase_Diagram ||
+ type == Uml::lvt_Component_Diagram ||
+ type == Uml::lvt_Deployment_Diagram ||
+ type == Uml::lvt_EntityRelationship_Diagram) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Uml::Model_Type convert_DT_MT(Uml::Diagram_Type dt) {
+ Uml::Model_Type mt;
+ switch (dt) {
+ case Uml::dt_UseCase:
+ mt = Uml::mt_UseCase;
+ break;
+ case Uml::dt_Collaboration:
+ case Uml::dt_Class:
+ case Uml::dt_Sequence:
+ case Uml::dt_State:
+ case Uml::dt_Activity:
+ mt = Uml::mt_Logical;
+ break;
+ case Uml::dt_Component:
+ mt = Uml::mt_Component;
+ break;
+ case Uml::dt_Deployment:
+ mt = Uml::mt_Deployment;
+ break;
+ case Uml::dt_EntityRelationship:
+ mt = Uml::mt_EntityRelationship;
+ break;
+ default:
+ kError() << "Model_Utils::convert_DT_MT: illegal input value " << dt << endl;
+ mt = Uml::N_MODELTYPES;
+ break;
+ }
+ return mt;
+}
+
+Uml::ListView_Type convert_MT_LVT(Uml::Model_Type mt) {
+ Uml::ListView_Type lvt = Uml::lvt_Unknown;
+ switch (mt) {
+ case Uml::mt_Logical:
+ lvt = Uml::lvt_Logical_View;
+ break;
+ case Uml::mt_UseCase:
+ lvt = Uml::lvt_UseCase_View;
+ break;
+ case Uml::mt_Component:
+ lvt = Uml::lvt_Component_View;
+ break;
+ case Uml::mt_Deployment:
+ lvt = Uml::lvt_Deployment_View;
+ break;
+ case Uml::mt_EntityRelationship:
+ lvt = Uml::lvt_EntityRelationship_Model;
+ break;
+ default:
+ break;
+ }
+ return lvt;
+}
+
+Uml::Model_Type convert_LVT_MT(Uml::ListView_Type lvt) {
+ Uml::Model_Type mt = Uml::N_MODELTYPES;
+ switch (lvt) {
+ case Uml::lvt_Logical_View:
+ mt = Uml::mt_Logical;
+ break;
+ case Uml::lvt_UseCase_View:
+ mt = Uml::mt_UseCase;
+ break;
+ case Uml::lvt_Component_View:
+ mt = Uml::mt_Component;
+ break;
+ case Uml::lvt_Deployment_View:
+ mt = Uml::mt_Deployment;
+ break;
+ case Uml::lvt_EntityRelationship_Model:
+ mt = Uml::mt_EntityRelationship;
+ break;
+ default:
+ break;
+ }
+ return mt;
+}
+
+Uml::ListView_Type convert_DT_LVT(Uml::Diagram_Type dt) {
+ Uml::ListView_Type type = Uml::lvt_Unknown;
+ switch(dt) {
+ case Uml::dt_UseCase:
+ type = Uml::lvt_UseCase_Diagram;
+ break;
+
+ case Uml::dt_Class:
+ type = Uml::lvt_Class_Diagram;
+ break;
+
+ case Uml::dt_Sequence:
+ type = Uml::lvt_Sequence_Diagram;
+ break;
+
+ case Uml::dt_Collaboration:
+ type = Uml::lvt_Collaboration_Diagram;
+ break;
+
+ case Uml::dt_State:
+ type = Uml::lvt_State_Diagram;
+ break;
+
+ case Uml::dt_Activity:
+ type = Uml::lvt_Activity_Diagram;
+ break;
+
+ case Uml::dt_Component:
+ type = Uml::lvt_Component_Diagram;
+ break;
+
+ case Uml::dt_Deployment:
+ type = Uml::lvt_Deployment_Diagram;
+ break;
+
+ case Uml::dt_EntityRelationship:
+ type = Uml::lvt_EntityRelationship_Diagram;
+ break;
+
+ default:
+ kWarning() << "convert_DT_LVT() called on unknown diagram type" << endl;
+ }
+ return type;
+}
+
+Uml::ListView_Type convert_OT_LVT(UMLObject *o) {
+ Uml::Object_Type ot = o->getBaseType();
+ Uml::ListView_Type type = Uml::lvt_Unknown;
+ switch(ot) {
+ case Uml::ot_UseCase:
+ type = Uml::lvt_UseCase;
+ break;
+
+ case Uml::ot_Actor:
+ type = Uml::lvt_Actor;
+ break;
+
+ case Uml::ot_Class:
+ type = Uml::lvt_Class;
+ break;
+
+ case Uml::ot_Package:
+ type = Uml::lvt_Package;
+ break;
+
+ case Uml::ot_Folder:
+ {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLFolder *f = static_cast<UMLFolder*>(o);
+ do {
+ const Uml::Model_Type mt = umldoc->rootFolderType(f);
+ if (mt != Uml::N_MODELTYPES) {
+ switch (mt) {
+ case Uml::mt_Logical:
+ type = Uml::lvt_Logical_Folder;
+ break;
+ case Uml::mt_UseCase:
+ type = Uml::lvt_UseCase_Folder;
+ break;
+ case Uml::mt_Component:
+ type = Uml::lvt_Component_Folder;
+ break;
+ case Uml::mt_Deployment:
+ type = Uml::lvt_Deployment_Folder;
+ break;
+ case Uml::mt_EntityRelationship:
+ type = Uml::lvt_EntityRelationship_Folder;
+ break;
+ default:
+ break;
+ }
+ return type;
+ }
+ } while ((f = static_cast<UMLFolder*>(f->getUMLPackage())) != NULL);
+ kError() << "convert_OT_LVT(" << o->getName()
+ << "): internal error - object is not properly nested in folder"
+ << endl;
+ }
+ break;
+
+ case Uml::ot_Component:
+ type = Uml::lvt_Component;
+ break;
+
+ case Uml::ot_Node:
+ type = Uml::lvt_Node;
+ break;
+
+ case Uml::ot_Artifact:
+ type = Uml::lvt_Artifact;
+ break;
+
+ case Uml::ot_Interface:
+ type = Uml::lvt_Interface;
+ break;
+
+ case Uml::ot_Datatype:
+ type = Uml::lvt_Datatype;
+ break;
+
+ case Uml::ot_Enum:
+ type = Uml::lvt_Enum;
+ break;
+
+ case Uml::ot_EnumLiteral:
+ type = Uml::lvt_EnumLiteral;
+ break;
+
+ case Uml::ot_Entity:
+ type = Uml::lvt_Entity;
+ break;
+
+ case Uml::ot_EntityAttribute:
+ type = Uml::lvt_EntityAttribute;
+ break;
+
+ case Uml::ot_Attribute:
+ type = Uml::lvt_Attribute;
+ break;
+
+ case Uml::ot_Operation:
+ type = Uml::lvt_Operation;
+ break;
+
+ case Uml::ot_Template:
+ type = Uml::lvt_Template;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+Uml::Object_Type convert_LVT_OT(Uml::ListView_Type lvt) {
+ Uml::Object_Type ot = (Uml::Object_Type)0;
+ switch (lvt) {
+ case Uml::lvt_UseCase:
+ ot = Uml::ot_UseCase;
+ break;
+
+ case Uml::lvt_Actor:
+ ot = Uml::ot_Actor;
+ break;
+
+ case Uml::lvt_Class:
+ ot = Uml::ot_Class;
+ break;
+
+ case Uml::lvt_Package:
+ case Uml::lvt_Subsystem:
+ ot = Uml::ot_Package;
+ break;
+
+ case Uml::lvt_Component:
+ ot = Uml::ot_Component;
+ break;
+
+ case Uml::lvt_Node:
+ ot = Uml::ot_Node;
+ break;
+
+ case Uml::lvt_Artifact:
+ ot = Uml::ot_Artifact;
+ break;
+
+ case Uml::lvt_Interface:
+ ot = Uml::ot_Interface;
+ break;
+
+ case Uml::lvt_Datatype:
+ ot = Uml::ot_Datatype;
+ break;
+
+ case Uml::lvt_Enum:
+ ot = Uml::ot_Enum;
+ break;
+
+ case Uml::lvt_Entity:
+ ot = Uml::ot_Entity;
+ break;
+
+ case Uml::lvt_EntityAttribute:
+ ot = Uml::ot_EntityAttribute;
+ break;
+
+ case Uml::lvt_Attribute:
+ ot = Uml::ot_Attribute;
+ break;
+
+ case Uml::lvt_Operation:
+ ot = Uml::ot_Operation;
+ break;
+
+ case Uml::lvt_Template:
+ ot = Uml::ot_Template;
+ break;
+
+ case Uml::lvt_EnumLiteral:
+ ot = Uml::ot_EnumLiteral;
+ break;
+
+ default:
+ if (typeIsFolder(lvt))
+ ot = Uml::ot_Folder;
+ break;
+ }
+ return ot;
+}
+
+Uml::Icon_Type convert_LVT_IT(Uml::ListView_Type lvt) {
+ Uml::Icon_Type icon = Uml::it_Home;
+ switch (lvt) {
+ case Uml::lvt_UseCase_View:
+ case Uml::lvt_UseCase_Folder:
+ icon = Uml::it_Folder_Grey;
+ break;
+ case Uml::lvt_Logical_View:
+ case Uml::lvt_Logical_Folder:
+ icon = Uml::it_Folder_Green;
+ break;
+ case Uml::lvt_Datatype_Folder:
+ icon = Uml::it_Folder_Orange;
+ break;
+ case Uml::lvt_Component_View:
+ case Uml::lvt_Component_Folder:
+ icon = Uml::it_Folder_Red;
+ break;
+ case Uml::lvt_Deployment_View:
+ case Uml::lvt_Deployment_Folder:
+ icon = Uml::it_Folder_Violet;
+ break;
+ case Uml::lvt_EntityRelationship_Model:
+ case Uml::lvt_EntityRelationship_Folder:
+ icon = Uml::it_Folder_Cyan;
+ break;
+
+ case Uml::lvt_Actor:
+ icon = Uml::it_Actor;
+ break;
+ case Uml::lvt_UseCase:
+ icon = Uml::it_UseCase;
+ break;
+ case Uml::lvt_Class:
+ icon = Uml::it_Class;
+ break;
+ case Uml::lvt_Package:
+ icon = Uml::it_Package;
+ break;
+ case Uml::lvt_Subsystem:
+ icon = Uml::it_Subsystem;
+ break;
+ case Uml::lvt_Component:
+ icon = Uml::it_Component;
+ break;
+ case Uml::lvt_Node:
+ icon = Uml::it_Node;
+ break;
+ case Uml::lvt_Artifact:
+ icon = Uml::it_Artifact;
+ break;
+ case Uml::lvt_Interface:
+ icon = Uml::it_Interface;
+ break;
+ case Uml::lvt_Datatype:
+ icon = Uml::it_Datatype;
+ break;
+ case Uml::lvt_Enum:
+ icon = Uml::it_Enum;
+ break;
+ case Uml::lvt_Entity:
+ icon = Uml::it_Entity;
+ break;
+ case Uml::lvt_Template:
+ icon = Uml::it_Template;
+ break;
+ case Uml::lvt_Attribute:
+ icon = Uml::it_Private_Attribute;
+ break;
+ case Uml::lvt_EntityAttribute:
+ icon = Uml::it_Private_Attribute;
+ break;
+ case Uml::lvt_EnumLiteral:
+ icon = Uml::it_Public_Attribute;
+ break;
+ case Uml::lvt_Operation:
+ icon = Uml::it_Public_Method;
+ break;
+
+ case Uml::lvt_Class_Diagram:
+ icon = Uml::it_Diagram_Class;
+ break;
+ case Uml::lvt_UseCase_Diagram:
+ icon = Uml::it_Diagram_Usecase;
+ break;
+ case Uml::lvt_Sequence_Diagram:
+ icon = Uml::it_Diagram_Sequence;
+ break;
+ case Uml::lvt_Collaboration_Diagram:
+ icon = Uml::it_Diagram_Collaboration;
+ break;
+ case Uml::lvt_State_Diagram:
+ icon = Uml::it_Diagram_State;
+ break;
+ case Uml::lvt_Activity_Diagram:
+ icon = Uml::it_Diagram_Activity;
+ break;
+ case Uml::lvt_Component_Diagram:
+ icon = Uml::it_Diagram_Component;
+ break;
+ case Uml::lvt_Deployment_Diagram:
+ icon = Uml::it_Diagram_Deployment;
+ break;
+ case Uml::lvt_EntityRelationship_Diagram:
+ icon = Uml::it_Diagram_EntityRelationship;
+ break;
+
+ default:
+ break;
+ }
+ return icon;
+}
+
+Uml::Diagram_Type convert_LVT_DT(Uml::ListView_Type lvt) {
+ Uml::Diagram_Type dt = Uml::dt_Undefined;
+ switch (lvt) {
+ case Uml::lvt_Class_Diagram:
+ dt = Uml::dt_Class;
+ break;
+ case Uml::lvt_UseCase_Diagram:
+ dt = Uml::dt_UseCase;
+ break;
+ case Uml::lvt_Sequence_Diagram:
+ dt = Uml::dt_Sequence;
+ break;
+ case Uml::lvt_Collaboration_Diagram:
+ dt = Uml::dt_Collaboration;
+ break;
+ case Uml::lvt_State_Diagram:
+ dt = Uml::dt_State;
+ break;
+ case Uml::lvt_Activity_Diagram:
+ dt = Uml::dt_Activity;
+ break;
+ case Uml::lvt_Component_Diagram:
+ dt = Uml::dt_Component;
+ break;
+ case Uml::lvt_Deployment_Diagram:
+ dt = Uml::dt_Deployment;
+ break;
+ case Uml::lvt_EntityRelationship_Diagram:
+ dt = Uml::dt_EntityRelationship;
+ break;
+ default:
+ break;
+ }
+ return dt;
+}
+
+Uml::Model_Type convert_OT_MT(Uml::Object_Type ot) {
+ Uml::Model_Type mt = Uml::N_MODELTYPES;
+ switch (ot) {
+ case Uml::ot_Actor:
+ case Uml::ot_UseCase:
+ mt = Uml::mt_UseCase;
+ break;
+ case Uml::ot_Component:
+ case Uml::ot_Artifact:
+ mt = Uml::mt_Component;
+ break;
+ case Uml::ot_Node:
+ mt = Uml::mt_Deployment;
+ break;
+ case Uml::ot_Entity:
+ case Uml::ot_EntityAttribute:
+ mt = Uml::mt_EntityRelationship;
+ break;
+ default:
+ mt = Uml::mt_Logical;
+ break;
+ }
+ return mt;
+}
+
+} // namespace Model_Utils
+
diff --git a/umbrello/umbrello/model_utils.h b/umbrello/umbrello/model_utils.h
new file mode 100644
index 00000000..3fa19afb
--- /dev/null
+++ b/umbrello/umbrello/model_utils.h
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef MODEL_UTILS_H
+#define MODEL_UTILS_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include "umlnamespace.h"
+#include "umlobjectlist.h"
+
+/**
+ * General purpose model utilities.
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+
+// forward declarations
+class UMLClassifier;
+class UMLPackage;
+
+namespace Model_Utils {
+
+/**
+ * Determines whether the given widget type is cloneable.
+ *
+ * @param type The input Widget_Type.
+ * @return True if the given type is cloneable.
+ */
+bool isCloneable(Uml::Widget_Type type);
+
+/**
+ * Seek the given id in the given list of objects.
+ * Each list element may itself contain other objects
+ * and the search is done recursively.
+ *
+ * @param id The unique ID to seek.
+ * @param inList The UMLObjectList in which to search.
+ * @return Pointer to the UMLObject that matches the ID
+ * (NULL if none matches.)
+ */
+UMLObject * findObjectInList(Uml::IDType id, const UMLObjectList& inList);
+
+/**
+ * Find the UML object of the given type and name in the passed-in list.
+ *
+ * @param inList List in which to seek the object.
+ * @param name Name of the object to find.
+ * @param type Object_Type of the object to find (optional.)
+ * When the given type is ot_UMLObject the type is
+ * disregarded, i.e. the given name is the only
+ * search criterion.
+ * @param currentObj Object relative to which to search (optional.)
+ * If given then the enclosing scope(s) of this
+ * object are searched before the global scope.
+ * @return Pointer to the UMLObject found, or NULL if not found.
+ */
+UMLObject* findUMLObject( const UMLObjectList& inList,
+ const QString& name,
+ Uml::Object_Type type = Uml::ot_UMLObject,
+ UMLObject *currentObj = NULL);
+
+/**
+ * Returns a name for the new object, appended with a number
+ * if the default name is taken e.g. new_actor, new_actor_1
+ * etc.
+ * @param type The object type.
+ * @param parentPkg The package in which to compare the name.
+ * @param prefix The prefix to use (optional.)
+ * If no prefix is given then a type related
+ * prefix will be chosen internally.
+ */
+QString uniqObjectName(Uml::Object_Type type,
+ UMLPackage *parentPkg,
+ QString prefix = QString::null);
+
+/**
+ * Return true if the given tag is a one of the common XMI
+ * attributes, such as:
+ * "name" | "visibility" | "isRoot" | "isLeaf" | "isAbstract" |
+ * "isActive" | "ownerScope"
+ */
+bool isCommonXMIAttribute(const QString &tag);
+
+/**
+ * Return true if the given type is common among the majority
+ * of programming languages, such as "bool" or "boolean".
+ * TODO: Make this depend on the active programming language.
+ */
+bool isCommonDataType(QString type);
+
+/**
+ * Return true if the given object type is a classifier list item type.
+ */
+bool isClassifierListitem(Uml::Object_Type ot);
+
+/**
+ * Return true if the listview type also has a widget representation in diagrams.
+ */
+bool typeIsCanvasWidget(Uml::ListView_Type type);
+
+/**
+ * Return true if the listview type is one of the predefined root views
+ * (root, logical, usecase, component, deployment, datatype, or entity-
+ * relationship view.)
+ */
+bool typeIsRootView(Uml::ListView_Type type);
+
+/**
+ * Return true if the listview type is a logical, usecase or component folder.
+ */
+bool typeIsFolder(Uml::ListView_Type type);
+
+/**
+ * Return true if the listview type may act as a container for other objects,
+ * i.e. if it is a folder, package, subsystem, or component.
+ */
+bool typeIsContainer(Uml::ListView_Type type);
+
+/**
+ * Return true if the listview type is a diagram.
+ */
+bool typeIsDiagram(Uml::ListView_Type type);
+
+/**
+ * Return true if the listview type is an attribute, operation, or template.
+ */
+bool typeIsClassifierList(Uml::ListView_Type type);
+
+/**
+ * Return the Model_Type which corresponds to the given Diagram_Type.
+ */
+Uml::Model_Type convert_DT_MT(Uml::Diagram_Type dt);
+
+/**
+ * Return the ListView_Type which corresponds to the given Model_Type.
+ */
+Uml::ListView_Type convert_MT_LVT(Uml::Model_Type mt);
+
+/**
+ * Return the Model_Type which corresponds to the given ListView_Type.
+ * Returns Uml::N_MODELTYPES if the list view type given does not map
+ * to a Model_Type.
+ */
+Uml::Model_Type convert_LVT_MT(Uml::ListView_Type lvt);
+
+/**
+ * Convert a diagram type enum to the equivalent list view type.
+ */
+Uml::ListView_Type convert_DT_LVT(Uml::Diagram_Type dt);
+
+/**
+ * Converts a list view type enum to the equivalent object type.
+ *
+ * @param lvt The ListView_Type to convert.
+ * @return The converted Object_Type if the listview type
+ * has a Uml::Object_Type representation, else 0.
+ */
+Uml::Object_Type convert_LVT_OT(Uml::ListView_Type lvt);
+
+/**
+ * Convert an object's type to the equivalent list view type
+ *
+ * @param o Pointer to the UMLObject whose type shall be converted
+ * to the equivalent Uml::ListView_Type. We cannot just
+ * pass in a Uml::Object_Type because a UMLFolder is mapped
+ * to different Uml::ListView_Type values, depending on its
+ * location in one of the predefined modelviews (Logical/
+ * UseCase/etc.)
+ * @return The equivalent Uml::ListView_Type.
+ */
+Uml::ListView_Type convert_OT_LVT(UMLObject *o);
+
+/**
+ * Return the Icon_Type which corresponds to the given listview type.
+ *
+ * @param lvt ListView_Type to convert.
+ * @return The Uml::Icon_Type corresponding to the lvt.
+ * Returns it_Home in case no mapping to Uml::Icon_Type exists.
+ */
+Uml::Icon_Type convert_LVT_IT(Uml::ListView_Type lvt);
+
+/**
+ * Return the Diagram_Type which corresponds to the given listview type.
+ *
+ * @param lvt ListView_Type to convert.
+ * @return The Uml::Diagram_Type corresponding to the lvt.
+ * Returns dt_Undefined in case no mapping to Diagram_Type exists.
+ */
+Uml::Diagram_Type convert_LVT_DT(Uml::ListView_Type lvt);
+
+/**
+ * Return the Model_Type which corresponds to the given Object_Type.
+ */
+Uml::Model_Type convert_OT_MT(Uml::Object_Type ot);
+
+/**
+ * Try to guess the correct container folder type of an UMLObject.
+ * Object types that can't be guessed are mapped to Uml::mt_Logical.
+ * NOTE: This function exists mainly for handling pre-1.5.5 files
+ * and should not be used for new code.
+ */
+Uml::Model_Type guessContainer(UMLObject *o);
+
+/**
+ * Parse a direction string into the Uml::Parameter_Direction.
+ *
+ * @param input The string to parse: "in", "out", or "inout"
+ * optionally followed by whitespace.
+ * @param result The corresponding Uml::Parameter_Direction.
+ * @return Length of the string matched, excluding the optional
+ * whitespace.
+ */
+int stringToDirection(QString input, Uml::Parameter_Direction & result);
+
+/**
+ * Return string corresponding to the given Uml::Programming_Language.
+ */
+QString progLangToString(Uml::Programming_Language pl);
+
+/**
+ * Return Uml::Programming_Language corresponding to the given string.
+ */
+Uml::Programming_Language stringToProgLang(QString str);
+
+/**
+ * Return type of parseOperation()
+ */
+enum Parse_Status {
+ PS_OK, PS_Empty, PS_Malformed_Arg, PS_Unknown_ArgType,
+ PS_Illegal_MethodName, PS_Unknown_ReturnType, PS_Unspecified_Error
+};
+
+/**
+ * Data structure filled by parseAttribute()
+ */
+struct NameAndType {
+ QString m_name;
+ UMLObject *m_type;
+ Uml::Parameter_Direction m_direction;
+ QString m_initialValue;
+ NameAndType() : m_type(0), m_direction(Uml::pd_In) {
+ }
+ NameAndType(QString name, UMLObject *type,
+ Uml::Parameter_Direction direction = Uml::pd_In,
+ QString initialValue = QString::null)
+ : m_name(name), m_type(type),
+ m_direction(direction), m_initialValue(initialValue) {
+ }
+};
+
+/**
+ * Auxiliary type for OpDescriptor
+ */
+typedef QValueList<NameAndType> NameAndType_List;
+typedef QValueListIterator<NameAndType> NameAndType_ListIt;
+
+/**
+ * Data structure filled by parseOperation()
+ */
+struct OpDescriptor {
+ QString m_name;
+ NameAndType_List m_args;
+ UMLObject *m_pReturnType;
+};
+
+/**
+ * Parses a template parameter given in UML syntax.
+ *
+ * @param t Input text of the template parameter.
+ * Example: parname : partype
+ * or just: parname (for class type)
+ * @param nmTp NameAndType returned by this method.
+ * @param owningScope Pointer to the owning scope of the template param.
+ * @return Error status of the parse, PS_OK for success.
+ */
+Parse_Status parseTemplate(QString t, NameAndType& nmTp, UMLClassifier *owningScope);
+
+/**
+ * Parses an attribute given in UML syntax.
+ *
+ * @param a Input text of the attribute in UML syntax.
+ * Example: argname : argtype
+ * @param nmTp NameAndType returned by this method.
+ * @param owningScope Pointer to the owning scope of the attribute.
+ * @param vis Optional pointer to visibility (return value.)
+ * The visibility may be given at the beginning of the
+ * attribute text in mnemonic form as follows:
+ * "+" stands for public
+ * "#" stands for protected
+ * "-" stands for private
+ * "~" stands for implementation level visibility
+ *
+ * @return Error status of the parse, PS_OK for success.
+ */
+Parse_Status parseAttribute(QString a, NameAndType& nmTp, UMLClassifier *owningScope,
+ Uml::Visibility *vis = 0);
+
+/**
+ * Parses an operation given in UML syntax.
+ *
+ * @param m Input text of the operation in UML syntax.
+ * Example of a two-argument operation returning "void":
+ * methodname (arg1name : arg1type, arg2name : arg2type) : void
+ * @param desc OpDescriptor returned by this method.
+ * @param owningScope Pointer to the owning scope of the operation.
+ * @return Error status of the parse, PS_OK for success.
+ */
+Parse_Status parseOperation(QString m, OpDescriptor& desc, UMLClassifier *owningScope);
+
+/**
+ * Returns the Parse_Status as a text.
+ */
+QString psText(Parse_Status value);
+
+}
+
+#endif
diff --git a/umbrello/umbrello/node.cpp b/umbrello/umbrello/node.cpp
new file mode 100644
index 00000000..0070f481
--- /dev/null
+++ b/umbrello/umbrello/node.cpp
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "node.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+UMLNode::UMLNode(const QString & name, Uml::IDType id)
+ : UMLCanvasObject(name, id) {
+ init();
+}
+
+UMLNode::~UMLNode() {
+}
+
+void UMLNode::init() {
+ m_BaseType = Uml::ot_Node;
+}
+
+UMLObject* UMLNode::clone() const {
+ UMLNode *clone = new UMLNode();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLNode::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement nodeElement = UMLObject::save("UML:Node", qDoc);
+ qElement.appendChild(nodeElement);
+}
+
+bool UMLNode::load(QDomElement& ) {
+ return true;
+}
+
+#include "node.moc"
diff --git a/umbrello/umbrello/node.h b/umbrello/umbrello/node.h
new file mode 100644
index 00000000..057ea219
--- /dev/null
+++ b/umbrello/umbrello/node.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NODE_H
+#define NODE_H
+
+#include "umlcanvasobject.h"
+
+
+/**
+ * This class contains the non-graphical information required for a UML Node.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Node.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLNode : public UMLCanvasObject {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a Node.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLNode(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Empty deconstructor.
+ */
+ virtual ~UMLNode();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates the <UML:Node> XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Loads the <UML:Node> XMI element (empty.)
+ */
+ bool load( QDomElement & element );
+
+};
+
+#endif
diff --git a/umbrello/umbrello/nodewidget.cpp b/umbrello/umbrello/nodewidget.cpp
new file mode 100644
index 00000000..2bd78a93
--- /dev/null
+++ b/umbrello/umbrello/nodewidget.cpp
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "nodewidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+
+// app includes
+#include "node.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+
+NodeWidget::NodeWidget(UMLView * view, UMLNode *n )
+ : UMLWidget(view, n) {
+ UMLWidget::setBaseType(Uml::wt_Node);
+ setZ(m_origZ = 1); // above box but below UMLWidget because may embed widgets
+ setSize(100, 30);
+ if (n && !UMLApp::app()->getDocument()->loading())
+ updateComponentSize();
+}
+
+NodeWidget::~NodeWidget() {}
+
+void NodeWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() ) {
+ p.setBrush( UMLWidget::getFillColour() );
+ } else {
+ p.setBrush( m_pView->viewport()->backgroundColor() );
+ }
+ const int w = width();
+ const int h = height();
+ const int wDepth = (w/3 > DEPTH ? DEPTH : w/3);
+ const int hDepth = (h/3 > DEPTH ? DEPTH : h/3);
+ const int bodyOffsetY = offsetY + hDepth;
+ const int bodyWidth = w - wDepth;
+ const int bodyHeight = h - hDepth;
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString name = getName();
+
+ QPointArray pointArray(5);
+ pointArray.setPoint(0, offsetX, bodyOffsetY);
+ pointArray.setPoint(1, offsetX + wDepth, offsetY);
+ pointArray.setPoint(2, offsetX + w - 1, offsetY);
+ pointArray.setPoint(3, offsetX + w - 1, offsetY + bodyHeight );
+ pointArray.setPoint(4, offsetX + bodyWidth, offsetY + h - 1);
+ p.drawPolygon(pointArray);
+ p.drawRect(offsetX, bodyOffsetY, bodyWidth, bodyHeight);
+ p.drawLine(offsetX + w - 1, offsetY, offsetX + bodyWidth - 2, bodyOffsetY + 1);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ int lines = 1;
+ if (m_pObject) {
+ QString stereotype = m_pObject->getStereotype();
+ if (!stereotype.isEmpty()) {
+ p.drawText(offsetX, bodyOffsetY + (bodyHeight/2) - fontHeight,
+ bodyWidth, fontHeight, Qt::AlignCenter, m_pObject->getStereotype(true));
+ lines = 2;
+ }
+ }
+
+ if ( UMLWidget::getIsInstance() ) {
+ font.setUnderline(true);
+ p.setFont(font);
+ name = UMLWidget::getInstanceName() + " : " + name;
+ }
+
+ if (lines == 1) {
+ p.drawText(offsetX, bodyOffsetY + (bodyHeight/2) - (fontHeight/2),
+ bodyWidth, fontHeight, Qt::AlignCenter, name);
+ } else {
+ p.drawText(offsetX, bodyOffsetY + (bodyHeight/2),
+ bodyWidth, fontHeight, Qt::AlignCenter, name);
+ }
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize NodeWidget::calculateSize() {
+ if (m_pObject == NULL) {
+ kDebug() << "NodeWidget::calculateSize: m_pObject is NULL" << endl;
+ return UMLWidget::calculateSize();
+ }
+
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ QString name = m_pObject->getName();
+ if ( UMLWidget::getIsInstance() ) {
+ name = UMLWidget::getInstanceName() + " : " + name;
+ }
+
+ int width = fm.width(name);
+
+ int tempWidth = 0;
+ if (!m_pObject->getStereotype().isEmpty()) {
+ tempWidth = fm.width(m_pObject->getStereotype(true));
+ }
+ if (tempWidth > width)
+ width = tempWidth;
+ width += DEPTH;
+
+ int height = (2*fontHeight) + DEPTH;
+
+ return QSize(width, height);
+}
+
+void NodeWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement conceptElement = qDoc.createElement("nodewidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
diff --git a/umbrello/umbrello/nodewidget.h b/umbrello/umbrello/nodewidget.h
new file mode 100644
index 00000000..90d28f63
--- /dev/null
+++ b/umbrello/umbrello/nodewidget.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NODEWIDGET_H
+#define NODEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLNode;
+
+/**
+ * Defines a graphical version of the Node. Most of the functionality
+ * will come from the @ref UMLNode class.
+ *
+ * @short A graphical version of a Node.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class NodeWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a NodeWidget.
+ *
+ * @param view The parent of this NodeWidget.
+ * @param n The UMLNode this will be representing.
+ */
+ NodeWidget(UMLView * view, UMLNode *n );
+
+ /**
+ * destructor
+ */
+ virtual ~NodeWidget();
+
+ /**
+ * Overrides standard method.
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "nodewidget" XMI element.
+ * Note: For loading we use the method inherited from UMLWidget.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+
+ static const int DEPTH = 30; ///< pixels on Z axis
+};
+
+#endif
diff --git a/umbrello/umbrello/notewidget.cpp b/umbrello/umbrello/notewidget.cpp
new file mode 100644
index 00000000..0cc7d079
--- /dev/null
+++ b/umbrello/umbrello/notewidget.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "notewidget.h"
+//qt includes
+#include <qpointarray.h>
+#include <qpainter.h>
+#include <qtextedit.h>
+#include <qframe.h>
+// kde includes
+#include <kdebug.h>
+#include <kcolordialog.h>
+// app includes
+#include "notewidgetcontroller.h"
+#include "dialogs/notedialog.h"
+#include "clipboard/umldrag.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "uml.h"
+#include "listpopupmenu.h"
+
+#define NOTEMARGIN 10
+
+NoteWidget::NoteWidget(UMLView * view, Uml::IDType id)
+ : UMLWidget(view, id, new NoteWidgetController(this)) {
+ init();
+ setSize(100,80);
+ setZ( 20 ); //make sure always on top.
+#ifdef NOTEWIDGET_EMBED_EDITOR
+ // NB: This code is currently deactivated because
+ // Zoom does not yet work with the embedded text editor.
+ m_pEditor = new QTextEdit(view);
+ m_pEditor->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
+ m_pEditor->setHScrollBarMode(QScrollView::AlwaysOff);
+ m_pEditor->setVScrollBarMode(QScrollView::AlwaysOff);
+ m_pEditor->setTextFormat(Qt::RichText);
+ m_pEditor->setShown(true);
+ setEditorGeometry();
+ connect(m_pView, SIGNAL(contentsMoving(int, int)),
+ this, SLOT(slotViewScrolled(int, int)));
+#endif
+}
+
+void NoteWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Note);
+ m_DiagramLink = Uml::id_None;
+}
+
+NoteWidget::~NoteWidget() {
+#ifdef NOTEWIDGET_EMBED_EDITOR
+ delete m_pEditor;
+#endif
+}
+
+void NoteWidget::setDiagramLink(Uml::IDType viewID) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLView *view = umldoc->findView(viewID);
+ if (view == NULL) {
+ kError() << "NoteWidget::setDiagramLink(" << ID2STR(viewID)
+ << "): no view found for this ID." << endl;
+ return;
+ }
+ QString linkText("Diagram: " + view->getName());
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ m_pEditor->setUnderline(true);
+ m_pEditor->insert(linkText);
+ m_pEditor->setUnderline(false);
+#else
+ setDoc(linkText);
+ update();
+#endif
+ m_DiagramLink = viewID;
+}
+
+Uml::IDType NoteWidget::getDiagramLink() const {
+ return m_DiagramLink;
+}
+
+void NoteWidget::slotViewScrolled(int x, int y) {
+ setEditorGeometry(x, y);
+}
+
+void NoteWidget::setFont(QFont font) {
+ UMLWidget::setFont(font);
+#ifdef NOTEWIDGET_EMBED_EDITOR
+ m_pEditor->setFont(font);
+#endif
+}
+
+void NoteWidget::setEditorGeometry(int dx /*=0*/, int dy /*=0*/) {
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ const QRect editorGeometry( UMLWidget::getX() - dx + 6,
+ UMLWidget::getY() - dy + 10,
+ UMLWidget::getWidth() - 16,
+ UMLWidget::getHeight() - 16);
+ m_pEditor->setGeometry( editorGeometry );
+ drawText();
+#else
+ dx=0; dy=0; // avoid "unused arg" warnings
+#endif
+}
+
+void NoteWidget::setX( int x ) {
+ UMLWidget::setX(x);
+ setEditorGeometry();
+}
+
+void NoteWidget::setY( int y ) {
+ UMLWidget::setY(y);
+ setEditorGeometry();
+}
+
+QString NoteWidget::getDoc() const {
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ return m_pEditor->text();
+#else
+ return m_Text;
+#endif
+}
+
+void NoteWidget::setDoc(const QString &newText) {
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ m_pEditor->setText(newText);
+#else
+ m_Text = newText;
+#endif
+}
+
+void NoteWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ int margin = 10;
+ int w = width()-1;
+
+ int h= height()-1;
+ QPointArray poly(6);
+ poly.setPoint(0, offsetX, offsetY);
+ poly.setPoint(1, offsetX, offsetY + h);
+ poly.setPoint(2, offsetX + w, offsetY + h);
+ poly.setPoint(3, offsetX + w, offsetY + margin);
+ poly.setPoint(4, offsetX + w - margin, offsetY);
+ poly.setPoint(5, offsetX, offsetY);
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() ) {
+ QBrush brush( UMLWidget::getFillColour() );
+ p.setBrush(brush);
+ p.drawPolygon(poly);
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ m_pEditor->setPaper(brush);
+#endif
+ } else
+ p.drawPolyline(poly);
+ p.drawLine(offsetX + w - margin, offsetY, offsetX + w - margin, offsetY + margin);
+ p.drawLine(offsetX + w - margin, offsetY + margin, offsetX + w, offsetY + margin);
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+
+ drawText(&p, offsetX, offsetY);
+}
+
+QSize NoteWidget::calculateSize() {
+ return QSize(50, 50);
+}
+
+void NoteWidget::slotMenuSelection(int sel) {
+ NoteDialog * dlg = 0;
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ switch(sel) {
+ ///OBSOLETE - remove ListPopupMenu::mt_Link_Docs
+ // case ListPopupMenu::mt_Link_Docs:
+ // m_pView->updateNoteWidgets();
+ // doc -> setModified(true);
+ // break;
+
+ case ListPopupMenu::mt_Rename:
+ m_pView -> updateDocumentation( false );
+ dlg = new NoteDialog( m_pView, this );
+ if( dlg -> exec() ) {
+ m_pView -> showDocumentation( this, true );
+ doc -> setModified(true);
+ update();
+ }
+ delete dlg;
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(sel);
+ break;
+ }
+}
+
+void NoteWidget::drawText(QPainter * p /*=NULL*/, int offsetX /*=0*/, int offsetY /*=0*/) {
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ m_pEditor->setText( getDoc() );
+ m_pEditor->setShown(true);
+ m_pEditor->repaint();
+#else
+ if (p == NULL)
+ return;
+ /*
+ Implement word wrap for text as follows:
+ wrap at width on whole words.
+ if word is wider than width then clip word
+ if reach height exit and don't print anymore
+ start new line on \n character
+ */
+ p->setPen( Qt::black );
+ QFont font = UMLWidget::getFont();
+ p->setFont( font );
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ QString text = getDoc();
+ if( text.length() == 0 )
+ return;
+ QString word = "";
+ QString fullLine = "";
+ QString testCombineLine = "";
+ const int margin = fm.width( "W" );
+ int textY = fontHeight / 2;
+ int textX = margin;
+ const int width = this -> width() - margin * 2;
+ const int height = this -> height() - fontHeight;
+ QChar returnChar('\n');
+ QChar c;
+ for (uint i = 0; i <= text.length(); i++) {
+ if (i < text.length()) {
+ c = text[i];
+ } else {
+ // all chars of text have been handled already ->
+ // perform this last run to spool current content of "word"
+ c = returnChar;
+ }
+ if (c == returnChar || c.isSpace()) {
+ // new word delimiter found -> its time to decide on word wrap
+ testCombineLine = fullLine + ' ' + word;
+ int textWidth = fm.width( testCombineLine );
+ if (textX + textWidth > width) {
+ // combination of "fullLine" and "word" doesn't fit into one line ->
+ // print "fullLine" in current line, update write position to next line
+ // and decide then on following actions
+ p->drawText(offsetX + textX, offsetY + textY,
+ textWidth, fontHeight, Qt::AlignLeft, fullLine );
+ fullLine = word;
+ word = "";
+ // update write position
+ textX = margin;
+ textY += fontHeight;
+ if (textY > height)
+ return;
+ // in case of c==newline ->
+ // print "word" and set write position one additional line lower
+ if (c == returnChar) {
+ // print "word" - which is now "fullLine" and set to next line
+ p->drawText(offsetX + textX, offsetY + textY,
+ textWidth, fontHeight, Qt::AlignLeft, fullLine);
+ fullLine = "";
+ textX = margin;
+ textY += fontHeight;
+ if( textY > height ) return;
+ }
+ }
+ else if ( c == returnChar ) {
+ // newline found and combination of "fullLine" and "word" fits
+ // in one line
+ p->drawText(offsetX + textX, offsetY + textY,
+ textWidth, fontHeight, Qt::AlignLeft, testCombineLine);
+ fullLine = word = "";
+ textX = margin;
+ textY += fontHeight;
+ if (textY > height)
+ return;
+ } else {
+ // word delimiter found, and combination of "fullLine", space and "word" fits into one line
+ fullLine = testCombineLine;
+ word = "";
+ }
+ } else {
+ // no word delimiter found --> add current char to "word"
+ if (c != '\0')
+ word += c;
+ }
+ }//end for
+#endif
+}
+
+void NoteWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement noteElement = qDoc.createElement( "notewidget" );
+ UMLWidget::saveToXMI( qDoc, noteElement );
+ noteElement.setAttribute( "text", getDoc() );
+ if (m_DiagramLink != Uml::id_None)
+ noteElement.setAttribute( "diagramlink", ID2STR(m_DiagramLink) );
+ qElement.appendChild( noteElement );
+}
+
+bool NoteWidget::loadFromXMI( QDomElement & qElement ) {
+ if( !UMLWidget::loadFromXMI( qElement ) )
+ return false;
+ setZ( 20 ); //make sure always on top.
+ setDoc( qElement.attribute("text", "") );
+ QString diagramlink = qElement.attribute("diagramlink", "");
+ if (!diagramlink.isEmpty())
+ m_DiagramLink = STR2ID(diagramlink);
+ return true;
+}
+
+
+#include "notewidget.moc"
+
diff --git a/umbrello/umbrello/notewidget.h b/umbrello/umbrello/notewidget.h
new file mode 100644
index 00000000..298839cb
--- /dev/null
+++ b/umbrello/umbrello/notewidget.h
@@ -0,0 +1,146 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NOTEWIDGET_H
+#define NOTEWIDGET_H
+
+//app includes
+#include "umlwidget.h"
+
+// forward declarations
+class NoteWidgetController;
+
+// Qt forward declarations
+class QPainter;
+class QTextEdit;
+
+/**
+ * Displays a note box to allow multiple lines of text to be displayed.
+ * These widgets are diagram specific. They will still need a unique id
+ * from the @ref UMLDoc class for deletion and other purposes.
+ *
+ * @short Displays a note box.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class NoteWidget : public UMLWidget {
+ Q_OBJECT
+public:
+ friend class NoteWidgetController;
+
+ /**
+ * Constructs a NoteWidget.
+ *
+ * @param view The parent to this widget.
+ * @param noteType The NoteWidget::NoteType of this NoteWidget
+ * @param id The unique id of the widget.
+ * The default (-1) will prompt a new ID.
+ */
+ explicit NoteWidget(UMLView * view, Uml::IDType id = Uml::id_None );
+
+ /**
+ * destructor
+ */
+ virtual ~NoteWidget();
+
+ /**
+ * Overrides method from UMLWidget.
+ */
+ QSize calculateSize();
+
+ /**
+ * Returns the text in the box.
+ *
+ * @return The text in the box.
+ */
+ QString getDoc() const;
+
+ /**
+ * Sets the note documentation.
+ *
+ * @param newText The text to set the documentation to.
+ */
+ void setDoc(const QString &newText);
+
+ /**
+ * Set the ID of the diagram hyperlinked to this note.
+ * To switch off the hyperlink, set this to Uml::id_None.
+ *
+ * @param viewID ID of an UMLView.
+ */
+ void setDiagramLink(Uml::IDType viewID);
+
+ /**
+ * Return the ID of the diagram hyperlinked to this note.
+ *
+ * @return ID of an UMLView, or Uml::id_None if no
+ * hyperlink is set.
+ */
+ Uml::IDType getDiagramLink() const;
+
+ /**
+ * Override default method.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Override method from UMLWidget.
+ */
+ void setFont(QFont font);
+
+ /**
+ * Override method from UMLWidget.
+ */
+ void setX(int x);
+
+ /**
+ * Override method from UMLWidget.
+ */
+ void setY(int y);
+
+ /**
+ * Saves to the "notewidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads a "notewidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+public slots:
+ void slotMenuSelection(int sel);
+ void slotViewScrolled(int x, int y);
+
+protected:
+ // Data loaded/saved
+ Uml::IDType m_DiagramLink;
+
+ /**
+ * Draws the text. Auxiliary to draw().
+ */
+ void drawText(QPainter * p = NULL, int offsetX = 0, int offsetY = 0);
+private:
+ /**
+ * Initializes key variables for the class.
+ */
+ void init();
+
+ void setEditorGeometry(int dx = 0, int dy = 0);
+#if defined (NOTEWIDGET_EMBED_EDITOR)
+ QTextEdit *m_pEditor;
+#else
+ QString m_Text;
+#endif
+};
+
+#endif
diff --git a/umbrello/umbrello/notewidgetcontroller.cpp b/umbrello/umbrello/notewidgetcontroller.cpp
new file mode 100644
index 00000000..e61a7d76
--- /dev/null
+++ b/umbrello/umbrello/notewidgetcontroller.cpp
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// app includes
+#include "notewidgetcontroller.h"
+#include "notewidget.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "listpopupmenu.h"
+
+NoteWidgetController::NoteWidgetController(NoteWidget *noteWidget):
+ UMLWidgetController(noteWidget) {
+ m_noteWidget = noteWidget;
+}
+
+NoteWidgetController::~NoteWidgetController() {
+}
+
+void NoteWidgetController::mouseMoveEvent(QMouseEvent *me) {
+ UMLWidgetController::mouseMoveEvent(me);
+ m_noteWidget->setEditorGeometry();
+}
+
+void NoteWidgetController::mouseReleaseEvent(QMouseEvent *me) {
+ UMLWidgetController::mouseReleaseEvent(me);
+ //TODO why is it needed? drawText is already called in draw,
+ //and draw is (well, I think that is) called when the canvas rectangle is resized
+ if (m_resized) {
+ m_noteWidget->drawText();
+ }
+}
+
+void NoteWidgetController::doMouseDoubleClick(QMouseEvent *me) {
+ //TODO Copied from old code. What it does?
+ if (m_noteWidget->m_DiagramLink == Uml::id_None) {
+ m_noteWidget->slotMenuSelection(ListPopupMenu::mt_Rename);
+ } else {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->changeCurrentView(m_noteWidget->m_DiagramLink);
+ }
+}
diff --git a/umbrello/umbrello/notewidgetcontroller.h b/umbrello/umbrello/notewidgetcontroller.h
new file mode 100644
index 00000000..f3295ce7
--- /dev/null
+++ b/umbrello/umbrello/notewidgetcontroller.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NOTEWIDGETCONTROLLER_H
+#define NOTEWIDGETCONTROLLER_H
+
+#include "umlwidgetcontroller.h"
+
+class NoteWidget;
+
+/**
+ * Controller for NoteWidget.
+ *
+ * MouseMove and MouseRelease execute the base code and then specific code
+ * for note widget.
+ *
+ * Double click behaviour is edit the text of the note.
+ *
+ * @author Umbrello UML Modeller Authors <uml-devel@lists.sourceforge.net>
+ */
+class NoteWidgetController : public UMLWidgetController {
+public:
+
+ /**
+ * Constructor for NoteWidgetController.
+ *
+ * @param noteWidget The NoteWidget which uses the controller.
+ */
+ NoteWidgetController(NoteWidget* noteWidget);
+
+ /**
+ * Destructor for NoteWidgetController.
+ */
+ virtual ~NoteWidgetController();
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Handles a mouse move event.
+ * Executes base code and then sets the geometry of the editor.
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseMoveEvent(QMouseEvent* me);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Handles a mouse release event.
+ * Executes base code and then draws the text in the note.
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseReleaseEvent(QMouseEvent * me);
+
+protected:
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Executes the action for double click in the widget.
+ * Shows the dialog to change the text of the note.
+ *
+ * @param me The QMouseEvent which triggered the double click event.
+ */
+ virtual void doMouseDoubleClick(QMouseEvent *me);
+
+private:
+
+ /**
+ * The note widget which uses the controller.
+ */
+ NoteWidget* m_noteWidget;
+};
+
+#endif
diff --git a/umbrello/umbrello/object_factory.cpp b/umbrello/umbrello/object_factory.cpp
new file mode 100644
index 00000000..f6fcbe41
--- /dev/null
+++ b/umbrello/umbrello/object_factory.cpp
@@ -0,0 +1,283 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "object_factory.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <qstringlist.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "umlobject.h"
+#include "umlpackagelist.h"
+#include "package.h"
+#include "folder.h"
+#include "classifier.h"
+#include "attribute.h"
+#include "operation.h"
+#include "enum.h"
+#include "entity.h"
+#include "actor.h"
+#include "usecase.h"
+#include "component.h"
+#include "node.h"
+#include "artifact.h"
+#include "stereotype.h"
+#include "association.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "codegenerator.h"
+#include "model_utils.h"
+#include "uniqueid.h"
+
+namespace Object_Factory {
+
+Uml::IDType g_predefinedId = Uml::id_None;
+
+void assignUniqueIdOnCreation(bool yesno) {
+ if (yesno)
+ g_predefinedId = Uml::id_None;
+ else
+ g_predefinedId = Uml::id_Reserved;
+}
+
+bool assignUniqueIdOnCreation() {
+ return (g_predefinedId == Uml::id_None);
+}
+
+UMLObject* createNewUMLObject(Uml::Object_Type type, const QString &name,
+ UMLPackage *parentPkg) {
+ if (parentPkg == NULL) {
+ kError() << "Object_Factory::createNewUMLObject(" << name
+ << "): parentPkg is NULL" << endl;
+ return NULL;
+ }
+ UMLObject *o = NULL;
+ switch (type) {
+ case Uml::ot_Actor:
+ o = new UMLActor(name, g_predefinedId);
+ break;
+ case Uml::ot_UseCase:
+ o = new UMLUseCase(name, g_predefinedId);
+ break;
+ case Uml::ot_Class:
+ o = new UMLClassifier(name, g_predefinedId);
+ break;
+ case Uml::ot_Package:
+ o = new UMLPackage(name, g_predefinedId);
+ break;
+ case Uml::ot_Component:
+ o = new UMLComponent(name, g_predefinedId);
+ break;
+ case Uml::ot_Node:
+ o = new UMLNode(name, g_predefinedId);
+ break;
+ case Uml::ot_Artifact:
+ o = new UMLArtifact(name, g_predefinedId);
+ break;
+ case Uml::ot_Interface: {
+ UMLClassifier *c = new UMLClassifier(name, g_predefinedId);
+ c->setBaseType(Uml::ot_Interface);
+ o = c;
+ break;
+ }
+ case Uml::ot_Datatype: {
+ UMLClassifier *c = new UMLClassifier(name, g_predefinedId);
+ c->setBaseType(Uml::ot_Datatype);
+ o = c;
+ break;
+ }
+ case Uml::ot_Enum:
+ o = new UMLEnum(name, g_predefinedId);
+ break;
+ case Uml::ot_Entity:
+ o = new UMLEntity(name, g_predefinedId);
+ break;
+ case Uml::ot_Folder:
+ o = new UMLFolder(name, g_predefinedId);
+ break;
+ default:
+ kWarning() << "createNewUMLObject error unknown type: " << type << endl;
+ return NULL;
+ }
+ o->setUMLPackage(parentPkg);
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ parentPkg->addObject(o);
+ doc->signalUMLObjectCreated(o);
+ kapp->processEvents();
+ return o;
+}
+
+UMLObject* createUMLObject(Uml::Object_Type type, const QString &n,
+ UMLPackage *parentPkg /* = NULL */,
+ bool solicitNewName /* = true */) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ if (parentPkg == NULL) {
+ if (type == Uml::ot_Datatype) {
+ parentPkg = doc->getDatatypeFolder();
+ } else {
+ Uml::Model_Type mt = Model_Utils::convert_OT_MT(type);
+ kDebug() << "Object_Factory::createUMLObject(" << n << "): "
+ << "parentPkg is not set, assuming Model_Type " << mt << endl;
+ parentPkg = doc->getRootFolder(mt);
+ }
+ }
+ if (!n.isEmpty()) {
+ UMLObject *o = doc->findUMLObject(n, type, parentPkg);
+ if (o) {
+ if (!solicitNewName)
+ return o;
+ } else {
+ o = createNewUMLObject(type, n, parentPkg);
+ return o;
+ }
+ }
+ bool ok = false;
+ QString name = Model_Utils::uniqObjectName(type, parentPkg, n);
+ bool bValidNameEntered = false;
+ do {
+ name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), name, &ok, (QWidget*)UMLApp::app());
+ if (!ok) {
+ return 0;
+ }
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name."),
+ i18n("Invalid Name"));
+ continue;
+ }
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ if (codegen != NULL && codegen->isReservedKeyword(name)) {
+ KMessageBox::error(0, i18n("This is a reserved keyword for the language of the configured code generator."),
+ i18n("Reserved Keyword"));
+ continue;
+ }
+ if (! doc->isUnique(name, parentPkg)) {
+ KMessageBox::error(0, i18n("That name is already being used."),
+ i18n("Not a Unique Name"));
+ continue;
+ }
+ bValidNameEntered = true;
+ } while (bValidNameEntered == false);
+ UMLObject *o = createNewUMLObject(type, name, parentPkg);
+ return o;
+}
+
+UMLAttribute *createAttribute(UMLObject *parent, const QString& name, UMLObject *type) {
+ UMLAttribute *attr = new UMLAttribute(parent);
+ attr->setName(name);
+ attr->setType(type);
+ if (g_predefinedId == Uml::id_None)
+ attr->setID(UniqueID::gen());
+ return attr;
+}
+
+UMLOperation *createOperation(UMLClassifier *parent, const QString& name) {
+ UMLOperation *op = new UMLOperation(parent, name, g_predefinedId);
+ return op;
+}
+
+UMLClassifierListItem* createChildObject(UMLClassifier* parent, Uml::Object_Type type) {
+ UMLObject* returnObject = NULL;
+ switch (type) {
+ case Uml::ot_Attribute:
+ case Uml::ot_EntityAttribute: {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(parent);
+ if (c && !c->isInterface())
+ returnObject = c->createAttribute();
+ break;
+ }
+ case Uml::ot_Operation: {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(parent);
+ if (c)
+ returnObject = c->createOperation();
+ break;
+ }
+ case Uml::ot_Template: {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(parent);
+ if (c)
+ returnObject = c->createTemplate();
+ break;
+ }
+ case Uml::ot_EnumLiteral: {
+ UMLEnum* umlenum = dynamic_cast<UMLEnum*>(parent);
+ if (umlenum) {
+ returnObject = umlenum->createEnumLiteral();
+ }
+ break;
+ }
+ default:
+ kDebug() << "ERROR UMLDoc::createChildObject type:" << type << endl;
+ }
+ return static_cast<UMLClassifierListItem*>(returnObject);
+}
+
+UMLObject* makeObjectFromXMI(const QString& xmiTag,
+ const QString& stereoID /* = QString::null */) {
+ UMLObject* pObject = 0;
+ if (Uml::tagEq(xmiTag, "UseCase")) {
+ pObject = new UMLUseCase();
+ } else if (Uml::tagEq(xmiTag, "Actor")) {
+ pObject = new UMLActor();
+ } else if (Uml::tagEq(xmiTag, "Class")) {
+ pObject = new UMLClassifier();
+ } else if (Uml::tagEq(xmiTag, "Package")) {
+ if (!stereoID.isEmpty()) {
+ UMLDoc *doc = UMLApp::app()->getDocument();
+ UMLObject *stereo = doc->findStereotypeById(STR2ID(stereoID));
+ if (stereo && stereo->getName() == "folder")
+ pObject = new UMLFolder();
+ }
+ if (pObject == NULL)
+ pObject = new UMLPackage();
+ } else if (Uml::tagEq(xmiTag, "Component")) {
+ pObject = new UMLComponent();
+ } else if (Uml::tagEq(xmiTag, "Node")) {
+ pObject = new UMLNode();
+ } else if (Uml::tagEq(xmiTag, "Artifact")) {
+ pObject = new UMLArtifact();
+ } else if (Uml::tagEq(xmiTag, "Interface")) {
+ UMLClassifier *c = new UMLClassifier();
+ c->setBaseType(Uml::ot_Interface);
+ pObject = c;
+ } else if (Uml::tagEq(xmiTag, "DataType") || Uml::tagEq(xmiTag, "Primitive")
+ || Uml::tagEq(xmiTag, "Datatype")) { // for bkwd compat.
+ UMLClassifier *c = new UMLClassifier();
+ c->setBaseType(Uml::ot_Datatype);
+ pObject = c;
+ } else if (Uml::tagEq(xmiTag, "Enumeration") ||
+ Uml::tagEq(xmiTag, "Enum")) { // for bkwd compat.
+ pObject = new UMLEnum();
+ } else if (Uml::tagEq(xmiTag, "Entity")) {
+ pObject = new UMLEntity();
+ } else if (Uml::tagEq(xmiTag, "Stereotype")) {
+ pObject = new UMLStereotype();
+ } else if (Uml::tagEq(xmiTag, "Association") ||
+ Uml::tagEq(xmiTag, "AssociationClass")) {
+ pObject = new UMLAssociation();
+ } else if (Uml::tagEq(xmiTag, "Generalization")) {
+ pObject = new UMLAssociation(Uml::at_Generalization);
+ } else if (Uml::tagEq(xmiTag, "Realization") ||
+ Uml::tagEq(xmiTag, "Abstraction")) {
+ pObject = new UMLAssociation(Uml::at_Realization);
+ } else if (Uml::tagEq(xmiTag, "Dependency")) {
+ pObject = new UMLAssociation(Uml::at_Dependency);
+ }
+ return pObject;
+}
+
+} // end namespace Object_Factory
+
diff --git a/umbrello/umbrello/object_factory.h b/umbrello/umbrello/object_factory.h
new file mode 100644
index 00000000..c7bf71d9
--- /dev/null
+++ b/umbrello/umbrello/object_factory.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OBJECT_FACTORY__H
+#define OBJECT_FACTORY__H
+
+#include <qstring.h>
+#include "umlnamespace.h"
+
+class UMLObject;
+class UMLPackage;
+class UMLClassifier;
+class UMLClassifierListItem;
+class UMLAttribute;
+class UMLOperation;
+
+namespace Object_Factory {
+
+/**
+ * Creates a UMLObject of the given type.
+ *
+ * @param type The type of @ref UMLObject to create.
+ * @param n A name to give to the object (optional.)
+ * If not given then an input dialog prompts
+ * the user to supply a name.
+ * @param parentPkg The object's parent package.
+ * @param solicitNewName Ask user for a different name if an object
+ * of the given name already exists.
+ * If set to false and the name already exists
+ * then the existing object is returned.
+ * The default is to ask for the new name.
+ */
+UMLObject* createUMLObject(Uml::Object_Type type,
+ const QString &n = QString::null,
+ UMLPackage *parentPkg = 0,
+ bool solicitNewName = true);
+
+/**
+ * Creates an operation, attribute, template, or enum literal
+ * for the parent classifier.
+ *
+ * @param parent The parent concept
+ * @param type The type to create
+ * @return Pointer to the UMLClassifierListItem created
+ */
+UMLClassifierListItem* createChildObject(UMLClassifier *parent, Uml::Object_Type type);
+
+UMLAttribute *createAttribute(UMLObject *parent, const QString& name,
+ UMLObject *type = 0);
+
+UMLOperation *createOperation(UMLClassifier *parent, const QString& name);
+
+/**
+ * Control whether the createUMLObject() solicits a new unique ID for the
+ * created object.
+ * By default, unique ID generation is turned on.
+ *
+ * @param yesno False turns UID generation off, true turns it on.
+ */
+void assignUniqueIdOnCreation(bool yesno);
+
+/**
+ * Return whether unique ID generation is on or off.
+ */
+bool assignUniqueIdOnCreation();
+
+/**
+ * Make a new UMLObject according to the given XMI tag.
+ * Used by loadFromXMI and clipboard paste.
+ */
+UMLObject* makeObjectFromXMI(const QString& xmiTag,
+ const QString& stereoID = QString::null);
+
+}
+
+#endif
diff --git a/umbrello/umbrello/objectwidget.cpp b/umbrello/umbrello/objectwidget.cpp
new file mode 100644
index 00000000..35e7bdde
--- /dev/null
+++ b/umbrello/umbrello/objectwidget.cpp
@@ -0,0 +1,403 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header file
+#include "objectwidget.h"
+
+// system includes
+#include <qpainter.h>
+#include <qvalidator.h>
+#include <qevent.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// local includes
+#include "objectwidgetcontroller.h"
+#include "seqlinewidget.h"
+#include "umlview.h"
+#include "umldoc.h"
+#include "uml.h"
+#include "umlobject.h"
+#include "listpopupmenu.h"
+#include "docwindow.h"
+#include "dialogs/classpropdlg.h"
+
+/**
+ * The number of pixels margin between the lowest message
+ * and the bottom of the vertical line
+ */
+static const int sequenceLineMargin = 20;
+
+ObjectWidget::ObjectWidget(UMLView * view, UMLObject *o, Uml::IDType lid)
+ : UMLWidget(view, o) {
+ init();
+ if( lid != Uml::id_None )
+ m_nLocalID = lid;
+ //updateComponentSize();
+ // Doing this during loadFromXMI() gives futile updates.
+ // Instead, it is done afterwards by UMLWidget::activate()
+}
+
+void ObjectWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Object);
+ m_nLocalID = Uml::id_None;
+ m_InstanceName = "";
+ m_bMultipleInstance = false;
+ m_bDrawAsActor = false;
+ m_bShowDestruction = false;
+ messageWidgetList.setAutoDelete(false);
+ if( m_pView != NULL && m_pView -> getType() == Uml::dt_Sequence ) {
+ m_pLine = new SeqLineWidget( m_pView, this );
+
+ //Sets specific widget controller for sequence diagrams
+ delete m_widgetController;
+ m_widgetController = new ObjectWidgetController(this);
+ } else {
+ m_pLine = NULL;
+ }
+}
+
+ObjectWidget::~ObjectWidget() {}
+
+void ObjectWidget::draw(QPainter & p , int offsetX, int offsetY) {
+ if ( m_bDrawAsActor )
+ drawActor( p, offsetX, offsetY );
+ else
+ drawObject( p, offsetX, offsetY );
+
+ UMLWidget::setPen(p);
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+void ObjectWidget::slotMenuSelection(int sel) {
+ QString name = "";
+ switch(sel) {
+ case ListPopupMenu::mt_Rename_Object:
+ {
+ bool ok;
+ QRegExpValidator* validator = new QRegExpValidator(QRegExp(".*"), 0);
+ name = KInputDialog::getText
+ (i18n("Rename Object"),
+ i18n("Enter object name:"),
+ m_InstanceName,
+ &ok,
+ m_pView,
+ "renameobject",
+ validator);
+ if (ok) {
+ m_InstanceName = name;
+ updateComponentSize();
+ moveEvent( 0 );
+ update();
+ UMLApp::app()->getDocument()->setModified(true);
+ }
+ delete validator;
+ break;
+ }
+ case ListPopupMenu::mt_Properties:
+ showProperties();
+ updateComponentSize();
+ moveEvent( 0 );
+ update();
+ break;
+
+ case ListPopupMenu::mt_Up:
+ tabUp();
+ break;
+
+ case ListPopupMenu::mt_Down:
+ tabDown();
+ break;
+
+ default:
+ UMLWidget::slotMenuSelection(sel);
+ break;
+ }
+}
+
+QSize ObjectWidget::calculateSize() {
+ int width, height;
+ const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
+ const int fontHeight = fm.lineSpacing();
+ const QString t = m_InstanceName + " : " + m_pObject->getName();
+ const int textWidth = fm.width(t);
+ if ( m_bDrawAsActor ) {
+ width = textWidth > A_WIDTH?textWidth:A_WIDTH;
+ height = A_HEIGHT + fontHeight + A_MARGIN;
+ width += A_MARGIN * 2;
+ } else {
+ width = textWidth > O_WIDTH?textWidth:O_WIDTH;
+ height = fontHeight + O_MARGIN * 2;
+ width += O_MARGIN * 2;
+ if (m_bMultipleInstance) {
+ width += 10;
+ height += 10;
+ }
+ }//end else drawasactor
+
+ return QSize(width, height);
+}
+
+void ObjectWidget::setDrawAsActor( bool drawAsActor ) {
+ m_bDrawAsActor = drawAsActor;
+ updateComponentSize();
+}
+
+void ObjectWidget::setMultipleInstance(bool multiple) {
+ //make sure only calling this in relation to an object on a collab. diagram
+ if(m_pView -> getType() != Uml::dt_Collaboration)
+ return;
+ m_bMultipleInstance = multiple;
+ updateComponentSize();
+ update();
+}
+
+bool ObjectWidget::activate(IDChangeLog* ChangeLog /*= 0*/) {
+ if (! UMLWidget::activate(ChangeLog))
+ return false;
+ if (m_bShowDestruction && m_pLine)
+ m_pLine->setupDestructionBox();
+ moveEvent(0);
+ return true;
+}
+
+void ObjectWidget::setX( int x ) {
+ UMLWidget::setX(x);
+ moveEvent(0);
+}
+
+void ObjectWidget::setY( int y ) {
+ UMLWidget::setY(y);
+ moveEvent(0);
+}
+
+void ObjectWidget::moveEvent(QMoveEvent */*m*/) {
+ emit sigWidgetMoved( m_nLocalID );
+ if (m_pLine) {
+ const int x = getX(); // for debugging: gdb has a problem evaluating getX() etc
+ const int w = width();
+ const int y = getY();
+ const int h = height();
+ m_pLine->setStartPoint(x + w / 2, y + h);
+ }
+}
+
+void ObjectWidget::slotColorChanged(Uml::IDType /*viewID*/) {
+ UMLWidget::setFillColour( m_pView->getFillColor() );
+ UMLWidget::setLineColor( m_pView->getLineColor() );
+
+ if( m_pLine)
+ m_pLine -> setPen( QPen( UMLWidget::getLineColor(), UMLWidget::getLineWidth(), Qt::DashLine ) );
+}
+
+void ObjectWidget::cleanup() {
+
+ UMLWidget::cleanup();
+ if( m_pLine ) {
+ m_pLine -> cleanup();
+ delete m_pLine;
+ }
+}
+
+void ObjectWidget::showProperties() {
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation(false);
+ ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this);
+ if (dlg->exec()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->getDocument()->setModified(true);
+ }
+ dlg->close(true);//wipe from memory
+}
+
+void ObjectWidget::drawObject(QPainter & p, int offsetX, int offsetY) {
+
+ QFont oldFont = p.font();
+ QFont font = UMLWidget::getFont();
+ font.setUnderline( true );
+ p.setFont( font );
+
+ UMLWidget::setPen(p);
+ if(UMLWidget::getUseFillColour())
+ p.setBrush(UMLWidget::getFillColour());
+ else
+ p.setBrush(m_pView -> viewport() -> backgroundColor());
+ const int w = width();
+ const int h = height();
+
+ const QString t = m_InstanceName + " : " + m_pObject -> getName();
+ int multiInstOfst = 0;
+ if ( m_bMultipleInstance ) {
+ p.drawRect(offsetX + 10, offsetY + 10, w - 10, h - 10);
+ p.drawRect(offsetX + 5, offsetY + 5, w - 10, h - 10);
+ multiInstOfst = 10;
+ }
+ p.drawRect(offsetX, offsetY, w - multiInstOfst, h - multiInstOfst);
+ p.setPen(QPen(Qt::black));
+ p.drawText(offsetX + O_MARGIN, offsetY + O_MARGIN,
+ w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst,
+ Qt::AlignCenter, t);
+
+ p.setFont( oldFont );
+}
+
+void ObjectWidget::drawActor(QPainter & p, int offsetX, int offsetY) {
+ const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
+
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() )
+ p.setBrush( UMLWidget::getFillColour() );
+ const int w = width();
+ const int textStartY = A_HEIGHT + A_MARGIN;
+ const int fontHeight = fm.lineSpacing();
+
+ const int middleX = offsetX + w / 2;
+ const int thirdH = A_HEIGHT / 3;
+
+ //draw actor
+ p.drawEllipse(middleX - A_WIDTH / 2, offsetY, A_WIDTH, thirdH);//head
+ p.drawLine(middleX, offsetY + thirdH, middleX, offsetY + thirdH * 2);//body
+ p.drawLine(middleX, offsetY + 2 * thirdH,
+ middleX - A_WIDTH / 2, offsetY + A_HEIGHT);//left leg
+ p.drawLine(middleX, offsetY + 2 * thirdH,
+ middleX + A_WIDTH / 2, offsetY + A_HEIGHT);//right leg
+ p.drawLine(middleX - A_WIDTH / 2, offsetY + thirdH + thirdH / 2,
+ middleX + A_WIDTH / 2, offsetY + thirdH + thirdH / 2);//arms
+ //draw text
+ p.setPen(QPen(Qt::black));
+ QString t = m_InstanceName + " : " + m_pObject -> getName();
+ p.drawText(offsetX + A_MARGIN, offsetY + textStartY,
+ w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, t);
+}
+
+void ObjectWidget::tabUp() {
+ int newY = getY() - height();
+ if (newY < topMargin())
+ newY = topMargin();
+ setY( newY );
+ moveEvent( 0 );
+ adjustAssocs( getX(), newY);
+}
+
+void ObjectWidget::tabDown() {
+ int newY = getY() + height();
+ setY( newY );
+ moveEvent( 0 );
+ adjustAssocs( getX(), newY);
+}
+
+int ObjectWidget::topMargin() {
+ return 80 - height();
+}
+
+bool ObjectWidget::canTabUp() {
+ int y = getY();
+ //kDebug() << "ObjectWidget::canTabUp: y is " << y << endl;
+ return (y > topMargin());
+}
+
+void ObjectWidget::setShowDestruction( bool bShow ) {
+ m_bShowDestruction = bShow;
+ if( m_pLine )
+ m_pLine -> setupDestructionBox();
+}
+
+int ObjectWidget::getEndLineY() {
+ int y = this -> getY() + getHeight();
+ if( m_pLine)
+ y += m_pLine -> getLineLength();
+ if ( m_bShowDestruction )
+ y += 10;
+ return y;
+}
+
+void ObjectWidget::messageAdded(MessageWidget* message) {
+ if (messageWidgetList.containsRef(message) ) {
+ kError() << "ObjectWidget::messageAdded("
+ << message->getName() << ") : duplicate entry !"
+ << endl;
+ return ;
+ }
+ messageWidgetList.append(message);
+}
+
+void ObjectWidget::messageRemoved(MessageWidget* message) {
+ if ( messageWidgetList.remove(message) == false ) {
+ kError() << "ObjectWidget::messageRemoved("
+ << message->getName() << ") : missing entry !"
+ << endl;
+ return ;
+ }
+}
+
+void ObjectWidget::slotMessageMoved() {
+ MessageWidgetListIt iterator(messageWidgetList);
+ MessageWidget* message;
+ int lowestMessage = 0;
+ while ( (message = iterator.current()) != 0 ) {
+ ++iterator;
+ int messageHeight = message->getY() + message->getHeight();
+ if (lowestMessage < messageHeight) {
+ lowestMessage = messageHeight;
+ }
+ }
+ m_pLine->setEndOfLine(lowestMessage + sequenceLineMargin);
+}
+
+bool ObjectWidget::messageOverlap(int y, MessageWidget* messageWidget) {
+ MessageWidgetListIt iterator(messageWidgetList);
+ MessageWidget* message;
+ while ( (message = iterator.current()) != 0 ) {
+ ++iterator;
+ const int msgY = message->getY();
+ const int msgHeight = msgY + message->getHeight();
+ if (y >= msgY && y <= msgHeight && message != messageWidget) {
+ return true;
+ }
+ }
+ return false;
+}
+
+SeqLineWidget *ObjectWidget::getSeqLine() {
+ return m_pLine;
+}
+
+void ObjectWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement objectElement = qDoc.createElement( "objectwidget" );
+ UMLWidget::saveToXMI( qDoc, objectElement );
+ objectElement.setAttribute( "instancename", m_InstanceName );
+ objectElement.setAttribute( "drawasactor", m_bDrawAsActor );
+ objectElement.setAttribute( "multipleinstance", m_bMultipleInstance );
+ objectElement.setAttribute( "localid", ID2STR(m_nLocalID) );
+ objectElement.setAttribute( "decon", m_bShowDestruction );
+ qElement.appendChild( objectElement );
+}
+
+bool ObjectWidget::loadFromXMI( QDomElement & qElement ) {
+ if( !UMLWidget::loadFromXMI( qElement ) )
+ return false;
+ m_InstanceName = qElement.attribute( "instancename", "" );
+ QString draw = qElement.attribute( "drawasactor", "0" );
+ QString multi = qElement.attribute( "multipleinstance", "0" );
+ QString localid = qElement.attribute( "localid", "0" );
+ QString decon = qElement.attribute( "decon", "0" );
+
+ m_bDrawAsActor = (bool)draw.toInt();
+ m_bMultipleInstance = (bool)multi.toInt();
+ m_nLocalID = STR2ID(localid);
+ m_bShowDestruction = (bool)decon.toInt();
+ return true;
+
+}
+
+#include "objectwidget.moc"
diff --git a/umbrello/umbrello/objectwidget.h b/umbrello/umbrello/objectwidget.h
new file mode 100644
index 00000000..bbf63053
--- /dev/null
+++ b/umbrello/umbrello/objectwidget.h
@@ -0,0 +1,331 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OBJECTWIDGET_H
+#define OBJECTWIDGET_H
+
+#define O_MARGIN 5
+#define O_WIDTH 40
+#define A_WIDTH 20
+#define A_HEIGHT 40
+#define A_MARGIN 5
+
+#include "messagewidgetlist.h"
+#include "messagewidget.h"
+
+
+class SeqLineWidget;
+
+/**
+ * Displays an instance UMLObject of a concept.
+ *
+ * @short Displays an instance of a Concept.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class ObjectWidget : public UMLWidget {
+ Q_OBJECT
+public:
+ /**
+ * Creates an ObjectWidget.
+ *
+ * @param view The parent to this object.
+ * @param o The object it will be representing.
+ * @param lid The local id for the object.
+ */
+ ObjectWidget(UMLView * view, UMLObject *o, Uml::IDType lid = Uml::id_None );
+
+ /**
+ * destructor
+ */
+ virtual ~ObjectWidget();
+
+ /**
+ * Sets the x-coordinate.
+ * Reimplements the method from UMLWidget.
+ *
+ * @param x The x-coordinate to be set.
+ */
+ virtual void setX( int x );
+
+ /**
+ * Sets the y-coordinate.
+ * Reimplements the method from UMLWidget.
+ *
+ * @param y The y-coordinate to be set.
+ */
+ virtual void setY( int y );
+
+ /**
+ * Returns the local ID for this object. This ID is used so that
+ * many objects of the same @ref UMLObject instance can be on the
+ * same diagram.
+ *
+ * @return The local ID.
+ */
+ Uml::IDType getLocalID() const {
+ return m_nLocalID;
+ }
+
+ /**
+ * Returns the instance name.
+ *
+ * @return The instance name.
+ */
+ QString getInstanceName() const {
+ return m_InstanceName;
+ }
+
+ /**
+ * Sets the instance name.
+ *
+ * @param name The name to set the instance name to.
+ */
+ void setInstanceName(const QString &name) {
+ m_InstanceName = name;
+ }
+
+ /**
+ * Returns whether object is representing a multi-object.
+ *
+ * @return True if object is representing a multi-object.
+ */
+ bool getMultipleInstance() const {
+ return m_bMultipleInstance;
+ }
+
+ /**
+ * Sets whether representing a multi-instance object.
+ *
+ * @param multiple Object state. true- multi, false - single.
+ */
+ void setMultipleInstance(bool multiple);
+
+ /**
+ * Sets the local id of the object.
+ *
+ * @param id The local id of the object.
+ */
+ void setLocalID(Uml::IDType id) {
+ m_nLocalID = id;
+ }
+
+ /**
+ * Activate the object after serializing it from a QDataStream
+ */
+ bool activate(IDChangeLog* ChangeLog = 0);
+
+ /**
+ * Override default method.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Overrides the standard operation.
+ */
+ virtual void moveEvent(QMoveEvent */*m*/);
+
+ /**
+ * Used to cleanup any other widget it may need to delete.
+ */
+ void cleanup();
+
+ /**
+ * Show a properties dialog for an ObjectWidget.
+ */
+ void showProperties();
+
+ /**
+ * Returns whether to draw as an Actor or not.
+ *
+ * @return True if widget is drawn as an actor.
+ */
+ bool getDrawAsActor() const {
+ return m_bDrawAsActor;
+ }
+
+ /**
+ * Sets whether to draw as an Actor.
+ *
+ * @param drawAsActor True if widget shall be drawn as an actor.
+ */
+ void setDrawAsActor( bool drawAsActor );
+
+ /**
+ * Sets whether to show deconstruction on sequence line.
+ *
+ * @param bShow True if destruction on line shall be shown.
+ */
+ void setShowDestruction( bool bShow );
+
+ /**
+ * Returns whether to show deconstruction on sequence line.
+ *
+ * @return True if destruction on sequence line is shown.
+ */
+ bool getShowDestruction() const {
+ return m_bShowDestruction;
+ }
+
+ /**
+ * Returns the top margin constant (Y axis value)
+ *
+ * @return Y coordinate of the space between the diagram top
+ * and the upper edge of the ObjectWidget.
+ */
+ int topMargin();
+
+ /**
+ * Returns the end Y co-ord of the seq. line.
+ *
+ * @return Y coordinate of the endpoint of the sequence line.
+ */
+ int getEndLineY();
+
+ /**
+ * Add a message widget to the list.
+ *
+ * @param message Pointer to the MessageWidget to add.
+ */
+ void messageAdded(MessageWidget* message);
+
+ /**
+ * Remove a message widget from the list.
+ *
+ * @param message Pointer to the MessageWidget to remove.
+ */
+ void messageRemoved(MessageWidget* message);
+
+ /**
+ * Returns whether or not the widget can be moved vertically up.
+ *
+ * @return True if widget can be moved upwards vertically.
+ */
+ bool canTabUp();
+
+ /**
+ * Returns whether a message is overlapping with another message.
+ * Used by MessageWidget::draw() methods.
+ *
+ * @param y The top of your message.
+ * @param messageWidget A pointer to your message so it doesn't
+ * check against itself.
+ */
+ bool messageOverlap(int y, MessageWidget* messageWidget);
+
+ /**
+ * Return the SeqLineWidget.
+ * Returns a non NULL pointer if this ObjectWidget is part of a
+ * sequence diagram.
+ */
+ SeqLineWidget *getSeqLine();
+
+ /**
+ * Saves to the "objectwidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads from a "objectwidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+public slots:
+ /**
+ * Handles a popup menu selection.
+ */
+ void slotMenuSelection(int sel);
+
+ /**
+ * Handles a color change signal.
+ */
+ virtual void slotColorChanged(Uml::IDType viewID);
+
+ /**
+ * Called when a message widget with an end on this object has
+ * moved up or down.
+ * Sets the bottom of the line to a nice position.
+ */
+ void slotMessageMoved();
+
+protected:
+ SeqLineWidget * m_pLine;
+
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+
+ /**
+ * Draw the object as an actor.
+ */
+ void drawActor(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Draw the object as an object (default).
+ */
+ void drawObject(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Move the object up on a sequence diagram.
+ */
+ void tabUp();
+
+ /**
+ * Move the object down on a sequence diagram.
+ */
+ void tabDown();
+
+ // Data loaded/saved:
+
+ /**
+ * Instance name of object.
+ */
+ QString m_InstanceName;
+
+ /**
+ * Local ID used on views. Needed as a it can represent a class
+ * that has many objects representing it.
+ */
+ Uml::IDType m_nLocalID;
+
+ /**
+ * Determines whether to draw an object as a multiple object
+ * instance.
+ */
+ bool m_bMultipleInstance;
+
+ /**
+ * Determines whether the object should be drawn as an Actor or
+ * an Object.
+ */
+ bool m_bDrawAsActor;
+
+ /**
+ * Determines whether to show object destruction on sequence
+ * diagram line.
+ */
+ bool m_bShowDestruction;
+
+private:
+ /**
+ * Initializes the key attributes of the class.
+ */
+ void init();
+
+ /**
+ * A list of the message widgets with an end on this widget.
+ */
+ MessageWidgetList messageWidgetList;
+};
+
+#endif
diff --git a/umbrello/umbrello/objectwidgetcontroller.cpp b/umbrello/umbrello/objectwidgetcontroller.cpp
new file mode 100644
index 00000000..1594b3fa
--- /dev/null
+++ b/umbrello/umbrello/objectwidgetcontroller.cpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "objectwidgetcontroller.h"
+
+// kde includes
+#include <kcursor.h>
+
+// app includes
+#include "objectwidget.h"
+#include "listpopupmenu.h"
+
+
+ObjectWidgetController::ObjectWidgetController(ObjectWidget* objectWidget):
+ UMLWidgetController(objectWidget) {
+}
+
+ObjectWidgetController::~ObjectWidgetController() {
+}
+
+QCursor ObjectWidgetController::getResizeCursor() {
+ return KCursor::sizeHorCursor();
+}
+
+void ObjectWidgetController::resizeWidget(int newW, int newH) {
+ m_widget->setSize(newW, m_widget->getHeight());
+}
+
+void ObjectWidgetController::moveWidgetBy(int diffX, int diffY) {
+ m_widget->setX(m_widget->getX() + diffX);
+}
+
+void ObjectWidgetController::constrainMovementForAllWidgets(int &diffX, int &diffY) {
+ diffY = 0;
+}
diff --git a/umbrello/umbrello/objectwidgetcontroller.h b/umbrello/umbrello/objectwidgetcontroller.h
new file mode 100644
index 00000000..1d8d699a
--- /dev/null
+++ b/umbrello/umbrello/objectwidgetcontroller.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OBJECTWIDGETCONTROLLER_H
+#define OBJECTWIDGETCONTROLLER_H
+
+#include "umlwidgetcontroller.h"
+
+class ObjectWidget;
+
+/**
+ * Controller for ObjectWidget.
+ *
+ * When moving an ObjectWidget, it is only moved along X axis. Y axis movement
+ * is always ignored.
+ * So, if the ObjectWidget is being moved as part of a selection and that
+ * selection is moved in X and/or Y axis, the ObjectWidget will only move in X axis.
+ * Also, when constraining the move of the selection because the receiver of
+ * mouse move events is an ObjectWidget, all the widgets are moved only in X axis.
+ *
+ * Only horizontal resize is allowed for ObjectWidget. Cursor is set to reflect this.
+ *
+ * @author Umbrello UML Modeller Authors <uml-devel@lists.sourceforge.net>
+ */
+class ObjectWidgetController : public UMLWidgetController {
+public:
+
+ /**
+ * Constructor for ObjectWidgetController.
+ *
+ * @param objectWidget The object widget which uses the controller.
+ */
+ ObjectWidgetController(ObjectWidget *objectWidget);
+
+ /**
+ * Destructor for ObjectWidgetController.
+ */
+ virtual ~ObjectWidgetController();
+
+protected:
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Returns the cursor to be shown when resizing the widget.
+ * The cursor shown is KCursor::sizeHorCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+ virtual QCursor getResizeCursor();
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Resizes the width of the object widget.
+ * Object widgets can only be resized horizontally, so height isn't modified.
+ *
+ * @param newW The new width for the widget.
+ * @param newH The new height for the widget (isn't used).
+ */
+ virtual void resizeWidget(int newW, int newH);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * Y position is ignored, and widget is only moved along X axis.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position
+ * (isn't used).
+ */
+ virtual void moveWidgetBy(int diffX, int diffY);
+
+ /**
+ * Overriden from UMLWidgetController.
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ * All the widgets are constrained to be moved only in X axis (diffY is set to 0).
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void constrainMovementForAllWidgets(int &diffX, int &diffY);
+};
+
+#endif
diff --git a/umbrello/umbrello/operation.cpp b/umbrello/umbrello/operation.cpp
new file mode 100644
index 00000000..1052c469
--- /dev/null
+++ b/umbrello/umbrello/operation.cpp
@@ -0,0 +1,431 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "operation.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// app includes
+#include "attribute.h"
+#include "classifier.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "uniqueid.h"
+#include "dialogs/umloperationdialog.h"
+
+UMLOperation::UMLOperation(const UMLClassifier *parent, const QString& name,
+ Uml::IDType id, Uml::Visibility s, UMLObject *rt)
+ : UMLClassifierListItem(parent, name, id)
+{
+ if (rt)
+ m_returnId = UniqueID::gen();
+ else
+ m_returnId = Uml::id_None;
+ m_pSecondary = rt;
+ m_Vis = s;
+ m_BaseType = Uml::ot_Operation;
+ m_bConst = false;
+}
+
+UMLOperation::UMLOperation(const UMLClassifier * parent)
+ : UMLClassifierListItem (parent)
+{
+ m_BaseType = Uml::ot_Operation;
+ m_bConst = false;
+}
+
+UMLOperation::~UMLOperation() {
+}
+
+void UMLOperation::setType(UMLObject *type) {
+ UMLClassifierListItem::setType(type);
+ if (m_returnId == Uml::id_None)
+ m_returnId = UniqueID::gen();
+}
+
+void UMLOperation::moveParmLeft(UMLAttribute * a) {
+ if (a == NULL) {
+ kDebug() << "UMLOperation::moveParmLeft called on NULL attribute"
+ << endl;
+ return;
+ }
+ kDebug() << "UMLOperation::moveParmLeft(" << a->getName() << ") called"
+ << endl;
+ disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ int idx;
+ if ( (idx=m_List.find( a )) == -1 ) {
+ kDebug() << "Error move parm left " << a->getName() << endl;
+ return;
+ }
+ if ( idx == 0 )
+ return;
+ m_List.remove( a );
+ m_List.insert( idx-1, a );
+}
+
+void UMLOperation::moveParmRight(UMLAttribute * a) {
+ if (a == NULL) {
+ kDebug() << "UMLOperation::moveParmRight called on NULL attribute"
+ << endl;
+ return;
+ }
+ kDebug() << "UMLOperation::moveParmRight(" << a->getName() << ") called"
+ << endl;
+ disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ int idx;
+ if ( (idx=m_List.find( a )) == -1 ) {
+ kDebug() << "Error move parm right " << a->getName() << endl;
+ return;
+ }
+ int count = m_List.count();
+ if ( idx == count-1 )
+ return;
+ m_List.remove( a );
+ m_List.insert( idx+1, a );
+}
+
+void UMLOperation::removeParm(UMLAttribute * a, bool emitModifiedSignal /* =true */) {
+ if (a == NULL) {
+ kDebug() << "UMLOperation::removeParm called on NULL attribute"
+ << endl;
+ return;
+ }
+ kDebug() << "UMLOperation::removeParm(" << a->getName() << ") called"
+ << endl;
+ disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
+ if(!m_List.remove(a))
+ kDebug() << "Error removing parm " << a->getName() << endl;
+
+ if (emitModifiedSignal)
+ emit modified();
+}
+
+UMLAttribute* UMLOperation::findParm(const QString &name) {
+ UMLAttribute * obj=0;
+ for (obj = m_List.first(); obj; obj = m_List.next()) {
+ if (obj->getName() == name)
+ return obj;
+ }
+ return 0;
+}
+
+QString UMLOperation::toString(Uml::Signature_Type sig) {
+ QString s = "";
+
+ if(sig == Uml::st_ShowSig || sig == Uml::st_NoSig)
+ s = m_Vis.toString(true) + ' ';
+
+ s += getName();
+ Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ bool parameterlessOpNeedsParentheses = (pl != Uml::pl_Pascal && pl != Uml::pl_Ada);
+
+ if (sig == Uml::st_NoSig || sig == Uml::st_NoSigNoVis) {
+ if (parameterlessOpNeedsParentheses)
+ s.append("()");
+ return s;
+ }
+ int last = m_List.count();
+ if (last) {
+ s.append("(");
+ int i = 0;
+ for (UMLAttribute *param = m_List.first(); param; param = m_List.next()) {
+ i++;
+ s.append(param->toString(Uml::st_SigNoVis));
+ if (i < last)
+ s.append(", ");
+ }
+ s.append(")");
+ } else if (parameterlessOpNeedsParentheses) {
+ s.append("()");
+ }
+ UMLClassifier *ownParent = static_cast<UMLClassifier*>(parent());
+ QString returnType;
+ UMLClassifier *retType = UMLClassifierListItem::getType();
+ if (retType) {
+ UMLPackage *retVisibility = retType->getUMLPackage();
+ if (retVisibility != ownParent && retVisibility != ownParent->getUMLPackage())
+ returnType = retType->getFullyQualifiedName();
+ else
+ returnType = retType->getName();
+ }
+ if (returnType.length() > 0 && returnType != "void") {
+ s.append(" : ");
+
+ if (returnType.startsWith("virtual ")) {
+ s += returnType.mid(8);
+ } else {
+ s += returnType;
+ }
+ }
+ return s;
+}
+
+void UMLOperation::addParm(UMLAttribute *parameter, int position) {
+ if( position >= 0 && position <= (int)m_List.count() )
+ m_List.insert(position,parameter);
+ else
+ m_List.append( parameter );
+ UMLObject::emitModified();
+ connect(parameter,SIGNAL(modified()),this,SIGNAL(modified()));
+}
+
+QString UMLOperation::getUniqueParameterName() {
+ QString currentName = i18n("new_parameter");
+ QString name = currentName;
+ for (int number = 1; findParm(name); number++) {
+ name = currentName + '_' + QString::number(number);
+ }
+ return name;
+}
+
+bool UMLOperation::operator==( UMLOperation & rhs ) {
+ if( this == &rhs )
+ return true;
+
+ if( !UMLObject::operator==( rhs ) )
+ return false;
+
+ if( getTypeName() != rhs.getTypeName() )
+ return false;
+
+ if( m_List.count() != rhs.m_List.count() )
+ return false;
+
+ if(!(m_List == rhs.m_List))
+ return false;
+
+ return true;
+}
+
+void UMLOperation::copyInto(UMLOperation *rhs) const
+{
+ UMLClassifierListItem::copyInto(rhs);
+
+ m_List.copyInto(&(rhs->m_List));
+}
+
+UMLObject* UMLOperation::clone() const
+{
+ //FIXME: The new operation should be slaved to the NEW parent not the old.
+ UMLOperation *clone = new UMLOperation( static_cast<UMLClassifier*>(parent()) );
+ copyInto(clone);
+
+ return clone;
+}
+
+bool UMLOperation::resolveRef() {
+ bool overallSuccess = UMLObject::resolveRef();
+ // See remark on iteration style in UMLClassifier::resolveRef()
+ for (UMLAttributeListIt ait(m_List); ait.current(); ++ait) {
+ UMLAttribute *pAtt = ait.current();
+ if (! pAtt->resolveRef())
+ overallSuccess = false;
+ }
+ return overallSuccess;
+}
+
+bool UMLOperation::isConstructorOperation() {
+ // if an operation has the stereotype constructor
+ // return true
+ QString strConstructor ("constructor");
+ if (getStereotype() == strConstructor)
+ return true;
+
+ UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
+ QString cName = c->getName();
+ QString opName = getName();
+ // It's a constructor operation if the operation name
+ // matches that of the parent classifier.
+ return (cName == opName);
+}
+
+bool UMLOperation::isDestructorOperation() {
+ if (getStereotype() == "destructor")
+ return true;
+ UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
+
+ QString cName = c->getName();
+ QString opName = getName();
+ // Special support for C++ syntax:
+ // It's a destructor operation if the operation name begins
+ // with "~" followed by the name of the parent classifier.
+ if (! opName.startsWith("~"))
+ return false;
+ opName.remove( QRegExp("^~\\s*") );
+ return (cName == opName);
+}
+
+bool UMLOperation::isLifeOperation() {
+ return (isConstructorOperation() || isDestructorOperation());
+}
+
+void UMLOperation::setConst(bool b) {
+ m_bConst = b;
+}
+
+bool UMLOperation::getConst() const {
+ return m_bConst;
+}
+
+bool UMLOperation::showPropertiesDialog(QWidget* parent) {
+ UMLOperationDialog dialog(parent, this);
+ return dialog.exec();
+}
+
+void UMLOperation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement operationElement = UMLObject::save("UML:Operation", qDoc);
+ operationElement.setAttribute( "isQuery", m_bConst ? "true" : "false" );
+ QDomElement featureElement = qDoc.createElement( "UML:BehavioralFeature.parameter" );
+ if (m_pSecondary) {
+ QDomElement retElement = qDoc.createElement("UML:Parameter");
+ if (m_returnId == Uml::id_None) {
+ kDebug() << "UMLOperation::saveToXMI(" << m_Name
+ << "): m_returnId is not set, setting it now." << endl;
+ m_returnId = UniqueID::gen();
+ }
+ retElement.setAttribute( "xmi.id", ID2STR(m_returnId) );
+ retElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) );
+ retElement.setAttribute( "kind", "return" );
+ featureElement.appendChild( retElement );
+ } else {
+ kDebug() << "UMLOperation::saveToXMI: m_SecondaryId is "
+ << m_SecondaryId << endl;
+ }
+ //save each attribute here, type different
+ UMLAttribute* pAtt = 0;
+ for( pAtt = m_List.first(); pAtt != 0; pAtt = m_List.next() ) {
+ QDomElement attElement = pAtt->UMLObject::save("UML:Parameter", qDoc);
+ UMLClassifier *attrType = pAtt->getType();
+ if (attrType) {
+ attElement.setAttribute( "type", ID2STR(attrType->getID()) );
+ } else {
+ attElement.setAttribute( "type", pAtt -> getTypeName() );
+ }
+ attElement.setAttribute( "value", pAtt -> getInitialValue() );
+
+ Uml::Parameter_Direction kind = pAtt->getParmKind();
+ if (kind == Uml::pd_Out)
+ attElement.setAttribute("kind", "out");
+ else if (kind == Uml::pd_InOut)
+ attElement.setAttribute("kind", "inout");
+ // The default for the parameter kind is "in".
+
+ featureElement.appendChild( attElement );
+ }
+ if (featureElement.hasChildNodes())
+ operationElement.appendChild( featureElement );
+ qElement.appendChild( operationElement );
+}
+
+bool UMLOperation::load( QDomElement & element ) {
+ m_SecondaryId = element.attribute( "type", "" );
+ QString isQuery = element.attribute( "isQuery", "" );
+ if (!isQuery.isEmpty()) {
+ // We need this extra test for isEmpty() because load() might have been
+ // called again by the processing for BehavioralFeature.parameter (see below)
+ m_bConst = (isQuery == "true");
+ }
+ QDomNode node = element.firstChild();
+ if (node.isComment())
+ node = node.nextSibling();
+ QDomElement attElement = node.toElement();
+ while( !attElement.isNull() ) {
+ QString tag = attElement.tagName();
+ if (Uml::tagEq(tag, "BehavioralFeature.parameter")) {
+ if (! load(attElement))
+ return false;
+ } else if (Uml::tagEq(tag, "Parameter")) {
+ QString kind = attElement.attribute("kind", "");
+ if (kind.isEmpty()) {
+ // Perhaps the kind is stored in a child node:
+ for (QDomNode n = attElement.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (n.isComment())
+ continue;
+ QDomElement tempElement = n.toElement();
+ QString tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "kind"))
+ continue;
+ kind = tempElement.attribute( "xmi.value", "" );
+ break;
+ }
+ if (kind.isEmpty()) {
+ // kDebug() << "UMLOperation::load(" << m_Name << "): "
+ // << "cannot find kind, using default \"in\"." << endl;
+ kind = "in";
+ }
+ }
+ if (kind == "return") {
+ QString returnId = attElement.attribute("xmi.id", "");
+ if (!returnId.isEmpty())
+ m_returnId = STR2ID(returnId);
+ m_SecondaryId = attElement.attribute( "type", "" );
+ if (m_SecondaryId.isEmpty()) {
+ // Perhaps the type is stored in a child node:
+ QDomNode node = attElement.firstChild();
+ while (!node.isNull()) {
+ if (node.isComment()) {
+ node = node.nextSibling();
+ continue;
+ }
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "type")) {
+ node = node.nextSibling();
+ continue;
+ }
+ m_SecondaryId = tempElement.attribute( "xmi.id", "" );
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute( "xmi.idref", "" );
+ if (m_SecondaryId.isEmpty()) {
+ QDomNode inner = node.firstChild();
+ QDomElement tmpElem = inner.toElement();
+ m_SecondaryId = tmpElem.attribute( "xmi.id", "" );
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tmpElem.attribute( "xmi.idref", "" );
+ }
+ break;
+ }
+ if (m_SecondaryId.isEmpty()) {
+ kError() << "UMLOperation::load(" << m_Name << "): "
+ << "cannot find return type." << endl;
+ }
+ }
+ // Use deferred xmi.id resolution.
+ m_pSecondary = NULL;
+ } else {
+ UMLAttribute * pAtt = new UMLAttribute( this );
+ if( !pAtt->loadFromXMI(attElement) ) {
+ delete pAtt;
+ return false;
+ }
+ if (kind == "out")
+ pAtt->setParmKind(Uml::pd_Out);
+ else if (kind == "inout")
+ pAtt->setParmKind(Uml::pd_InOut);
+ else
+ pAtt->setParmKind(Uml::pd_In);
+ m_List.append( pAtt );
+ }
+ }
+ node = node.nextSibling();
+ if (node.isComment())
+ node = node.nextSibling();
+ attElement = node.toElement();
+ }//end while
+ return true;
+}
+
+
+#include "operation.moc"
diff --git a/umbrello/umbrello/operation.h b/umbrello/umbrello/operation.h
new file mode 100644
index 00000000..eb94576e
--- /dev/null
+++ b/umbrello/umbrello/operation.h
@@ -0,0 +1,209 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OPERATION_H
+#define OPERATION_H
+
+#include "umlattributelist.h"
+#include "classifierlistitem.h"
+
+class UMLClassifier;
+
+/**
+ * This class represents an operation in the UML model.
+ *
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLOperation : public UMLClassifierListItem {
+ Q_OBJECT
+public:
+ /**
+ * Constructs an UMLOperation.
+ * Not intended for general use: The operation is not tied in with
+ * umbrello's Qt signalling for object creation.
+ * If you want to create an Operation use the method in UMLDoc instead.
+ *
+ * @param parent The parent to this operation.
+ * @param name The name of the operation.
+ * @param id The id of the operation.
+ * @param s The visibility of the operation.
+ * @param rt The return type of the operation.
+ */
+ UMLOperation(const UMLClassifier * parent, const QString& name,
+ Uml::IDType id = Uml::id_None,
+ Uml::Visibility s = Uml::Visibility::Public,
+ UMLObject *rt = 0);
+
+ /**
+ * Constructs an UMLOperation.
+ * Not intended for general use: The operation is not tied in with
+ * umbrello's Qt signalling for object creation.
+ * If you want to create an Operation use the method in UMLDoc instead.
+ *
+ * @param parent The parent to this operation.
+ */
+ UMLOperation(const UMLClassifier * parent);
+public:
+
+ /**
+ * destructor
+ */
+ virtual ~UMLOperation();
+
+ /**
+ * Overloaded '==' operator.
+ */
+ bool operator==( UMLOperation & rhs );
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLOperation *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Reimplement method from UMLClassifierListItem.
+ *
+ * @param type Pointer to the type object.
+ */
+ void setType(UMLObject *type);
+
+ /**
+ * Move a parameter one position to the left.
+ *
+ * @param a The parameter to move.
+ */
+ void moveParmLeft(UMLAttribute *a);
+
+ /**
+ *Move a parameter one position to the right.
+ *
+ * @param a The parameter to move.
+ */
+ void moveParmRight(UMLAttribute *a);
+
+ /**
+ * Remove a parameter from the operation.
+ *
+ * @param a The parameter to remove.
+ * @param emitModifiedSignal Whether to emit the "modified" signal
+ * which creates an entry in the Undo stack for the
+ * removal. Default: true.
+ */
+ void removeParm(UMLAttribute *a, bool emitModifiedSignal = true);
+
+ /**
+ * Returns a list of parameters.
+ *
+ * @return A list of the parameters in the operation.
+ */
+ UMLAttributeList getParmList() {
+ return m_List;
+ }
+
+ /**
+ * Finds a parameter of the operation.
+ *
+ * @param name The parameter name to search for.
+ * @return The found parameter, 0 if not found.
+ */
+ UMLAttribute * findParm(const QString &name);
+
+ /**
+ * Returns a string representation of the operation.
+ *
+ * @param sig What type of operation string to show.
+ * @return The string representation of the operation.
+ */
+ QString toString(Uml::Signature_Type sig = Uml::st_NoSig);
+
+ /**
+ * Add a parameter to the operation.
+ *
+ * @param parameter The parameter to add.
+ * @param position The position in the parameter list.
+ * If position = -1 the parameter will be
+ * appended to the list.
+ */
+ void addParm(UMLAttribute *parameter, int position = -1);
+
+ /**
+ * Calls resolveRef() on all parameters.
+ * Needs to be called after all UML objects are loaded from file.
+ *
+ * @return True for success.
+ */
+ bool resolveRef();
+
+ /**
+ * Returns an unused parameter name for a new parameter.
+ */
+ QString getUniqueParameterName();
+
+ /**
+ * Display the properties configuration dialog for the template.
+ */
+ bool showPropertiesDialog(QWidget* parent);
+
+ /**
+ * Returns whether this operation is a constructor.
+ *
+ * @return True if this operation is a constructor.
+ */
+ bool isConstructorOperation();
+
+ /**
+ * Returns whether this operation is a destructor.
+ *
+ * @return True if this operation is a destructor.
+ */
+ bool isDestructorOperation();
+
+ /**
+ * Shortcut for (isConstructorOperation() || isDestructorOperation())
+ *
+ * @return True if this operation is a constructor or destructor.
+ */
+ bool isLifeOperation();
+
+ /**
+ * Sets whether this operation is a query (C++ "const".)
+ */
+ void setConst(bool b);
+
+ /**
+ * Returns whether this operation is a query (C++ "const".)
+ */
+ bool getConst() const;
+
+ /**
+ * Saves to the <UML:Operation> XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Loads a <UML:Operation> XMI element.
+ */
+ bool load( QDomElement & element );
+
+private:
+ Uml::IDType m_returnId; ///< Holds the xmi.id of the <UML:Parameter kind="return">
+ UMLAttributeList m_List; /// Parameter list
+ bool m_bConst; ///< Holds the isQuery attribute of the <UML:Operation>
+};
+
+#endif
diff --git a/umbrello/umbrello/optionstate.cpp b/umbrello/umbrello/optionstate.cpp
new file mode 100644
index 00000000..16daef83
--- /dev/null
+++ b/umbrello/umbrello/optionstate.cpp
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "optionstate.h"
+
+namespace Settings{
+
+OptionState pd_optionState;
+
+OptionState& getOptionState() {
+ return pd_optionState;
+}
+
+void setOptionState(const OptionState& optstate) {
+ pd_optionState = optstate;
+}
+
+} // namespace Settings
+
diff --git a/umbrello/umbrello/optionstate.h b/umbrello/umbrello/optionstate.h
new file mode 100644
index 00000000..b8429f62
--- /dev/null
+++ b/umbrello/umbrello/optionstate.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef OPTIONSTATE_H
+#define OPTIONSTATE_H
+
+
+#include "umlnamespace.h"
+#include "codeviewerstate.h"
+
+namespace Settings {
+
+enum Page
+{
+ page_general = 0,
+ page_font,
+ page_UI,
+ page_class,
+ page_codegen,
+ page_codeview
+};
+
+//public structs
+struct GeneralState {
+ bool undo;
+ bool tabdiagrams;
+ bool newcodegen;
+ bool angularlines;
+ bool autosave;
+ int time; //old autosave time, kept for compatibility
+ int autosavetime;
+ QString autosavesuffix; ///< Text input field for suffix of autosave
+ bool logo;
+ bool tip;
+ bool loadlast;
+ Uml::Diagram_Type diagram;
+ QString lastFile;
+};
+
+struct UIState {
+ bool useFillColor;
+ QColor fillColor;
+ QColor lineColor;
+ uint lineWidth;
+ QFont font;
+};
+
+struct ClassState {
+ bool showVisibility;
+ bool showAtts;
+ bool showOps;
+ bool showStereoType;
+ bool showAttSig;
+ bool showOpSig;
+ bool showPackage;
+ Uml::Visibility defaultAttributeScope;
+ Uml::Visibility defaultOperationScope;
+};
+
+struct OptionState {
+ GeneralState generalState;
+ UIState uiState;
+ ClassState classState;
+ CodeViewerState codeViewerState;
+};
+
+
+OptionState& getOptionState();
+void setOptionState(const OptionState& optstate);
+
+} // namespace Settings
+
+#endif
diff --git a/umbrello/umbrello/ownedcodeblock.cpp b/umbrello/umbrello/ownedcodeblock.cpp
new file mode 100644
index 00000000..99b3c865
--- /dev/null
+++ b/umbrello/umbrello/ownedcodeblock.cpp
@@ -0,0 +1,180 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Aug 19 2003
+ */
+
+// own header
+#include "ownedcodeblock.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "association.h"
+#include "classifier.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlrole.h"
+#include "uml.h"
+#include "codedocument.h"
+#include "codegenerator.h"
+
+
+// Constructors/Destructors
+//
+
+OwnedCodeBlock::OwnedCodeBlock ( UMLObject * parent )
+ : QObject ( (QObject*)parent, "anOwnedCodeBlock" )
+{
+ initFields(parent);
+}
+
+OwnedCodeBlock::~OwnedCodeBlock ( ) {
+ /*
+ if(m_parentObject)
+ m_parentObject->disconnect(this);
+ */
+}
+
+//
+// Methods
+//
+
+void OwnedCodeBlock::release () {
+ if(m_parentObject)
+ m_parentObject->disconnect(this);
+ m_parentObject = 0;
+}
+
+/**
+ * Get the value of m_parentObject
+ * @return the value of m_parentObject
+ */
+UMLObject * OwnedCodeBlock::getParentObject () {
+ return m_parentObject;
+}
+
+// Other methods
+//
+
+void OwnedCodeBlock::setAttributesFromObject (TextBlock * obj) {
+
+ OwnedCodeBlock * oc = dynamic_cast<OwnedCodeBlock*>(obj);
+ if(oc)
+ {
+ m_parentObject->disconnect(this);
+ initFields(oc->getParentObject());
+ }
+}
+
+/** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+void OwnedCodeBlock::setAttributesOnNode(QDomDocument& /*doc*/, QDomElement& elem) {
+
+ // set local class attributes
+ // setting ID's takes special treatment
+ // as UMLRoles arent properly stored in the XMI right now.
+ // (change would break the XMI format..save for big version change )
+ UMLRole * role = dynamic_cast<UMLRole*>(m_parentObject);
+ if(role)
+ {
+ elem.setAttribute("parent_id",ID2STR(role->getParentAssociation()->getID()));
+ // CAUTION: role_id here is numerically inverted wrt Uml::Role_Type,
+ // i.e. role A is 1 and role B is 0.
+ // I'll resist the temptation to change this -
+ // in order to maintain backward compatibility.
+ elem.setAttribute("role_id", (role->getRole() == Uml::A));
+ }
+ else
+ {
+ elem.setAttribute("parent_id",ID2STR(m_parentObject->getID()));
+ //elem.setAttribute("role_id","-1");
+ }
+
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void OwnedCodeBlock::setAttributesFromNode ( QDomElement & elem) {
+
+ // set local attributes, parent object first
+ QString idStr = elem.attribute("parent_id","-1");
+ Uml::IDType id = STR2ID(idStr);
+
+ // always disconnect from current parent
+ getParentObject()->disconnect(this);
+
+ // now, what is the new object we want to set?
+ UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(id);
+ if(obj)
+ {
+
+ // FIX..one day.
+ // Ugh. This is UGLY, but we have to do it this way because UMLRoles
+ // don't go into the document list of UMLobjects, and have the same
+ // ID as their parent UMLAssociations. So..the drill is then special
+ // for Associations..in that case we need to find out which role will
+ // serve as the parametger here. The REAL fix, of course, would be to
+ // treat UMLRoles on a more even footing, but im not sure how that change
+ // might ripple throughout the code and cause problems. Thus, since the
+ // change appears to be needed for only this part, I'll do this crappy
+ // change instead. -b.t.
+ UMLAssociation * assoc = dynamic_cast<UMLAssociation*>(obj);
+ if(assoc) {
+ // In this case we init with indicated role child obj.
+ UMLRole * role = 0;
+ int role_id = elem.attribute("role_id","-1").toInt();
+ // see comment on role_id at setAttributesOnNode()
+ if(role_id == 1)
+ role = assoc->getUMLRole(Uml::A);
+ else if(role_id == 0)
+ role = assoc->getUMLRole(Uml::B);
+ else // this will cause a crash
+ kError() << "corrupt save file? "
+ << "cant get proper UMLRole for ownedcodeblock uml id:"
+ << ID2STR(id) << " w/role_id:" << role_id << endl;
+
+ // init using UMLRole obj
+ initFields ( role );
+ } else
+ initFields ( obj); // just the regular approach
+
+ }
+ else
+ kError() << "ERROR: can't load ownedcodeblock: parentUMLObject w/id:"
+ << ID2STR(id) << " not found, corrupt save file?" << endl;
+
+}
+
+void OwnedCodeBlock::initFields(UMLObject * parent )
+{
+
+ m_parentObject = parent;
+
+ // one reason for being: set up the connection between
+ // this code block and the parent UMLObject..when the parent
+ // signals a change has been made, we automatically update
+ // ourselves
+ connect(m_parentObject, SIGNAL(modified()), this, SLOT(syncToParent()));
+}
+
+/**
+ */
+void OwnedCodeBlock::syncToParent ( ) {
+ updateContent();
+}
+
+#include "ownedcodeblock.moc"
diff --git a/umbrello/umbrello/ownedcodeblock.h b/umbrello/umbrello/ownedcodeblock.h
new file mode 100644
index 00000000..b089e50e
--- /dev/null
+++ b/umbrello/umbrello/ownedcodeblock.h
@@ -0,0 +1,100 @@
+
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Tue Aug 19 2003
+ */
+
+#ifndef OWNEDCODEBLOCK_H
+#define OWNEDCODEBLOCK_H
+
+#include <qdom.h>
+#include <qstring.h>
+#include <qobject.h>
+
+class TextBlock;
+class CodeDocument;
+// class CodeGenObjectWithTextBlocks;
+class UMLObject;
+
+/**
+ * class OwnedCodeBlock
+ * Describes any codeblock which is 'owned' by a UMLobject of some sort and should
+ * be in sync with that parent.
+ */
+
+class OwnedCodeBlock : virtual public QObject
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructor
+ */
+ OwnedCodeBlock ( UMLObject * parent );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~OwnedCodeBlock ( );
+
+ /**
+ * @return UMLObject
+ */
+ UMLObject * getParentObject ( );
+
+ // get the parent code document of this code block
+ virtual CodeDocument * getParentDocument ( ) = 0;
+
+protected:
+
+ /** causes the text block to release all of its connections
+ * and any other text blocks that it 'owns'.
+ * needed to be called prior to deletion of the textblock.
+ */
+ virtual void release ();
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+ /**
+ * This is the method called from within syncToParent
+ */
+ virtual void updateContent ( ) = 0;
+
+private:
+
+ void initFields ( UMLObject * parent );
+
+ UMLObject * m_parentObject;
+
+public slots:
+
+ virtual void syncToParent ( );
+
+};
+
+#endif // OWNEDCODEBLOCK_H
diff --git a/umbrello/umbrello/ownedhierarchicalcodeblock.cpp b/umbrello/umbrello/ownedhierarchicalcodeblock.cpp
new file mode 100644
index 00000000..bb2b38ad
--- /dev/null
+++ b/umbrello/umbrello/ownedhierarchicalcodeblock.cpp
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Aug 07 2003
+ */
+
+// own header
+#include "ownedhierarchicalcodeblock.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// local includes
+#include "association.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "umlrole.h"
+#include "codedocument.h"
+#include "codegenerator.h"
+
+// Constructors/Destructors
+//
+
+OwnedHierarchicalCodeBlock::OwnedHierarchicalCodeBlock ( UMLObject *parent, CodeDocument * doc, const QString &start, const QString &end, const QString &comment)
+ : HierarchicalCodeBlock ( doc, start, end, comment), OwnedCodeBlock(parent)
+{
+
+}
+
+OwnedHierarchicalCodeBlock::~OwnedHierarchicalCodeBlock ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+// Other methods
+//
+
+void OwnedHierarchicalCodeBlock::release () {
+ OwnedCodeBlock::release();
+ HierarchicalCodeBlock::release();
+}
+
+void OwnedHierarchicalCodeBlock::setAttributesFromObject (TextBlock * obj) {
+
+ HierarchicalCodeBlock::setAttributesFromObject(obj);
+ OwnedCodeBlock::setAttributesFromObject(obj);
+}
+
+void OwnedHierarchicalCodeBlock::setAttributesOnNode (QDomDocument & doc, QDomElement & elem ) {
+
+ // set super-class attributes
+ HierarchicalCodeBlock::setAttributesOnNode(doc, elem);
+ OwnedCodeBlock::setAttributesOnNode(doc, elem);
+
+ // set local class attributes
+ elem.setAttribute("parent_id",ID2STR(getParentObject()->getID()));
+
+ // setting ID's takes special treatment
+ // as UMLRoles arent properly stored in the XMI right now.
+ // (change would break the XMI format..save for big version change )
+ UMLRole * role = dynamic_cast<UMLRole*>(getParentObject());
+ if(role) {
+ // see comment on role_id at OwnedCodeBlock::setAttributesOnNode()
+ elem.setAttribute("role_id", (role->getRole() == Uml::A));
+ }
+ /* else
+ elem.setAttribute("role_id","-1");
+ */
+}
+
+/** set the class attributes of this object from
+ * the passed element node.
+ */
+void OwnedHierarchicalCodeBlock::setAttributesFromNode ( QDomElement & root)
+{
+
+ // set attributes from the XMI
+ HierarchicalCodeBlock::setAttributesFromNode(root); // superclass load
+ OwnedCodeBlock::setAttributesFromNode(root); // superclass load
+
+}
+
+CodeDocument * OwnedHierarchicalCodeBlock::getParentDocument() {
+ return TextBlock::getParentDocument();
+}
+
+/**
+ */
+void OwnedHierarchicalCodeBlock::syncToParent ( ) {
+
+ if(getContentType() != CodeBlock::AutoGenerated)
+ return;
+
+ updateContent();
+}
+
+
+#include "ownedhierarchicalcodeblock.moc"
diff --git a/umbrello/umbrello/ownedhierarchicalcodeblock.h b/umbrello/umbrello/ownedhierarchicalcodeblock.h
new file mode 100644
index 00000000..af5ade94
--- /dev/null
+++ b/umbrello/umbrello/ownedhierarchicalcodeblock.h
@@ -0,0 +1,98 @@
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Fri Aug 07 2003
+ */
+
+#ifndef OWNEDHIERARCHICALCODEBLOCK_H
+#define OWNEDHIERARCHICALCODEBLOCK_H
+
+#include "hierarchicalcodeblock.h"
+
+class UMLObject;
+class CodeDocument;
+
+/**
+ * class OwnedHierarchicalCodeBlock
+ * A "chunk" of code within the code document that is "owned" by some
+ * umlobject. This is an abstract class that should be inherited.
+ */
+
+class OwnedHierarchicalCodeBlock : public HierarchicalCodeBlock, public OwnedCodeBlock
+{
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /** constructor with QString so we can create & populate it in
+ * one step.
+ */
+ OwnedHierarchicalCodeBlock ( UMLObject * parent, CodeDocument * parentDoc, const QString &start="", const QString &end="", const QString &comment="" );
+
+ /**
+ * Empty Destructor
+ */
+ virtual ~OwnedHierarchicalCodeBlock ( );
+
+ // Public attributes
+ //
+
+ // Return the parent code document
+ CodeDocument * getParentDocument();
+
+ // these next 2 methods should be supplied by inheriting classes
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ) = 0;
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root ) = 0;
+
+protected:
+
+ /** causes the text block to release all of its connections
+ * and any other text blocks that it 'owns'.
+ * needed to be called prior to deletion of the textblock.
+ */
+ virtual void release ();
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+ virtual void updateContent ( ) = 0;
+
+private:
+
+public slots:
+
+ void syncToParent ( );
+
+
+};
+
+#endif // OWNEDHIERARCHICALCODEBLOCK_H
diff --git a/umbrello/umbrello/package.cpp b/umbrello/umbrello/package.cpp
new file mode 100644
index 00000000..54dc18a5
--- /dev/null
+++ b/umbrello/umbrello/package.cpp
@@ -0,0 +1,298 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header file
+#include "package.h"
+
+// system includes
+#include <kdebug.h>
+#include <klocale.h>
+
+// local includes
+#include "uml.h"
+#include "umldoc.h"
+#include "classifier.h"
+#include "association.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+
+using namespace Uml;
+
+UMLPackage::UMLPackage(const QString & name, Uml::IDType id)
+ : UMLCanvasObject(name, id) {
+ init();
+}
+
+UMLPackage::~UMLPackage() {
+}
+
+void UMLPackage::init() {
+ m_BaseType = ot_Package;
+}
+
+void UMLPackage::copyInto(UMLPackage *rhs) const
+{
+ UMLCanvasObject::copyInto(rhs);
+
+ m_objects.copyInto(&(rhs->m_objects));
+}
+
+UMLObject* UMLPackage::clone() const
+{
+ UMLPackage *clone = new UMLPackage();
+ copyInto(clone);
+
+ return clone;
+}
+
+void UMLPackage::addAssocToConcepts(UMLAssociation* a) {
+ if (! UMLAssociation::assocTypeHasUMLRepresentation(a->getAssocType()) )
+ return;
+ Uml::IDType AId = a->getObjectId(Uml::A);
+ Uml::IDType BId = a->getObjectId(Uml::B);
+ UMLObject *o;
+ for (UMLObjectListIt it(m_objects); (o = it.current()) != NULL; ++it) {
+ UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
+ if (c == NULL)
+ continue;
+ if (AId == c->getID() || (BId == c->getID())) {
+ if (c->hasAssociation(a))
+ kDebug() << "UMLPackage::addAssocToConcepts: " << c->getName()
+ << " already has association id=" << ID2STR(a->getID())
+ << endl;
+ else
+ c->addAssociationEnd(a);
+ }
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
+ if (pkg)
+ pkg->addAssocToConcepts(a);
+ }
+}
+
+void UMLPackage::removeAssocFromConcepts(UMLAssociation *assoc)
+{
+ UMLObject *o;
+ for (UMLObjectListIt it(m_objects); (o = it.current()) != NULL; ++it) {
+ UMLCanvasObject *c = dynamic_cast<UMLCanvasObject*>(o);
+ if (c == NULL)
+ continue;
+ if (c->hasAssociation(assoc))
+ c->removeAssociationEnd(assoc);
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(c);
+ if (pkg)
+ pkg->removeAssocFromConcepts(assoc);
+ }
+}
+
+bool UMLPackage::addObject(UMLObject *pObject) {
+ if (pObject == NULL) {
+ kError() << "UMLPackage::addObject is called with a NULL object"
+ << endl;
+ return false;
+ }
+ if (m_objects.find(pObject) != -1) {
+ kDebug() << "UMLPackage::addObject: " << pObject->getName()
+ << " is already there" << endl;
+ return false;
+ }
+ if (pObject->getBaseType() == Uml::ot_Association) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(pObject);
+ // Adding the UMLAssociation at the participating concepts is done
+ // again later (in UMLAssociation::resolveRef()) if they are not yet
+ // known right here.
+ if (assoc->getObject(Uml::A) && assoc->getObject(Uml::B)) {
+ UMLPackage *pkg = pObject->getUMLPackage();
+ if (pkg != this) {
+ kError() << "UMLPackage " << m_Name << " addObject: "
+ << "assoc's UMLPackage is " << pkg->getName() << endl;
+ }
+ addAssocToConcepts(assoc);
+ }
+ }
+ m_objects.append( pObject );
+ return true;
+}
+
+void UMLPackage::removeObject(UMLObject *pObject) {
+ if (pObject->getBaseType() == Uml::ot_Association) {
+ UMLObject *o = const_cast<UMLObject*>(pObject);
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ removeAssocFromConcepts(assoc);
+ }
+ if (m_objects.findRef(pObject) == -1)
+ kDebug() << m_Name << " removeObject: object with id="
+ << ID2STR(pObject->getID()) << "not found." << endl;
+ else
+ m_objects.remove(pObject);
+}
+
+void UMLPackage::removeAllObjects() {
+ UMLCanvasObject::removeAllChildObjects();
+ UMLObject *o;
+ while ((o = m_objects.first()) != NULL) {
+ UMLPackage *pkg = dynamic_cast<UMLPackage*>(o);
+ if (pkg)
+ pkg->removeAllObjects();
+ removeObject(o);
+ //delete o;
+ // CHECK: Direct usage of the destructor crashes on associations.
+ o->deleteLater();
+ }
+}
+
+UMLObjectList UMLPackage::containedObjects() {
+ return m_objects;
+}
+
+UMLObject * UMLPackage::findObject(const QString &name) {
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (caseSensitive) {
+ if (obj->getName() == name)
+ return obj;
+ } else if (obj->getName().lower() == name.lower()) {
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+UMLObject * UMLPackage::findObjectById(Uml::IDType id) {
+ return Model_Utils::findObjectInList(id, m_objects);
+}
+
+void UMLPackage::appendClassifiers(UMLClassifierList& classifiers,
+ bool includeNested /* = true */) {
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *o = oit.current();
+ Object_Type ot = o->getBaseType();
+ if (ot == ot_Class || ot == ot_Interface ||
+ ot == ot_Datatype || ot == ot_Enum || ot == ot_Entity) {
+ classifiers.append((UMLClassifier *)o);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendClassifiers(classifiers);
+ }
+ }
+}
+
+void UMLPackage::appendClasses(UMLClassifierList& classes,
+ bool includeNested /* = true */) {
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *o = oit.current();
+ Object_Type ot = o->getBaseType();
+ if (ot == ot_Class) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ classes.append(c);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendClasses(classes);
+ }
+ }
+}
+
+void UMLPackage::appendClassesAndInterfaces(UMLClassifierList& classifiers,
+ bool includeNested /* = true */) {
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *o = oit.current();
+ Object_Type ot = o->getBaseType();
+ if (ot == ot_Class || ot == ot_Interface) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ classifiers.append(c);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendClassesAndInterfaces(classifiers);
+ }
+ }
+}
+
+void UMLPackage::appendInterfaces( UMLClassifierList& interfaces,
+ bool includeNested /* = true */) {
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *o = oit.current();
+ Object_Type ot = o->getBaseType();
+ if (ot == ot_Interface) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ interfaces.append(c);
+ } else if (includeNested && (ot == ot_Package || ot == ot_Folder)) {
+ UMLPackage *inner = static_cast<UMLPackage *>(o);
+ inner->appendInterfaces(interfaces);
+ }
+ }
+}
+
+bool UMLPackage::resolveRef() {
+ bool overallSuccess = UMLCanvasObject::resolveRef();
+ for (UMLObjectListIt oit(m_objects); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (! obj->resolveRef()) {
+ Uml::Object_Type ot = obj->getBaseType();
+ if (ot != Uml::ot_Package && ot != Uml::ot_Folder)
+ m_objects.remove(obj);
+ overallSuccess = false;
+ }
+ }
+ return overallSuccess;
+}
+
+void UMLPackage::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement packageElement = UMLObject::save("UML:Package", qDoc);
+ QDomElement ownedElement = qDoc.createElement("UML:Namespace.ownedElement");
+ UMLObject *obj;
+ // save classifiers etc.
+ for (UMLObjectListIt oit(m_objects); (obj = oit.current()) != NULL; ++oit)
+ obj->saveToXMI (qDoc, ownedElement);
+ // save associations
+ for (UMLObjectListIt ait(m_List); (obj = ait.current()) != NULL; ++ait)
+ obj->saveToXMI (qDoc, ownedElement);
+
+ packageElement.appendChild(ownedElement);
+ qElement.appendChild(packageElement);
+}
+
+bool UMLPackage::load(QDomElement& element) {
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (tagEq(type, "Namespace.ownedElement") ||
+ tagEq(type, "Namespace.contents")) {
+ //CHECK: Umbrello currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore these tags are not further interpreted.
+ if (! load(tempElement))
+ return false;
+ continue;
+ }
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+ if( !pObject ) {
+ kWarning() << "UMLPackage::load: "
+ << "Unknown type of umlobject to create: "
+ << type << endl;
+ continue;
+ }
+ pObject->setUMLPackage(this);
+ if (!pObject->loadFromXMI(tempElement)) {
+ removeObject(pObject);
+ delete pObject;
+ }
+ }
+ return true;
+}
+
+#include "package.moc"
diff --git a/umbrello/umbrello/package.h b/umbrello/umbrello/package.h
new file mode 100644
index 00000000..b7d51000
--- /dev/null
+++ b/umbrello/umbrello/package.h
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PACKAGE_H
+#define PACKAGE_H
+
+#include "umlcanvasobject.h"
+#include "umlclassifierlist.h"
+
+// forward declarations
+class UMLAssociation;
+
+
+/**
+ * This class contains the non-graphical information required for a UML
+ * Package.
+ * This class inherits from @ref UMLCanvasObject which contains most of the
+ * information.
+ *
+ * @short Non-graphical information for a Package.
+ * @author Jonathan Riddell
+ * @see UMLCanvasObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLPackage : public UMLCanvasObject {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a Package.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLPackage(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Empty deconstructor.
+ */
+ virtual ~UMLPackage();
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLPackage *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * Adds an object in this package.
+ *
+ * @param pObject Pointer to the UMLObject to add.
+ * @return True if the object was actually added.
+ */
+ bool addObject(UMLObject *pObject);
+
+ /**
+ * Removes an object from this package.
+ * Does not physically delete the object.
+ *
+ * @param pObject Pointer to the UMLObject to be removed.
+ */
+ void removeObject(UMLObject *pObject);
+
+ /**
+ * Removes all objects from this package.
+ * Inner containers (e.g. nested packages) are removed recursively.
+ */
+ virtual void removeAllObjects();
+
+ /**
+ * Returns the list of objects contained in this package.
+ */
+ UMLObjectList containedObjects();
+
+ /**
+ * Adds an existing association to the matching concept in the list of concepts.
+ * The selection of the matching concept depends on the association type:
+ * For generalizations, the assoc is added to the concept that matches role A.
+ * For aggregations and compositions , the assoc is added to the concept
+ * that matches role B.
+ *
+ * @param assoc The association to add
+ */
+ void addAssocToConcepts(UMLAssociation* assoc);
+
+ /**
+ * Remove the association from the participating concepts.
+ */
+ void removeAssocFromConcepts(UMLAssociation *assoc);
+
+ /**
+ * Find the object of the given name in the list of contained objects.
+ *
+ * @param name The name to seek.
+ * @return Pointer to the UMLObject found or NULL if not found.
+ */
+ UMLObject * findObject(const QString &name);
+
+ /**
+ * Find the object of the given ID in the list of contained objects.
+ *
+ * @param id The ID to seek.
+ * @return Pointer to the UMLObject found or NULL if not found.
+ */
+ UMLObject * findObjectById(Uml::IDType id);
+
+ /**
+ * Append all classifiers from this package (and those from
+ * nested packages) to the given UMLClassifierList.
+ *
+ * @param classifiers The list to append to.
+ * @param includeNested Whether to include the classifiers from
+ * nested packages (default: true.)
+ */
+ void appendClassifiers( UMLClassifierList& classifiers,
+ bool includeNested = true );
+
+ /**
+ * Append all classes from this package (and those from
+ * nested packages) to the given UMLClassifierList.
+ *
+ * @param classes The list to append to.
+ * @param includeNested Whether to include the classes from
+ * nested packages (default: true.)
+ */
+ void appendClasses( UMLClassifierList& classes, bool includeNested = true );
+
+ /**
+ * Append all classes and interfaces from this package (and those
+ * from nested packages) to the given UMLClassifierList.
+ *
+ * @param classifiers The list to append to.
+ * @param includeNested Whether to include the classifiers from
+ * nested packages (default: true.)
+ */
+ void appendClassesAndInterfaces(UMLClassifierList& classifiers,
+ bool includeNested = true);
+
+ /**
+ * Append all interfaces from this package (and those from
+ * nested packages) to the given UMLClassifierList.
+ *
+ * @param interfaces The list to append to.
+ * @param includeNested Whether to include the interfaces from
+ * nested packages (default: true.)
+ */
+ void appendInterfaces(UMLClassifierList& interfaces,
+ bool includeNested = true );
+
+ /**
+ * Resolve types. Required when dealing with foreign XMI files.
+ * Needs to be called after all UML objects are loaded from file.
+ * Overrides the method from UMLObject.
+ * Calls resolveRef() on each contained object.
+ *
+ * @return True for overall success.
+ */
+ virtual bool resolveRef();
+
+ /**
+ * Creates the <UML:Package> XMI element.
+ */
+ virtual void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Loads the <UML:Package> XMI element.
+ * Auxiliary to UMLObject::loadFromXMI.
+ */
+ virtual bool load(QDomElement& element);
+
+ /**
+ * References to the objects contained in this package.
+ * The UMLPackage is the owner of the objects.
+ */
+ UMLObjectList m_objects;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/packagewidget.cpp b/umbrello/umbrello/packagewidget.cpp
new file mode 100644
index 00000000..002f723e
--- /dev/null
+++ b/umbrello/umbrello/packagewidget.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "packagewidget.h"
+
+// qt/kde includes
+#include <qpainter.h>
+#include <kdebug.h>
+
+// app includes
+#include "package.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umlobject.h"
+
+
+PackageWidget::PackageWidget(UMLView * view, UMLPackage *o)
+ : UMLWidget(view, o) {
+ init();
+}
+
+void PackageWidget::init() {
+ UMLWidget::setBaseType(Uml::wt_Package);
+ setSize(100, 30);
+ setZ(m_origZ = 1); // above box but below UMLWidget because may embed widgets
+ m_pMenu = 0;
+ //set defaults from m_pView
+ if (m_pView) {
+ //check to see if correct
+ const Settings::OptionState& ops = m_pView->getOptionState();
+ m_bShowStereotype = ops.classState.showStereoType;
+ }
+ //maybe loading and this may not be set.
+ if (m_pObject && !UMLApp::app()->getDocument()->loading())
+ updateComponentSize();
+}
+
+PackageWidget::~PackageWidget() {}
+
+void PackageWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() )
+ p.setBrush( UMLWidget::getFillColour() );
+ else
+ p.setBrush(m_pView -> viewport() -> backgroundColor());
+
+ int w = width();
+ int h = height();
+ QFont font = UMLWidget::getFont();
+ font.setBold(true);
+ //FIXME italic is true when a package is first created until you click elsewhere, not sure why
+ font.setItalic(false);
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ QString name = getName();
+
+ p.drawRect(offsetX, offsetY, 50, fontHeight);
+ if (m_pObject->getStereotype() == "subsystem") {
+ const int fHalf = fontHeight / 2;
+ const int symY = offsetY + fHalf;
+ const int symX = offsetX + 38;
+ p.drawLine(symX, symY, symX, symY + fHalf - 2); // left leg
+ p.drawLine(symX + 8, symY, symX + 8, symY + fHalf - 2); // right leg
+ p.drawLine(symX, symY, symX + 8, symY); // waist
+ p.drawLine(symX + 4, symY, symX + 4, symY - fHalf + 2); // head
+ }
+ p.drawRect(offsetX, offsetY + fontHeight - 1, w, h - fontHeight);
+
+ p.setPen( QPen(Qt::black) );
+ p.setFont(font);
+
+ int lines = 1;
+ if (m_pObject != NULL) {
+ QString stereotype = m_pObject->getStereotype();
+ if (!stereotype.isEmpty()) {
+ p.drawText(offsetX, offsetY + fontHeight + PACKAGE_MARGIN,
+ w, fontHeight, Qt::AlignCenter, m_pObject->getStereotype(true));
+ lines = 2;
+ }
+ }
+
+ p.drawText(offsetX, offsetY + (fontHeight*lines) + PACKAGE_MARGIN,
+ w, fontHeight, Qt::AlignCenter, name );
+
+ if(m_bSelected) {
+ drawSelected(&p, offsetX, offsetY);
+ }
+}
+
+QSize PackageWidget::calculateSize() {
+ if ( !m_pObject ) {
+ return UMLWidget::calculateSize();
+ }
+
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
+ const int fontHeight = fm.lineSpacing();
+
+ int lines = 1;
+
+ int width = fm.width( m_pObject->getName() );
+
+ int tempWidth = 0;
+ if (!m_pObject->getStereotype().isEmpty()) {
+ tempWidth = fm.width(m_pObject->getStereotype(true));
+ lines = 2;
+ }
+ if (tempWidth > width)
+ width = tempWidth;
+ width += PACKAGE_MARGIN * 2;
+ if (width < 70)
+ width = 70; // minumin width of 70
+
+ int height = (lines*fontHeight) + fontHeight + (PACKAGE_MARGIN * 2);
+
+ return QSize(width, height);
+}
+
+void PackageWidget::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement conceptElement = qDoc.createElement("packagewidget");
+ UMLWidget::saveToXMI(qDoc, conceptElement);
+ qElement.appendChild(conceptElement);
+}
+
diff --git a/umbrello/umbrello/packagewidget.h b/umbrello/umbrello/packagewidget.h
new file mode 100644
index 00000000..5acb63d1
--- /dev/null
+++ b/umbrello/umbrello/packagewidget.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PACKAGEWIDGET_H
+#define PACKAGEWIDGET_H
+
+#include "umlwidget.h"
+
+class UMLPackage;
+
+#define PACKAGE_MARGIN 5
+
+/**
+ * Defines a graphical version of the Package. Most of the functionality
+ * will come from the @ref UMLPackage class.
+ *
+ * @short A graphical version of a Package.
+ * @author Jonathan Riddell
+ * @see UMLWidget
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PackageWidget : public UMLWidget {
+public:
+
+ /**
+ * Constructs a PackageWidget.
+ *
+ * @param view The parent of this PackageWidget.
+ * @param o The UMLObject this will be representing.
+ */
+ PackageWidget(UMLView * view, UMLPackage * o);
+
+ /**
+ * destructor
+ */
+ virtual ~PackageWidget();
+
+ /**
+ * Overrides standard method.
+ */
+ void draw(QPainter& p, int offsetX, int offsetY);
+
+ /**
+ * Saves to the "packagewidget" XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+
+private:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init();
+
+ /**
+ * The right mouse button menu.
+ */
+ ListPopupMenu* m_pMenu;
+};
+
+#endif
diff --git a/umbrello/umbrello/petalnode.cpp b/umbrello/umbrello/petalnode.cpp
new file mode 100644
index 00000000..9d9aa0ad
--- /dev/null
+++ b/umbrello/umbrello/petalnode.cpp
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "petalnode.h"
+
+PetalNode::PetalNode(NodeType nt) {
+ m_type = nt;
+}
+
+PetalNode::~PetalNode() {
+}
+
+PetalNode::NodeType PetalNode::type() const {
+ return m_type;
+}
+
+QStringList PetalNode::initialArgs() const {
+ return m_initialArgs;
+}
+
+QString PetalNode::name() const {
+ if (m_initialArgs.count() == 0)
+ return QString();
+ return m_initialArgs.first();
+}
+
+PetalNode::NameValueList PetalNode::attributes() const {
+ return m_attributes;
+}
+
+/*
+void PetalNode::setType(PetalNode::NodeType t) {
+ m_type = t;
+}
+ */
+
+void PetalNode::setInitialArgs(const QStringList& args) {
+ m_initialArgs = args;
+}
+
+void PetalNode::setAttributes(PetalNode::NameValueList vl) {
+ m_attributes = vl;
+}
+
+PetalNode::StringOrNode PetalNode::findAttribute(const QString& name) const {
+ for (uint i = 0; i < m_attributes.count(); i++) {
+ if (m_attributes[i].first == name)
+ return m_attributes[i].second;
+ }
+ return StringOrNode();
+}
+
diff --git a/umbrello/umbrello/petalnode.h b/umbrello/umbrello/petalnode.h
new file mode 100644
index 00000000..705de417
--- /dev/null
+++ b/umbrello/umbrello/petalnode.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PETALNODE__H
+#define PETALNODE__H
+
+#include <qstring.h>
+#include <qpair.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+
+/**
+ * Rose petal node - parse tree for model import
+ *
+ * A Rose petal node can be of type:
+ * + object - initialArgs() contains the object type name and further
+ * initial arguments which depend on the exact object type
+ * - subordinate attributes are contained in attributes()
+ * + list - initialArgs() contains the list type name
+ * - list elements are contained in attributes() but the name
+ * of each NameValue is empty.
+ * + value - not represented as a node, instead the stripped down value
+ * is saved in the value string of the NameValue.
+ * Example: for the input
+ * (value Text "This is some text")
+ * the following is saved in the value string of the NameValue:
+ * "This is some text"
+ *
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PetalNode {
+public:
+ /**
+ * Use `string' if it is not empty.
+ * Use `node' if it is not NULL.
+ * Either `string' is set, or `node', but never both.
+ * (Perhaps this should be a union but that is ugly.)
+ */
+ struct StringOrNode {
+ QString string;
+ PetalNode *node;
+ StringOrNode() { node = 0; }
+ virtual ~StringOrNode() { }
+ bool isEmpty() { return (string.isEmpty() && node == 0); }
+ };
+ typedef QPair<QString, StringOrNode> NameValue;
+ typedef QValueList<NameValue> NameValueList;
+
+ enum NodeType { nt_object, nt_list };
+
+ PetalNode(NodeType nt);
+ virtual ~PetalNode();
+
+ // getters
+ NodeType type() const;
+ QStringList initialArgs() const; // name and other initial args
+ QString name() const; // convenience function: equal to initialArgs().first()
+ NameValueList attributes() const;
+ // setters
+ //void setType(NodeType nt); see constructor
+ void setInitialArgs(const QStringList& args);
+ void setAttributes(NameValueList vl);
+ // utilities
+ /**
+ * Find an attribute by name.
+ * @return The value of the attribute. StringOrNode::isEmpty() returns true
+ * if the name could not be found.
+ */
+ StringOrNode findAttribute(const QString& name) const;
+private:
+ NodeType m_type;
+ QStringList m_initialArgs;
+ NameValueList m_attributes;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/petaltree2uml.cpp b/umbrello/umbrello/petaltree2uml.cpp
new file mode 100644
index 00000000..41563785
--- /dev/null
+++ b/umbrello/umbrello/petaltree2uml.cpp
@@ -0,0 +1,631 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "petaltree2uml.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "petalnode.h"
+#include "codeimport/import_utils.h"
+#include "package.h"
+#include "classifier.h"
+#include "attribute.h"
+#include "operation.h"
+#include "association.h"
+#include "umlrole.h"
+#include "actor.h"
+#include "usecase.h"
+#include "component.h"
+#include "node.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+
+namespace Import_Rose {
+
+/**
+ * Return the given string without surrounding quotation marks.
+ * Also remove a possible prefix "Logical View::", it is not modeled in Umbrello.
+ */
+QString clean(const QString& s) {
+ if (s.isNull())
+ return QString();
+ QString str = s;
+ str.remove("\"");
+ str.remove(QRegExp("^Logical View::"));
+ return str;
+}
+
+/**
+ * Extract the quid attribute from a petal node and return it as a Uml::IDType.
+ */
+Uml::IDType quid(const PetalNode *node) {
+ QString quidStr = node->findAttribute("quid").string;
+ if (quidStr.isEmpty())
+ return Uml::id_None;
+ quidStr.remove("\"");
+ return STR2ID(quidStr);
+}
+
+/**
+ * Extract the quidu attribute from a petal node.
+ */
+QString quidu(const PetalNode *node) {
+ QString quiduStr = node->findAttribute("quidu").string;
+ if (quiduStr.isEmpty())
+ return QString();
+ quiduStr.remove("\"");
+ return quiduStr;
+}
+
+/**
+ * Determine the model type corresponding to a name.
+ * If the given name consists only of letters, digits, underscores, and
+ * scope separators, then return Uml::ot_Class, else return Uml::ot_Datatype.
+ */
+Uml::Object_Type typeToCreate(const QString& name) {
+ QString n = name;
+ n.remove(QRegExp("^.*::")); // don't consider the scope prefix, it may contain spaces
+ Uml::Object_Type t = (n.contains(QRegExp("\\W")) ? Uml::ot_Datatype : Uml::ot_Class);
+ return t;
+}
+
+/**
+ * Transfer the Rose attribute "exportControl" to the Umbrello object given.
+ *
+ * @param from Pointer to PetalNode from which to read the "exportControl" attribute
+ * @param to Pointer to UMLObject in which to set the Uml::Visibility
+ */
+void transferVisibility(const PetalNode *from, UMLObject *to) {
+ QString vis = from->findAttribute("exportControl").string;
+ if (!vis.isEmpty()) {
+ Uml::Visibility v = Uml::Visibility::fromString(clean(vis.lower()));
+ to->setVisibility(v);
+ }
+}
+
+/**
+ * ClassifierListReader factors the common processing for attributes, operations,
+ * and operation parameters.
+ */
+class ClassifierListReader {
+public:
+ /// constructor
+ ClassifierListReader(const char* attributeTag,
+ const char* elementName,
+ const char* itemTypeDesignator) :
+ m_attributeTag(attributeTag),
+ m_elementName(elementName),
+ m_itemTypeDesignator(itemTypeDesignator) {
+ }
+ /// destructor
+ virtual ~ClassifierListReader() {}
+
+ /**
+ * Return a UMLClassifierListItem of the specific type desired.
+ * Abstract method to be implemented by inheriting classes.
+ */
+ virtual UMLObject *createListItem() = 0;
+
+ virtual void setTypeReferences(UMLObject *item,
+ const QString& quid, const QString& type) {
+ if (!quid.isEmpty()) {
+ item->setSecondaryId(quid);
+ }
+ if (!type.isEmpty()) {
+ item->setSecondaryFallback(type);
+ }
+ }
+
+ /**
+ * Insert the given UMLClassifierListItem at the parent Umbrello object.
+ * Abstract method to be implemented by inheriting classes.
+ * NB the parent Umbrello object is not included in the ClassifierListReader
+ * class - it must be added at inheriting classes.
+ *
+ * @param node The PetalNode which corresponds to the parent Umbrello object.
+ * @param o The UMLObject to insert.
+ */
+ virtual void insertAtParent(const PetalNode *node, UMLObject *o) = 0;
+
+ /**
+ * Iterate over the attributes of the given PetalNode and for each recognized
+ * attribute do the following:
+ * - invoke createListItem()
+ * - fill common properties such as name, unique ID, visibility, etc. into
+ * the new UMLClassifierListItem
+ * - invoke insertAtParent() with the new classifier list item as the argument
+ * This is the user entry point.
+ */
+ void read(const PetalNode *node, const QString& name) {
+ PetalNode *attributes = node->findAttribute(m_attributeTag).node;
+ if (attributes == NULL) {
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "read(" << name << "): no " << m_attributeTag << " found"
+ << endl;
+#endif
+ return;
+ }
+ PetalNode::NameValueList attributeList = attributes->attributes();
+ for (uint i = 0; i < attributeList.count(); i++) {
+ PetalNode *attNode = attributeList[i].second.node;
+ QStringList initialArgs = attNode->initialArgs();
+ if (attNode->name() != m_elementName) {
+ kDebug() << "read(" << name << "): expecting " << m_elementName
+ << ", " << "found " << initialArgs[0] << endl;
+ continue;
+ }
+ UMLObject *item = createListItem();
+ if (initialArgs.count() > 1)
+ item->setName(clean(initialArgs[1]));
+ item->setID(quid(attNode));
+ QString quidref = quidu(attNode);
+ QString type = clean(attNode->findAttribute(m_itemTypeDesignator).string);
+ setTypeReferences(item, quidref, type);
+ transferVisibility(attNode, item);
+ QString doc = attNode->findAttribute("documentation").string;
+ if (! doc.isEmpty())
+ item->setDoc(doc);
+ insertAtParent(attNode, item);
+ }
+ }
+protected:
+ const QString m_attributeTag, m_elementName, m_itemTypeDesignator;
+};
+
+class AttributesReader : public ClassifierListReader {
+public:
+ AttributesReader(UMLClassifier *c)
+ : ClassifierListReader("class_attributes", "ClassAttribute", "type") {
+ m_classifier = c;
+ }
+ virtual ~AttributesReader() {}
+ UMLObject *createListItem() {
+ return new UMLAttribute(m_classifier);
+ }
+ void insertAtParent(const PetalNode *, UMLObject *item) {
+ m_classifier->addAttribute(static_cast<UMLAttribute*>(item));
+ }
+protected:
+ UMLClassifier *m_classifier;
+};
+
+class ParametersReader : public ClassifierListReader {
+public:
+ ParametersReader(UMLOperation *op)
+ : ClassifierListReader("parameters", "Parameter", "type") {
+ m_operation = op;
+ }
+ virtual ~ParametersReader() {}
+ UMLObject *createListItem() {
+ return new UMLAttribute(m_operation);
+ }
+ void insertAtParent(const PetalNode *, UMLObject *item) {
+ m_operation->addParm(static_cast<UMLAttribute*>(item));
+ }
+protected:
+ UMLOperation *m_operation;
+};
+
+class OperationsReader : public ClassifierListReader {
+public:
+ OperationsReader(UMLClassifier *c)
+ : ClassifierListReader("operations", "Operation", "result") {
+ m_classifier = c;
+ }
+ virtual ~OperationsReader() {}
+ UMLObject *createListItem() {
+ return new UMLOperation(m_classifier);
+ }
+ void insertAtParent(const PetalNode *node, UMLObject *item) {
+ UMLOperation *op = static_cast<UMLOperation*>(item);
+ ParametersReader parmReader(op);
+ parmReader.read(node, m_classifier->getName());
+ m_classifier->addOperation(op);
+ }
+protected:
+ UMLClassifier *m_classifier;
+};
+
+class SuperclassesReader : public ClassifierListReader {
+public:
+ SuperclassesReader(UMLClassifier *c)
+ : ClassifierListReader("superclasses", "Inheritance_Relationship", "supplier") {
+ m_classifier = c;
+ }
+ virtual ~SuperclassesReader() {}
+ UMLObject *createListItem() {
+ return new UMLAssociation(Uml::at_Generalization);
+ }
+ /**
+ * Override parent implementation: The secondary data is not for the
+ * UMLAssociation itself but for its role B object.
+ */
+ void setTypeReferences(UMLObject *item,
+ const QString& quid, const QString& type) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
+ if (!quid.isEmpty()) {
+ assoc->getUMLRole(Uml::B)->setSecondaryId(quid);
+ }
+ if (!type.isEmpty()) {
+ assoc->getUMLRole(Uml::B)->setSecondaryFallback(type);
+ }
+ }
+ void insertAtParent(const PetalNode *, UMLObject *item) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
+ assoc->setObject(m_classifier, Uml::A);
+ UMLApp::app()->getDocument()->addAssociation(assoc);
+ }
+protected:
+ UMLClassifier *m_classifier;
+};
+
+class RealizationsReader : public ClassifierListReader {
+public:
+ RealizationsReader(UMLClassifier *c)
+ : ClassifierListReader("realized_interfaces", "Realize_Relationship", "supplier") {
+ m_classifier = c;
+ }
+ virtual ~RealizationsReader() {}
+ UMLObject *createListItem() {
+ return new UMLAssociation(Uml::at_Realization);
+ }
+ /**
+ * Override parent implementation: The secondary data is not for the
+ * UMLAssociation itself but for its role B object.
+ */
+ void setTypeReferences(UMLObject *item,
+ const QString& quid, const QString& type) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
+ if (!quid.isEmpty()) {
+ assoc->getUMLRole(Uml::B)->setSecondaryId(quid);
+ }
+ if (!type.isEmpty()) {
+ assoc->getUMLRole(Uml::B)->setSecondaryFallback(type);
+ }
+ }
+ void insertAtParent(const PetalNode *, UMLObject *item) {
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
+ assoc->setObject(m_classifier, Uml::A);
+ UMLApp::app()->getDocument()->addAssociation(assoc);
+ }
+protected:
+ UMLClassifier *m_classifier;
+};
+
+/**
+ * Handle a controlled unit.
+ *
+ * @param node Pointer to the PetalNode which may contain a controlled unit
+ * @param name Name of the current node
+ * @param id QUID of the current node
+ * @param parentPkg Pointer to the current parent UMLPackage.
+ * @return True if the node actually contained a controlled unit.
+ */
+bool handleControlledUnit(PetalNode *node, const QString& name, Uml::IDType id, UMLPackage *parentPkg) {
+ if (node->findAttribute("is_unit").string != "TRUE")
+ return false;
+ bool is_loaded = (node->findAttribute("is_loaded").string != "FALSE");
+ QString file_name = node->findAttribute("file_name").string;
+ if (file_name.isEmpty()) {
+ kError() << "handleControlledUnit(" << name
+ << "): attribute file_name not found (?)" << endl;
+ return true;
+ }
+ // To Be Continued.
+
+ return true;
+}
+
+/**
+ * Create an Umbrello object from a PetalNode of the Logical View.
+ *
+ * @return True for success.
+ * Given a PetalNode for which the mapping to Umbrello is not yet
+ * implemented umbrellify() is a no-op but also returns true.
+ */
+bool umbrellify(PetalNode *node, UMLPackage *parentPkg = NULL) {
+ if (node == NULL) {
+ kError() << "umbrellify: node is NULL" << endl;
+ return false;
+ }
+ QStringList args = node->initialArgs();
+ QString objType = args[0];
+ QString name = clean(args[1]);
+ Uml::IDType id = quid(node);
+
+ if (objType == "Class_Category") {
+ UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Package, name, parentPkg);
+ o->setID(id);
+ PetalNode *logical_models = node->findAttribute("logical_models").node;
+ if (logical_models) {
+ UMLPackage *localParent = static_cast<UMLPackage*>(o);
+ PetalNode::NameValueList atts = logical_models->attributes();
+ for (uint i = 0; i < atts.count(); i++) {
+ umbrellify(atts[i].second.node, localParent);
+ }
+ } else if (!handleControlledUnit(node, name, id, parentPkg)) {
+ kDebug() << "umbrellify: handling of " << objType << " " << name
+ << " is not yet implemented" << endl;
+ }
+
+ } else if (objType == "Class") {
+ UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Class, name, parentPkg);
+ o->setID(id);
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ // set stereotype
+ QString stereotype = clean(node->findAttribute("stereotype").string);
+ if (!stereotype.isEmpty()) {
+ if (stereotype.lower() == "interface")
+ c->setBaseType(Uml::ot_Interface);
+ else
+ c->setStereotype(stereotype);
+ }
+ // insert attributes
+ AttributesReader attReader(c);
+ attReader.read(node, c->getName());
+ // insert operations
+ OperationsReader opReader(c);
+ opReader.read(node, c->getName());
+ // insert generalizations
+ SuperclassesReader superReader(c);
+ superReader.read(node, c->getName());
+ // insert realizations
+ RealizationsReader realReader(c);
+ realReader.read(node, c->getName());
+
+ } else if (objType == "Association") {
+ PetalNode *roles = node->findAttribute("roles").node;
+ if (node == NULL) {
+ kError() << "umbrellify: cannot find roles of Association" << endl;
+ return false;
+ }
+ UMLAssociation *assoc = new UMLAssociation(Uml::at_UniAssociation);
+ PetalNode::NameValueList roleList = roles->attributes();
+ for (uint i = 0; i <= 1; i++) {
+ PetalNode *roleNode = roleList[i].second.node;
+ if (roleNode == NULL) {
+ kError() << "umbrellify: roleNode of Association is NULL" << endl;
+ return false;
+ }
+ if (roleNode->name() != "Role") {
+ kDebug() << "umbrellify(" << name << "): expecting Role, found \""
+ << roleNode->name() << endl;
+ continue;
+ }
+ // index 0 corresponds to Umbrello roleB
+ // index 1 corresponds to Umbrello roleA
+ UMLRole *role = assoc->getUMLRole((Uml::Role_Type) !i);
+ QStringList initialArgs = roleNode->initialArgs();
+ if (initialArgs.count() > 1) {
+ QString roleName = clean(initialArgs[1]);
+ if (! roleName.startsWith("$UNNAMED"))
+ role->setName(roleName);
+ }
+ role->setID(quid(roleNode));
+ QString quidref = quidu(roleNode);
+ QString type = clean(roleNode->findAttribute("supplier").string);
+ if (!quidref.isEmpty()) {
+ role->setSecondaryId(quidref);
+ }
+ if (!type.isEmpty()) {
+ role->setSecondaryFallback(type);
+ }
+ QString label = clean(roleNode->findAttribute("label").string);
+ if (!label.isEmpty()) {
+ role->setName(label);
+ }
+ QString client_cardinality = clean(roleNode->findAttribute("client_cardinality").string);
+ if (!client_cardinality.isEmpty()) {
+ role->setMultiplicity(client_cardinality);
+ }
+ QString is_navigable = clean(roleNode->findAttribute("is_navigable").string);
+ if (is_navigable == "FALSE") {
+ assoc->setAssocType(Uml::at_Association);
+ }
+ QString is_aggregate = clean(roleNode->findAttribute("is_aggregate").string);
+ if (is_aggregate == "TRUE") {
+ assoc->setAssocType(Uml::at_Aggregation);
+ }
+ QString containment = clean(roleNode->findAttribute("Containment").string);
+ if (containment == "By Value") {
+ assoc->setAssocType(Uml::at_Composition);
+ }
+ QString doc = roleNode->findAttribute("documentation").string;
+ if (! doc.isEmpty())
+ role->setDoc(doc);
+ }
+ UMLApp::app()->getDocument()->addAssociation(assoc);
+
+ } else {
+ kDebug() << "umbrellify: object type " << objType
+ << " is not yet implemented" << endl;
+ }
+ return true;
+}
+
+Uml::ListView_Type folderType(UMLListViewItem *parent) {
+ Uml::ListView_Type type = Uml::lvt_Unknown;
+ switch (parent->getType()) {
+ case Uml::lvt_Logical_View:
+ case Uml::lvt_Logical_Folder:
+ type = Uml::lvt_Logical_Folder;
+ break;
+ case Uml::lvt_UseCase_View:
+ case Uml::lvt_UseCase_Folder:
+ type = Uml::lvt_UseCase_Folder;
+ break;
+ case Uml::lvt_Component_View:
+ case Uml::lvt_Component_Folder:
+ type = Uml::lvt_Component_Folder;
+ break;
+ case Uml::lvt_Deployment_View:
+ case Uml::lvt_Deployment_Folder:
+ type = Uml::lvt_Deployment_Folder;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+/**
+ * Create an Umbrello object from a PetalNode of the UseCase, Component,
+ * or Deployment View.
+ *
+ * @return True for success.
+ * Given a PetalNode for which the mapping to Umbrello is not yet
+ * implemented umbrellify() is a no-op but also returns true.
+ */
+bool umbrellify(PetalNode *node, const QString& modelsName, UMLListViewItem *parent) {
+ if (node == NULL) {
+ kError() << "umbrellify(" << modelsName << "): node is NULL" << endl;
+ return false;
+ }
+ QStringList args = node->initialArgs();
+ QString objType = args[0];
+ QString name = clean(args[1]);
+ Uml::IDType id = quid(node);
+ UMLObject *obj = NULL;
+ UMLListViewItem *item = NULL;
+
+ if (objType == "Class_Category") {
+ Uml::ListView_Type lvType = folderType(parent);
+ item = new UMLListViewItem( parent, name, lvType, id );
+ } else if (objType == "Class") {
+ QString stereotype = clean(node->findAttribute("stereotype").string);
+ if (stereotype == "Actor") {
+ UMLActor *act = new UMLActor(name, id);
+ item = new UMLListViewItem(parent, name, Uml::lvt_Actor, act);
+ obj = act;
+ } else {
+ kDebug() << "umbrellify(" << name << "): handling of Class stereotype "
+ << stereotype << " is not yet implemented" << endl;
+ }
+ } else if (objType == "UseCase") {
+ UMLUseCase *uc = new UMLUseCase(name, id);
+ item = new UMLListViewItem(parent, name, Uml::lvt_UseCase, uc);
+ obj = uc;
+ } else if (objType == "SubSystem") {
+ UMLComponent *comp = new UMLComponent(name, id);
+ item = new UMLListViewItem(parent, name, Uml::lvt_Component, comp);
+ obj = comp;
+ } else if (objType == "Processor" || objType == "Device") {
+ UMLNode *un = new UMLNode(name, id);
+ un->setStereotype(objType.lower());
+ item = new UMLListViewItem(parent, name, Uml::lvt_Node, un);
+ obj = un;
+ } else {
+ kDebug() << "umbrellify: object type " << objType
+ << " is not yet implemented" << endl;
+ return true;
+ }
+ PetalNode *models = node->findAttribute(modelsName).node;
+ if (models) {
+ PetalNode::NameValueList atts = models->attributes();
+ for (uint i = 0; i < atts.count(); i++) {
+ if (! umbrellify(atts[i].second.node, modelsName, item))
+ return false;
+ }
+ }
+ if (obj) {
+ QString doc = node->findAttribute("documentation").string;
+ if (! doc.isEmpty())
+ obj->setDoc(doc);
+ UMLDoc *theDocument = UMLApp::app()->getDocument();
+ theDocument->addUMLObject(obj);
+ }
+ return true;
+}
+
+/**
+ * Auxiliary function for UseCase/Component/Deployment view import
+ */
+bool importView(PetalNode *root, const QString& rootName,
+ const QString& modelsName, UMLListViewItem *lvParent) {
+ PetalNode *viewRoot = root->findAttribute(rootName).node;
+ if (viewRoot == NULL) {
+ kDebug() << "importView: cannot find " << rootName << endl;
+ return false;
+ }
+ PetalNode *models = viewRoot->findAttribute(modelsName).node;
+ if (models == NULL) {
+ kError() << "importView: cannot find " << modelsName
+ << " of " << rootName << endl;
+ return false;
+ }
+ PetalNode::NameValueList atts = models->attributes();
+ for (uint i = 0; i < atts.count(); i++) {
+ umbrellify(atts[i].second.node, modelsName, lvParent);
+ }
+ return true;
+}
+
+bool petalTree2Uml(PetalNode *root) {
+ if (root == NULL) {
+ kError() << "petalTree2Uml: root is NULL" << endl;
+ return false;
+ }
+ if (root->name() != "Design") {
+ kError() << "petalTree2Uml: expecting root name Design" << endl;
+ return false;
+ }
+ /*************************** import Logical View ********************************/
+ PetalNode *root_category = root->findAttribute("root_category").node;
+ if (root_category == NULL) {
+ kError() << "petalTree2Uml: cannot find root_category" << endl;
+ return false;
+ }
+ if (root_category->name() != "Class_Category") {
+ kError() << "petalTree2Uml: expecting root_category object Class_Category"
+ << endl;
+ return false;
+ }
+ PetalNode *logical_models = root_category->findAttribute("logical_models").node;
+ if (logical_models == NULL) {
+ kError() << "petalTree2Uml: cannot find logical_models" << endl;
+ return false;
+ }
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umldoc->setCurrentRoot(Uml::mt_Logical);
+ Import_Utils::assignUniqueIdOnCreation(false);
+ PetalNode::NameValueList atts = logical_models->attributes();
+ for (uint i = 0; i < atts.count(); i++) {
+ umbrellify(atts[i].second.node);
+ }
+
+ /** Shorthand for UMLApp::app()->getListView() **/
+ UMLListView *lv = UMLApp::app()->getListView();
+
+ /*************************** import Use Case View ********************************/
+ umldoc->setCurrentRoot(Uml::mt_UseCase);
+ importView(root, "root_usecase_package", "logical_models", lv->theUseCaseView());
+
+ /*************************** import Component View *******************************/
+ umldoc->setCurrentRoot(Uml::mt_Component);
+ importView(root, "root_subsystem", "physical_models", lv->theComponentView());
+
+ /*************************** import Deployment View ******************************/
+ umldoc->setCurrentRoot(Uml::mt_Deployment);
+ importView(root, "process_structure", "ProcsNDevs", lv->theDeploymentView());
+
+ /*************************** wrap up ********************************/
+ umldoc->setCurrentRoot(Uml::mt_Logical);
+ Import_Utils::assignUniqueIdOnCreation(true);
+ umldoc->resolveTypes();
+ return true;
+}
+
+} // namespace Import_Rose
+
diff --git a/umbrello/umbrello/petaltree2uml.h b/umbrello/umbrello/petaltree2uml.h
new file mode 100644
index 00000000..a60f3cbc
--- /dev/null
+++ b/umbrello/umbrello/petaltree2uml.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PETALTREE2UML_H
+#define PETALTREE2UML_H
+
+// fwd decl
+class PetalNode;
+
+/**
+ * Traverse the PetalNode tree and create corresponding Umbrello objects
+ * for the PetalNodes encountered.
+ *
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Import_Rose {
+
+ /**
+ * This is really an auxiliary method for loadFromMDL() but is kept in a
+ * separate file to reflect that it is not coupled with the parser
+ * (other than by the PetalNode.)
+ *
+ * @return true for success.
+ */
+ bool petalTree2Uml(PetalNode *root);
+
+}
+
+#endif
+
diff --git a/umbrello/umbrello/pics/COPYING b/umbrello/umbrello/pics/COPYING
new file mode 100644
index 00000000..5e09cc93
--- /dev/null
+++ b/umbrello/umbrello/pics/COPYING
@@ -0,0 +1,3 @@
+Images under this directory as well as the Umbrello and Umbrello
+mimetype icons may be copied under the terms of the LGPL plus add-on as
+found in kdelibs/pics/LICENSE.crystalsvg
diff --git a/umbrello/umbrello/pics/CVglobal_meth.png b/umbrello/umbrello/pics/CVglobal_meth.png
new file mode 100644
index 00000000..a7bb6659
--- /dev/null
+++ b/umbrello/umbrello/pics/CVglobal_meth.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVglobal_var.png b/umbrello/umbrello/pics/CVglobal_var.png
new file mode 100644
index 00000000..f7f85455
--- /dev/null
+++ b/umbrello/umbrello/pics/CVglobal_var.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVimplementation_meth.png b/umbrello/umbrello/pics/CVimplementation_meth.png
new file mode 100644
index 00000000..97b23df4
--- /dev/null
+++ b/umbrello/umbrello/pics/CVimplementation_meth.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVimplementation_signal.png b/umbrello/umbrello/pics/CVimplementation_signal.png
new file mode 100644
index 00000000..c89e1e11
--- /dev/null
+++ b/umbrello/umbrello/pics/CVimplementation_signal.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVimplementation_slot.png b/umbrello/umbrello/pics/CVimplementation_slot.png
new file mode 100644
index 00000000..c1a77f5f
--- /dev/null
+++ b/umbrello/umbrello/pics/CVimplementation_slot.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVimplementation_var.png b/umbrello/umbrello/pics/CVimplementation_var.png
new file mode 100644
index 00000000..026df532
--- /dev/null
+++ b/umbrello/umbrello/pics/CVimplementation_var.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVnamespace.png b/umbrello/umbrello/pics/CVnamespace.png
new file mode 100644
index 00000000..bc40283d
--- /dev/null
+++ b/umbrello/umbrello/pics/CVnamespace.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprivate_meth.png b/umbrello/umbrello/pics/CVprivate_meth.png
new file mode 100644
index 00000000..45c7b3e1
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprivate_meth.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprivate_signal.png b/umbrello/umbrello/pics/CVprivate_signal.png
new file mode 100644
index 00000000..114a7148
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprivate_signal.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprivate_slot.png b/umbrello/umbrello/pics/CVprivate_slot.png
new file mode 100644
index 00000000..e9b8ecd6
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprivate_slot.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprivate_var.png b/umbrello/umbrello/pics/CVprivate_var.png
new file mode 100644
index 00000000..4bf6180c
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprivate_var.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprotected_meth.png b/umbrello/umbrello/pics/CVprotected_meth.png
new file mode 100644
index 00000000..fe96d4db
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprotected_meth.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprotected_signal.png b/umbrello/umbrello/pics/CVprotected_signal.png
new file mode 100644
index 00000000..07aef0b3
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprotected_signal.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprotected_slot.png b/umbrello/umbrello/pics/CVprotected_slot.png
new file mode 100644
index 00000000..db084899
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprotected_slot.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVprotected_var.png b/umbrello/umbrello/pics/CVprotected_var.png
new file mode 100644
index 00000000..f97903f0
--- /dev/null
+++ b/umbrello/umbrello/pics/CVprotected_var.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVpublic_meth.png b/umbrello/umbrello/pics/CVpublic_meth.png
new file mode 100644
index 00000000..56063b02
--- /dev/null
+++ b/umbrello/umbrello/pics/CVpublic_meth.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVpublic_signal.png b/umbrello/umbrello/pics/CVpublic_signal.png
new file mode 100644
index 00000000..5a101850
--- /dev/null
+++ b/umbrello/umbrello/pics/CVpublic_signal.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVpublic_slot.png b/umbrello/umbrello/pics/CVpublic_slot.png
new file mode 100644
index 00000000..b04b49de
--- /dev/null
+++ b/umbrello/umbrello/pics/CVpublic_slot.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVpublic_var.png b/umbrello/umbrello/pics/CVpublic_var.png
new file mode 100644
index 00000000..d17730e7
--- /dev/null
+++ b/umbrello/umbrello/pics/CVpublic_var.png
Binary files differ
diff --git a/umbrello/umbrello/pics/CVstruct.png b/umbrello/umbrello/pics/CVstruct.png
new file mode 100644
index 00000000..ec953add
--- /dev/null
+++ b/umbrello/umbrello/pics/CVstruct.png
Binary files differ
diff --git a/umbrello/umbrello/pics/Makefile.am b/umbrello/umbrello/pics/Makefile.am
new file mode 100644
index 00000000..43292145
--- /dev/null
+++ b/umbrello/umbrello/pics/Makefile.am
@@ -0,0 +1,112 @@
+picsdir = $(kde_datadir)/umbrello/pics
+
+pics_DATA = actor.png \
+aggregation.png \
+align_left.png \
+align_right.png \
+align_top.png \
+align_bottom.png \
+align_vert_middle.png \
+align_hori_middle.png \
+align_vert_distribute.png \
+align_hori_distribute.png \
+anchor.png \
+andline.png \
+arrow.png \
+association.png \
+choice-rhomb.png \
+choice-round.png \
+component.png \
+composition.png \
+containment.png \
+CVglobal_meth.png \
+CVglobal_var.png \
+CVimplementation_meth.png \
+CVimplementation_signal.png \
+CVimplementation_slot.png \
+CVimplementation_var.png \
+CVnamespace.png \
+CVprivate_meth.png \
+CVprivate_signal.png \
+CVprivate_slot.png \
+CVprivate_var.png \
+CVprotected_meth.png \
+CVprotected_signal.png \
+CVprotected_slot.png \
+CVprotected_var.png \
+CVpublic_meth.png \
+CVpublic_signal.png \
+CVpublic_slot.png \
+CVpublic_var.png \
+CVstruct.png \
+deep-history.png \
+shallow-history.png \
+dependency.png \
+end_state.png \
+generalisation.png \
+initial_state.png \
+interface.png \
+join.png \
+junction.png \
+datatype.png \
+enum.png \
+message-synchronous.png \
+message-asynchronous.png \
+note.png \
+object.png \
+startlogo.png \
+template.png \
+text.png \
+class.png \
+uniassociation.png \
+usecase.png \
+branch.png \
+fork.png \
+state-fork.png \
+package.png \
+subsystem.png \
+artifact.png \
+box.png \
+node.png \
+entity.png \
+relationship.png \
+cursor-actor.png \
+cursor-andline.png \
+cursor-choice-rhomb.png \
+cursor-choice-round.png \
+cursor-deep-history.png \
+cursor-join.png \
+cursor-junction.png \
+cursor-shallow-history.png \
+cursor-state-fork.png \
+cursor-usecase.png \
+cursor-initial_state.png \
+cursor-package.png \
+cursor-aggregation.png \
+cursor-component.png \
+cursor-containment.png \
+cursor-interface.png \
+cursor-datatype.png \
+cursor-enum.png \
+cursor-text.png \
+cursor-anchor.png \
+cursor-composition.png \
+cursor-message-asynchronous.png \
+cursor-class.png \
+cursor-artifact.png \
+cursor-dependency.png \
+cursor-message-synchronous.png \
+cursor-uniassociation.png \
+cursor-association.png \
+cursor-end_state.png \
+cursor-node.png \
+cursor-box.png \
+cursor-fork.png \
+cursor-note.png \
+cursor-branch.png \
+cursor-generalisation.png \
+cursor-object.png \
+cursor-entity.png \
+cursor-relationship.png
+
+KDE_ICON = umbrello_diagram_activity umbrello_diagram_class umbrello_diagram_collaboration umbrello_diagram_component umbrello_diagram_deployment umbrello_diagram_sequence umbrello_diagram_state umbrello_diagram_usecase umbrello_diagram_entityrelationship
diff --git a/umbrello/umbrello/pics/actor.png b/umbrello/umbrello/pics/actor.png
new file mode 100644
index 00000000..728be176
--- /dev/null
+++ b/umbrello/umbrello/pics/actor.png
Binary files differ
diff --git a/umbrello/umbrello/pics/aggregation.png b/umbrello/umbrello/pics/aggregation.png
new file mode 100644
index 00000000..cb9ce67d
--- /dev/null
+++ b/umbrello/umbrello/pics/aggregation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_bottom.png b/umbrello/umbrello/pics/align_bottom.png
new file mode 100644
index 00000000..555239ec
--- /dev/null
+++ b/umbrello/umbrello/pics/align_bottom.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_hori_distribute.png b/umbrello/umbrello/pics/align_hori_distribute.png
new file mode 100644
index 00000000..03215af6
--- /dev/null
+++ b/umbrello/umbrello/pics/align_hori_distribute.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_hori_middle.png b/umbrello/umbrello/pics/align_hori_middle.png
new file mode 100644
index 00000000..62956a49
--- /dev/null
+++ b/umbrello/umbrello/pics/align_hori_middle.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_left.png b/umbrello/umbrello/pics/align_left.png
new file mode 100644
index 00000000..9bf21f99
--- /dev/null
+++ b/umbrello/umbrello/pics/align_left.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_right.png b/umbrello/umbrello/pics/align_right.png
new file mode 100644
index 00000000..80b5c0c5
--- /dev/null
+++ b/umbrello/umbrello/pics/align_right.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_top.png b/umbrello/umbrello/pics/align_top.png
new file mode 100644
index 00000000..b168cd5a
--- /dev/null
+++ b/umbrello/umbrello/pics/align_top.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_vert_distribute.png b/umbrello/umbrello/pics/align_vert_distribute.png
new file mode 100644
index 00000000..7da67730
--- /dev/null
+++ b/umbrello/umbrello/pics/align_vert_distribute.png
Binary files differ
diff --git a/umbrello/umbrello/pics/align_vert_middle.png b/umbrello/umbrello/pics/align_vert_middle.png
new file mode 100644
index 00000000..096782fc
--- /dev/null
+++ b/umbrello/umbrello/pics/align_vert_middle.png
Binary files differ
diff --git a/umbrello/umbrello/pics/anchor.png b/umbrello/umbrello/pics/anchor.png
new file mode 100644
index 00000000..9fc2bc06
--- /dev/null
+++ b/umbrello/umbrello/pics/anchor.png
Binary files differ
diff --git a/umbrello/umbrello/pics/andline.png b/umbrello/umbrello/pics/andline.png
new file mode 100644
index 00000000..7fe6081b
--- /dev/null
+++ b/umbrello/umbrello/pics/andline.png
Binary files differ
diff --git a/umbrello/umbrello/pics/arrow.png b/umbrello/umbrello/pics/arrow.png
new file mode 100644
index 00000000..6f48d945
--- /dev/null
+++ b/umbrello/umbrello/pics/arrow.png
Binary files differ
diff --git a/umbrello/umbrello/pics/artifact.png b/umbrello/umbrello/pics/artifact.png
new file mode 100644
index 00000000..41e3ccd9
--- /dev/null
+++ b/umbrello/umbrello/pics/artifact.png
Binary files differ
diff --git a/umbrello/umbrello/pics/association.png b/umbrello/umbrello/pics/association.png
new file mode 100644
index 00000000..60f742bb
--- /dev/null
+++ b/umbrello/umbrello/pics/association.png
Binary files differ
diff --git a/umbrello/umbrello/pics/box.png b/umbrello/umbrello/pics/box.png
new file mode 100644
index 00000000..03e2b41b
--- /dev/null
+++ b/umbrello/umbrello/pics/box.png
Binary files differ
diff --git a/umbrello/umbrello/pics/branch.png b/umbrello/umbrello/pics/branch.png
new file mode 100644
index 00000000..36bea8f5
--- /dev/null
+++ b/umbrello/umbrello/pics/branch.png
Binary files differ
diff --git a/umbrello/umbrello/pics/choice-rhomb.png b/umbrello/umbrello/pics/choice-rhomb.png
new file mode 100644
index 00000000..d067c3ee
--- /dev/null
+++ b/umbrello/umbrello/pics/choice-rhomb.png
Binary files differ
diff --git a/umbrello/umbrello/pics/choice-round.png b/umbrello/umbrello/pics/choice-round.png
new file mode 100644
index 00000000..423748d8
--- /dev/null
+++ b/umbrello/umbrello/pics/choice-round.png
Binary files differ
diff --git a/umbrello/umbrello/pics/class.png b/umbrello/umbrello/pics/class.png
new file mode 100644
index 00000000..8b47d5b0
--- /dev/null
+++ b/umbrello/umbrello/pics/class.png
Binary files differ
diff --git a/umbrello/umbrello/pics/component.png b/umbrello/umbrello/pics/component.png
new file mode 100644
index 00000000..1ba3d604
--- /dev/null
+++ b/umbrello/umbrello/pics/component.png
Binary files differ
diff --git a/umbrello/umbrello/pics/composition.png b/umbrello/umbrello/pics/composition.png
new file mode 100644
index 00000000..3d53ea48
--- /dev/null
+++ b/umbrello/umbrello/pics/composition.png
Binary files differ
diff --git a/umbrello/umbrello/pics/containment.png b/umbrello/umbrello/pics/containment.png
new file mode 100644
index 00000000..1972fda5
--- /dev/null
+++ b/umbrello/umbrello/pics/containment.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_activity.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_activity.png
new file mode 100644
index 00000000..0295b8b6
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_activity.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_class.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_class.png
new file mode 100644
index 00000000..0e8c6060
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_class.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_collaboration.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_collaboration.png
new file mode 100644
index 00000000..76207be2
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_collaboration.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_component.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_component.png
new file mode 100644
index 00000000..f80cc31f
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_component.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_deployment.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_deployment.png
new file mode 100644
index 00000000..fe515150
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_deployment.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_sequence.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_sequence.png
new file mode 100644
index 00000000..e60ca4c6
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_sequence.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_state.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_state.png
new file mode 100644
index 00000000..4fe826df
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr16-action-umbrello_diagram_usecase.png b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_usecase.png
new file mode 100644
index 00000000..3259c733
--- /dev/null
+++ b/umbrello/umbrello/pics/cr16-action-umbrello_diagram_usecase.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_activity.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_activity.png
new file mode 100644
index 00000000..053af9e5
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_activity.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_class.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_class.png
new file mode 100644
index 00000000..cf9e168d
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_class.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_collaboration.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_collaboration.png
new file mode 100644
index 00000000..323947e8
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_collaboration.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_component.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_component.png
new file mode 100644
index 00000000..48202c8f
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_component.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_deployment.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_deployment.png
new file mode 100644
index 00000000..5343363c
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_deployment.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_entityrelationship.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_entityrelationship.png
new file mode 100644
index 00000000..570b8ac1
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_entityrelationship.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_sequence.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_sequence.png
new file mode 100644
index 00000000..b2cfd3c2
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_sequence.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_state.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_state.png
new file mode 100644
index 00000000..f812a17c
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cr22-action-umbrello_diagram_usecase.png b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_usecase.png
new file mode 100644
index 00000000..bc07439d
--- /dev/null
+++ b/umbrello/umbrello/pics/cr22-action-umbrello_diagram_usecase.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-actor.png b/umbrello/umbrello/pics/cursor-actor.png
new file mode 100644
index 00000000..97e05a98
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-actor.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-aggregation.png b/umbrello/umbrello/pics/cursor-aggregation.png
new file mode 100644
index 00000000..f75e323d
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-aggregation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-anchor.png b/umbrello/umbrello/pics/cursor-anchor.png
new file mode 100644
index 00000000..6facf249
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-anchor.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-andline.png b/umbrello/umbrello/pics/cursor-andline.png
new file mode 100644
index 00000000..ca66655d
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-andline.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-artifact.png b/umbrello/umbrello/pics/cursor-artifact.png
new file mode 100644
index 00000000..47965eed
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-artifact.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-association.png b/umbrello/umbrello/pics/cursor-association.png
new file mode 100644
index 00000000..543a857d
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-association.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-box.png b/umbrello/umbrello/pics/cursor-box.png
new file mode 100644
index 00000000..c4fea53c
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-box.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-branch.png b/umbrello/umbrello/pics/cursor-branch.png
new file mode 100644
index 00000000..a7f04705
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-branch.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-choice-rhomb.png b/umbrello/umbrello/pics/cursor-choice-rhomb.png
new file mode 100644
index 00000000..84db46bd
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-choice-rhomb.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-choice-round.png b/umbrello/umbrello/pics/cursor-choice-round.png
new file mode 100644
index 00000000..5cad8062
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-choice-round.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-class.png b/umbrello/umbrello/pics/cursor-class.png
new file mode 100644
index 00000000..4be74cee
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-class.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-component.png b/umbrello/umbrello/pics/cursor-component.png
new file mode 100644
index 00000000..6b4a814e
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-component.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-composition.png b/umbrello/umbrello/pics/cursor-composition.png
new file mode 100644
index 00000000..f2eabb9c
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-composition.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-containment.png b/umbrello/umbrello/pics/cursor-containment.png
new file mode 100644
index 00000000..824074b6
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-containment.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-datatype.png b/umbrello/umbrello/pics/cursor-datatype.png
new file mode 100644
index 00000000..82f20c16
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-datatype.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-deep-history.png b/umbrello/umbrello/pics/cursor-deep-history.png
new file mode 100644
index 00000000..9d8550d7
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-deep-history.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-dependency.png b/umbrello/umbrello/pics/cursor-dependency.png
new file mode 100644
index 00000000..621ddb6e
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-dependency.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-end_state.png b/umbrello/umbrello/pics/cursor-end_state.png
new file mode 100644
index 00000000..a282e503
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-end_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-entity.png b/umbrello/umbrello/pics/cursor-entity.png
new file mode 100644
index 00000000..dd103eb0
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-entity.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-enum.png b/umbrello/umbrello/pics/cursor-enum.png
new file mode 100644
index 00000000..d4cc0525
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-enum.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-fork.png b/umbrello/umbrello/pics/cursor-fork.png
new file mode 100644
index 00000000..40edc63c
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-fork.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-generalisation.png b/umbrello/umbrello/pics/cursor-generalisation.png
new file mode 100644
index 00000000..fa7a71ab
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-generalisation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-initial_state.png b/umbrello/umbrello/pics/cursor-initial_state.png
new file mode 100644
index 00000000..91ae1b3e
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-initial_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-interface.png b/umbrello/umbrello/pics/cursor-interface.png
new file mode 100644
index 00000000..ad8277d5
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-interface.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-join.png b/umbrello/umbrello/pics/cursor-join.png
new file mode 100644
index 00000000..a485f4a8
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-join.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-junction.png b/umbrello/umbrello/pics/cursor-junction.png
new file mode 100644
index 00000000..be0ddee0
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-junction.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-message-asynchronous.png b/umbrello/umbrello/pics/cursor-message-asynchronous.png
new file mode 100644
index 00000000..549afe0e
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-message-asynchronous.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-message-synchronous.png b/umbrello/umbrello/pics/cursor-message-synchronous.png
new file mode 100644
index 00000000..a6535c12
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-message-synchronous.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-node.png b/umbrello/umbrello/pics/cursor-node.png
new file mode 100644
index 00000000..c4a14312
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-node.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-note.png b/umbrello/umbrello/pics/cursor-note.png
new file mode 100644
index 00000000..6b656a2e
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-note.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-object.png b/umbrello/umbrello/pics/cursor-object.png
new file mode 100644
index 00000000..97e0f7bf
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-object.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-package.png b/umbrello/umbrello/pics/cursor-package.png
new file mode 100644
index 00000000..afdbdbbe
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-package.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-relationship.png b/umbrello/umbrello/pics/cursor-relationship.png
new file mode 100644
index 00000000..5c4d27a3
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-relationship.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-shallow-history.png b/umbrello/umbrello/pics/cursor-shallow-history.png
new file mode 100644
index 00000000..8e3a83b2
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-shallow-history.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-state-fork.png b/umbrello/umbrello/pics/cursor-state-fork.png
new file mode 100644
index 00000000..b1028ef7
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-state-fork.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-text.png b/umbrello/umbrello/pics/cursor-text.png
new file mode 100644
index 00000000..91058cb0
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-text.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-uniassociation.png b/umbrello/umbrello/pics/cursor-uniassociation.png
new file mode 100644
index 00000000..b8980073
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-uniassociation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/cursor-usecase.png b/umbrello/umbrello/pics/cursor-usecase.png
new file mode 100644
index 00000000..d91d5b40
--- /dev/null
+++ b/umbrello/umbrello/pics/cursor-usecase.png
Binary files differ
diff --git a/umbrello/umbrello/pics/datatype.png b/umbrello/umbrello/pics/datatype.png
new file mode 100644
index 00000000..cce13889
--- /dev/null
+++ b/umbrello/umbrello/pics/datatype.png
Binary files differ
diff --git a/umbrello/umbrello/pics/deep-history.png b/umbrello/umbrello/pics/deep-history.png
new file mode 100644
index 00000000..01b9d64d
--- /dev/null
+++ b/umbrello/umbrello/pics/deep-history.png
Binary files differ
diff --git a/umbrello/umbrello/pics/dependency.png b/umbrello/umbrello/pics/dependency.png
new file mode 100644
index 00000000..0cd1a323
--- /dev/null
+++ b/umbrello/umbrello/pics/dependency.png
Binary files differ
diff --git a/umbrello/umbrello/pics/end_state.png b/umbrello/umbrello/pics/end_state.png
new file mode 100644
index 00000000..ac78110c
--- /dev/null
+++ b/umbrello/umbrello/pics/end_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/entity.png b/umbrello/umbrello/pics/entity.png
new file mode 100644
index 00000000..2983c1db
--- /dev/null
+++ b/umbrello/umbrello/pics/entity.png
Binary files differ
diff --git a/umbrello/umbrello/pics/enum.png b/umbrello/umbrello/pics/enum.png
new file mode 100644
index 00000000..d4b9fcd8
--- /dev/null
+++ b/umbrello/umbrello/pics/enum.png
Binary files differ
diff --git a/umbrello/umbrello/pics/fork.png b/umbrello/umbrello/pics/fork.png
new file mode 100644
index 00000000..abb0649b
--- /dev/null
+++ b/umbrello/umbrello/pics/fork.png
Binary files differ
diff --git a/umbrello/umbrello/pics/generalisation.png b/umbrello/umbrello/pics/generalisation.png
new file mode 100644
index 00000000..2ea9d66d
--- /dev/null
+++ b/umbrello/umbrello/pics/generalisation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/initial_state.png b/umbrello/umbrello/pics/initial_state.png
new file mode 100644
index 00000000..d5d6f4f3
--- /dev/null
+++ b/umbrello/umbrello/pics/initial_state.png
Binary files differ
diff --git a/umbrello/umbrello/pics/interface.png b/umbrello/umbrello/pics/interface.png
new file mode 100644
index 00000000..66d52761
--- /dev/null
+++ b/umbrello/umbrello/pics/interface.png
Binary files differ
diff --git a/umbrello/umbrello/pics/join.png b/umbrello/umbrello/pics/join.png
new file mode 100644
index 00000000..0582a7dc
--- /dev/null
+++ b/umbrello/umbrello/pics/join.png
Binary files differ
diff --git a/umbrello/umbrello/pics/junction.png b/umbrello/umbrello/pics/junction.png
new file mode 100644
index 00000000..ee131fa2
--- /dev/null
+++ b/umbrello/umbrello/pics/junction.png
Binary files differ
diff --git a/umbrello/umbrello/pics/message-asynchronous.png b/umbrello/umbrello/pics/message-asynchronous.png
new file mode 100644
index 00000000..21eb52f7
--- /dev/null
+++ b/umbrello/umbrello/pics/message-asynchronous.png
Binary files differ
diff --git a/umbrello/umbrello/pics/message-synchronous.png b/umbrello/umbrello/pics/message-synchronous.png
new file mode 100644
index 00000000..0567346d
--- /dev/null
+++ b/umbrello/umbrello/pics/message-synchronous.png
Binary files differ
diff --git a/umbrello/umbrello/pics/node.png b/umbrello/umbrello/pics/node.png
new file mode 100644
index 00000000..6a12d3a1
--- /dev/null
+++ b/umbrello/umbrello/pics/node.png
Binary files differ
diff --git a/umbrello/umbrello/pics/note.png b/umbrello/umbrello/pics/note.png
new file mode 100644
index 00000000..11bc3dd9
--- /dev/null
+++ b/umbrello/umbrello/pics/note.png
Binary files differ
diff --git a/umbrello/umbrello/pics/object.png b/umbrello/umbrello/pics/object.png
new file mode 100644
index 00000000..eb246070
--- /dev/null
+++ b/umbrello/umbrello/pics/object.png
Binary files differ
diff --git a/umbrello/umbrello/pics/package.png b/umbrello/umbrello/pics/package.png
new file mode 100644
index 00000000..8f35b7c2
--- /dev/null
+++ b/umbrello/umbrello/pics/package.png
Binary files differ
diff --git a/umbrello/umbrello/pics/relationship.png b/umbrello/umbrello/pics/relationship.png
new file mode 100644
index 00000000..8154868e
--- /dev/null
+++ b/umbrello/umbrello/pics/relationship.png
Binary files differ
diff --git a/umbrello/umbrello/pics/shallow-history.png b/umbrello/umbrello/pics/shallow-history.png
new file mode 100644
index 00000000..7d871cc1
--- /dev/null
+++ b/umbrello/umbrello/pics/shallow-history.png
Binary files differ
diff --git a/umbrello/umbrello/pics/sources/actor.svg b/umbrello/umbrello/pics/sources/actor.svg
new file mode 100644
index 00000000..ae4a2d81
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/actor.svg
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="actor.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0000000"
+ inkscape:cx="-134.65454"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <g
+ id="g1190">
+ <path
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;"
+ d="M 25.093750,44.875000 L 29.375000,70.812500 L 75.375000,92.968750 L 74.906250,105.96875 L 9.4375000,130.71875 L 39.312500,151.71875 L 77.468750,118.50000 L 83.156250,118.43750 L 127.21875,152.31250 L 153.81250,127.56250 L 86.187500,106.68750 L 86.625000,93.218750 L 129.62500,88.812500 L 136.31250,62.625000 L 86.500000,81.250000 L 86.187500,55.250000 L 74.937500,55.375000 L 75.218750,78.562500 L 25.093750,44.875000 z "
+ id="path972"
+ sodipodi:nodetypes="ccccccccccccccccccc" />
+ <g
+ id="g909"
+ transform="matrix(0.813839,0.000000,0.000000,1.000000,22.06356,-5.625000)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:10.800957;stroke-dasharray:none;"
+ id="path863"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.841497,0.000000,0.000000,0.838191,19.68138,6.062272)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path864"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.741224,0.000000,0.000000,0.702062,25.43390,11.29160)" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/aggregation.svg b/umbrello/umbrello/pics/sources/aggregation.svg
new file mode 100644
index 00000000..7d9fe672
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/aggregation.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="aggregation.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="-0.86529595"
+ y1="1.3691810"
+ x2="0.76164871"
+ y2="0.21797939" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="12.5539655"
+ inkscape:cy="11.2242088"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ vertgrid="false"
+ horizgrid="false" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:2.41066;stroke-dashoffset:0;"
+ d="M 13.785788 0.093954178 L 13.684594 24.651886 "
+ id="path861"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:2.17721;"
+ id="rect854"
+ width="8.17145930"
+ height="8.02591249"
+ x="-5.79334815"
+ y="-27.37266770"
+ transform="matrix(0.625322,-0.780367,-0.632360,-0.774675,0.000000,0.000000)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:11.0521;"
+ id="rect855"
+ width="32.068266"
+ height="31.499338"
+ x="-12.765084"
+ y="-157.22844"
+ transform="matrix(0.114057,-0.143654,-0.113959,-0.143717,-2.848009,-0.461202)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_bottom.svg b/umbrello/umbrello/pics/sources/align_bottom.svg
new file mode 100644
index 00000000..0f292766
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_bottom.svg
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_bottom.svg">
+ <metadata
+ id="metadata1589">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.750000"
+ inkscape:cy="11.418942"
+ inkscape:window-width="1016"
+ inkscape:window-height="713"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="false"
+ snaptoguides="true"
+ inkscape:guide-bbox="false"
+ inkscape:grid-bbox="false"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g4550">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect863"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_hori_distribute.svg b/umbrello/umbrello/pics/sources/align_hori_distribute.svg
new file mode 100644
index 00000000..f6174a83
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_hori_distribute.svg
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_hori_distribute.svg"
+ inkscape:export-filename="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/align_hori_distribute.png"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-ydpi="72.000000">
+ <metadata
+ id="metadata1589">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="16.000000"
+ inkscape:cx="13.750000"
+ inkscape:cy="13.186709"
+ inkscape:window-width="1016"
+ inkscape:window-height="713"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="false"
+ snaptoguides="true"
+ inkscape:guide-bbox="false"
+ inkscape:grid-bbox="false"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g4550"
+ transform="matrix(0.000000,-1.000000,1.000000,0.000000,0.000000,27.50000)">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect863"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+ <use
+ x="0.0000000"
+ y="0.0000000"
+ xlink:href="#g4550"
+ id="use1412"
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,27.50000)"
+ width="27.500000"
+ height="27.500000" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_hori_middle.svg b/umbrello/umbrello/pics/sources/align_hori_middle.svg
new file mode 100644
index 00000000..4c7b1234
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_hori_middle.svg
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="27.500000px"
+ height="27.500000px"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_vert_distribute.svg">
+ <metadata
+ id="metadata47">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="12.844517"
+ inkscape:cy="16.176523"
+ inkscape:window-width="1016"
+ inkscape:window-height="713"
+ gridspacingy="1.2500000px"
+ gridspacingx="1.2500000px"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="false"
+ snaptoguides="true"
+ inkscape:grid-bbox="false"
+ inkscape:guide-bbox="false"
+ gridoriginy="0.0000000px"
+ gridoriginx="0.0000000px"
+ inkscape:guide-points="false"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ </sodipodi:namedview>
+ <g
+ id="g5975">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path1009"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <rect
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt"
+ id="rect1209"
+ width="2.5000000"
+ height="11.250000"
+ x="12.500000"
+ y="15.000000" />
+ </g>
+ <use
+ x="0.0000000"
+ y="0.0000000"
+ xlink:href="#g5975"
+ id="use5979"
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,27.50000)"
+ width="27.500000"
+ height="27.500000" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_left.svg b/umbrello/umbrello/pics/sources/align_left.svg
new file mode 100644
index 00000000..362e4e34
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_left.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_left.svg">
+ <metadata
+ id="metadata5028">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="16.000000"
+ inkscape:cx="13.797281"
+ inkscape:cy="14.222243"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="true"
+ snaptoguides="true"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g4550"
+ transform="matrix(0.000000,1.000000,-1.000000,0.000000,27.50000,0.000000)">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect4879"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_right.svg b/umbrello/umbrello/pics/sources/align_right.svg
new file mode 100644
index 00000000..8fa3af6e
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_right.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_right.svg">
+ <metadata
+ id="metadata4876">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.797281"
+ inkscape:cy="14.954476"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="true"
+ snaptoguides="true"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g4550"
+ transform="matrix(0.000000,-1.000000,1.000000,0.000000,0.000000,27.50000)">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect4879"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_top.svg b/umbrello/umbrello/pics/sources/align_top.svg
new file mode 100644
index 00000000..e7cec488
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_top.svg
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_top.svg">
+ <metadata
+ id="metadata4677">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.797281"
+ inkscape:cy="16.548827"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="true"
+ snaptoguides="true"
+ inkscape:current-layer="svg1" />
+ <g
+ id="g4550"
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,27.50000)">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect4680"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_vert_distribute.svg b/umbrello/umbrello/pics/sources/align_vert_distribute.svg
new file mode 100644
index 00000000..135eda26
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_vert_distribute.svg
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_vert_distribute.svg"
+ inkscape:export-filename="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/align_hori_distribute.png"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-ydpi="72.000000">
+ <metadata
+ id="metadata1589">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.313709"
+ inkscape:cx="13.750000"
+ inkscape:cy="16.722243"
+ inkscape:window-width="1016"
+ inkscape:window-height="713"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="false"
+ snaptoguides="true"
+ inkscape:guide-bbox="false"
+ inkscape:grid-bbox="false"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="11.048543"
+ id="guide875" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g4550">
+ <rect
+ height="1.0000000"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ id="rect863"
+ width="12.500000"
+ x="7.5000000"
+ y="26.250000" />
+ <g
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,40.00000)"
+ id="g5975">
+ <path
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ id="path1593"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="15.000000"
+ x="12.500000"
+ height="11.250000"
+ width="2.5000000"
+ id="rect1595"
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+ <use
+ x="0.0000000"
+ y="0.0000000"
+ xlink:href="#g4550"
+ id="use1412"
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,27.50000)"
+ width="27.500000"
+ height="27.500000" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/align_vert_middle.svg b/umbrello/umbrello/pics/sources/align_vert_middle.svg
new file mode 100644
index 00000000..b7b62def
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/align_vert_middle.svg
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/dani/Proyectos/umbrello-svn/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="align_vert_middle.svg">
+ <metadata
+ id="metadata1467">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="10.511311"
+ inkscape:cx="11.950527"
+ inkscape:cy="9.8572805"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ showguides="false"
+ snaptoguides="true"
+ inkscape:guide-bbox="false"
+ inkscape:current-layer="svg1">
+ <sodipodi:guide
+ orientation="vertical"
+ position="11.004349"
+ id="guide876" />
+ </sodipodi:namedview>
+ <g
+ id="g5975"
+ transform="matrix(0.000000,1.000000,-1.000000,0.000000,27.50000,0.000000)">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path1470"
+ d="M 13.750000,13.750000 L 8.4000000,19.100000 L 9.1000000,19.800000 L 13.750000,15.200000 L 18.400000,19.800000 L 19.100000,19.100000 L 13.750000,13.750000 z "
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <rect
+ style="font-size:12.000000px;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt"
+ id="rect1472"
+ width="2.5000000"
+ height="11.250000"
+ x="12.500000"
+ y="15.000000" />
+ </g>
+ <use
+ x="0.0000000"
+ y="0.0000000"
+ xlink:href="#g5975"
+ id="use1494"
+ transform="matrix(-1.000000,0.000000,0.000000,-1.000000,27.50000,27.50000)"
+ width="27.500000"
+ height="27.500000" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/anchor.svg b/umbrello/umbrello/pics/sources/anchor.svg
new file mode 100644
index 00000000..27fd26b9
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/anchor.svg
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="anchor.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs857">
+ <linearGradient
+ id="linearGradient858">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop859" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop860" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient861">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop862" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop863" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient864"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient865"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient866" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview867"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="10.6838309"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.25;stroke-dasharray:1.25,1.25;stroke-dashoffset:1.5;"
+ d="M 15.231442 6.8825364 L 21.810285 6.8825364 L 21.810285 6.8957665 "
+ id="path915" />
+ <path
+ style="font-size:12;fill:#f6f600;fill-rule:evenodd;stroke-width:5;"
+ d="M 8.2733326,28.387267 L 8.2733326,124.03331 L 149.01926,124.03331 L 149.01926,81.523954 C 150.50079,49.641942 119.72304,33.000935 97.500000,28.750000 L 8.2733326,28.387267 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.108514,0.000000,0.000000,0.119774,-0.622904,-3.017803)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#fb0000;stroke-width:1.19298;"
+ d="M 0.60632471 0.65846708 L 9.7139922 0.70128454 C 11.312264 0.55373295 14.933205 2.5419716 10.513128 5.275384 C 13.310105 4.9802809 15.174756 4.2425228 15.574325 6.6033484 L 15.603014 11.948649 L 0.60632471 11.948649 L 0.60632471 0.65846708 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;text-anchor:middle;"
+ x="12.4761734"
+ y="21.7533916"
+ id="text838"
+ transform="scale(0.646933,0.508553)"
+ sodipodi:linespacing="100%"><tspan
+ x="12.4761734"
+ y="21.7533913"
+ sodipodi:role="line"
+ id="tspan840">XYZ</tspan></text>
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.24954;"
+ id="rect869"
+ width="13.74189394"
+ height="11.15417004"
+ x="13.18875200"
+ y="15.73248386" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect871"
+ width="12.38913868"
+ height="3.31526423"
+ ry="0"
+ x="13.81419851"
+ y="16.25072289" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;stroke-width:1pt;font-family:Bitstream Vera Sans;"
+ x="26.9685458"
+ y="63.8042984"
+ id="text873"
+ transform="scale(0.510825,0.298872)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.449315;"
+ d="M 13.821664 19.408703 L 26.727376 19.408703 "
+ id="path842" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.449315;"
+ d="M 13.736684 22.820721 L 26.642397 22.820721 "
+ id="path845" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect878"
+ width="12.27865329"
+ height="3.04870009"
+ ry="0"
+ x="13.82501222"
+ y="19.53512001" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect879"
+ width="12.27865324"
+ height="2.95871878"
+ ry="0"
+ x="13.82924364"
+ y="23.11286545" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.25;stroke-dasharray:1.25,1.25;stroke-dashoffset:1.5;"
+ d="M 21.529111 5.6671972 L 21.92077 5.6671972 L 21.92077 15.845087 "
+ id="path884" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/andline.svg b/umbrello/umbrello/pics/sources/andline.svg
new file mode 100644
index 00000000..20948588
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/andline.svg
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="89.999504"
+ inkscape:export-xdpi="89.999504"
+ inkscape:export-filename="F:\pics\andline.png"
+ id="svg1"
+ height="22.000000px"
+ width="22.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="andline.svg"
+ sodipodi:docbase="F:\pics">
+ <metadata
+ id="metadata39">
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ rdf:about=""
+ id="Work41">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ id="type43"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title
+ id="title1">And Line</dc:title>
+ <cc:license
+ id="license2"
+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+ <dc:date
+ id="date12">2005-02-28</dc:date>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/"
+ id="License3">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction"
+ id="permits4" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution"
+ id="permits5" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice"
+ id="requires6" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks"
+ id="permits7" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike"
+ id="requires8" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/SourceCode"
+ id="requires9" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.00000000"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1035"
+ inkscape:window-height="691"
+ inkscape:zoom="23.500000"
+ inkscape:cx="11.000000"
+ inkscape:cy="11.000000"
+ inkscape:window-x="1918"
+ inkscape:window-y="129"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3" />
+ <g
+ transform="translate(-0.173293,-6.209109e-2)"
+ id="g11">
+ <rect
+ rx="5.0000000"
+ ry="5.0000000"
+ y="3.9911418"
+ x="1.7973769"
+ height="14.384930"
+ width="18.709280"
+ id="rect182"
+ style="fill:#e6ca25;fill-opacity:1.0000000;stroke:#908787;stroke-width:1.8478020;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path183"
+ d="M 11.189410,18.008550 C 11.181540,1.5742100 11.181540,1.5742100 11.181540,1.5742100 L 11.181540,1.5742100"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.5000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:1.5000000 4.5000000 ;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/artifact.svg b/umbrello/umbrello/pics/sources/artifact.svg
new file mode 100644
index 00000000..4f78d3c6
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/artifact.svg
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="artifact.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274169"
+ inkscape:cx="13.4437273"
+ inkscape:cy="10.2499949"
+ inkscape:window-width="1008"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#f6f600;fill-rule:evenodd;stroke-width:5;"
+ d="M 8.2733326,28.387267 L 8.2733326,124.03331 L 149.01926,124.03331 L 149.01926,81.523954 C 150.50079,49.641942 119.72304,33.000935 97.500000,28.750000 L 8.2733326,28.387267 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.187394,0.000000,0.000000,0.275027,-0.932117,-7.199541)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#fb0000;stroke-width:5;"
+ d="M 8.2733326,28.387267 L 93.750000,28.750000 C 108.75000,27.500000 142.73301,44.343588 101.25000,67.500000 C 127.50000,65.000000 145.00000,58.750000 148.75000,78.750000 L 149.01926,124.03331 L 8.2733326,124.03331 L 8.2733326,28.387267 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc"
+ transform="matrix(0.187394,0.000000,0.000000,0.275027,-0.932117,-7.199541)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/association.svg b/umbrello/umbrello/pics/sources/association.svg
new file mode 100644
index 00000000..a51cb414
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/association.svg
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="association.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ff0000;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="0.096153848"
+ y1="0.60000002"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="14.4343441"
+ inkscape:cy="11.6181504"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect737"
+ width="2.48592234"
+ height="27.40038872"
+ x="12.54009754"
+ y="0.09961223" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/asynchro.svg b/umbrello/umbrello/pics/sources/asynchro.svg
new file mode 100644
index 00000000..7bb8054e
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/asynchro.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="asynchro.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274169"
+ inkscape:cx="12.5595019"
+ inkscape:cy="9.96780389"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <path
+ style="font-size:12;fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:12.5;"
+ d="M 23.25456 20.532266 L 17.245615 18.773952 L 17.395532 22.409137 L 23.25456 20.532266 z "
+ id="path875"
+ sodipodi:nodetypes="cccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:normal;stroke-width:1pt;font-family:Bitstream Vera Sans;"
+ x="-0.14150786"
+ y="14.0554683"
+ id="text1033"
+ transform="scale(1.409838,1.034795)"><tspan
+ id="tspan1034">f(x)</tspan></text>
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect923"
+ width="16.51757205"
+ height="1.32582528"
+ x="-0.05524272"
+ y="20.04223250" />
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.14332;"
+ d="M 25.48674 20.457131 L 16.806844 18.331919 L 16.858498 23.071545 L 25.48674 20.457131 z "
+ id="path874"
+ sodipodi:nodetypes="cccc" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/box.svg b/umbrello/umbrello/pics/sources/box.svg
new file mode 100644
index 00000000..9fd9bebd
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/box.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="box.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.3508714"
+ inkscape:cy="11.0070359"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.22432;"
+ id="rect837"
+ width="23.71333344"
+ height="23.69648009"
+ x="1.95820236"
+ y="1.89102376" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/branch.svg b/umbrello/umbrello/pics/sources/branch.svg
new file mode 100644
index 00000000..939c12dc
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/branch.svg
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="branch_merge.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <g
+ id="g900"
+ transform="matrix(1.033419,0.000000,0.000000,1.028243,-0.413036,-0.304948)">
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.0940815;stroke-dasharray:none;"
+ id="rect854"
+ width="41.480559"
+ height="40.741544"
+ x="74.760017"
+ y="-59.764663"
+ transform="matrix(1.438607,1.462473,-1.437488,1.463230,-116.1987,-4.837583)" />
+ <rect
+ style="fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:11.052127;"
+ id="rect855"
+ width="72.749743"
+ height="71.403139"
+ x="72.801592"
+ y="-35.372109"
+ transform="matrix(0.710624,0.703572,-0.699330,0.714799,0.000000,0.000000)"
+ ry="0.0000000" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/choice-rhomb.svg b/umbrello/umbrello/pics/sources/choice-rhomb.svg
new file mode 100644
index 00000000..9f3014f8
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/choice-rhomb.svg
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="22.000000px"
+ width="22.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="choice-rhomb.svg"
+ sodipodi:docbase="F:\pics">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.00000000"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1012"
+ inkscape:window-height="579"
+ inkscape:zoom="14.727273"
+ inkscape:cx="13.750000"
+ inkscape:cy="13.750000"
+ inkscape:window-x="1811"
+ inkscape:window-y="299"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <rect
+ style="fill:#00f5c5;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.6613264;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000"
+ id="rect1"
+ width="12.072264"
+ height="12.027812"
+ x="9.4153738"
+ y="-5.0952759"
+ transform="matrix(0.746765,0.665088,-0.737169,0.675708,0.000000,0.000000)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/choice-round.svg b/umbrello/umbrello/pics/sources/choice-round.svg
new file mode 100644
index 00000000..ecb862e1
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/choice-round.svg
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="choice-round.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="22.000000px"
+ height="22.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="299"
+ inkscape:window-x="1811"
+ inkscape:cy="11.000000"
+ inkscape:cx="11.000000"
+ inkscape:zoom="18.409091"
+ inkscape:window-height="579"
+ inkscape:window-width="692"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker1"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path237"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker258"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path259"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker255"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path256"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker252"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path253"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker249"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path250"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path238"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-383.3103,-518.6704)"
+ id="g190">
+ <path
+ transform="matrix(2.612069,0.000000,0.000000,2.612069,-637.8584,-857.8712)"
+ d="M 398.73051 531.23523 A 3.5248239 3.5248239 0 1 1 391.68086,531.23523 A 3.5248239 3.5248239 0 1 1 398.73051 531.23523 z"
+ sodipodi:ry="3.5248239"
+ sodipodi:rx="3.5248239"
+ sodipodi:cy="531.23523"
+ sodipodi:cx="395.20569"
+ id="path45"
+ style="fill:#00f5c5;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.77524751;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ sodipodi:type="arc" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text179"
+ y="534.39539"
+ x="388.94608"
+ style="font-size:13.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial;text-anchor:start;writing-mode:lr-tb"
+ xml:space="preserve"><tspan
+ y="534.39539"
+ x="388.94608"
+ id="tspan180"
+ sodipodi:role="line">C</tspan></text>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/class.svg b/umbrello/umbrello/pics/sources/class.svg
new file mode 100644
index 00000000..03124a31
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/class.svg
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="class.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="17.1043724"
+ inkscape:cx="12.2503213"
+ inkscape:cy="6.66230400"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ snaptogrid="false"
+ showgrid="true" />
+ <g
+ id="g615">
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.23963;"
+ id="rect837"
+ width="26.24992934"
+ height="26.18856802"
+ x="0.66534913"
+ y="0.71917963" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.99192419"
+ height="7.33014917"
+ ry="0"
+ x="1.21161342"
+ y="1.36787295" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:normal;stroke-width:1pt;font-family:Bitstream Vera Sans;"
+ x="2.59171310"
+ y="11.3147535"
+ id="text838"
+ transform="scale(0.933669,0.722645)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.25;"
+ d="M 1.1533278 9.3908034 L 26.731652 9.3908034 "
+ id="path842" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.51621;stroke-dasharray:none;"
+ d="M 12.845456,96.712602 L 148.81938,96.712602"
+ id="path845"
+ transform="matrix(0.188112,0.000000,0.000000,0.195620,-1.468156,-1.975509)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect846"
+ width="24.77268353"
+ height="6.20569849"
+ ry="0"
+ x="1.26971898"
+ y="10.02771664" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect847"
+ width="24.99192296"
+ height="8.63132715"
+ ry="0"
+ x="1.31451130"
+ y="17.58032418" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/component.svg b/umbrello/umbrello/pics/sources/component.svg
new file mode 100644
index 00000000..514cc765
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/component.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="component.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="63.313473"
+ inkscape:cy="66.872360"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:7.5000000;stroke-dasharray:none;"
+ id="rect837"
+ width="117.17106"
+ height="134.99545"
+ x="33.896471"
+ y="12.776533" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect825"
+ width="108.93759"
+ height="127.71573"
+ ry="0.0000000"
+ x="38.080124"
+ y="16.221853" />
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-dasharray:none;"
+ id="rect849"
+ width="48.366001"
+ height="19.281309"
+ x="7.6920013"
+ y="46.921844" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect850"
+ width="40.187591"
+ height="14.590707"
+ ry="0.0000000"
+ x="10.218712"
+ y="48.954636" />
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-dasharray:none;"
+ id="rect851"
+ width="48.366001"
+ height="19.281309"
+ x="8.0044994"
+ y="95.984344" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect852"
+ width="40.187592"
+ height="14.590707"
+ ry="0.0000000"
+ x="10.531210"
+ y="98.017136" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/composition.svg b/umbrello/umbrello/pics/sources/composition.svg
new file mode 100644
index 00000000..04bec885
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/composition.svg
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="composition.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient892"
+ x1="1.7810326"
+ y1="-0.77207518"
+ x2="-0.77287894"
+ y2="1.0071716"
+ spreadMethod="pad" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="78.777267"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:12.951884;stroke-dashoffset:0.0000000;"
+ d="M 83.854692,3.1467970 L 83.910715,142.25704"
+ id="path861"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:11.858918;"
+ id="rect854"
+ width="44.507047"
+ height="43.717121"
+ x="-20.046628"
+ y="-162.59821"
+ transform="matrix(0.588591,-0.808431,-0.588093,-0.808793,0.000000,0.000000)" />
+ <rect
+ style="fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:11.052127;"
+ id="rect855"
+ width="41.237688"
+ height="40.506848"
+ x="-15.112020"
+ y="-162.64811"
+ transform="matrix(0.566729,-0.823905,-0.566229,-0.824248,0.000000,0.000000)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/containment.svg b/umbrello/umbrello/pics/sources/containment.svg
new file mode 100644
index 00000000..7d33113b
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/containment.svg
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="containment.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="10.8971871"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ vertgrid="false"
+ showgrid="true" />
+ <path
+ sodipodi:type="arc"
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:10.0339;stroke-dasharray:none;"
+ id="path851"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.172334,0.000000,0.000000,-0.171503,2.790291,27.93712)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2336;"
+ d="M 8.6805098 21.368615 L 18.435554 21.337956 "
+ id="path853"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.32889;"
+ d="M 13.745542 26.675526 L 13.810379 15.306314 "
+ id="path854"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="font-size:12;fill:url(#linearGradient892);fill-opacity:0.75;fill-rule:evenodd;stroke-width:10;"
+ id="path858"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.143170,0.000000,0.000000,-0.145251,4.723210,26.90351)" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect701"
+ width="2.48592252"
+ height="15.19174844"
+ x="12.54009724"
+ y="0.09961176" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-andline.svg b/umbrello/umbrello/pics/sources/cursor-andline.svg
new file mode 100644
index 00000000..fc315835
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-andline.svg
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="32.000000px"
+ width="32.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="cursor-andline.svg"
+ sodipodi:docbase="F:\pics"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1111"
+ inkscape:window-height="870"
+ inkscape:zoom="21.750000"
+ inkscape:cx="16.000000"
+ inkscape:cy="16.000000"
+ inkscape:window-x="1861"
+ inkscape:window-y="104"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker12"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path455"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker11"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path454"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker553"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path554"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker556"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path557"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker25"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path26"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker23"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path24"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker21"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path22"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker19"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path20"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker17"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path18"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker15"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path16"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker13"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path14"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker52"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path53"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker50"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path51"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker48"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path49"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker46"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path47"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker44"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path45"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker42"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path43"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker40"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path41"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker20"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path21"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker18"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path19"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker16"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path17"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker14"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path15"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.8806,-513.0186)"
+ id="g191">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ id="path85" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ id="path347" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ id="path348" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ id="path349" />
+ <rect
+ rx="5.0000000"
+ ry="5.0000000"
+ y="528.88312"
+ x="379.64066"
+ height="14.384930"
+ width="18.709280"
+ id="rect182"
+ style="opacity:0.59999990;fill:#e6ca25;fill-opacity:1.0000000;stroke:#908787;stroke-width:1.8478020;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path183"
+ d="M 389.03268,542.60983 C 389.02481,526.17549 389.02481,526.17549 389.02481,526.17549 L 389.02481,526.17549"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.5000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:1.5000000 4.5000000 ;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-choice-rhomb.svg b/umbrello/umbrello/pics/sources/cursor-choice-rhomb.svg
new file mode 100644
index 00000000..81277a0c
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-choice-rhomb.svg
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="32.000000px"
+ width="32.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="cursor-choice-rhomb.svg"
+ sodipodi:docbase="F:\umbrello\pics"
+ inkscape:export-filename="F:\umbrello\pics\cursor-junction-temp.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="1.0000000"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1111"
+ inkscape:window-height="870"
+ inkscape:zoom="21.750000"
+ inkscape:cx="16.000000"
+ inkscape:cy="16.000000"
+ inkscape:window-x="1861"
+ inkscape:window-y="104"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker12"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path455"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker11"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path454"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker553"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path554"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker556"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path557"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker25"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path26"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker23"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path24"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker21"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path22"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker19"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path20"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker17"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path18"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker15"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path16"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker13"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path14"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker52"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path53"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker50"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path51"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker48"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path49"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker46"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path47"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker44"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path45"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker42"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path43"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker40"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path41"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="cursor">
+ <g
+ id="g197">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 9.4805000,0.52068000 C 9.4805000,8.5252100 9.4823300,8.5252100 9.4823300,8.5252100"
+ id="path347" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 8.4962800,9.5391100 C 0.49175000,9.5391100 0.49175000,9.5409400 0.49175000,9.5409400"
+ id="path348" />
+ <rect
+ style="fill:#00f5c5;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.6613266;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;opacity:1.0000000"
+ id="rect1"
+ width="12.072264"
+ height="12.027816"
+ x="24.273464"
+ y="-3.6065087"
+ transform="matrix(0.746765,0.665088,-0.737169,0.675708,0.000000,0.000000)" />
+ </g>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 9.5086200,10.552770 C 9.5086200,18.557300 9.5104500,18.557300 9.5104500,18.557300"
+ id="path85" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 18.485910,9.5018600 C 10.481380,9.5018600 10.481380,9.5036900 10.481380,9.5036900"
+ id="path349" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-choice-round.svg b/umbrello/umbrello/pics/sources/cursor-choice-round.svg
new file mode 100644
index 00000000..747a511f
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-choice-round.svg
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="cursor-choice-round.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="32.000000px"
+ height="32.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:document-units="pt"
+ inkscape:current-layer="svg1"
+ inkscape:window-y="104"
+ inkscape:window-x="1861"
+ inkscape:cy="16.000000"
+ inkscape:cx="16.000000"
+ inkscape:zoom="21.750000"
+ inkscape:window-height="870"
+ inkscape:window-width="1111"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker1"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path237"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker258"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path259"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker255"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path256"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker252"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path253"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker249"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path250"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path238"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker12"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path455"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker11"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path454"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker553"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path554"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker556"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path557"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker25"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path26"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker23"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path24"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker21"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path22"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker19"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path20"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker17"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path18"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker15"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path16"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker13"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path14"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9488,-513.0081)"
+ id="g193">
+ <path
+ id="path85"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path347"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path348"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ id="g29"
+ transform="translate(-0.290740,-0.387653)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#00f5c5;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.77524751;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="path45"
+ sodipodi:cx="395.20569"
+ sodipodi:cy="531.23523"
+ sodipodi:rx="3.5248239"
+ sodipodi:ry="3.5248239"
+ d="M 398.73051 531.23523 A 3.5248239 3.5248239 0 1 1 391.68086,531.23523 A 3.5248239 3.5248239 0 1 1 398.73051 531.23523 z"
+ transform="matrix(2.612069,0.000000,0.000000,2.612069,-643.0990,-853.1921)" />
+ <text
+ xml:space="preserve"
+ style="font-size:13.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial;text-anchor:start;writing-mode:lr-tb"
+ x="383.70551"
+ y="539.07446"
+ id="text179"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan180"
+ x="383.70551"
+ y="539.07446">C</tspan></text>
+ </g>
+ <path
+ id="path349"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-deep-history.svg b/umbrello/umbrello/pics/sources/cursor-deep-history.svg
new file mode 100644
index 00000000..2cb89831
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-deep-history.svg
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="cursor-deep-history.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="32.000000px"
+ height="32.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="104"
+ inkscape:window-x="1861"
+ inkscape:cy="16.000000"
+ inkscape:cx="16.000000"
+ inkscape:zoom="21.750000"
+ inkscape:window-height="870"
+ inkscape:window-width="1111"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker1"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path237"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker258"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path259"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker255"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path256"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker252"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path253"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker249"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path250"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path238"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9537,-512.9979)"
+ id="g194">
+ <path
+ id="path85"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path347"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path348"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path349"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ id="g91"
+ transform="translate(-4.030134,5.404877)">
+ <path
+ d="M 402.82519,529.87519 C 402.82519,534.58139 399.02964,538.39651 394.34760,538.39651 C 389.66555,538.39651 385.87000,534.58139 385.87000,529.87519 C 385.87000,525.16900 389.66555,521.35388 394.34760,521.35388 C 399.02964,521.35388 402.82519,525.16900 402.82519,529.87519 z "
+ style="fill:none;stroke:#d30000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="path21" />
+ <text
+ x="387.91888"
+ y="535.10229"
+ style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr-tb"
+ id="text111"
+ xml:space="preserve"
+ sodipodi:linespacing="100%"><tspan
+ x="387.91888"
+ y="535.10229"
+ sodipodi:role="line"
+ id="tspan1">H</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:11.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial;text-anchor:start;writing-mode:lr-tb"
+ x="396.16739"
+ y="532.53491"
+ id="text2"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3"
+ x="396.16739"
+ y="532.53491">*</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-join.svg b/umbrello/umbrello/pics/sources/cursor-join.svg
new file mode 100644
index 00000000..f84032bb
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-join.svg
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="cursor-join.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="32.000000px"
+ height="32.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="104"
+ inkscape:window-x="1861"
+ inkscape:cy="16.000000"
+ inkscape:cx="16.000000"
+ inkscape:zoom="21.750000"
+ inkscape:window-height="870"
+ inkscape:window-width="1111"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker200"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path201"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker198"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path199"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker196"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path197"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker1"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path237"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker258"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path259"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker255"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path256"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker252"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path253"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker249"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path250"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path238"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker12"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path455"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker11"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path454"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker553"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path554"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker556"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path557"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9454,-513.0373)"
+ id="g195">
+ <path
+ id="path85"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path347"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path348"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path349"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path15"
+ d="M 389.38956,527.73586 C 389.39744,543.12488 389.39744,543.12488 389.39744,543.12488 L 389.39744,543.12488"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.0250001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path16"
+ d="M 390.87505,535.72872 L 396.61921,535.72872"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path555"
+ d="M 379.68711,540.10437 L 385.43127,540.10437"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path558"
+ d="M 379.68711,530.50226 L 385.43127,530.50226"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-junction.svg b/umbrello/umbrello/pics/sources/cursor-junction.svg
new file mode 100644
index 00000000..73154f52
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-junction.svg
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="32.000000px"
+ width="32.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="cursor-junction.svg"
+ sodipodi:docbase="F:\pics"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="810"
+ inkscape:window-height="682"
+ inkscape:zoom="15.875000"
+ inkscape:cx="16.000000"
+ inkscape:cy="16.000000"
+ inkscape:window-x="1861"
+ inkscape:window-y="104"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker211"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path212"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker209"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path210"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker207"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path208"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker205"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path206"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker203"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path204"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9140,-513.0387)"
+ id="g202">
+ <g
+ id="g350"
+ transform="translate(-3.391966,4.458013)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:0.20000000;stroke-miterlimit:4.0000000;stroke-opacity:0.68161434"
+ id="path45"
+ sodipodi:cx="395.20569"
+ sodipodi:cy="531.23523"
+ sodipodi:rx="3.5248239"
+ sodipodi:ry="3.5248239"
+ d="M 398.73051 531.23523 A 3.5248239 3.5248239 0 1 1 391.68086,531.23523 A 3.5248239 3.5248239 0 1 1 398.73051 531.23523 z"
+ transform="translate(-0.668501,-2.243091)" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)"
+ d="M 386.54045,519.66500 L 390.14727,524.34150"
+ id="path134" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)"
+ d="M 402.60019,519.65950 L 398.99337,524.33600"
+ id="path251" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)"
+ d="M 394.57026,531.49266 L 394.66966,537.39766"
+ id="path254" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)"
+ d="M 396.98786,531.45492 L 400.59468,536.13142"
+ id="path260" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)"
+ d="M 392.59468,531.45492 L 388.98786,536.13142"
+ id="path435" />
+ </g>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ id="path85" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ id="path347" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ id="path348" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ id="path349" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-shallow-history.svg b/umbrello/umbrello/pics/sources/cursor-shallow-history.svg
new file mode 100644
index 00000000..8f840682
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-shallow-history.svg
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="32.000000px"
+ width="32.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="cursor-shallow-history.svg"
+ sodipodi:docbase="F:\pics"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1111"
+ inkscape:window-height="870"
+ inkscape:zoom="21.750000"
+ inkscape:cx="16.000000"
+ inkscape:cy="16.000000"
+ inkscape:window-x="1861"
+ inkscape:window-y="104"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9487,-513.0004)"
+ id="g213">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ id="path85" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ id="path347" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ id="path348" />
+ <g
+ id="g15"
+ transform="translate(-0.484567,0.193827)">
+ <path
+ id="path12"
+ style="fill:none;stroke:#d30000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 399.08565,535.18315 C 399.08565,539.88935 395.29010,543.70447 390.60806,543.70447 C 385.92601,543.70447 382.13046,539.88935 382.13046,535.18315 C 382.13046,530.47696 385.92601,526.66184 390.60806,526.66184 C 395.29010,526.66184 399.08565,530.47696 399.08565,535.18315 z " />
+ <text
+ xml:space="preserve"
+ id="text13"
+ style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr-tb"
+ y="539.54547"
+ x="385.79855"
+ sodipodi:linespacing="100%"><tspan
+ x="385.79855"
+ y="539.54547"
+ sodipodi:role="line"
+ id="tspan22">H</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ id="path349" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/cursor-state-fork.svg b/umbrello/umbrello/pics/sources/cursor-state-fork.svg
new file mode 100644
index 00000000..92f6fa29
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/cursor-state-fork.svg
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="32.000000px"
+ width="32.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="cursor-state-fork.svg"
+ sodipodi:docbase="F:\pics"
+ inkscape:export-filename="F:\pics\cursor-junction.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ rdf:about=""
+ id="Work19">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ id="type21"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1111"
+ inkscape:window-height="870"
+ inkscape:zoom="21.750000"
+ inkscape:cx="16.000000"
+ inkscape:cy="16.000000"
+ inkscape:window-x="1861"
+ inkscape:window-y="104"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <marker
+ style="overflow:visible;"
+ id="marker219"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path220"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker217"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path218"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker215"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path216"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker1"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path2"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Mend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(0.6) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path237"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker258"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path259"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker255"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path256"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker252"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path253"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker249"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path250"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow2Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="scale(1.1) rotate(180) translate(-5,0)"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ id="path238"
+ sodipodi:nodetypes="cccc" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker12"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path455"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker11"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path454"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker553"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path554"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker556"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path557"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-367.9252,-513.0373)"
+ id="g214">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.45252,523.54977 C 377.45252,531.55430 377.45435,531.55430 377.45435,531.55430"
+ id="path85" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 377.42440,513.51768 C 377.42440,521.52221 377.42623,521.52221 377.42623,521.52221"
+ id="path347" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 376.44018,522.53611 C 368.43565,522.53611 368.43565,522.53794 368.43565,522.53794"
+ id="path348" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 386.42981,522.49886 C 378.42528,522.49886 378.42528,522.50069 378.42528,522.50069"
+ id="path349" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.0250001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 389.38956,527.73586 C 389.39744,543.12488 389.39744,543.12488 389.39744,543.12488 L 389.39744,543.12488"
+ id="path15" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 379.55344,535.63181 L 385.29760,535.63181"
+ id="path16" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 391.20254,540.10437 L 396.94670,540.10437"
+ id="path555" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 391.20254,530.50226 L 396.94670,530.50226"
+ id="path558" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/datatype.svg b/umbrello/umbrello/pics/sources/datatype.svg
new file mode 100644
index 00000000..b6c1f36c
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/datatype.svg
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="datatype.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="10.0143610"
+ inkscape:cy="10.8012676"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="175.11363"
+ y="-1.7772827" />
+ <g
+ id="g751">
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.21179;"
+ id="rect837"
+ width="26.27943831"
+ height="13.71849245"
+ x="0.61992770"
+ y="6.90882921" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.87571098"
+ height="12.43472181"
+ ry="0"
+ x="1.31112826"
+ y="7.51523018" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;text-anchor:middle;font-weight:bold;font-style:normal;writing-mode:lr;"
+ x="15.9604130"
+ y="20.7664032"
+ id="text838"
+ transform="scale(0.868102,0.571713)"
+ sodipodi:linespacing="100%"><tspan
+ x="15.9604130"
+ y="20.7664032"
+ sodipodi:role="line"
+ id="tspan747">«xy»</tspan><tspan
+ x="15.9604130"
+ y="32.7664032"
+ sodipodi:role="line"
+ id="tspan749">ABC</tspan></text>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/deep-history.svg b/umbrello/umbrello/pics/sources/deep-history.svg
new file mode 100644
index 00000000..913cb3f4
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/deep-history.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg1"
+ height="22.000000px"
+ width="22.000000px"
+ y="0.00000000"
+ x="0.00000000"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.40+cvs"
+ sodipodi:docname="deep-history.svg"
+ sodipodi:docbase="F:\pics">
+ <metadata
+ id="metadata39">
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ rdf:about=""
+ id="Work41">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ id="type43"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1035"
+ inkscape:window-height="691"
+ inkscape:zoom="23.500000"
+ inkscape:cx="11.000000"
+ inkscape:cy="11.000000"
+ inkscape:window-x="1806"
+ inkscape:window-y="316"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3" />
+ <g
+ transform="translate(-383.3264,-518.8539)"
+ id="g91">
+ <path
+ id="path21"
+ style="fill:none;stroke:#d30000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 402.82519,529.87519 C 402.82519,534.58139 399.02964,538.39651 394.34760,538.39651 C 389.66555,538.39651 385.87000,534.58139 385.87000,529.87519 C 385.87000,525.16900 389.66555,521.35388 394.34760,521.35388 C 399.02964,521.35388 402.82519,525.16900 402.82519,529.87519 z " />
+ <text
+ sodipodi:linespacing="100%"
+ xml:space="preserve"
+ id="text111"
+ style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr-tb"
+ y="535.10229"
+ x="387.91888"><tspan
+ id="tspan1"
+ sodipodi:role="line"
+ y="535.10229"
+ x="387.91888">H</tspan></text>
+ <text
+ sodipodi:linespacing="100%"
+ id="text2"
+ y="532.53491"
+ x="396.16739"
+ style="font-size:11.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial;text-anchor:start;writing-mode:lr-tb"
+ xml:space="preserve"><tspan
+ y="532.53491"
+ x="396.16739"
+ id="tspan3"
+ sodipodi:role="line">*</tspan></text>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/dependency.svg b/umbrello/umbrello/pics/sources/dependency.svg
new file mode 100644
index 00000000..8a98444a
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/dependency.svg
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="dependency.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="10.5907033"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:2.5;stroke-dasharray:5,2.5;stroke-dashoffset:0;"
+ d="M 13.748607 27.494737 L 13.746247 2.0126593 "
+ id="path861"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.74;"
+ d="M 8.9275346 10.500689 L 13.717045 1.762889 L 19.121251 10.500689 "
+ id="path1009"
+ sodipodi:nodetypes="ccc" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_activity.svg b/umbrello/umbrello/pics/sources/diag_activity.svg
new file mode 100644
index 00000000..d5c42951
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_activity.svg
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_activity.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.9999999"
+ inkscape:cx="5.95499421"
+ inkscape:cy="8.21358110"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.132695,0.000000,0.000000,0.133731,-0.712414,-0.542557)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.22079;"
+ d="M 0.63038772 0.64037571 L 12.041529 0.71149742 C 14.044031 0.46640741 18.580764 3.7689643 13.04278 8.3092899 C 16.547157 7.8191096 18.883407 6.5936594 19.384032 10.515101 L 19.419979 19.393892 L 0.63038772 19.393892 L 0.63038772 0.64037571 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g1567"
+ transform="matrix(6.414801e-2,0.000000,0.000000,8.074578e-2,0.594654,-1.730309)"
+ style="font-size:12;">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.5509048;"
+ id="path1536"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(2.033142,0.000000,0.000000,1.146119,-49.35104,33.00004)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path1537"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.866513,0.000000,0.000000,0.989918,-38.73914,38.52544)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="6.9204906"
+ y="27.309141"
+ id="text869"
+ transform="scale(4.148831,3.402401)"><tspan
+ id="tspan870">ABC</tspan></text>
+ </g>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.62664;stroke-dashoffset:0;"
+ d="M 5.5931752 7.7939546 L 5.6661327 14.774106 L 10.262453 14.774106 "
+ id="path1573"
+ sodipodi:nodetypes="ccc" />
+ <g
+ id="g900"
+ transform="matrix(5.889270e-2,0.000000,0.000000,5.818225e-2,10.22868,10.24438)"
+ style="font-size:12;">
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.0940815;stroke-dasharray:none;"
+ id="rect854"
+ width="41.480559"
+ height="40.741544"
+ x="74.760017"
+ y="-59.764663"
+ transform="matrix(1.438607,1.462473,-1.437488,1.463230,-116.1987,-4.837583)" />
+ <rect
+ style="fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:11.052127;"
+ id="rect855"
+ width="72.749743"
+ height="71.403139"
+ x="72.801592"
+ y="-35.372109"
+ transform="matrix(0.710624,0.703572,-0.699330,0.714799,0.000000,0.000000)"
+ ry="0.0000000" />
+ </g>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.627605;"
+ d="M 8.0261215 13.401058 L 10.37964 14.734718 L 8.1045721 16.539083 "
+ id="path971"
+ sodipodi:nodetypes="ccc" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_class.svg b/umbrello/umbrello/pics/sources/diag_class.svg
new file mode 100644
index 00000000..ef84ebe6
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_class.svg
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_class.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.9999999"
+ inkscape:cx="9.31250049"
+ inkscape:cy="7.28113176"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <g
+ id="g827">
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.132243,0.000000,0.000000,0.133732,-0.669713,-0.542563)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.22454;"
+ d="M 0.59132113 0.67943931 L 12.057516 0.75041341 C 14.069678 0.50583204 18.628299 3.8015352 13.063597 8.3324382 C 16.584879 7.8432753 18.932402 6.6203681 19.435443 10.533671 L 19.471562 19.394037 L 0.59132113 19.394037 L 0.59132113 0.67943931 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g1413"
+ transform="matrix(0.125094,0.000000,0.000000,0.125522,2.584431e-2,-0.563749)"
+ style="font-size:12;">
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ id="rect1360"
+ width="140.70964"
+ height="134.99545"
+ x="10.564683"
+ y="13.401533"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1362"
+ width="48.750000"
+ height="10.452705"
+ ry="0.0000000"
+ x="18.750000"
+ y="25.127287" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="5.3621841"
+ y="17.418277"
+ id="text838"
+ transform="matrix(1.800535,0.000000,0.000000,0.909408,11.83765,18.07640)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ d="M 13.158769,56.609700 L 149.13268,56.609700"
+ id="path842"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ d="M 12.845456,96.712602 L 148.81938,96.712602"
+ id="path845"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1369"
+ width="48.750000"
+ height="9.8123989"
+ ry="0.0000000"
+ x="18.750000"
+ y="40.000000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1370"
+ width="48.750000"
+ height="12.500000"
+ ry="0.0000000"
+ x="18.750000"
+ y="55.000000" />
+ </g>
+ <g
+ id="g1423"
+ transform="matrix(0.125094,0.000000,0.000000,0.125522,8.782425,9.321107)"
+ style="font-size:12;">
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ id="rect1424"
+ width="140.70964"
+ height="134.99545"
+ x="10.564683"
+ y="13.401533"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1425"
+ width="48.750000"
+ height="10.452705"
+ ry="0.0000000"
+ x="18.750000"
+ y="25.127287" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="5.3621841"
+ y="17.418277"
+ id="text1426"
+ transform="matrix(1.800535,0.000000,0.000000,0.909408,11.83765,18.07640)"><tspan
+ id="tspan1427">ABC</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ d="M 13.158769,56.609700 L 149.13268,56.609700"
+ id="path1429"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:13.551165;stroke-dasharray:none;"
+ d="M 12.845456,96.712602 L 148.81938,96.712602"
+ id="path1430"
+ transform="matrix(0.386648,0.000000,0.000000,0.352104,11.83765,18.07640)" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1431"
+ width="48.750000"
+ height="9.8123989"
+ ry="0.0000000"
+ x="18.750000"
+ y="40.000000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1432"
+ width="48.750000"
+ height="12.500000"
+ ry="0.0000000"
+ x="18.750000"
+ y="55.000000" />
+ </g>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M 43.750000,95.000000 L 43.750000,116.25000 L 86.250000,116.25000"
+ id="path1433"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.125094,0.000000,0.000000,0.125522,-1.512848e-2,-5.192415e-2)" />
+ <g
+ id="g1436"
+ transform="matrix(0.125094,0.000000,0.000000,0.125522,-1.512848e-2,-5.192415e-2)"
+ style="font-size:12;">
+ <polygon
+ sodipodi:type="star"
+ style="fill:#ffff00;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;"
+ id="polygon1434"
+ sodipodi:sides="3"
+ sodipodi:cx="27.500000"
+ sodipodi:cy="88.750000"
+ sodipodi:r1="16.682701"
+ sodipodi:r2="8.3413503"
+ sodipodi:arg1="0.51728738"
+ sodipodi:arg2="1.5644849"
+ inkscape:flatsided="true"
+ points="42.000000,97.000000 13.105290,97.182368 27.394710,72.067632 42.000000,97.000000 "
+ transform="translate(15.50000,-0.817633)" />
+ <polygon
+ sodipodi:type="star"
+ style="fill:url(#linearGradient834);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;"
+ id="polygon1435"
+ sodipodi:sides="3"
+ sodipodi:cx="27.500000"
+ sodipodi:cy="88.750000"
+ sodipodi:r1="16.682701"
+ sodipodi:r2="8.3413503"
+ sodipodi:arg1="0.51728738"
+ sodipodi:arg2="1.5644849"
+ inkscape:flatsided="true"
+ points="42.000000,97.000000 13.105290,97.182368 27.394710,72.067632 42.000000,97.000000 "
+ transform="matrix(0.778688,0.000000,0.000000,0.739979,21.04506,22.49123)" />
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_collaboration.svg b/umbrello/umbrello/pics/sources/diag_collaboration.svg
new file mode 100644
index 00000000..6d84d6e3
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_collaboration.svg
@@ -0,0 +1,1111 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_collaboration.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1253">
+ <linearGradient
+ id="linearGradient1254">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1255" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1256" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1257">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1258" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1259" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1260"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1261"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1262" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1263"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="96.390219"
+ inkscape:cy="55.703735"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1365">
+ <linearGradient
+ id="linearGradient1366">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1367" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1368" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1369">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1370" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1371" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1372">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1373" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1374" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1375">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1376" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1377" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1378"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1379" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1380" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1381"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1382"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1383">
+ <linearGradient
+ id="linearGradient1384">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1385" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1386" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1387">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1388" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1389" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1390"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1391"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1392" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1393"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1394">
+ <linearGradient
+ id="linearGradient1395">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1396" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1397" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1398">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1399" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1400" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1401">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1402" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1403" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1404">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1405" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1406" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1407">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1408" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1409" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1410"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1411"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1412" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1413" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient1414"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1415" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1416"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient1417"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1418"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1419">
+ <linearGradient
+ id="linearGradient1420">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1421" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1422" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1423">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1424" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1425" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1426">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1427" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1428" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1429">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1430" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1431" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1432"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1433"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1434" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1435" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1436"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1437">
+ <linearGradient
+ id="linearGradient1438">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1439" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1440" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1441">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1442" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1443" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1444">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1445" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1446" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1447">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1448" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1449" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1450"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1451"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1452" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1453"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1454"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1455"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="106.45706"
+ inkscape:cy="64.249115"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="false"
+ snaptogrid="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="1.89864068"
+ inkscape:cy="9.31486758"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1456"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1458"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 0.31849596 0.80526346 L 0.31849596 20.002095 L 19.625748 20.002095 L 19.625748 11.470169 C 19.828982 5.0712257 15.606949 1.731259 12.558436 0.87806654 L 0.31849596 0.80526346 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.21772;"
+ d="M 0.63498263 0.72032515 L 12.05856 0.79124256 C 14.063244 0.54685657 18.604921 3.8399269 13.0609 8.3672103 C 16.569096 7.8784382 18.907893 6.6565079 19.409064 10.566685 L 19.445049 19.419973 L 0.63498263 19.419973 L 0.63498263 0.72032515 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.603437;"
+ id="rect837"
+ width="9.58012390"
+ height="6.48194178"
+ x="1.66582549"
+ y="1.92005699" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1267"
+ width="8.88955975"
+ height="5.83366172"
+ ry="0"
+ x="2.02622056"
+ y="2.26269646" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:normal;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="62.241082"
+ y="18.111817"
+ id="text838"
+ transform="matrix(0.363236,0.000000,0.000000,0.306934,-20.18922,0.613913)"
+ sodipodi:linespacing="100%"><tspan
+ x="62.2410812"
+ y="18.1118164"
+ sodipodi:role="line"
+ id="tspan1117">A:B</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:5;"
+ d="M 179.16981,52.967263 L 240.02454,52.967263"
+ id="path842"
+ transform="matrix(0.125840,0.000000,0.000000,0.125610,-20.18922,0.613913)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.646377;stroke-dashoffset:0;"
+ d="M 3.8776774 8.5881294 L 3.8776774 15.726366 L 6.9450274 15.726366 "
+ id="path1471"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M 41.875000,114.68750 L 60.625000,125.31250 L 42.500000,139.68750"
+ id="path971"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.125840,0.000000,0.000000,0.125610,-5.482262e-2,-1.413717e-2)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ id="rect1605"
+ width="76.129402"
+ height="56.001663"
+ x="171.91731"
+ y="10.398407"
+ transform="matrix(0.125840,0.000000,0.000000,0.125610,-13.30508,9.803950)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1606"
+ width="70.641762"
+ height="50.840607"
+ ry="0.0000000"
+ x="173.90324"
+ y="12.246621"
+ transform="matrix(0.125840,0.000000,0.000000,0.125610,-13.30508,9.803950)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:normal;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="62.241082"
+ y="18.111817"
+ id="text1607"
+ transform="matrix(0.363236,0.000000,0.000000,0.306934,-13.30508,9.803950)"
+ sodipodi:linespacing="100%"><tspan
+ x="62.2410812"
+ y="18.1118164"
+ sodipodi:role="line"
+ id="tspan1125">A:B</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:5;"
+ d="M 179.16981,52.967263 L 240.02454,52.967263"
+ id="path1610"
+ transform="matrix(0.125840,0.000000,0.000000,0.125610,-13.30508,9.803950)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_component.svg b/umbrello/umbrello/pics/sources/diag_component.svg
new file mode 100644
index 00000000..e8859441
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_component.svg
@@ -0,0 +1,732 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_component.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1778">
+ <linearGradient
+ id="linearGradient1779">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1780" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1781" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1782">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1783" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1784" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1785"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1786"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1787" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1788"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="99.562933"
+ inkscape:cy="65.172729"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1917">
+ <linearGradient
+ id="linearGradient1918">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1919" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1920" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1921">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1922" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1923" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1924"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1925"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1926" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1927"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="63.313473"
+ inkscape:cy="66.872360"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="28.2842712"
+ inkscape:cx="9.03636094"
+ inkscape:cy="8.65257187"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 0.39048661 0.89309599 L 0.39048661 20.047181 L 19.632719 20.047181 L 19.632719 11.534254 C 19.835269 5.1495589 15.627454 1.8170296 12.589207 0.96573696 L 0.39048661 0.89309599 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.22267;"
+ d="M 0.66394573 0.6429877 L 12.054746 0.71428771 C 14.053677 0.46858326 18.582323 3.7794196 13.05421 8.3311276 C 16.55234 7.8397185 18.884427 6.611196 19.384159 10.542468 L 19.420041 19.443519 L 0.66394573 19.443519 L 0.66394573 0.6429877 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;stroke-dashoffset:0;"
+ d="M 46.250000,63.437500 L 46.875000,127.68750 L 80.000000,127.68750"
+ id="path1573"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.342000e-2,-3.521324e-2)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:11.9708;"
+ id="rect837"
+ width="117.17106"
+ height="134.99545"
+ x="33.896471"
+ y="12.776533"
+ transform="matrix(5.365033e-2,0.000000,0.000000,5.111246e-2,1.471943,1.669161)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1929"
+ width="46.101215"
+ height="50.085411"
+ ry="0.0000000"
+ x="40.383366"
+ y="19.214735"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.487058,0.215447)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ id="rect849"
+ width="20.689960"
+ height="9.3916094"
+ x="26.883967"
+ y="28.720773"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.487058,0.215447)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect850"
+ width="16.191408"
+ height="4.4504242"
+ ry="0.0000000"
+ x="29.464840"
+ y="31.063915"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.487058,0.215447)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ id="rect851"
+ width="20.689960"
+ height="9.3916094"
+ x="27.017647"
+ y="51.229589"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.487058,0.215447)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect852"
+ width="15.691408"
+ height="3.4504242"
+ ry="0.0000000"
+ x="29.598520"
+ y="54.072731"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,-1.487058,0.215447)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:11.9708;"
+ id="rect1979"
+ width="117.17106"
+ height="134.99545"
+ x="33.896471"
+ y="12.776533"
+ transform="matrix(5.365033e-2,0.000000,0.000000,5.111246e-2,9.743065,10.52538)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1980"
+ width="46.101215"
+ height="50.085411"
+ ry="0.0000000"
+ x="40.383366"
+ y="19.214735"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,6.784064,9.071668)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ id="rect1981"
+ width="20.689960"
+ height="9.3916094"
+ x="26.883967"
+ y="28.720773"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,6.784064,9.071668)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1982"
+ width="16.191408"
+ height="4.4504242"
+ ry="0.0000000"
+ x="29.464840"
+ y="31.063915"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,6.784064,9.071668)" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ id="rect1983"
+ width="20.689960"
+ height="9.3916094"
+ x="27.017647"
+ y="51.229589"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,6.784064,9.071668)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1984"
+ width="15.691408"
+ height="3.4504242"
+ ry="0.0000000"
+ x="29.598520"
+ y="54.072731"
+ transform="matrix(0.125416,0.000000,0.000000,0.125330,6.784064,9.071668)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_deployment.svg b/umbrello/umbrello/pics/sources/diag_deployment.svg
new file mode 100644
index 00000000..940cce17
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_deployment.svg
@@ -0,0 +1,676 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_deployment.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1778">
+ <linearGradient
+ id="linearGradient1779">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1780" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1781" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1782">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1783" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1784" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1785"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1786"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1787" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1788"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="99.562933"
+ inkscape:cy="65.172729"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.9999999"
+ inkscape:cx="9.31250051"
+ inkscape:cy="8.17808345"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <g
+ id="g1500">
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 0.71260935 0.81201239 L 0.71260935 19.93956 L 19.851798 19.93956 L 19.851798 11.438427 C 20.053263 5.0625781 15.867982 1.7346659 12.846005 0.88455272 L 0.71260935 0.81201239 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.22576;"
+ d="M 0.64263643 0.67943812 L 12.052584 0.75049689 C 14.054876 0.50562376 18.591135 3.8052584 13.053729 8.3415662 C 16.557739 7.8518198 18.893746 6.6274538 19.394319 10.545425 L 19.430261 19.41636 L 0.64263643 19.41636 L 0.64263643 0.67943812 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;stroke-dashoffset:0;"
+ d="M 46.250000,63.437500 L 46.875000,119.68750 L 77.500000,119.68750"
+ id="path1573"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,3.733392e-2,2.753162e-2)" />
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -84.422455,7.3251026 L -102.91372,19.247785 L -102.32767,63.644850 L -55.082643,64.524763 L -36.912006,51.706112 L -36.843985,7.8955677 L -84.422455,7.3251026 z "
+ id="path991"
+ sodipodi:nodetypes="ccccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,14.69487,1.005321)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1794"
+ width="42.145744"
+ height="38.517403"
+ ry="0.0000000"
+ x="-100.31789"
+ y="24.109026"
+ transform="matrix(0.124736,1.482898e-3,0.000000,0.125157,14.69487,1.005321)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;stroke-width:1pt;font-family:Bitstream Vera Sans;font-weight:normal;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="-48.233853"
+ y="25.958897"
+ id="text838"
+ transform="matrix(0.243909,0.000000,0.000000,0.255155,14.69487,1.005321)"
+ sodipodi:linespacing="100%"><tspan
+ x="-48.2338524"
+ y="25.9588966"
+ sodipodi:role="line"
+ id="tspan1487">XY</tspan></text>
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M -54.267621,23.369170 L -53.907472,60.592869 L -38.977447,50.401945 L -39.362477,10.880432 L -54.267621,23.369170 z "
+ id="path944"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,14.69487,1.005321)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M -83.527997,9.7916987 L -97.606582,18.881702 L -55.651918,18.333301 L -43.955918,10.104199 L -83.527997,9.7916987 z "
+ id="path990"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,14.69487,1.005321)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -105.15625,20.312500 L -54.843750,20.937500 L -36.406250,8.1250000"
+ id="path999"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,14.69487,1.005321)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -56.532642,18.413382 L -56.592358,66.899118"
+ id="path1000"
+ sodipodi:nodetypes="cc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,14.69487,1.005321)" />
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -84.422455,7.3251026 L -102.91372,19.247785 L -102.32767,63.644850 L -55.082643,64.524763 L -36.912006,51.706112 L -36.843985,7.8955677 L -84.422455,7.3251026 z "
+ id="path1017"
+ sodipodi:nodetypes="ccccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,22.74482,10.06908)" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect1018"
+ width="42.145744"
+ height="38.517403"
+ ry="0.0000000"
+ x="-100.31789"
+ y="24.109026"
+ transform="matrix(0.124736,1.482898e-3,0.000000,0.125157,22.74482,10.06908)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;stroke-width:1pt;font-family:Bitstream Vera Sans;font-weight:normal;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="-48.233853"
+ y="25.958897"
+ id="text1019"
+ transform="matrix(0.243909,0.000000,0.000000,0.255155,22.74482,10.06908)"
+ sodipodi:linespacing="100%"><tspan
+ x="-48.2338524"
+ y="25.9588966"
+ sodipodi:role="line"
+ id="tspan1498">XY</tspan></text>
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M -54.267621,23.369170 L -53.907472,60.592869 L -38.977447,50.401945 L -39.362477,10.880432 L -54.267621,23.369170 z "
+ id="path1022"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,22.74482,10.06908)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M -83.527997,9.7916987 L -97.606582,18.881702 L -55.651918,18.333301 L -43.955918,10.104199 L -83.527997,9.7916987 z "
+ id="path1023"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,22.74482,10.06908)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -105.15625,20.312500 L -54.843750,20.937500 L -36.406250,8.1250000"
+ id="path1024"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,22.74482,10.06908)" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:5;"
+ d="M -56.532642,18.413382 L -56.592358,66.899118"
+ id="path1025"
+ sodipodi:nodetypes="cc"
+ transform="matrix(0.124745,0.000000,0.000000,0.125157,22.74482,10.06908)" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_entityrelationship.svg b/umbrello/umbrello/pics/sources/diag_entityrelationship.svg
new file mode 100644
index 00000000..586f8e2e
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_entityrelationship.svg
@@ -0,0 +1,715 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.40"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/devel/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="diag_entityrelationship.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata1733">
+ <rdf:RDF
+ id="RDF1734">
+ <cc:Work
+ rdf:about=""
+ id="Work1735">
+ <dc:format
+ id="format1736">image/svg+xml</dc:format>
+ <dc:type
+ id="type1738"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient830"
+ id="linearGradient1089"
+ spreadMethod="reflect"
+ x1="23.537647"
+ y1="37.602750"
+ x2="3.7720042"
+ y2="28.123806"
+ gradientTransform="matrix(1.701614,0.000000,0.000000,1.095210,-5.421016e-16,-22.63705)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient830"
+ id="linearGradient1213"
+ spreadMethod="reflect"
+ x1="21.635329"
+ y1="9.6104371"
+ x2="3.4203537"
+ y2="0.87514110"
+ gradientTransform="scale(1.846475,0.541572)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient830"
+ id="linearGradient1773"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.846475,0.541572)"
+ spreadMethod="reflect"
+ x1="21.635329"
+ y1="9.6104371"
+ x2="3.4203537"
+ y2="0.87514110" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient830"
+ id="linearGradient1774"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.701614,0.000000,0.000000,1.095210,2.749537e-15,-22.63705)"
+ spreadMethod="reflect"
+ x1="23.537647"
+ y1="37.602750"
+ x2="3.7720042"
+ y2="28.123806" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="32.000000"
+ inkscape:cx="6.6746645"
+ inkscape:cy="7.4813442"
+ inkscape:window-width="1016"
+ inkscape:window-height="692"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false"
+ inkscape:current-layer="svg1" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path833"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path1533"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <rect
+ style="fill:url(#linearGradient836);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ id="rect835"
+ width="495.39624"
+ height="385.66864"
+ x="-679.56819"
+ y="64.886958" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path941"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <rect
+ style="fill:url(#linearGradient836);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ id="rect942"
+ width="495.39624"
+ height="385.66864"
+ x="-679.56819"
+ y="64.886958" />
+ <path
+ style="font-size:12.000000;fill:#8df2ff;fill-rule:evenodd;stroke-width:5.0000000;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.132588,0.000000,0.000000,0.134001,-0.711555,-0.583531)" />
+ <path
+ style="font-size:12.000000;fill:url(#linearGradient1762);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.2182600;"
+ d="M 0.63038442 0.67944183 L 12.032096 0.75041412 C 14.032942 0.50583897 18.565925 3.8014585 13.032518 8.3322463 C 16.533998 7.8430958 18.868318 6.6202197 19.36853 10.533424 L 19.404446 19.393563 L 0.63038442 19.393563 L 0.63038442 0.67944183 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g1196"
+ transform="matrix(0.225031,0.000000,0.000000,0.228044,2.568472,2.486405)">
+ <rect
+ style="font-size:12.000000;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2396300"
+ id="rect1206"
+ width="26.249929"
+ height="26.188568"
+ x="0.66534913"
+ y="0.71917963" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient1213);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt"
+ id="rect1207"
+ width="24.991924"
+ height="7.3301492"
+ ry="0.0000000"
+ x="1.2116134"
+ y="1.3678730" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;font-weight:normal;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans"
+ x="2.5917132"
+ y="11.314754"
+ id="text838"
+ transform="scale(0.933669,0.722645)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2500000"
+ d="M 1.1533278,9.3908034 L 26.731652,9.3908034"
+ id="path842" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient1089);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt"
+ id="rect1212"
+ width="24.991922"
+ height="16.085562"
+ ry="0.0000000"
+ x="1.3145113"
+ y="10.126090" />
+ </g>
+ <g
+ id="g1765"
+ transform="matrix(0.223484,0.000000,0.000000,0.223484,11.32810,11.30963)">
+ <rect
+ style="font-size:12.000000;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2396300"
+ id="rect1766"
+ width="26.249929"
+ height="26.188568"
+ x="0.66534913"
+ y="0.71917963" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient1773);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt"
+ id="rect1767"
+ width="24.991924"
+ height="7.3301492"
+ ry="0.0000000"
+ x="1.2116134"
+ y="1.3678730" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;font-weight:normal;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans"
+ x="2.5917132"
+ y="11.314754"
+ id="text1768"
+ transform="scale(0.933669,0.722645)"><tspan
+ id="tspan1769">ABC</tspan></text>
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2500000"
+ d="M 1.1533278,9.3908034 L 26.731652,9.3908034"
+ id="path1771" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient1774);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt"
+ id="rect1772"
+ width="24.991922"
+ height="16.085562"
+ ry="0.0000000"
+ x="1.3145113"
+ y="10.126090" />
+ </g>
+ <g
+ id="g1117"
+ transform="matrix(0.275357,0.000000,0.000000,0.264187,1.877265,8.790732)">
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:2.0050871"
+ d="M 19.138844,-0.51630137 L 13.730893,9.7597702 L 7.6288725,-0.51630137"
+ id="path1009"
+ sodipodi:nodetypes="ccc" />
+ <rect
+ style="font-size:12.000000;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt"
+ id="rect1209"
+ width="2.4859223"
+ height="27.510872"
+ x="12.540097"
+ y="-0.010873318" />
+ </g>
+ <rect
+ style="font-size:12.000000;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt"
+ id="rect1367"
+ width="0.68451649"
+ height="5.3054056"
+ x="15.359846"
+ y="-11.284021"
+ transform="matrix(0.000000,1.000000,-1.000000,0.000000,0.000000,0.000000)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_sequence.svg b/umbrello/umbrello/pics/sources/diag_sequence.svg
new file mode 100644
index 00000000..654c9847
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_sequence.svg
@@ -0,0 +1,729 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="diag_sequence.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1253">
+ <linearGradient
+ id="linearGradient1254">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1255" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1256" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1257">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1258" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1259" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1260"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1261"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1262" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1263"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="96.390219"
+ inkscape:cy="55.703735"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="80.979755"
+ inkscape:cy="83.920441"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="false"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <g
+ id="g1441"
+ transform="translate(0.312500,0.000000)">
+ <path
+ style="fill:#8df2ff;fill-rule:evenodd;stroke-width:5.0000000;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(1.057150,0.000000,0.000000,1.065409,-5.232740,-3.908785)" />
+ <path
+ style="fill:url(#linearGradient1762);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#0083e3;stroke-width:6.2179222;stroke-opacity:1.0000000;"
+ d="M 8.0588132,7.0930279 L 96.199432,7.6370399 C 111.66692,5.7623392 146.70903,31.023695 103.93317,65.752779 C 131.00127,62.003376 149.04667,52.629870 152.91354,82.625089 L 153.19119,150.53923 L 8.0588132,150.53923 L 8.0588132,7.0930279 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc"
+ transform="matrix(1.057150,0.000000,0.000000,1.065409,-5.232740,-3.908785)" />
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1.0000000;stroke-width:5.0000000;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:0.75;stroke-dasharray:20.000000,5.0000000;stroke-dashoffset:0.0000000;"
+ d="M 45.937500,64.062500 L 47.187500,148.43750"
+ id="path1573"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g1752"
+ transform="translate(3.125000,4.375000)">
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ id="rect837"
+ width="76.129402"
+ height="56.001663"
+ x="10.354806"
+ y="11.023407" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect1267"
+ width="70.641762"
+ height="50.840607"
+ ry="0.0000000"
+ x="12.340744"
+ y="12.871621" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Luxi Sans;font-weight:bold;font-style:normal;font-stretch:normal;font-variant:normal;text-anchor:start;writing-mode:lr;"
+ x="6.2691227"
+ y="18.367592"
+ id="text838"
+ transform="scale(2.886490,2.443551)"
+ sodipodi:linespacing="100%"><tspan
+ x="6.2691226"
+ y="18.367592"
+ sodipodi:role="line"
+ id="tspan1005">A:B</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:5.0000000;"
+ d="M 17.607313,53.592263 L 78.462038,53.592263"
+ id="path842" />
+ </g>
+ <g
+ id="g1332"
+ transform="matrix(0.635968,0.000000,0.000000,0.557565,45.87930,66.31573)">
+ <defs
+ id="defs1333">
+ <linearGradient
+ id="linearGradient1334">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1335" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1336" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1337">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1338" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1339" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1340">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1341" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1342" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1343">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1344" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1345" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1346"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1347"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1348" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1350"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1351"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.25000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="72.498291"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:11.939221;stroke-dashoffset:0.0000000;"
+ d="M 43.128730,142.68636 L 117.59907,33.942607"
+ id="path861"
+ sodipodi:nodetypes="cc"
+ transform="matrix(0.576132,0.451941,-0.865718,0.308049,103.0792,49.29771)" />
+ <path
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:8.9251652;"
+ d="M 119.08212,25.935929 L 72.532380,52.741368 L 116.08013,81.378318 L 119.08212,25.935929 z "
+ id="path874"
+ sodipodi:nodetypes="cccc"
+ transform="matrix(0.576132,0.451941,-0.865718,0.308049,103.0792,49.29771)" />
+ <path
+ style="fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:12.500000;"
+ d="M 136.52988,111.65883 L 102.33395,102.23422 L 103.18710,121.71891 L 136.52988,111.65883 z "
+ id="path875"
+ sodipodi:nodetypes="cccc" />
+ <text
+ xml:space="preserve"
+ style="fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;font-style:normal;font-weight:normal;font-size:12px;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
+ x="0.90846729"
+ y="15.456690"
+ id="text1033"
+ transform="scale(8.480023,5.154386)"><tspan
+ id="tspan1034">f(x)</tspan></text>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_state.svg b/umbrello/umbrello/pics/sources/diag_state.svg
new file mode 100644
index 00000000..3d428ff4
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_state.svg
@@ -0,0 +1,629 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_state.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs921">
+ <linearGradient
+ id="linearGradient922">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop923" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop924" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient925">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop926" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop927" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient929">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop930" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop931" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient932">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop933" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop934" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient935"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient936"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient938" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient939"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview940"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.9999999"
+ inkscape:cx="6.67466737"
+ inkscape:cy="7.48134805"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path833"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path1533"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <rect
+ style="fill:url(#linearGradient836);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ id="rect835"
+ width="495.39624"
+ height="385.66864"
+ x="-679.56819"
+ y="64.886958" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path941"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <rect
+ style="fill:url(#linearGradient836);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ id="rect942"
+ width="495.39624"
+ height="385.66864"
+ x="-679.56819"
+ y="64.886958" />
+ <g
+ id="g2088">
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.132588,0.000000,0.000000,0.134001,-0.711555,-0.583531)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.21826;"
+ d="M 0.63038442 0.67944183 L 12.032096 0.75041412 C 14.032942 0.50583897 18.565925 3.8014585 13.032518 8.3322463 C 16.533998 7.8430958 18.868318 6.6202197 19.36853 10.533424 L 19.404446 19.393563 L 0.63038442 19.393563 L 0.63038442 0.67944183 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g1567"
+ transform="matrix(6.409639e-2,0.000000,0.000000,8.090853e-2,0.672650,-1.499688)"
+ style="font-size:12;">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.5509048;"
+ id="path1536"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(2.033142,0.000000,0.000000,1.146119,-49.35104,33.00004)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path1537"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.866513,0.000000,0.000000,0.989918,-38.73914,38.52544)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="6.9204906"
+ y="27.309141"
+ id="text869"
+ transform="scale(4.148831,3.402401)"><tspan
+ id="tspan870">ABC</tspan></text>
+ </g>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.554883;stroke-dashoffset:0;"
+ d="M 5.667023 7.9654895 L 5.728223 15.040277 L 8.727023 15.040277 "
+ id="path1573"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.627984;"
+ d="M 6.9618605 13.625319 L 9.3134855 14.961668 L 7.040248 16.769669 "
+ id="path971"
+ sodipodi:nodetypes="ccc" />
+ <g
+ id="g972"
+ transform="matrix(6.409639e-2,0.000000,0.000000,8.090853e-2,9.147869,8.561800)"
+ style="font-size:12;">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.5509048;"
+ id="path973"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(2.033142,0.000000,0.000000,1.146119,-49.35104,33.00004)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path974"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.866513,0.000000,0.000000,0.989918,-38.73914,38.52544)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="6.9204906"
+ y="27.309141"
+ id="text975"
+ transform="scale(4.148831,3.402401)"><tspan
+ id="tspan976">ABC</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diag_usecase.svg b/umbrello/umbrello/pics/sources/diag_usecase.svg
new file mode 100644
index 00000000..9f1d6400
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diag_usecase.svg
@@ -0,0 +1,489 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="diag_usecase.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ <defs
+ id="defs1348">
+ <linearGradient
+ id="linearGradient1349">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1350" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1352">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1353" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1354" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1355"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1356"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1357" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1358"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1445">
+ <linearGradient
+ id="linearGradient973">
+ <stop
+ style="stop-color:#0000ff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop974" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop975" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1455">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1456" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1458">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1459" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1460" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1461"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1462"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1463" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ <linearGradient
+ xlink:href="#linearGradient973"
+ id="linearGradient926"
+ x1="1.5043305e-18"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient928" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient937"
+ x1="0.010563380"
+ y1="0.48571429"
+ x2="0.98943663"
+ y2="0.48571429"
+ spreadMethod="pad" />
+ <radialGradient
+ xlink:href="#linearGradient973"
+ id="radialGradient976"
+ cx="0.49275362"
+ cy="0.46875000"
+ r="0.80203730"
+ fx="0.49275362"
+ fy="0.46875000"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1469"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="66.817627"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <defs
+ id="defs1515">
+ <linearGradient
+ id="linearGradient1516">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1517" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1518" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1519">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1520" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1521" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1522">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1523" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1525">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop1526" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1527" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1528"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1529"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient1530" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient1531" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview1532"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.9999999"
+ inkscape:cx="11.2369790"
+ inkscape:cy="7.78464891"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#8df2ff;fill-rule:evenodd;stroke-width:5;"
+ d="M 0.70221666 0.81324909 L 0.70221666 20.035184 L 19.94503 20.035184 L 19.94503 11.492101 C 20.147586 5.0847898 15.939644 1.7404556 12.901305 0.88614738 L 0.70221666 0.81324909 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#0083e3;stroke-width:1.21953;"
+ d="M 0.63038443 0.67944234 L 12.032095 0.75056278 C 14.032942 0.50547713 18.565925 3.8079757 13.032517 8.3482207 C 16.533998 7.8580492 18.868318 6.6326205 19.368529 10.553993 L 19.404447 19.432627 L 0.63038443 19.432627 L 0.63038443 0.67944234 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g1509"
+ transform="matrix(6.244386e-2,0.000000,0.000000,5.641895e-2,8.731110,9.897060)"
+ style="font-size:12;">
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;"
+ d="M 25.093750,44.875000 L 29.375000,70.812500 L 75.375000,92.968750 L 74.906250,105.96875 L 9.4375000,130.71875 L 39.312500,151.71875 L 77.468750,118.50000 L 83.156250,118.43750 L 127.21875,152.31250 L 153.81250,127.56250 L 86.187500,106.68750 L 86.625000,93.218750 L 129.62500,88.812500 L 136.31250,62.625000 L 86.500000,81.250000 L 86.187500,55.250000 L 74.937500,55.375000 L 75.218750,78.562500 L 25.093750,44.875000 z "
+ id="path972"
+ sodipodi:nodetypes="ccccccccccccccccccc" />
+ <g
+ id="g909"
+ transform="matrix(0.813839,0.000000,0.000000,1.000000,22.06356,-5.625000)"
+ style="">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:10.800957;stroke-dasharray:none;"
+ id="path863"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.841497,0.000000,0.000000,0.838191,19.68138,6.062272)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path864"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(0.741224,0.000000,0.000000,0.702062,25.43390,11.29160)" />
+ </g>
+ </g>
+ <g
+ id="g1567"
+ transform="matrix(6.409639e-2,0.000000,0.000000,8.090853e-2,1.063275,-1.460626)"
+ style="font-size:12;">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.5509048;"
+ id="path1536"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(2.033142,0.000000,0.000000,1.146119,-49.35104,33.00004)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path1537"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.866513,0.000000,0.000000,0.989918,-38.73914,38.52544)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="6.9204906"
+ y="27.309141"
+ id="text869"
+ transform="scale(4.148831,3.402401)"><tspan
+ id="tspan870">ABC</tspan></text>
+ </g>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:7.5;stroke-dasharray:15 7.5 ;stroke-dashoffset:0;"
+ d="M 48.750000,68.437500 L 49.375000,123.43750 L 93.125000,123.43750"
+ id="path1573"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.125420,0.000000,0.000000,0.125774,-0.133652,-5.284487e-2)" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/diagbase.svg b/umbrello/umbrello/pics/sources/diagbase.svg
new file mode 100644
index 00000000..44774402
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/diagbase.svg
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="diagbase.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.113403"
+ inkscape:cy="71.451782"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="true" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient834);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;"
+ id="path833"
+ sodipodi:cx="541.27716"
+ sodipodi:cy="303.78741"
+ sodipodi:rx="172.74803"
+ sodipodi:ry="161.23149"
+ d="M 714.02519 303.78741 A 172.74803 161.23149 0 1 0 368.52913,303.78741 A 172.74803 161.23149 0 1 0 714.02519 303.78741 z"
+ transform="translate(224.5724,63.34093)" />
+ <rect
+ style="fill:url(#linearGradient836);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-opacity:1.0000000;stroke-dasharray:none;"
+ id="rect835"
+ width="495.39624"
+ height="385.66864"
+ x="-679.56819"
+ y="64.886958" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect841"
+ width="135.18759"
+ height="38.339100"
+ ry="0.0000000"
+ x="438.75000"
+ y="104.16090" />
+ <rect
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.5942383;"
+ id="rect837"
+ width="140.70964"
+ height="69.757812"
+ x="81.250000"
+ y="262.74219"
+ ry="0.0000000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="fill:url(#linearGradient1762);fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:0.75;"
+ d="M 323.12500,279.37500 L 409.37500,279.37500 C 409.37500,279.37500 441.87500,288.12500 406.87500,305.00000 C 423.75000,297.50000 438.12500,303.75000 440.00000,313.75000 L 440.00000,348.75000 L 323.12500,349.37500 L 323.12500,279.37500 z "
+ id="path1761"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#8df2ff;fill-rule:evenodd;stroke-width:5.0000000;fill-opacity:1.0000000;"
+ d="M 10.662893,8.9661054 L 10.662893,152.41231 L 155.79528,152.41231 L 155.79528,88.658436 C 157.32299,40.843037 125.58602,15.885505 102.67038,9.5101184 L 10.662893,8.9661054 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:url(#linearGradient1762);fill-opacity:0.75000000;fill-rule:evenodd;stroke:#2642d7;stroke-width:6.2179222;"
+ d="M 8.0588132,7.0930279 L 96.199432,7.6370399 C 111.66692,5.7623392 146.70903,31.023695 103.93317,65.752779 C 131.00127,62.003376 149.04667,52.629870 152.91354,82.625089 L 153.19119,150.53923 L 8.0588132,150.53923 L 8.0588132,7.0930279 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/end_state.svg b/umbrello/umbrello/pics/sources/end_state.svg
new file mode 100644
index 00000000..65d22943
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/end_state.svg
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="final.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.6418063;stroke-dasharray:none;"
+ id="path851"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.897276,0.000000,0.000000,1.866883,-40.40849,6.907883)" />
+ <g
+ id="g862"
+ transform="matrix(0.661598,0.000000,0.000000,0.612172,25.66010,32.61122)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:10.000000;stroke-opacity:1.0000000;stroke-dasharray:none;"
+ id="path863"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.663793,0.000000,0.000000,1.760684,-24.92188,9.110577)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:10.000000;stroke-opacity:1.0000000;stroke-dasharray:none;"
+ id="path864"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.331034,0.000000,0.000000,1.429466,-1.732780,22.15226)" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/entity.svg b/umbrello/umbrello/pics/sources/entity.svg
new file mode 100644
index 00000000..a40611eb
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/entity.svg
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.40"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/devel/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="entity.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ inkscape:export-filename="/home/jr/devel/kdesdk/umbrello/umbrello/pics/entity.png"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-ydpi="72.000000">
+ <metadata
+ id="metadata23">
+ <rdf:RDF
+ id="RDF24">
+ <cc:Work
+ rdf:about=""
+ id="Work25">
+ <dc:format
+ id="format26">image/svg+xml</dc:format>
+ <dc:type
+ id="type28"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient830"
+ id="linearGradient1089"
+ spreadMethod="reflect"
+ x1="23.537647"
+ y1="37.602750"
+ x2="3.7720042"
+ y2="28.123806"
+ gradientTransform="matrix(1.701614,0.000000,0.000000,1.095210,0.000000,-22.63705)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="17.104372"
+ inkscape:cx="12.250321"
+ inkscape:cy="20.076918"
+ inkscape:window-width="1016"
+ inkscape:window-height="692"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ snaptogrid="false"
+ showgrid="true"
+ inkscape:current-layer="svg1" />
+ <g
+ id="g1196">
+ <rect
+ style="font-size:12.000000;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2396300;"
+ id="rect837"
+ width="26.24992934"
+ height="26.18856802"
+ x="0.66534913"
+ y="0.71917963" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt;"
+ id="rect825"
+ width="24.99192419"
+ height="7.33014917"
+ ry="0"
+ x="1.21161342"
+ y="1.36787295" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;font-weight:normal;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="2.59171310"
+ y="11.3147535"
+ id="text838"
+ transform="scale(0.933669,0.722645)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2500000;"
+ d="M 1.1533278 9.3908034 L 26.731652 9.3908034 "
+ id="path842" />
+ <rect
+ style="font-size:12.000000;fill:url(#linearGradient1089);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652699pt"
+ id="rect847"
+ width="24.991922"
+ height="16.085562"
+ ry="0.0000000"
+ x="1.3145113"
+ y="10.126090" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/enum.svg b/umbrello/umbrello/pics/sources/enum.svg
new file mode 100644
index 00000000..ca09e448
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/enum.svg
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="enum.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.0070359"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.23958;"
+ id="rect837"
+ width="26.26486117"
+ height="26.28001541"
+ x="0.61830062"
+ y="0.67129415" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.94706100"
+ height="24.85842942"
+ ry="0"
+ x="1.36898315"
+ y="1.32233311" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="1.94527822"
+ y="15.4448805"
+ id="text838"
+ transform="scale(0.671250,0.505970)"
+ sodipodi:linespacing="133%"><tspan
+ x="1.94527817"
+ y="15.4448805"
+ sodipodi:role="line"
+ id="tspan854">- ABC</tspan><tspan
+ x="1.94527817"
+ y="31.4048810"
+ sodipodi:role="line"
+ id="tspan856">- DEF</tspan><tspan
+ x="1.94527817"
+ y="47.3648815"
+ sodipodi:role="line"
+ id="tspan858">- IJK</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/fork.svg b/umbrello/umbrello/pics/sources/fork.svg
new file mode 100644
index 00000000..c9e6c53b
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/fork.svg
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="fork_join.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="0.39932632"
+ y1="0.50707734"
+ x2="0.64623892"
+ y2="0.60370040"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="11.6871303"
+ inkscape:cy="11.8587637"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.30478;"
+ id="rect903"
+ width="23.63188207"
+ height="3.75598452"
+ x="1.95761454"
+ y="11.92267035" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/generalise.svg b/umbrello/umbrello/pics/sources/generalise.svg
new file mode 100644
index 00000000..d43ed6c2
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/generalise.svg
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="generalize.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.74305558"
+ y2="1.48437500" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="11.3902303"
+ inkscape:cy="10.2421455"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <g
+ id="g907">
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.63317;"
+ d="M 13.877015 1.8212949 L 18.663308 10.505802 L 8.8978064 10.489535 L 13.877015 1.8212949 z "
+ id="path874"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:12.5;"
+ d="M 13.846029 3.6304434 L 17.217581 9.7045394 L 10.441627 9.6475659 L 13.846029 3.6304434 z "
+ id="path875"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect906"
+ width="2.54116492"
+ height="17.06999987"
+ x="12.54009724"
+ y="10.43000108" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/initial.svg b/umbrello/umbrello/pics/sources/initial.svg
new file mode 100644
index 00000000..2ab111b5
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/initial.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="initial.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <g
+ id="g859"
+ transform="matrix(1.140332,0.000000,0.000000,1.060317,-11.98927,-2.752217)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:10.000000;stroke-opacity:1.0000000;stroke-dasharray:none;"
+ id="path851"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.663793,0.000000,0.000000,1.760684,-24.92188,9.110577)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:10.000000;stroke-opacity:1.0000000;stroke-dasharray:none;"
+ id="path858"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.331034,0.000000,0.000000,1.429466,-1.732780,22.15226)" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/interface.svg b/umbrello/umbrello/pics/sources/interface.svg
new file mode 100644
index 00000000..00c0a274
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/interface.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="interface.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.3558311"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.227;"
+ id="rect837"
+ width="26.22858411"
+ height="18.73091698"
+ x="0.68923926"
+ y="4.44105864" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.90570598"
+ height="9.89791008"
+ ry="0"
+ x="1.33175063"
+ y="5.06444607" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;text-anchor:middle;font-style:normal;writing-mode:lr;"
+ x="15.8012514"
+ y="19.6672548"
+ id="text838"
+ transform="scale(0.882660,0.446496)"
+ sodipodi:linespacing="100%"><tspan
+ x="15.8012514"
+ y="19.6672554"
+ sodipodi:role="line"
+ id="tspan943">«xy»</tspan><tspan
+ x="15.8012514"
+ y="31.6672554"
+ sodipodi:role="line"
+ id="tspan945">ABC</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.25;"
+ d="M 0.84533027 15.610254 L 26.618236 15.610254 "
+ id="path845" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect846"
+ width="25.07143413"
+ height="6.13441568"
+ ry="0"
+ x="1.29826760"
+ y="16.29058838" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="175.11363"
+ y="-1.7772827" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/join.svg b/umbrello/umbrello/pics/sources/join.svg
new file mode 100644
index 00000000..9bdd1f88
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/join.svg
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="F:\pics\join.png"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="join.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="22.000000px"
+ height="22.000000px"
+ id="svg1">
+ <metadata
+ id="metadata39">
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ id="Work41"
+ rdf:about="">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type43" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="134"
+ inkscape:window-x="1483"
+ inkscape:cy="11.000000"
+ inkscape:cx="11.000000"
+ inkscape:zoom="23.500000"
+ inkscape:window-height="691"
+ inkscape:window-width="1035"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker226"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path227"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker224"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path225"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker222"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path223"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker556"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path557"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker553"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path554"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path454"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path455"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-383.5096,-519.0587)"
+ id="g221">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.0250001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 394.53323,522.08766 C 394.54111,537.47668 394.54111,537.47668 394.54111,537.47668 L 394.54111,537.47668"
+ id="path15" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 396.01872,530.08052 L 401.76288,530.08052"
+ id="path16" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 384.83078,534.45617 L 390.57494,534.45617"
+ id="path555" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 384.83078,524.85406 L 390.57494,524.85406"
+ id="path558" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/junction.svg b/umbrello/umbrello/pics/sources/junction.svg
new file mode 100644
index 00000000..98ef166d
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/junction.svg
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="junction.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="22.000000px"
+ height="22.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="511"
+ inkscape:window-x="2276"
+ inkscape:cy="11.000000"
+ inkscape:cx="11.000000"
+ inkscape:zoom="18.409091"
+ inkscape:window-height="579"
+ inkscape:window-width="692"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker237"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path239"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker235"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path236"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker233"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path234"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker231"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path232"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker229"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path230"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker1"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path237"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker258"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path259"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker255"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path256"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker252"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path253"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker249"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path250"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path238"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-383.5432,-518.5878)"
+ id="g228">
+ <path
+ transform="translate(-0.668501,-2.243091)"
+ d="M 398.73051 531.23523 A 3.5248239 3.5248239 0 1 1 391.68086,531.23523 A 3.5248239 3.5248239 0 1 1 398.73051 531.23523 z"
+ sodipodi:ry="3.5248239"
+ sodipodi:rx="3.5248239"
+ sodipodi:cy="531.23523"
+ sodipodi:cx="395.20569"
+ id="path45"
+ style="fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:0.20000000;stroke-miterlimit:4.0000000;stroke-opacity:0.68161434"
+ sodipodi:type="arc" />
+ <path
+ id="path134"
+ d="M 386.54045,519.66500 L 390.14727,524.34150"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path251"
+ d="M 402.60019,519.65950 L 398.99337,524.33600"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path254"
+ d="M 394.57026,531.49266 L 394.66966,537.39766"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path260"
+ d="M 396.98786,531.45492 L 400.59468,536.13142"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)" />
+ <path
+ id="path435"
+ d="M 392.59468,531.45492 L 388.98786,536.13142"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.61250001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-end:url(#Arrow2Mend)" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/message-asynchronous.svg b/umbrello/umbrello/pics/sources/message-asynchronous.svg
new file mode 100644
index 00000000..7bb8054e
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/message-asynchronous.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="asynchro.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274169"
+ inkscape:cx="12.5595019"
+ inkscape:cy="9.96780389"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <path
+ style="font-size:12;fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:12.5;"
+ d="M 23.25456 20.532266 L 17.245615 18.773952 L 17.395532 22.409137 L 23.25456 20.532266 z "
+ id="path875"
+ sodipodi:nodetypes="cccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:normal;stroke-width:1pt;font-family:Bitstream Vera Sans;"
+ x="-0.14150786"
+ y="14.0554683"
+ id="text1033"
+ transform="scale(1.409838,1.034795)"><tspan
+ id="tspan1034">f(x)</tspan></text>
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect923"
+ width="16.51757205"
+ height="1.32582528"
+ x="-0.05524272"
+ y="20.04223250" />
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.14332;"
+ d="M 25.48674 20.457131 L 16.806844 18.331919 L 16.858498 23.071545 L 25.48674 20.457131 z "
+ id="path874"
+ sodipodi:nodetypes="cccc" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/message-synchronous.svg b/umbrello/umbrello/pics/sources/message-synchronous.svg
new file mode 100644
index 00000000..098a56b5
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/message-synchronous.svg
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="synchro.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.72477067"
+ y2="1.3515625" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient903" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient905"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.21100917"
+ y2="1.1328125" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="64.126236"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.3214993;stroke-dashoffset:0.0000000;"
+ d="M 7.4009479,65.202546 L 101.77436,65.315532"
+ id="path861"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:4.7256370;fill-opacity:1.0000000;"
+ d="M 107.13596,64.029793 L 72.687667,54.881453 L 72.892707,75.283958 L 107.13596,64.029793 z "
+ id="path874"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:url(#linearGradient905);fill-rule:evenodd;stroke-width:12.500000;"
+ d="M 98.388232,64.426032 L 74.840062,57.679774 L 75.427563,71.627168 L 98.388232,64.426032 z "
+ id="path875"
+ sodipodi:nodetypes="cccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;stroke-width:1.0000000pt;font-family:Bitstream Vera Sans;"
+ x="1.6763363"
+ y="11.255447"
+ id="text1033"
+ transform="scale(6.321334,3.689577)"><tspan
+ id="tspan1034">f(x)</tspan></text>
+ <rect
+ style="fill:#ffff00;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:5.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;"
+ id="rect899"
+ width="29.375000"
+ height="74.574653"
+ x="115.93750"
+ y="62.400174" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.3214993;stroke-dashoffset:0.0000000;stroke-dasharray:12.642999,6.3214993;"
+ d="M 109.15604,135.11984 L 14.782623,135.23283"
+ id="path900"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:4.7256370;fill-opacity:1.0000000;"
+ d="M 9.4210230,133.94709 L 43.869316,124.79875 L 43.664276,145.20126 L 9.4210230,133.94709 z "
+ id="path901"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:url(#linearGradient892);fill-rule:evenodd;stroke-width:12.500000;"
+ d="M 18.168751,134.34333 L 41.716921,127.59707 L 41.129420,141.54447 L 18.168751,134.34333 z "
+ id="path902"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:url(#linearGradient903);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;"
+ id="rect904"
+ width="25.000000"
+ height="69.574654"
+ x="117.50000"
+ y="65.212677" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/node.svg b/umbrello/umbrello/pics/sources/node.svg
new file mode 100644
index 00000000..ee76129a
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/node.svg
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="node.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="8.96789045"
+ inkscape:cy="11.0305950"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <path
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.21561;"
+ d="M 10.627136 0.70957548 L 0.95934281 8.1782719 L 18.381224 8.3835186 L 26.830203 0.65256253 L 18.403285 8.8168169 L 18.403285 26.850013 L 26.929473 19.66068 L 26.835718 0.6867703 L 10.627136 0.70957548 z M 0.4850529 8.6343755 L 0.70565286 26.895623 L 18.259895 26.895623 L 18.259895 8.8624273 L 0.4850529 8.6343755 z "
+ id="path942"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="16.51280659"
+ height="16.97894525"
+ ry="0"
+ x="1.10901392"
+ y="9.30482388" />
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M 18.887334 9.2865065 L 19.01291 25.592705 L 26.288674 19.298496 L 26.263384 2.0156589 L 18.887334 9.2865065 z "
+ id="path944"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ d="M 11.035012 1.2781133 L 2.8924094 7.5753492 L 18.102003 7.784321 L 25.13882 1.2781133 L 11.035012 1.2781133 z "
+ id="path946"
+ sodipodi:nodetypes="ccccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="2.47432498"
+ y="22.8059085"
+ id="text838"
+ transform="scale(0.963354,0.987729)"
+ sodipodi:linespacing="100%"><tspan
+ x="2.47432494"
+ y="22.8059082"
+ sodipodi:role="line"
+ id="tspan981">XY</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/note.svg b/umbrello/umbrello/pics/sources/note.svg
new file mode 100644
index 00000000..314d3026
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/note.svg
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="note.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1796">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1797" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1798" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1763">
+ <stop
+ style="stop-color:#ffff21;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop1764" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop1765" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient1763"
+ id="linearGradient1762"
+ x1="-0.34579438"
+ y1="-0.16406250"
+ x2="0.71962619"
+ y2="0.80468750" />
+ <linearGradient
+ xlink:href="#linearGradient1796"
+ id="linearGradient1795"
+ x1="0.65555555"
+ y1="0.88281250"
+ x2="0.48888889"
+ y2="0.53906250"
+ spreadMethod="reflect" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274169"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.4517668"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect825"
+ width="137.68759"
+ height="66.465706"
+ ry="0.0000000"
+ x="359.81241"
+ y="197.28429" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:0.45652742pt;"
+ id="rect846"
+ width="135.18759"
+ height="37.082668"
+ ry="0.0000000"
+ x="316.25000"
+ y="81.250000" />
+ <rect
+ style="fill:url(#linearGradient829);fill-opacity:0.75000000;fill-rule:evenodd;stroke:none;stroke-width:0.45652742pt;stroke-opacity:1.0000000;"
+ id="rect847"
+ width="135.18759"
+ height="47.111610"
+ ry="0.0000000"
+ x="255.00000"
+ y="157.88839" />
+ <path
+ style="font-size:12;fill:#f6f600;fill-rule:evenodd;stroke-width:5;"
+ d="M 8.2733326,28.387267 L 8.2733326,124.03331 L 149.01926,124.03331 L 149.01926,81.523954 C 150.50079,49.641942 119.72304,33.000935 97.500000,28.750000 L 8.2733326,28.387267 z "
+ id="path1780"
+ sodipodi:nodetypes="cccccc"
+ transform="matrix(0.188023,0.000000,0.000000,0.198158,-0.994639,-2.576479)" />
+ <path
+ style="font-size:12;fill:url(#linearGradient1762);fill-opacity:0.75;fill-rule:evenodd;stroke:#fb0000;stroke-width:1.24062;"
+ d="M 0.67142325 3.0486851 L 16.642354 3.119935 C 19.445037 2.8744034 25.794609 6.1829098 18.043695 10.731414 C 22.94839 10.240351 26.218186 9.0126933 26.918857 12.941199 L 26.969167 21.835986 L 0.67142325 21.835986 L 0.67142325 3.0486851 z "
+ id="path1781"
+ sodipodi:nodetypes="ccccccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;text-anchor:middle;font-style:normal;writing-mode:lr;"
+ x="12.9370291"
+ y="23.9665241"
+ id="text838"
+ transform="scale(1.068059,0.832361)"
+ sodipodi:linespacing="100%"><tspan
+ x="12.9370289"
+ y="23.9665241"
+ sodipodi:role="line"
+ id="tspan1022">XYZ</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/object.svg b/umbrello/umbrello/pics/sources/object.svg
new file mode 100644
index 00000000..184f6228
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/object.svg
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="object.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.7392690"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.22029;"
+ id="rect837"
+ width="26.29639788"
+ height="16.16913223"
+ x="0.59771752"
+ y="5.66733170" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.69446781"
+ height="14.49439839"
+ ry="0"
+ x="1.18516719"
+ y="6.32596101" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="2.18484960"
+ y="19.2367096"
+ id="text838"
+ transform="scale(1.061648,0.843136)"
+ sodipodi:linespacing="100%"><tspan
+ x="2.18484950"
+ y="19.2367096"
+ sodipodi:role="line"
+ id="tspan1049">A:B</tspan></text>
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.836365;"
+ d="M 2.5317946 18.322741 L 25.019316 18.322741 "
+ id="path842" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/package.svg b/umbrello/umbrello/pics/sources/package.svg
new file mode 100644
index 00000000..bbfe4d43
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/package.svg
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="package.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.0296644"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.22372;"
+ id="rect837"
+ width="26.25515313"
+ height="18.67122459"
+ x="0.67679340"
+ y="8.24792004" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.88985211"
+ height="17.23700789"
+ ry="0"
+ x="1.31681693"
+ y="8.87139037" />
+ <text
+ xml:space="preserve"
+ style="font-size:12;font-weight:bold;font-stretch:normal;stroke-width:1pt;font-family:Bitstream Vera Sans Mono;font-style:normal;text-anchor:start;writing-mode:lr;"
+ x="3.76967978"
+ y="24.3642572"
+ id="text838"
+ transform="scale(0.953250,0.970198)"
+ sodipodi:linespacing="133%"><tspan
+ x="3.76967978"
+ y="24.3642578"
+ sodipodi:role="line"
+ id="tspan1078">XYZ</tspan></text>
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.26017;"
+ id="rect879"
+ width="11.14999145"
+ height="7.45160484"
+ x="0.67036957"
+ y="0.69067132" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect880"
+ width="9.81101704"
+ height="6.12117195"
+ ry="0"
+ x="1.34353799"
+ y="1.39571142" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/relationship.svg b/umbrello/umbrello/pics/sources/relationship.svg
new file mode 100644
index 00000000..89981396
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/relationship.svg
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.40"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/devel/kdesdk/umbrello/umbrello/pics/sources"
+ sodipodi:docname="relationship.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ inkscape:export-filename="/home/jr/devel/kdesdk/umbrello/umbrello/pics/sources/relationship.png"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-ydpi="72.000000">
+ <metadata
+ id="metadata42">
+ <rdf:RDF
+ id="RDF43">
+ <cc:Work
+ rdf:about=""
+ id="Work44">
+ <dc:format
+ id="format45">image/svg+xml</dc:format>
+ <dc:type
+ id="type47"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.797281"
+ inkscape:cy="12.674791"
+ inkscape:window-width="1016"
+ inkscape:window-height="692"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ inkscape:current-layer="svg1" />
+ <g
+ id="g1117">
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ff0000;stroke-width:2.0050871"
+ d="M 19.138844,-0.51630137 L 13.730893,9.7597702 L 7.6288725,-0.51630137"
+ id="path1009"
+ sodipodi:nodetypes="ccc" />
+ <rect
+ style="font-size:12.000000;fill:#ff0000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt"
+ id="rect1209"
+ width="2.4859223"
+ height="27.510872"
+ x="12.540097"
+ y="-0.010873318" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/shallow-history.svg b/umbrello/umbrello/pics/sources/shallow-history.svg
new file mode 100644
index 00000000..d5ce2653
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/shallow-history.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="shallow-history.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="22.000000px"
+ height="22.000000px"
+ id="svg1">
+ <metadata
+ id="metadata17">
+ <rdf:RDF
+ id="RDF18">
+ <cc:Work
+ id="Work19"
+ rdf:about="">
+ <dc:format
+ id="format20">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type21" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="317"
+ inkscape:window-x="1889"
+ inkscape:cy="11.000000"
+ inkscape:cx="11.000000"
+ inkscape:zoom="18.409091"
+ inkscape:window-height="579"
+ inkscape:window-width="692"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3" />
+ <g
+ transform="translate(-383.9018,-518.6851)"
+ id="g240">
+ <path
+ d="M 403.40652,529.87519 C 403.40652,534.58139 399.61097,538.39651 394.92893,538.39651 C 390.24688,538.39651 386.45133,534.58139 386.45133,529.87519 C 386.45133,525.16900 390.24688,521.35388 394.92893,521.35388 C 399.61097,521.35388 403.40652,525.16900 403.40652,529.87519 z "
+ style="fill:none;stroke:#d30000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="path21" />
+ <text
+ sodipodi:linespacing="100%"
+ x="390.11942"
+ y="534.23749"
+ style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr-tb"
+ id="text111"
+ xml:space="preserve"><tspan
+ id="tspan22"
+ sodipodi:role="line"
+ y="534.23749"
+ x="390.11942">H</tspan></text>
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/state-fork.svg b/umbrello/umbrello/pics/sources/state-fork.svg
new file mode 100644
index 00000000..9e12691a
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/state-fork.svg
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docbase="F:\pics"
+ sodipodi:docname="state-fork.svg"
+ inkscape:version="0.40+cvs"
+ sodipodi:version="0.32"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ width="22.000000px"
+ height="22.000000px"
+ id="svg1">
+ <metadata
+ id="metadata39">
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ id="Work41"
+ rdf:about="">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type43" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:current-layer="svg1"
+ inkscape:window-y="134"
+ inkscape:window-x="1483"
+ inkscape:cy="11.000000"
+ inkscape:cx="11.000000"
+ inkscape:zoom="23.500000"
+ inkscape:window-height="691"
+ inkscape:window-width="1035"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker246"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path247"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker244"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path245"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker242"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path243"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker556"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path557"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker553"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path554"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path454"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path455"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ </defs>
+ <g
+ transform="translate(-383.7683,-518.9311)"
+ id="g241">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.0250001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 394.53323,522.08766 C 394.54111,537.47668 394.54111,537.47668 394.54111,537.47668 L 394.54111,537.47668"
+ id="path15" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 384.86403,529.65511 L 390.60819,529.65511"
+ id="path16" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 395.73687,534.45617 L 401.48103,534.45617"
+ id="path555" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.60290909px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Mend)"
+ d="M 395.73687,524.85406 L 401.48103,524.85406"
+ id="path558" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/subsystem.svg b/umbrello/umbrello/pics/sources/subsystem.svg
new file mode 100644
index 00000000..ca5f1ce7
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/subsystem.svg
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ id="svg1"
+ sodipodi:version="0.34"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docname="subsystem.svg">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="11.0296644"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.22372;"
+ id="rect837"
+ width="26.25515313"
+ height="18.67122459"
+ x="0.67679340"
+ y="8.24792004" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect825"
+ width="24.88985211"
+ height="17.23700789"
+ ry="0"
+ x="1.31681693"
+ y="8.87139037" />
+ <rect
+ style="font-size:12;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.26017;"
+ id="rect879"
+ width="11.14999145"
+ height="7.45160484"
+ x="0.67036957"
+ y="0.69067132" />
+ <rect
+ style="font-size:12;fill:url(#linearGradient829);fill-opacity:0.75;fill-rule:evenodd;stroke-width:0.456527pt;"
+ id="rect880"
+ width="9.81101704"
+ height="6.12117195"
+ ry="0"
+ x="1.34353799"
+ y="1.39571142" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-rule:evenodd;stroke-width:1;fill-opacity:1;"
+ id="rect624"
+ width="1.21451104"
+ height="4.94479527"
+ x="12.665616"
+ y="11.364354" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-rule:evenodd;stroke-width:1;fill-opacity:1;"
+ id="rect626"
+ width="8.84858036"
+ height="1.38801145"
+ x="8.84858036"
+ y="16.3091492" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-rule:evenodd;stroke-width:1;fill-opacity:1;"
+ id="rect627"
+ width="1.21451092"
+ height="6.2460556"
+ x="8.84858036"
+ y="17.6104107" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-rule:evenodd;stroke-width:1;fill-opacity:1;"
+ id="rect628"
+ width="1.38801193"
+ height="6.2460556"
+ x="16.3091488"
+ y="17.6104107" />
+</svg>
diff --git a/umbrello/umbrello/pics/sources/template.svg b/umbrello/umbrello/pics/sources/template.svg
new file mode 100644
index 00000000..5c299757
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/template.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="16pt"
+ height="16pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="template.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.26725582"
+ inkscape:cx="87.469639"
+ inkscape:cy="55.703730"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true"
+ snaptogrid="false" />
+ <rect
+ style="font-size:12.000;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.250131;"
+ id="rect837"
+ width="15.04155"
+ height="14.94933"
+ x="0.672622"
+ y="4.443538" />
+ <rect
+ style="font-size:12.000;fill:url(#linearGradient829);fill-opacity:0.750000;fill-rule:evenodd;stroke-width:0.456527;"
+ id="rect825"
+ width="14.62770"
+ height="4.262030"
+ ry="0"
+ x="1.220295"
+ y="5.096904" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000;font-weight:normal;font-family:Bitstream Vera Sans;"
+ x="2.58085157"
+ y="21.7099400"
+ id="text838"
+ transform="scale(0.457094,0.398859)"><tspan
+ id="tspan839">ABC</tspan></text>
+ <path
+ style="font-size:12.000;fill:none;fill-opacity:0.750000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.249990;"
+ d="M 0.585981 9.445099 L 15.29877 9.445099 "
+ id="path842" />
+ <path
+ style="font-size:12.000;fill:none;fill-opacity:0.750000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.249990;"
+ d="M 0.506163 14.38251 L 15.21895 14.38251 "
+ id="path845" />
+ <rect
+ style="font-size:12.000;fill:url(#linearGradient829);fill-opacity:0.750000;fill-rule:evenodd;stroke-width:0.456527;"
+ id="rect846"
+ width="13.89305"
+ height="3.689761"
+ ry="0"
+ x="1.307394"
+ y="10.00005" />
+ <rect
+ style="font-size:12.000;fill:url(#linearGradient829);fill-opacity:0.750000;fill-rule:evenodd;stroke-width:0.456527;"
+ id="rect847"
+ width="13.29614"
+ height="3.545959"
+ ry="0"
+ x="1.283363"
+ y="15.21296" />
+ <rect
+ style="font-size:12.000;fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.2500;stroke-dasharray:none;"
+ id="rect632"
+ width="6.335767"
+ height="6.325978"
+ x="13.06549"
+ y="0.607178" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000;font-weight:normal;font-family:Bitstream Vera Sans;"
+ x="61.0662308"
+ y="-0.90945697"
+ id="text633"
+ transform="scale(0.222374,0.562059)"
+ sodipodi:linespacing="100%"><tspan
+ x="61.0662308"
+ y="11.0905430"
+ sodipodi:role="line"
+ id="tspan636">XYZ</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/text.svg b/umbrello/umbrello/pics/sources/text.svg
new file mode 100644
index 00000000..24eba425
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/text.svg
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="text.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="7.69284241"
+ inkscape:cy="12.0771046"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <text
+ xml:space="preserve"
+ style="fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans Mono;font-style:normal;font-weight:bold;font-size:12;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;font-stretch:normal;font-variant:normal;text-anchor:middle;writing-mode:lr;"
+ x="10.5612742"
+ y="12.4468273"
+ id="text865"
+ transform="scale(1.305010,1.709686)"
+ sodipodi:linespacing="100%"><tspan
+ x="10.5612745"
+ y="12.4468269"
+ sodipodi:role="line"
+ id="tspan1162">XYZ</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/uniassociation.svg b/umbrello/umbrello/pics/sources/uniassociation.svg
new file mode 100644
index 00000000..4fce2c33
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/uniassociation.svg
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.37"
+ width="22pt"
+ height="22pt"
+ sodipodi:docbase="/home/jr/tmp/umbrello/icons/inkscape-svg"
+ sodipodi:docname="uniassociation.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient993">
+ <stop
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ id="stop995" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ id="stop994" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892"
+ x1="1.8449316"
+ y1="0.98914021"
+ x2="0.14743590"
+ y2="0.67741936"
+ spreadMethod="reflect" />
+ <defs
+ id="defs940">
+ <linearGradient
+ id="linearGradient941"
+ x1="0.0000000"
+ y1="0.50000000"
+ x2="1.0000000"
+ y2="0.50000000"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad"
+ xlink:href="#linearGradient993" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient947">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop948" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop949" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient950">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop951" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop952" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient953"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient954"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient955" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient956"
+ x1="-0.49264705"
+ y1="0.43750000"
+ x2="0.022058824"
+ y2="0.92187500" />
+ </defs>
+ <sodipodi:namedview
+ id="namedview957"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132843"
+ inkscape:cy="33.777672"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.6274170"
+ inkscape:cx="13.7972814"
+ inkscape:cy="10.5907033"
+ inkscape:window-width="1016"
+ inkscape:window-height="693"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showgrid="true" />
+ <g
+ id="g1210">
+ <path
+ style="font-size:12;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.62628;"
+ d="M 18.100766 10.114902 L 13.714502 1.7802173 L 8.7652941 10.114902 "
+ id="path1009"
+ sodipodi:nodetypes="ccc" />
+ <rect
+ style="font-size:12;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1pt;"
+ id="rect1209"
+ width="2.48592234"
+ height="25.08019308"
+ x="12.54009724"
+ y="2.41980620" />
+ </g>
+</svg>
diff --git a/umbrello/umbrello/pics/sources/usecase.svg b/umbrello/umbrello/pics/sources/usecase.svg
new file mode 100644
index 00000000..cd0851c5
--- /dev/null
+++ b/umbrello/umbrello/pics/sources/usecase.svg
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.38.1"
+ width="128.00000pt"
+ height="128.00000pt"
+ sodipodi:docbase="/home/bartkozoltan/Documents/work/umbrello/new pics"
+ sodipodi:docname="usecase.svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient868">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop869" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop870" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient893">
+ <stop
+ style="stop-color:#19839a;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop894" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop895" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient830">
+ <stop
+ style="stop-color:#ebffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop831" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop832" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient826">
+ <stop
+ style="stop-color:#000;stop-opacity:1;"
+ offset="0"
+ id="stop827" />
+ <stop
+ style="stop-color:#fff;stop-opacity:1;"
+ offset="1"
+ id="stop828" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient829"
+ x1="1.5500000"
+ y1="0.52343750"
+ x2="0.20422535"
+ y2="-0.12195122"
+ spreadMethod="reflect" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient834"
+ x1="-0.31159419"
+ y1="0.19531250"
+ x2="0.77536231"
+ y2="0.94531250" />
+ <linearGradient
+ xlink:href="#linearGradient830"
+ id="linearGradient836" />
+ <linearGradient
+ xlink:href="#linearGradient868"
+ id="linearGradient892" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.0000000"
+ inkscape:cx="79.132812"
+ inkscape:cy="69.358765"
+ inkscape:window-width="1022"
+ inkscape:window-height="701"
+ gridspacingy="1.0000000pt"
+ gridspacingx="1.0000000pt"
+ gridtolerance="1.0000000px"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#ff0000;stroke-width:6.5509048;stroke-opacity:1.0000000;fill-opacity:1.0000000;stroke-dasharray:none;"
+ id="path863"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(2.033142,0.000000,0.000000,1.146119,-49.35104,33.00004)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient892);fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:10.000000;"
+ id="path864"
+ sodipodi:cx="63.437500"
+ sodipodi:cy="39.375000"
+ sodipodi:rx="31.250000"
+ sodipodi:ry="31.562500"
+ d="M 94.687500 39.375000 A 31.250000 31.562500 0 1 0 32.187500,39.375000 A 31.250000 31.562500 0 1 0 94.687500 39.375000 z"
+ transform="matrix(1.866513,0.000000,0.000000,0.989918,-38.73914,38.52544)" />
+ <text
+ xml:space="preserve"
+ style="fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;font-style:normal;font-weight:normal;font-size:12px;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
+ x="6.9204906"
+ y="27.309141"
+ id="text869"
+ transform="scale(4.148831,3.402401)"><tspan
+ id="tspan870">ABC</tspan></text>
+</svg>
diff --git a/umbrello/umbrello/pics/startlogo.png b/umbrello/umbrello/pics/startlogo.png
new file mode 100644
index 00000000..29d6e15d
--- /dev/null
+++ b/umbrello/umbrello/pics/startlogo.png
Binary files differ
diff --git a/umbrello/umbrello/pics/state-fork.png b/umbrello/umbrello/pics/state-fork.png
new file mode 100644
index 00000000..5a3108a1
--- /dev/null
+++ b/umbrello/umbrello/pics/state-fork.png
Binary files differ
diff --git a/umbrello/umbrello/pics/subsystem.png b/umbrello/umbrello/pics/subsystem.png
new file mode 100644
index 00000000..a002b73e
--- /dev/null
+++ b/umbrello/umbrello/pics/subsystem.png
Binary files differ
diff --git a/umbrello/umbrello/pics/template.png b/umbrello/umbrello/pics/template.png
new file mode 100644
index 00000000..0993de43
--- /dev/null
+++ b/umbrello/umbrello/pics/template.png
Binary files differ
diff --git a/umbrello/umbrello/pics/text.png b/umbrello/umbrello/pics/text.png
new file mode 100644
index 00000000..77893ded
--- /dev/null
+++ b/umbrello/umbrello/pics/text.png
Binary files differ
diff --git a/umbrello/umbrello/pics/uniassociation.png b/umbrello/umbrello/pics/uniassociation.png
new file mode 100644
index 00000000..f4be9352
--- /dev/null
+++ b/umbrello/umbrello/pics/uniassociation.png
Binary files differ
diff --git a/umbrello/umbrello/pics/usecase.png b/umbrello/umbrello/pics/usecase.png
new file mode 100644
index 00000000..83201d44
--- /dev/null
+++ b/umbrello/umbrello/pics/usecase.png
Binary files differ
diff --git a/umbrello/umbrello/plugin.cpp b/umbrello/umbrello/plugin.cpp
new file mode 100644
index 00000000..1447afcd
--- /dev/null
+++ b/umbrello/umbrello/plugin.cpp
@@ -0,0 +1,167 @@
+/***************************************************************************
+ plugin.h
+ -------------------
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// own header
+#include "plugin.h"
+
+// KDE includes
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kconfig.h>
+
+// app includes
+#include "pluginloader.h"
+
+using namespace Umbrello;
+
+Plugin::Plugin(QObject *parent,
+ const char *name,
+ const QStringList & /* args */) :
+ QObject(parent, name),
+ Configurable(),
+ _ref(0),
+ _instanceName(name),
+ _config(NULL)
+{
+}
+
+Plugin::~Plugin()
+{
+}
+
+void
+Plugin::ref()
+{
+ _ref++;
+}
+
+void
+Plugin::unload()
+{
+ _ref--;
+ if(_ref == 0) {
+ // save the name
+ QString pluginName = _instanceName;
+
+ // shutdown and delete
+ shutdown();
+ delete this;
+
+ // once the object is destroyed, we can have the plugin loader unload
+ // the library.
+ PluginLoader::instance()->unloadPlugin(pluginName);
+ }
+}
+
+bool
+Plugin::init()
+{
+ bool ret = true;
+
+ // initialize this plugin first - then load other plugins
+ ret = onInit();
+ if(!ret) {
+ kdError() << "failed to initialize " << instanceName() << endl;
+ }
+
+ // configure on load plugins
+ if(ret) {
+ ret = configure();
+ if(!ret) {
+ kdError() << "failed configuration " << instanceName() << endl;
+ }
+ }
+
+ return true;
+}
+
+bool
+Plugin::shutdown()
+{
+ bool ret = true;
+
+ // always unload plugins, even if things are failing
+ unloadPlugins();
+
+ // shutdown this plugin
+ ret = onShutdown();
+ if(!ret) {
+ kdError() << "failed to shutdown " << instanceName() << endl;
+ }
+
+ return true;
+}
+
+QCString
+Plugin::instanceName() const
+{
+ return _instanceName;
+}
+
+KConfig *
+Plugin::config()
+{
+ return _config;
+}
+
+bool
+Plugin::onInit()
+{
+ return true;
+}
+
+bool
+Plugin::onShutdown()
+{
+ return true;
+}
+
+bool
+Plugin::configure()
+{
+ bool ret = true;
+
+ // grab the OnStartup map
+ KConfig *conf = config();
+ if(!conf) {
+ kdDebug() << "no configuration for " << instanceName() << endl;
+ ret = false;
+ }
+
+ if(ret) {
+ // set the config group to Load Actions
+ conf->setGroup("Load Actions");
+
+ // load standard plugins by default
+ loadPlugins(conf, "Load");
+
+ // only load GUI plugins if this is not a terminal app
+ if(KApplication::kApplication()->type() != QApplication::Tty) {
+ loadPlugins(conf, "LoadGUI");
+ }
+ }
+
+ return ret;
+}
+
+QString
+Plugin::category()
+{
+ return QString("miscellaneous");
+}
+
+#include "plugin.moc"
diff --git a/umbrello/umbrello/plugin.h b/umbrello/umbrello/plugin.h
new file mode 100644
index 00000000..8d1eacc8
--- /dev/null
+++ b/umbrello/umbrello/plugin.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+ plugin.h
+ -------------------
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMBRELLO_PLUGIN_H
+#define UMBRELLO_PLUGIN_H
+
+// Qt includes
+#include <qobject.h>
+
+// KDE includes
+#include <kgenericfactory.h>
+
+// local includes
+#include "configurable.h"
+
+// forward declarations
+class QStringList;
+class KConfig;
+
+/**
+ * This macro replaces the K_EXPORT_COMPONENT_FACTORY macro because of
+ * a simple defficiency for this application - the construction of the
+ * factory with a default instance name. This macro must be used in
+ * the .cpp file implementing the plugin.
+ *
+ *
+ * @param libname The name of the plugin. This corresponds to
+ * the name of the shared object without the ".so"
+ * extension.
+ * @param factory The type of factory. Typically, this will be
+ * KGenericFactory<> with the name of the plugin
+ * as the parameter.
+ */
+#define UMBRELLO_EXPORT_PLUGIN_FACTORY(libname, factory) \
+ extern "C" { KDE_EXPORT void *init_##libname() { return new factory(#libname); } }
+
+namespace Umbrello
+{
+// forward declarations
+class PluginLoader;
+
+/**
+ * @ingroup U2_Lib
+ *
+ * The Plugin class is the base class for all modular functionality in
+ * the core Umbrello library. Because Umbrello is a plugin architecture,
+ * this class is derived from many times. Plugins are created via the
+ * KLibFactory of the encapsulating shared library and created from some
+ * other functional object (application, tool or plugin). After the plugin
+ * has been created, the init method is called. Before unloading, the
+ * shutdown method is called. Derived plugins can implement specific
+ * startup/shutdown behavior by overloading the onInit and onShutdown
+ * methods respectively.
+ *
+ * By default, plugins use a configuration group called [LoadActions] in
+ * the config file. Entries in this group define any dependant or on-demand
+ * plugins that should be loaded in conjunction with this plugin. Known
+ * entries (actions) are "Load" and "LoadGUI". Because plugins can be used
+ * by both GUI and command line tools, they must be selective about some
+ * functionality. Specifically, during configuration, a plugin for a tool
+ * must not load GUI plugins.
+ *
+ * In order to provide application-like functionality, this class offers
+ * support for accessing the configuration records of the KInstance object
+ * corresponding to the shared library. Because the KInstance object is
+ * only available within the scope of the shared library, the configuration
+ * records must be set in the constructor of the derived plugin class. However,
+ * because the construction name is passed to this constructor (as are the
+ * parent object and args), we can simply capture the name when the object
+ * is constructed.
+ */
+class Plugin :
+ public QObject,
+ public Configurable
+{
+ Q_OBJECT
+ friend class PluginLoader;
+public:
+ /** Destroy a plugin.*/
+ virtual ~Plugin();
+
+ /** Return the instance name of the plugin */
+ QCString instanceName() const;
+
+ /** Return the configuration record for the plugin */
+ KConfig *config();
+
+ /** Return the category descriptor string */
+ virtual QString category();
+
+ /**
+ * Unload the plugin. This method actually only decrements
+ * the reference count. When the refcount is 0, the object
+ * calls shutdown and deletes itself.
+ */
+ void unload();
+
+protected:
+ /** Construct a plugin */
+ Plugin(QObject *parent, const char *name, const QStringList &args);
+
+ /** Can be reimplemented to define plugin specific startup behavior */
+ virtual bool onInit();
+
+ /** Can be reimplemented to define plugin specific shutdown behavior */
+ virtual bool onShutdown();
+
+private:
+ /**
+ * This method is called by the loader to initialize and configure the
+ * plugin. During initialization, any configured plugins are loaded.
+ * Before loading plugins, onInit is called to perform plugin specific
+ * initialization. This allows dependencies in the plugin chain.
+ *
+ * @return True on success, false on failure.
+ */
+ bool init();
+
+ /**
+ * This method is called by the loader to shutdown the plugin. During
+ * shutdown, any configured plugins are unloaded this occurs before
+ * plugin specific shutdown so as to reduce dependency errors.
+ *
+ * @return True on success, false on failure.
+ */
+ bool shutdown();
+
+ /**
+ * The configure method is called by init to parse the configuration
+ * file and load any plugins. Note that the libraries loaded depends
+ * on the GUI state of the application. If the application is type
+ * Qt::Tty, then we don't use the "loadGUI" action.
+ *
+ * @return True on success, false on failure.
+ */
+ virtual bool configure();
+
+ /** Add to the reference count */
+ void ref();
+
+protected:
+ uint _ref; ///< Reference counter
+ QCString _instanceName; ///< Instance name of the plugin
+ KConfig *_config; ///< Configuration record
+};
+}
+
+#endif
diff --git a/umbrello/umbrello/pluginloader.cpp b/umbrello/umbrello/pluginloader.cpp
new file mode 100644
index 00000000..db79bca1
--- /dev/null
+++ b/umbrello/umbrello/pluginloader.cpp
@@ -0,0 +1,177 @@
+/***************************************************************************
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// own header
+#include "pluginloader.h"
+
+// Qt includes
+#include <qstring.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klibloader.h>
+
+// u2 includes
+#include "plugin.h"
+
+using namespace Umbrello;
+
+// static data
+PluginLoader *PluginLoader::_instance = NULL;
+
+PluginLoader::PluginLoader() :
+ _plugins(),
+ _categories()
+{
+ // preseed the categories
+ _categories["metamodel"] = PluginList();
+ _categories["storage"] = PluginList();
+ _categories["visual"] = PluginList();
+}
+
+PluginLoader::~PluginLoader()
+{
+}
+
+PluginLoader *
+PluginLoader::instance()
+{
+ if(!_instance) _instance = new PluginLoader;
+ return _instance;
+}
+
+Plugin *
+PluginLoader::loadPlugin(const QString &name)
+{
+ KLibrary *lib = NULL;
+ KLibFactory *factory = NULL;
+ Plugin *plugin = NULL;
+ PluginMap::iterator it;
+ bool success = true;
+
+ // if the plugin has already been loaded, increment
+ // its reference and return.
+ if((it = _plugins.find(name)) != _plugins.end()) {
+ plugin = it.data();
+ plugin->ref();
+ return plugin;
+ }
+
+ // use KLibLoader to get a reference to the library
+ lib = KLibLoader::self()->library(name.latin1());
+ if(!lib) {
+ kdError() << "failed loading plugin library " << name << endl;
+ success = false;
+ }
+
+ // get the factory from the library
+ if(success) {
+ factory = lib->factory();
+ if(!factory) {
+ kdError() << "failed to find factory for " << name << endl;
+ success = false;
+ }
+ }
+
+ // use the factory to create the plugin
+ if(success) {
+ plugin = dynamic_cast<Plugin *>(factory->create((QObject*)0, name.latin1()));
+ if(!plugin) {
+ kdError() << "failed to create a plugin object for " << name << endl;
+ success = false;
+ }
+ else {
+ // we have to register the plugin here, otherwise, we can get
+ // recursive loads
+ _plugins[name] = plugin;
+ _categories[plugin->category()].append(plugin);
+ }
+ }
+
+ // initialize the plugin
+ if(success && plugin) {
+ success = plugin->init();
+ if(!success) {
+ // on failure, delete the plugin. this should cause the
+ // library to unload.
+ kdError() << "failure initializing " << name << endl;
+ _categories[plugin->category()].remove(plugin);
+ _plugins.remove(name);
+ delete plugin;
+ }
+ }
+
+ // finally, finally connect to the destroyed signal and keep a
+ // reference to it
+ if(success) {
+ plugin->ref();
+ connect(plugin, SIGNAL(destroyed(QObject *)), SLOT(slotDestroyed(QObject *)));
+ }
+
+ return plugin;
+}
+
+Plugin *
+PluginLoader::findPlugin(const QString &name)
+{
+ Plugin *ret = NULL;
+ PluginMap::iterator it = _plugins.find(name);
+ if(it != _plugins.end()) {
+ ret = it.data();
+ }
+ return ret;
+}
+
+void
+PluginLoader::unloadPlugin(const QString &name)
+{
+ KLibLoader::self()->unloadLibrary(name.latin1());
+}
+
+const PluginLoader::PluginMap &
+PluginLoader::plugins() const
+{
+ return _plugins;
+}
+
+const PluginLoader::CategoryMap &
+PluginLoader::categories() const
+{
+ return _categories;
+}
+
+void
+PluginLoader::slotDestroyed(QObject *obj)
+{
+ Plugin *plugin = static_cast<Plugin *>(obj);
+
+ // we can't just use the name because its already been destroyed
+ // at this point. we have to iterate thru and find the reference
+ // by hand.
+
+ PluginMap::iterator end(_plugins.end());
+ for(PluginMap::iterator i = _plugins.begin(); i != end; ++i) {
+ Plugin *p = i.data();
+ if(p == plugin) {
+ kdDebug() << "unloading plugin " << i.key() << endl;
+
+ // remove it from the mapping
+ _plugins.remove(i);
+ break;
+ }
+ }
+}
+
+#include "pluginloader.moc"
diff --git a/umbrello/umbrello/pluginloader.h b/umbrello/umbrello/pluginloader.h
new file mode 100644
index 00000000..64ebed6f
--- /dev/null
+++ b/umbrello/umbrello/pluginloader.h
@@ -0,0 +1,132 @@
+/***************************************************************************
+ pluginloader.h
+ -------------------
+ begin : Mon Jan 13 2003
+ copyright : (C) 2003 by Andrew Sutton
+ email : ansutton@kent.edu
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMBRELLO_PLUGINLOADER_H
+#define UMBRELLO_PLUGINLOADER_H
+
+// Qt includes
+#include <qobject.h>
+#include <qvaluelist.h>
+#include <qmap.h>
+
+// forward declarations
+class QString;
+
+namespace Umbrello
+{
+// forward declarations
+class Plugin;
+
+/**
+ * @ingroup U2_Lib
+ *
+ * The plugin loader is an abstraction that sits on top of KLibLoader.
+ * Whereas plugins are specialized shared objects, the plugin must
+ * specialize the loading of those objects. Essentially, the plugin
+ * loader provides a single unit of functionality - loading plugins.
+ * In order to load a plugin, we must first load a shared library
+ * and then use the libraries factory to create the plugin. However,
+ * because a plugin is required to be a singleton, we must ensure
+ * that no plugin is ever created more than once. To that end, the
+ * loader must also retain a map of loaded plugins. When a loaded
+ * plugin is requested, we can increase its reference count.
+ *
+ * On the subject of unloading, we actually have very little to do.
+ * The unload method on a plugin is simply a reference decrementer.
+ * When it reaches 0, the object destroys itself. Being a QObject,
+ * it will emit the destroyed signal just before deletion, allowing
+ * the plugin loader to respond to the event and remove the plugin
+ * from its mapping.
+ *
+ * The PluginLoader also manages categories of plugins. The runtime
+ * categories actually reflect the directory structure of the build
+ * environment with each category represented by the name of a
+ * directory. The categories are "pre-seeded" at startup.
+ *
+ * @bug Plugins are not removed from their respective categories
+ * when they are destroyed. It may be acceptable to call
+ * Plugin::category() from slotDestroyed because the category()
+ * method doesn't reference any local variables - it just returns
+ * a string.
+ */
+class PluginLoader : public QObject
+{
+ Q_OBJECT
+public:
+ /** Destry the plugin loader */
+ ~PluginLoader();
+
+
+ /** Just a container of plugins */
+ typedef QValueList<Plugin *> PluginList;
+
+ /** The containment type for mapping plugins */
+ typedef QMap<QString, Plugin *> PluginMap;
+
+ /** Container of plugin categories */
+ typedef QMap<QString, PluginList> CategoryMap;
+
+ /** Singleton accessor */
+ static PluginLoader *instance();
+
+ /**
+ * Load a plugin. Test to see if the plugin already exists. If it
+ * does, just add a reference to it and continue on.
+ */
+ Plugin *loadPlugin(const QString &name);
+
+ /** Find a plugin */
+ Plugin *findPlugin(const QString &name);
+
+ /**
+ * Unload a plugin. Never use this method. It is only used by the deref
+ * method of a plugin to cause this class to unload the corresponding
+ * library. In fact, there is actually no corresponding plugin to unload,
+ * we just unload the library.
+ */
+ void unloadPlugin(const QString &name);
+
+ /**
+ * Get a reference to the plugin mapping. This method wraps everything
+ * in consts with the express purpose that no changes are made to the
+ * plugin map after using this method.
+ */
+ const PluginMap &plugins() const;
+
+ /** Get a reference to the plugin category mapping. */
+ const CategoryMap &categories() const;
+
+private slots:
+ /**
+ * This is used to connect to the destroyed signal emitted by plugins
+ * when they are finally deleted. The plugin loader uses this signal
+ * to remove the plugin from the plugin map.
+ */
+ void slotDestroyed(QObject *obj);
+
+private:
+ /** Private constructor - This must be created through the instance method */
+ PluginLoader();
+
+ static PluginLoader *_instance; ///< Singleton instance
+ PluginMap _plugins; ///< The plugin mapping
+ CategoryMap _categories; ///< Categories of plugins
+};
+}
+
+#endif
diff --git a/umbrello/umbrello/refactoring/Makefile.am b/umbrello/umbrello/refactoring/Makefile.am
new file mode 100644
index 00000000..4ab82c59
--- /dev/null
+++ b/umbrello/umbrello/refactoring/Makefile.am
@@ -0,0 +1,8 @@
+noinst_LTLIBRARIES = librefactoring.la
+
+INCLUDES = -I$(top_srcdir) -I$(top_builddir)/umbrello/umbrello/dialogs $(all_includes)
+
+librefactoring_la_METASOURCES = AUTO
+
+librefactoring_la_SOURCES = refactoringassistant.cpp
+
diff --git a/umbrello/umbrello/refactoring/refactoringassistant.cpp b/umbrello/umbrello/refactoring/refactoringassistant.cpp
new file mode 100644
index 00000000..0cbcf6aa
--- /dev/null
+++ b/umbrello/umbrello/refactoring/refactoringassistant.cpp
@@ -0,0 +1,701 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003 Luis De la Parra <lparrab@gmx.net> *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "refactoringassistant.h"
+
+#include "../umlnamespace.h"
+#include "../umldoc.h"
+#include "../classifier.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../dialogs/classpropdlg.h"
+#include "../dialogs/umloperationdialog.h"
+#include "../dialogs/umlattributedialog.h"
+#include "../object_factory.h"
+
+#include <qpoint.h>
+#include <qpopupmenu.h>
+
+#include <typeinfo>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+using std::type_info;
+
+
+RefactoringAssistant::RefactoringAssistant( UMLDoc *doc, UMLClassifier *obj, QWidget *parent, const char *name ):
+ KListView( parent, name ), m_doc( doc )
+{
+ loadPixmaps();
+
+ setRootIsDecorated( true );
+ setAcceptDrops( true );
+ setDropVisualizer( false );
+ setItemsMovable( true );
+ setSelectionModeExt( Single );
+ setShowToolTips( true );
+ setTooltipColumn( 0 );
+ setDragEnabled( true );
+ setDropHighlighter( true );
+ setFullWidth( true );
+ setSorting( -1 );
+
+ addColumn("Name ");
+
+ m_menu = new QPopupMenu(this);
+
+ connect(this,SIGNAL(doubleClicked(QListViewItem*)),this,SLOT(itemExecuted(QListViewItem*)));
+ connect(this,SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this,SLOT(showContextMenu(KListView*,QListViewItem*,const QPoint&)));
+
+ resize(300,400);
+
+ refactor( obj );
+}
+
+RefactoringAssistant::~RefactoringAssistant()
+{
+ m_umlObjectMap.clear();
+ clear();
+}
+
+void RefactoringAssistant::refactor( UMLClassifier *obj )
+{
+ clear();
+ m_umlObjectMap.clear();
+ m_umlObject = obj;
+ if (! m_umlObject )
+ {
+ return;
+ }
+
+ addClassifier( obj, 0, true, true, true );
+ QListViewItem *item = firstChild();
+ item->setOpen(true);
+ for( item = item->firstChild(); item ; item = item->nextSibling() )
+ item->setOpen(true);
+}
+
+
+UMLObject* RefactoringAssistant::findUMLObject( const QListViewItem *item )
+{
+ QListViewItem *i = const_cast<QListViewItem*>(item);
+ if( m_umlObjectMap.find(i) == m_umlObjectMap.end() )
+ {
+ kWarning()<<"RefactoringAssistant::findUMLObject( QListViewItem *item )"
+ <<"item with text "<<item->text(0)<<"not found in uml map!"<<endl;
+ return 0L;
+ }
+ return m_umlObjectMap[i];
+
+}
+
+QListViewItem* RefactoringAssistant::findListViewItem( const UMLObject *obj )
+{
+ UMLObjectMap::iterator end(m_umlObjectMap.end());
+ for( UMLObjectMap::iterator it(m_umlObjectMap.begin()) ; it != end ; ++it )
+ if( (*it).second == obj )
+ return (*it).first;
+ kWarning() << "RefactoringAssistant::findListViewItem:"
+ << "object id " << ID2STR(obj->getID())
+ << "does not have a ListItem" << endl;
+ return 0L;
+}
+
+
+void RefactoringAssistant::itemExecuted( QListViewItem *item )
+{
+ UMLObject *o = findUMLObject( item );
+ if(o) editProperties( );
+}
+
+void RefactoringAssistant::setVisibilityIcon( QListViewItem *item , const UMLObject *obj )
+{
+ switch(obj->getVisibility())
+ {
+ case Uml::Visibility::Public:
+ item->setPixmap(0,m_pixmaps.Public);
+ break;
+ case Uml::Visibility::Protected:
+ item->setPixmap(0,m_pixmaps.Protected);
+ break;
+ case Uml::Visibility::Private:
+ item->setPixmap(0,m_pixmaps.Private);
+ break;
+ case Uml::Visibility::Implementation:
+ item->setPixmap(0,m_pixmaps.Implementation);
+ break;
+ break;
+ }
+}
+
+void RefactoringAssistant::umlObjectModified( const UMLObject *obj )
+{
+ if( !obj )
+ obj = dynamic_cast<const UMLObject*>(sender());
+ QListViewItem *item = findListViewItem( obj );
+ if( !item )
+ return;
+ item->setText( 0, obj->getName() );
+ if( typeid(*obj) == typeid(UMLOperation) ||
+ typeid(*obj) == typeid(UMLAttribute) )
+ {
+ setVisibilityIcon( item, obj );
+ }
+}
+
+void RefactoringAssistant::operationAdded( UMLClassifierListItem *o )
+{
+ UMLOperation *op = static_cast<UMLOperation*>(o);
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(op->parent());
+ if(!c)
+ {
+ kWarning() << "RefactoringAssistant::operationAdded(" << op->getName()
+ << ") - Parent of operation is not a classifier!" << endl;
+ return;
+ }
+ QListViewItem *item = findListViewItem( c );
+ if( !item )
+ {
+ return;
+ }
+ for( QListViewItem *folder = item->firstChild(); folder; folder = folder->nextSibling() )
+ {
+ if( folder->text(1) == "operations" )
+ {
+ item = new KListViewItem( folder, op->getName() );
+ m_umlObjectMap[item] = op;
+ connect( op, SIGNAL( modified() ), this, SLOT( umlObjectModified() ) );
+ setVisibilityIcon( item, op );
+ break;
+ }
+ }
+}
+
+void RefactoringAssistant::operationRemoved( UMLClassifierListItem *o )
+{
+ UMLOperation *op = static_cast<UMLOperation*>(o);
+ QListViewItem *item = findListViewItem( op );
+ if( !item )
+ {
+ return;
+ }
+ disconnect( op, SIGNAL( modified() ), this, SLOT( umlObjectModified() ) );
+ m_umlObjectMap.erase(item);
+ delete item;
+}
+
+
+void RefactoringAssistant::attributeAdded( UMLClassifierListItem *a )
+{
+ UMLAttribute *att = static_cast<UMLAttribute*>(a);
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(att->parent());
+ if(!c)
+ {
+ kWarning() << "RefactoringAssistant::attributeAdded(" << att->getName()
+ << ") - Parent is not a class!" << endl;
+ return;
+ }
+ QListViewItem *item = findListViewItem( c );
+ if( !item )
+ {
+ return;
+ }
+ for( QListViewItem *folder = item->firstChild(); folder; folder = folder->nextSibling() )
+ {
+ if( folder->text(1) == "attributes" )
+ {
+ item = new KListViewItem( folder, att->getName() );
+ m_umlObjectMap[item] = att;
+ connect( att, SIGNAL( modified() ), this, SLOT( umlObjectModified() ) );
+ setVisibilityIcon( item, att );
+ break;
+ }
+ }
+}
+
+void RefactoringAssistant::attributeRemoved( UMLClassifierListItem *a )
+{
+ UMLAttribute *att = static_cast<UMLAttribute*>(a);
+ QListViewItem *item = findListViewItem( att );
+ if( !item )
+ {
+ return;
+ }
+ disconnect( att, SIGNAL( modified() ), this, SLOT( umlObjectModified() ) );
+ m_umlObjectMap.erase(item);
+ delete item;
+}
+
+void RefactoringAssistant::editProperties( )
+{
+ QListViewItem *item = selectedItem();
+ if( item )
+ {
+ UMLObject *o = findUMLObject( item );
+ if( o ) editProperties( o );
+ }
+}
+
+void RefactoringAssistant::editProperties( UMLObject *obj )
+{
+ KDialogBase *dia(0);
+ Uml::Object_Type t = obj->getBaseType();
+ if (t == Uml::ot_Class || t == Uml::ot_Interface)
+ {
+ dia = new ClassPropDlg(this,obj,0,true);
+ }
+ else if (t == Uml::ot_Operation)
+ {
+ dia = new UMLOperationDialog(this,static_cast<UMLOperation*>(obj));
+ }
+ else if (t == Uml::ot_Attribute)
+ {
+ dia = new UMLAttributeDialog(this,static_cast<UMLAttribute*>(obj));
+ }
+ else
+ {
+ kWarning()<<"RefactoringAssistant::editProperties( UMLObject *o ) caled for unknown type "<<typeid(*obj).name()<<endl;
+ return;
+ }
+ if( dia && dia->exec() )
+ {
+ // need to update something?
+ }
+ delete dia;
+}
+
+void RefactoringAssistant::showContextMenu(KListView* ,QListViewItem *item, const QPoint &p)
+{
+ m_menu->clear();
+ UMLObject *obj = findUMLObject( item );
+ if(obj)
+ {// Menu for UMLObjects
+ Uml::Object_Type t = obj->getBaseType();
+ if (t == Uml::ot_Class)
+ {
+ m_menu->insertItem(i18n("Add Base Class"),this,SLOT(addBaseClassifier()));
+ m_menu->insertItem(i18n("Add Derived Class"),this,SLOT(addDerivedClassifier()));
+ // m_menu->insertItem(i18n("Add Interface Implementation"),this,SLOT(addInterfaceImplementation()));
+ m_menu->insertItem(i18n("Add Operation"),this,SLOT(createOperation()));
+ m_menu->insertItem(i18n("Add Attribute"),this,SLOT(createAttribute()));
+ }
+ else if (t == Uml::ot_Interface)
+ {
+ m_menu->insertItem(i18n("Add Base Interface"),this,SLOT(addSuperClassifier()));
+ m_menu->insertItem(i18n("Add Derived Interface"),this,SLOT(addDerivedClassifier()));
+ m_menu->insertItem(i18n("Add Operation"),this,SLOT(createOperation()));
+ }
+ // else
+ // {
+ // kDebug()<<"No context menu for objects of type "<<typeid(*obj).name()<<endl;
+ // return;
+ // }
+ m_menu->insertSeparator();
+ m_menu->insertItem(i18n("Properties"),this,SLOT(editProperties()));
+ }
+ else
+ {//menu for other ViewItems
+ if( item->text(1) == "operations" )
+ {
+ m_menu->insertItem(i18n("Add Operation"),this,SLOT(createOperation()));
+ }
+ else if( item->text(1) == "attributes" )
+ {
+ m_menu->insertItem(i18n("Add Attribute"),this,SLOT(createAttribute()));
+ }
+ else
+ {
+ kWarning()<<"RefactoringAssistant::showContextMenu() "
+ <<"called for extraneous item"<<endl;
+ return;
+ }
+ }
+ m_menu->exec(p);
+}
+
+void RefactoringAssistant::addBaseClassifier()
+{
+ QListViewItem *item = selectedItem();
+ if(!item)
+ {
+ kWarning()<<"RefactoringAssistant::addBaseClassifier() "
+ <<"called with no item selected"<<endl;
+ return;
+ }
+ UMLObject *obj = findUMLObject( item );
+ if( !dynamic_cast<UMLClassifier*>(obj) )
+ {
+ kWarning()<<"RefactoringAssistant::addBaseClassifier() "
+ <<"called for a non-classifier object"<<endl;
+ return;
+ }
+
+ //classes have classes and interfaces interfaces as super/derived classifiers
+ Uml::Object_Type t = obj->getBaseType();
+ UMLClassifier *super = static_cast<UMLClassifier*>(Object_Factory::createUMLObject(t));
+ if(!super)
+ return;
+ m_doc->createUMLAssociation( obj, super, Uml::at_Generalization );
+ ////////////////////// Manually add the classifier to the assitant - would be nicer to do it with
+ ///////////////////// a signal, like operations and attributes
+ QListViewItem *baseFolder = item->firstChild();
+ while( baseFolder->text(0) != i18n("Base Classifiers") )
+ baseFolder = baseFolder->nextSibling();
+ if(!baseFolder)
+ {
+ kWarning()<<"Cannot find Base Folder"<<endl;
+ return;
+ }
+ item = new KListViewItem( baseFolder, super->getName() );
+ item->setPixmap(0,m_pixmaps.Generalization);
+ item->setExpandable( true );
+ m_umlObjectMap[item] = super;
+ addClassifier( super, item, true, false, true);
+ /////////////////////////
+}
+
+void RefactoringAssistant::addDerivedClassifier()
+{
+ QListViewItem *item = selectedItem();
+ if(!item)
+ {
+ kWarning()<<"RefactoringAssistant::addDerivedClassifier() "
+ <<"called with no item selected"<<endl;
+ return;
+ }
+ UMLObject *obj = findUMLObject( item );
+ if( !dynamic_cast<UMLClassifier*>(obj) )
+ {
+ kWarning()<<"RefactoringAssistant::addDerivedClassifier() "
+ <<"called for a non-classifier object"<<endl;
+ return;
+ }
+
+ //classes have classes and interfaces interfaces as super/derived classifiers
+ Uml::Object_Type t = obj->getBaseType();
+ UMLClassifier *derived = static_cast<UMLClassifier*>(Object_Factory::createUMLObject(t));
+ if(!derived)
+ return;
+ m_doc->createUMLAssociation( derived, obj, Uml::at_Generalization );
+
+ ////////////////////// Manually add the classifier to the assitant - would be nicer to do it with
+ ///////////////////// a signal, like operations and attributes
+ QListViewItem *derivedFolder = item->firstChild();
+ while( derivedFolder->text(0) != i18n("Derived Classifiers") )
+ derivedFolder = derivedFolder->nextSibling();
+ if(!derivedFolder)
+ {
+ kWarning()<<"Cannot find Derived Folder"<<endl;
+ return;
+ }
+ item = new KListViewItem( derivedFolder, derived->getName() );
+ item->setPixmap(0,m_pixmaps.Subclass);
+ item->setExpandable( true );
+ m_umlObjectMap[item] = derived;
+ addClassifier( derived, item, false, true, true);
+ /////////////////////////
+}
+
+void RefactoringAssistant::addInterfaceImplementation()
+{
+ kWarning()<<"RefactoringAssistant::addInterfaceImplementation()"
+ <<"not implemented... finish addSuperClassifier() first!!"<<endl;
+ return;
+ // QListViewItem *item = selectedListViewItem( );
+ // UMLObject *obj = findUMLObject( item );
+ // if( !dynamic_cast<UMLClassifier*>(obj) )
+ // return;
+ // UMLObject *n = Object_Factory::createUMLObject( Uml::ot_Interface) );
+ // if(!n)
+ // return;
+ // m_doc->createUMLAssociation( n, obj, Uml::at_Realization );
+ // //refresh, add classifier to assistant
+}
+
+void RefactoringAssistant::createOperation()
+{
+ QListViewItem *item = selectedItem();
+ if(!item)
+ {
+ kWarning()<<"RefactoringAssistant::createOperation() "
+ <<"called with no item selected"<<endl;
+ return;
+ }
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(findUMLObject( item ));
+ if( !c )
+ return;
+ c->createOperation();
+}
+
+void RefactoringAssistant::createAttribute()
+{
+ QListViewItem *item = selectedItem();
+ if(!item)
+ {
+ kWarning()<<"RefactoringAssistant::createAttribute() "
+ <<"called with no item selected"<<endl;
+ return;
+ }
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(findUMLObject( item ));
+ if( !c )
+ return;
+ c->createAttribute();
+}
+
+
+void RefactoringAssistant::addClassifier( UMLClassifier *classifier, QListViewItem *parent, bool addSuper, bool addSub, bool recurse)
+{
+ QListViewItem *classifierItem, *item;
+ if( parent )
+ {
+ classifierItem = parent;
+ }
+ else
+ {
+ classifierItem= new KListViewItem( this, classifier->getName() );
+ m_umlObjectMap[classifierItem] = classifier;
+ }
+
+ connect( classifier, SIGNAL( modified() ), this, SLOT( umlObjectModified() ) );
+
+ UMLClassifier *klass = dynamic_cast<UMLClassifier*>(classifier);
+ if( klass )
+ {// only Classes have attributes...
+ connect( classifier, SIGNAL(attributeAdded(UMLClassifierListItem*)),
+ this, SLOT(attributeAdded(UMLClassifierListItem*)));
+ connect( classifier, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(attributeRemoved(UMLClassifierListItem*)));
+
+ QListViewItem *attsFolder = new KListViewItem( classifierItem, i18n("Attributes"), "attributes" );
+ attsFolder->setPixmap(0,SmallIcon("folder_green_open"));
+ attsFolder->setExpandable( true );
+ UMLAttributeList atts = klass->getAttributeList();
+ for( UMLAttribute *att = atts.first(); att; att = atts.next() )
+ {
+ attributeAdded( att );
+ }
+
+ }
+
+ // add operations
+ connect( classifier, SIGNAL(operationAdded(UMLClassifierListItem*)),
+ this, SLOT(operationAdded(UMLClassifierListItem*)));
+ connect( classifier, SIGNAL(operationRemoved(UMLClassifierListItem*)),
+ this, SLOT(operationRemoved(UMLClassifierListItem*)));
+
+ QListViewItem *opsFolder = new KListViewItem( classifierItem, i18n("Operations"), "operations" );
+ opsFolder->setPixmap(0,SmallIcon("folder_blue_open"));
+ opsFolder->setExpandable( true );
+ UMLOperationList ops(classifier->getOpList());
+ for( UMLOperation *op = ops.first(); op ; op = ops.next() )
+ {
+ operationAdded( op );
+ }
+
+ //if add parents
+ if(addSuper)
+ {
+ QListViewItem *superFolder = new KListViewItem( classifierItem, i18n("Base Classifiers") );
+ superFolder->setExpandable( true );
+ UMLClassifierList super = classifier->findSuperClassConcepts();
+ for( UMLClassifier *cl = super.first(); cl ; cl = super.next() )
+ {
+ item = new KListViewItem( superFolder, cl->getName() );
+ item->setPixmap(0,m_pixmaps.Generalization);
+ item->setExpandable( true );
+ m_umlObjectMap[item] = cl;
+ if( recurse )
+ {
+ addClassifier( cl, item, true, false, true);
+ }
+
+ }
+ }
+ if(addSub)
+ {
+ //add derived classifiers
+ QListViewItem *derivedFolder = new KListViewItem( classifierItem, i18n("Derived Classifiers") );
+ derivedFolder->setExpandable( true );
+ UMLClassifierList derived = classifier->findSubClassConcepts();
+ for( UMLClassifier *d = derived.first(); d ; d = derived.next() )
+ {
+ item = new KListViewItem( derivedFolder, d->getName() );
+ item->setPixmap(0,m_pixmaps.Subclass);
+ item->setExpandable( true );
+ m_umlObjectMap[item] = d;
+ if( recurse )
+ {
+ addClassifier( d, item, false, true, true);
+ }
+
+ }
+ }
+}
+
+
+bool RefactoringAssistant::acceptDrag(QDropEvent *event) const
+{
+ //first check if we can accept drops at all, and if the operation
+ // is a move within the list itself
+ if( !acceptDrops() || !itemsMovable() || (event->source()!=viewport()))
+ {
+ return false;
+ }
+
+ RefactoringAssistant *me = const_cast<RefactoringAssistant*>(this);
+
+ //ok, check if the move is valid
+ QListViewItem *movingItem = 0, *afterme = 0, *parentItem = 0;
+ me->findDrop(event->pos(), parentItem, afterme);
+ for( movingItem = firstChild(); movingItem != 0; movingItem = movingItem->itemBelow() )
+ {
+ if( movingItem->isSelected() )
+ break;
+ }
+ if(!movingItem || !parentItem)
+ { kDebug()<<"moving/parent items not found - can't accept drag!"<<endl;
+ return false;
+ }
+
+ UMLObject *movingObject;
+ if( !(movingObject = me->findUMLObject(movingItem)) )
+ {
+ kDebug()<<"Moving object not found in uml map!"<<movingItem->text(0)<<endl;
+ return false;
+ }
+ Uml::Object_Type t = movingObject->getBaseType();
+ if (t != Uml::ot_Attribute && t != Uml::ot_Operation)
+ {
+ kDebug()<<"only operations and attributes are movable! - return false"<<endl;
+ return false;
+ }
+
+ kDebug()<<"parent item is "<<parentItem->text(0)<<endl;
+ UMLObject *parentObject = me->findUMLObject(parentItem);
+ if( parentObject && dynamic_cast<UMLClassifier*>(parentObject) )
+ {
+ //droping to a classifier, ok
+ }
+ else
+ {//parent is not a classifier, so maybe it's a folder.. check types
+ if( (parentItem->text(1) == "operations" && t == Uml::ot_Operation)
+ || (parentItem->text(1) == "attributes" && t == Uml::ot_Attribute))
+ {
+ parentObject = me->findUMLObject( parentItem->parent() );
+ }
+ else
+ {
+ kDebug()<<"moving to item "<<parentItem->text(0)<<" -- "<<parentItem->text(1)<<" not valid"<<endl;
+ return false;
+ }
+ }
+ if (dynamic_cast<UMLClassifier*>(parentObject) &&
+ (t == Uml::ot_Attribute || t == Uml::ot_Operation))
+ {
+ return true;
+ }
+
+ kDebug()<<"how did I get here? return false!!"<<endl;
+ return false;
+}
+
+
+void RefactoringAssistant::movableDropEvent (QListViewItem* parentItem, QListViewItem* afterme)
+{
+ //when dropping on a class, we have to put the item in the appropriate folder!
+ UMLObject *movingObject;
+ UMLClassifier *newClassifier;
+ QListViewItem *movingItem;
+
+ for( movingItem = firstChild(); movingItem != 0; movingItem = movingItem->itemBelow() )
+ {
+ if( movingItem->isSelected() )
+ break;
+ }
+ if( !movingItem || (movingItem == afterme) || !(movingObject = findUMLObject(movingItem)) )
+ {
+ kWarning()<<"Moving item not found or dropping after itself or item not found in uml obj map. aborting. (drop had already been accepted)"<<endl;
+ return;
+ }
+ Uml::Object_Type t = movingObject->getBaseType();
+ newClassifier = dynamic_cast<UMLClassifier*>( findUMLObject( parentItem ) );
+ if(!newClassifier)
+ {
+ if ((parentItem->text(1) == "operations" && t == Uml::ot_Operation)
+ || (parentItem->text(1) == "attributes" && t == Uml::ot_Attribute))
+ {
+ newClassifier = dynamic_cast<UMLClassifier*>( findUMLObject( parentItem->parent() ) );
+ }
+ if(!newClassifier)
+ {
+ kWarning()<<"New parent of object is not a Classifier - Drop had already been accepted - check!"<<endl;
+ return;
+ }
+ }
+ if (t == Uml::ot_Operation)
+ {kDebug()<<"moving operation"<<endl;
+ UMLOperation *op = static_cast<UMLOperation*>(movingObject);
+ if(newClassifier->checkOperationSignature(op->getName(), op->getParmList()))
+ {
+ QString msg = QString(i18n("An operation with that signature already exists in %1.\n")).arg(newClassifier->getName())
+ +
+ QString(i18n("Choose a different name or parameter list." ));
+ KMessageBox::error(this, msg, i18n("Operation Name Invalid"), false);
+ return;
+ }
+ UMLClassifier *oldClassifier = dynamic_cast<UMLClassifier*>(op->parent());
+ if(oldClassifier)
+ oldClassifier->removeOperation( op );
+ newClassifier->addOperation( op );
+ }
+ else if (t == Uml::ot_Attribute)
+ {kDebug()<<"moving attribute - not implemented"<<endl;
+ // UMLAttribute *att = static_cast<UMLAttribute*>(movingObject);
+ // if(!newClassifier->checkAttributeSignature(att))
+ // {
+ // QString msg = QString(i18n("An attribute with that signature already exists in %1.\n")).arg(newClassifier->getName())
+ // +
+ // QString(i18n("Choose a different name or parameter list." ));
+ // KMessageBox::error(this, msg, i18n("Operation Name Invalid"), false);
+ // return;
+ // }
+ // oldClassifier->removeAttribute( att );
+ // newClassifier->addAttribute( att );
+ }
+ //emit moved(moving, afterFirst, afterme);
+ emit moved();
+}
+
+void RefactoringAssistant::loadPixmaps()
+{
+ KStandardDirs *dirs = KGlobal::dirs();
+ QString dataDir = dirs -> findResourceDir( "data", "umbrello/pics/object.png" );
+ dataDir += "/umbrello/pics/";
+
+ m_pixmaps.Public.load( dataDir + "CVpublic_var.png" );
+ m_pixmaps.Protected.load( dataDir + "CVprotected_var.png" );
+ m_pixmaps.Private.load( dataDir + "CVprivate_var.png" );
+ m_pixmaps.Implementation.load( dataDir + "CVimplementation_var.png" );
+ m_pixmaps.Generalization.load( dataDir + "generalisation.png" );
+ m_pixmaps.Subclass.load( dataDir + "uniassociation.png" );
+
+
+}
+
+
+
+
+#include "refactoringassistant.moc"
diff --git a/umbrello/umbrello/refactoring/refactoringassistant.h b/umbrello/umbrello/refactoring/refactoringassistant.h
new file mode 100644
index 00000000..5d8bd79f
--- /dev/null
+++ b/umbrello/umbrello/refactoring/refactoringassistant.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003 Luis De la Parra <lparrab@gmx.net> *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+
+#ifndef REFACTORING_ASSISTANT
+#define REFACTORING_ASSISTANT
+
+
+#include <klistview.h>
+#include <qpixmap.h>
+#include <map>
+
+
+class UMLObject;
+class UMLClassifier;
+class UMLClassifierListItem;
+class UMLDoc;
+
+class QPopupMenu;
+class QPoint;
+
+class RefactoringAssistant : public KListView
+{
+ Q_OBJECT
+public:
+ typedef std::map<QListViewItem*, UMLObject*> UMLObjectMap;
+
+ explicit RefactoringAssistant( UMLDoc *doc, UMLClassifier *obj = 0, QWidget *parent = 0, const char *name = 0 );
+ virtual ~RefactoringAssistant();
+
+ void refactor( UMLClassifier *obj );
+
+public slots:
+
+ void addBaseClassifier();
+ void addDerivedClassifier();
+ void addInterfaceImplementation();
+ void createOperation( );
+ void createAttribute( );
+ void editProperties( );
+
+ void umlObjectModified( const UMLObject *obj = 0 );
+
+ void operationAdded( UMLClassifierListItem *o );
+ void operationRemoved( UMLClassifierListItem *o );
+
+ void attributeAdded( UMLClassifierListItem *a );
+ void attributeRemoved( UMLClassifierListItem *a );
+
+ void itemExecuted( QListViewItem *item );
+ void showContextMenu( KListView*, QListViewItem*, const QPoint&);
+
+protected:
+ struct { QPixmap Public,
+ Protected,
+ Private,
+ Implementation,
+ Generalization,
+ Subclass;
+ } m_pixmaps;
+
+ UMLObject* findUMLObject( const QListViewItem* );
+ QListViewItem* findListViewItem( const UMLObject *obj );
+ void editProperties( UMLObject *obj );
+ void addClassifier( UMLClassifier *classifier, QListViewItem *parent = 0, bool addSuper = true, bool addSub = true, bool recurse = false );
+ void loadPixmaps();
+ virtual bool acceptDrag(QDropEvent *event) const;
+ virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme);
+ void setVisibilityIcon( QListViewItem *item , const UMLObject *obj );
+ UMLClassifier *m_umlObject;
+ UMLDoc *m_doc;
+ QPopupMenu *m_menu;
+ UMLObjectMap m_umlObjectMap;
+
+
+};
+
+
+#endif
+
diff --git a/umbrello/umbrello/seqlinewidget.cpp b/umbrello/umbrello/seqlinewidget.cpp
new file mode 100644
index 00000000..a4be0216
--- /dev/null
+++ b/umbrello/umbrello/seqlinewidget.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "seqlinewidget.h"
+
+//kde includes
+#include <kcursor.h>
+#include <kdebug.h>
+//app includes
+#include "umlview.h"
+#include "objectwidget.h"
+#include "messagewidget.h"
+
+// class members
+int const SeqLineWidget::m_nMouseDownEpsilonX = 20;
+
+SeqLineWidget::SeqLineWidget( UMLView * pView, ObjectWidget * pObject ) : QCanvasLine( pView -> canvas() ) {
+ m_pView = pView;
+ m_pObject = pObject;
+ setPen( QPen( m_pObject->getLineColor(), 0, Qt::DashLine ) );
+ setZ( 0 );
+ setVisible( true );
+ m_DestructionBox.line1 = 0;
+ m_nLengthY = 250;
+ setupDestructionBox();
+}
+
+SeqLineWidget::~SeqLineWidget() {}
+
+int SeqLineWidget::onWidget( const QPoint & p ) {
+ int nOnWidget = 0;
+ QPoint sp = startPoint();
+ QPoint ep = endPoint();
+ //see if on widget ( for message creation )
+ if( sp.x() - m_nMouseDownEpsilonX < p.x()
+ && ep.x() + m_nMouseDownEpsilonX > p.x()
+ && sp.y() < p.y() && ep.y() + 3 > p.y() )
+ {
+ nOnWidget = 1;
+ }
+ return nOnWidget;
+}
+
+void SeqLineWidget::cleanup() {
+ cleanupDestructionBox();
+}
+
+void SeqLineWidget::setStartPoint( int startX, int startY ) {
+ int endX = startX;
+ int endY = startY + m_nLengthY;
+ QCanvasLine::setPoints( startX, startY, endX, endY );
+ moveDestructionBox();
+}
+
+void SeqLineWidget::cleanupDestructionBox() {
+ if ( m_DestructionBox.line1 ) {
+ delete m_DestructionBox.line1;
+ m_DestructionBox.line1 = 0;
+ delete m_DestructionBox.line2;
+ m_DestructionBox.line2 = 0;
+ }
+}
+
+void SeqLineWidget::setupDestructionBox() {
+ cleanupDestructionBox();
+ if( !m_pObject->getShowDestruction() ) {
+ return;
+ }
+ QRect rect;
+ rect.setX( m_pObject->getX() + m_pObject->getWidth() / 2 - 10 );
+ rect.setY( m_pObject->getY() + m_pObject->getHeight() + m_nLengthY );
+ rect.setWidth( 14 );
+ rect.setHeight( 14 );
+
+ m_DestructionBox.line1 = new QCanvasLine( m_pView->canvas() );
+ m_DestructionBox.setLine1Points(rect);
+ m_DestructionBox.line1->setVisible( true );
+ m_DestructionBox.line1->setPen( QPen(m_pObject->getLineColor(), 2) );
+ m_DestructionBox.line1->setZ( 3 );
+
+ m_DestructionBox.line2 = new QCanvasLine( m_pView -> canvas() );
+ m_DestructionBox.setLine2Points(rect);
+ m_DestructionBox.line2->setVisible( true );
+ m_DestructionBox.line2->setPen( QPen(m_pObject->getLineColor(), 2) );
+ m_DestructionBox.line2->setZ( 3 );
+}
+
+void SeqLineWidget::moveDestructionBox() {
+ if( !m_DestructionBox.line1 ) {
+ return;
+ }
+ QRect rect;
+ rect.setX( m_pObject->getX() + m_pObject->getWidth() / 2 - 7 );
+ rect.setY( m_pObject->getY() + m_pObject->getHeight() + m_nLengthY - 7 );
+ rect.setWidth( 14 );
+ rect.setHeight( 14 );
+ m_DestructionBox.setLine1Points(rect);
+ m_DestructionBox.setLine2Points(rect);
+}
+
+void SeqLineWidget::setEndOfLine(int yPosition) {
+ QPoint sp = startPoint();
+ int newY = yPosition;
+ m_nLengthY = yPosition - m_pObject->getY() - m_pObject->getHeight();
+ // normally the managing Objectwidget is responsible for the call of this function
+ // but to be sure - make a double check _against current position_
+ if ( m_nLengthY < 0 ) {
+ m_nLengthY = 0;
+ newY = m_pObject->getY() + m_pObject->getHeight();
+ }
+ setPoints( sp.x(), sp.y(), sp.x(), newY );
+ moveDestructionBox();
+ m_pView->resizeCanvasToItems();
+}
+
diff --git a/umbrello/umbrello/seqlinewidget.h b/umbrello/umbrello/seqlinewidget.h
new file mode 100644
index 00000000..1978fafd
--- /dev/null
+++ b/umbrello/umbrello/seqlinewidget.h
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef SEQLINEWIDGET_H
+#define SEQLINEWIDGET_H
+
+#include <qcanvas.h>
+
+class UMLView;
+class ObjectWidget;
+
+/**
+ * @short Widget class for graphical representation of sequence lines
+ * @author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class SeqLineWidget : public QCanvasLine {
+public:
+ /**
+ * Constructor.
+ */
+ SeqLineWidget( UMLView * pView, ObjectWidget * pObject );
+
+ /**
+ * Destructor.
+ */
+ ~SeqLineWidget();
+
+ /**
+ * Return whether on seq. line.
+ * Takes into account destruction box if shown.
+ *
+ * @param p The point to investigate.
+ * @return Non-zero if point is on this sequence line.
+ */
+ int onWidget(const QPoint & p);
+
+ /**
+ * Clean up anything before deletion.
+ */
+ void cleanup();
+
+ /**
+ * Set up destruction box.
+ */
+ void setupDestructionBox();
+
+ /**
+ * Set the start point of the line.
+ *
+ * @param startX X coordinate of the start point.
+ * @param startY Y coordinate of the start point.
+ */
+ void setStartPoint( int startX, int startY );
+
+ /**
+ * Gets the length of the line.
+ *
+ * @return Length of the line.
+ */
+ int getLineLength() {
+ return m_nLengthY;
+ }
+
+ /**
+ * Returns the @ref ObjectWidget associated with this sequence line.
+ *
+ * @return Pointer to the associated ObjectWidget.
+ */
+ ObjectWidget * getObjectWidget() {
+ return m_pObject;
+ }
+
+ /**
+ * Sets the y position of the bottom of the vertical line.
+ *
+ * @param yPosition The y coordinate for the bottom of the line.
+ */
+ void setEndOfLine(int yPosition);
+
+protected:
+ /**
+ * Clean up destruction box.
+ */
+ void cleanupDestructionBox();
+
+ /**
+ * Move destruction box.
+ */
+ void moveDestructionBox();
+
+ /**
+ * ObjectWidget associated with this sequence line.
+ */
+ ObjectWidget * m_pObject;
+
+ /**
+ * View displayed on.
+ */
+ UMLView * m_pView;
+
+ /// The destruction box.
+ struct DestructionBox {
+ QCanvasLine * line1;
+ QCanvasLine * line2;
+ void setLine1Points(QRect rect) {
+ line1->setPoints( rect.x(), rect.y(),
+ rect.x() + rect.width(), rect.y() + rect.height() );
+ }
+ void setLine2Points(QRect rect) {
+ line2->setPoints( rect.x(), rect.y() + rect.height(),
+ rect.x() + rect.width(), rect.y() );
+ }
+ } m_DestructionBox;
+
+ /**
+ * The length of the line.
+ */
+ int m_nLengthY;
+
+ /**
+ * Margin used for mouse clicks.
+ */
+ static int const m_nMouseDownEpsilonX;
+};
+
+#endif
diff --git a/umbrello/umbrello/statewidget.cpp b/umbrello/umbrello/statewidget.cpp
new file mode 100644
index 00000000..9d104234
--- /dev/null
+++ b/umbrello/umbrello/statewidget.cpp
@@ -0,0 +1,297 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "statewidget.h"
+
+// qt includes
+#include <qevent.h>
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "docwindow.h"
+#include "umlwidget.h"
+#include "umlview.h"
+#include "dialogs/statedialog.h"
+#include "listpopupmenu.h"
+
+StateWidget::StateWidget(UMLView * view, StateType stateType, Uml::IDType id)
+ : UMLWidget(view, id) {
+ UMLWidget::setBaseType(Uml::wt_State);
+ m_StateType = stateType;
+ m_Text = "State";
+ updateComponentSize();
+}
+
+StateWidget::~StateWidget() {}
+
+void StateWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ const int w = width();
+ const int h = height();
+ switch (m_StateType)
+ {
+ case Normal :
+ if(UMLWidget::getUseFillColour())
+ p.setBrush(UMLWidget::getFillColour());
+ {
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ int textStartY = (h / 2) - (fontHeight / 2);
+ const int count = m_Activities.count();
+ if( count == 0 ) {
+ p.drawRoundRect(offsetX, offsetY, w, h, (h*40)/w, (w*40)/h);
+ p.setPen(Qt::black);
+ QFont font = UMLWidget::getFont();
+ font.setBold( false );
+ p.setFont( font );
+ p.drawText(offsetX + STATE_MARGIN, offsetY + textStartY,
+ w - STATE_MARGIN * 2, fontHeight,
+ Qt::AlignCenter, getName());
+ UMLWidget::setPen(p);
+ } else {
+ p.drawRoundRect(offsetX, offsetY, w, h, (h*40)/w, (w*40)/h);
+ textStartY = offsetY + STATE_MARGIN;
+ p.setPen(Qt::black);
+ QFont font = UMLWidget::getFont();
+ font.setBold( true );
+ p.setFont( font );
+ p.drawText(offsetX + STATE_MARGIN, textStartY, w - STATE_MARGIN * 2,
+ fontHeight, Qt::AlignCenter, getName());
+ font.setBold( false );
+ p.setFont( font );
+ UMLWidget::setPen(p);
+ int linePosY = textStartY + fontHeight;
+
+ QStringList::Iterator end(m_Activities.end());
+ for( QStringList::Iterator it(m_Activities.begin()); it != end; ++it ) {
+ textStartY += fontHeight;
+ p.drawLine( offsetX, linePosY, offsetX + w - 1, linePosY );
+ p.setPen(Qt::black);
+ p.drawText(offsetX + STATE_MARGIN, textStartY, w - STATE_MARGIN * 2 - 1,
+ fontHeight, Qt::AlignCenter, *it);
+ UMLWidget::setPen(p);
+ linePosY += fontHeight;
+ }//end for
+ }//end else
+ }
+ break;
+ case Initial :
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX, offsetY, w, h );
+ break;
+ case End :
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX, offsetY, w, h );
+ p.setBrush( Qt::white );
+ p.drawEllipse( offsetX + 1, offsetY + 1, w - 2, h - 2 );
+ p.setBrush( WidgetBase::getLineColor() );
+ p.drawEllipse( offsetX + 3, offsetY + 3, w - 6, h - 6 );
+ break;
+ default:
+ kWarning() << "Unknown state type:" << m_StateType << endl;
+ break;
+ }
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+QSize StateWidget::calculateSize() {
+ int width = 10, height = 10;
+ if ( m_StateType == Normal ) {
+ const QFontMetrics &fm = getFontMetrics(FT_BOLD);
+ const int fontHeight = fm.lineSpacing();
+ int textWidth = fm.width(getName());
+ const int count = m_Activities.count();
+ height = fontHeight;
+ if( count > 0 ) {
+ height = fontHeight * ( count + 1);
+
+ QStringList::Iterator end(m_Activities.end());
+ for( QStringList::Iterator it(m_Activities.begin()); it != end; ++it ) {
+ int w = fm.width( *it );
+ if( w > textWidth )
+ textWidth = w;
+ }//end for
+ }//end if
+ width = textWidth > STATE_WIDTH?textWidth:STATE_WIDTH;
+ height = height > STATE_HEIGHT?height:STATE_HEIGHT;
+ width += STATE_MARGIN * 2;
+ height += STATE_MARGIN * 2;
+ }
+
+ return QSize(width, height);
+}
+
+void StateWidget::setName(const QString &strName) {
+ m_Text = strName;
+ updateComponentSize();
+ adjustAssocs( getX(), getY() );
+}
+
+QString StateWidget::getName() const {
+ return m_Text;
+}
+
+StateWidget::StateType StateWidget::getStateType() const {
+ return m_StateType;
+}
+
+void StateWidget::setStateType( StateType stateType ) {
+ m_StateType = stateType;
+}
+
+void StateWidget::slotMenuSelection(int sel) {
+ bool done = false;
+ bool ok = false;
+ QString name = getName();
+
+ switch( sel ) {
+ case ListPopupMenu::mt_Rename:
+ name = KInputDialog::getText( i18n("Enter State Name"), i18n("Enter the name of the new state:"), getName(), &ok );
+ if( ok && name.length() > 0 )
+ setName( name );
+ done = true;
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ showProperties();
+ done = true;
+ break;
+ case ListPopupMenu::mt_New_Activity:
+ name = KInputDialog::getText( i18n("Enter Activity"), i18n("Enter the name of the new activity:"), i18n("new activity"), &ok );
+ if( ok && name.length() > 0 )
+ addActivity( name );
+ done = true;
+ break;
+ }
+
+ if( !done )
+ UMLWidget::slotMenuSelection( sel );
+}
+
+bool StateWidget::addActivity( const QString &activity ) {
+ m_Activities.append( activity );
+ updateComponentSize();
+ return true;
+}
+
+bool StateWidget::removeActivity( const QString &activity ) {
+ int index = - 1;
+ if( ( index = m_Activities.findIndex( activity ) ) == -1 )
+ return false;
+ m_Activities.remove( m_Activities.at( index ) );
+ updateComponentSize();
+ return true;
+}
+
+void StateWidget::setActivities( QStringList & list ) {
+ m_Activities = list;
+ updateComponentSize();
+}
+
+QStringList & StateWidget::getActivityList() {
+ return m_Activities;
+}
+
+bool StateWidget::renameActivity( const QString &activity, const QString &newName ) {
+ int index = - 1;
+ if( ( index = m_Activities.findIndex( activity ) ) == -1 )
+ return false;
+ m_Activities[ index ] = newName;
+ return true;
+}
+
+void StateWidget::showProperties() {
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation(false);
+
+ StateDialog dialog(m_pView, this);
+ if (dialog.exec() && dialog.getChangesMade()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->getDocument()->setModified(true);
+ }
+}
+
+bool StateWidget::isState(WorkToolBar::ToolBar_Buttons tbb, StateType& resultType)
+{
+ bool status = true;
+ switch (tbb) {
+ case WorkToolBar::tbb_Initial_State:
+ resultType = Initial;
+ break;
+ case WorkToolBar::tbb_State:
+ resultType = Normal;
+ break;
+ case WorkToolBar::tbb_End_State:
+ resultType = End;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ return status;
+}
+
+void StateWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement stateElement = qDoc.createElement( "statewidget" );
+ UMLWidget::saveToXMI( qDoc, stateElement );
+ stateElement.setAttribute( "statename", m_Text );
+ stateElement.setAttribute( "documentation", m_Doc );
+ stateElement.setAttribute( "statetype", m_StateType );
+ //save states activities
+ QDomElement activitiesElement = qDoc.createElement( "Activities" );
+
+ QStringList::Iterator end(m_Activities.end());
+ for( QStringList::Iterator it(m_Activities.begin()); it != end; ++it ) {
+ QDomElement tempElement = qDoc.createElement( "Activity" );
+ tempElement.setAttribute( "name", *it );
+ activitiesElement.appendChild( tempElement );
+ }//end for
+ stateElement.appendChild( activitiesElement );
+ qElement.appendChild( stateElement );
+}
+
+bool StateWidget::loadFromXMI( QDomElement & qElement ) {
+ if( !UMLWidget::loadFromXMI( qElement ) )
+ return false;
+ m_Text = qElement.attribute( "statename", "" );
+ m_Doc = qElement.attribute( "documentation", "" );
+ QString type = qElement.attribute( "statetype", "1" );
+ m_StateType = (StateType)type.toInt();
+ //load states activities
+ QDomNode node = qElement.firstChild();
+ QDomElement tempElement = node.toElement();
+ if( !tempElement.isNull() && tempElement.tagName() == "Activities" ) {
+ QDomNode node = tempElement.firstChild();
+ QDomElement activityElement = node.toElement();
+ while( !activityElement.isNull() ) {
+ if( activityElement.tagName() == "Activity" ) {
+ QString name = activityElement.attribute( "name", "" );
+ if( !name.isEmpty() )
+ m_Activities.append( name );
+ }//end if
+ node = node.nextSibling();
+ activityElement = node.toElement();
+ }//end while
+ }//end if
+ return true;
+}
+
+
+#include "statewidget.moc"
+
diff --git a/umbrello/umbrello/statewidget.h b/umbrello/umbrello/statewidget.h
new file mode 100644
index 00000000..d214980b
--- /dev/null
+++ b/umbrello/umbrello/statewidget.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+***************************************************************************/
+
+#ifndef STATEWIDGET_H
+#define STATEWIDGET_H
+#include <qpainter.h>
+#include <qstringlist.h>
+#include "umlwidget.h"
+#include "worktoolbar.h"
+
+#define STATE_MARGIN 5
+#define STATE_WIDTH 30
+#define STATE_HEIGHT 10
+
+/**
+ * This class is the graphical version of a UML State.
+ *
+ * A StateWidget is created by a @ref UMLView. A StateWidget belongs to
+ * only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to is destroyed,
+ * it will be automatically deleted.
+ *
+ * The StateWidget class inherits from the @ref UMLWidget class which adds
+ * most of the functionality to this class.
+ *
+ * @short A graphical version of a UML State.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class StateWidget : public UMLWidget {
+ Q_OBJECT
+public:
+
+ /// Enumeration that codes the different types of state.
+ enum StateType
+ {
+ Initial = 0,
+ Normal,
+ End
+ };
+
+ /**
+ * Creates a State widget.
+ *
+ * @param view The parent of the widget.
+ * @param stateType The type of state.
+ * @param id The ID to assign (-1 will prompt a new ID.)
+ */
+ explicit StateWidget( UMLView * view, StateType stateType = Normal, Uml::IDType id = Uml::id_None );
+
+ /**
+ * destructor
+ */
+ virtual ~StateWidget();
+
+ /**
+ * Overrides the standard paint event.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Sets the name of the State.
+ */
+ virtual void setName(const QString &strName);
+
+ /**
+ * Returns the name of the State.
+ */
+ virtual QString getName() const;
+
+ /**
+ * Returns the type of state.
+ */
+ StateType getStateType() const;
+
+ /**
+ * Sets the type of state.
+ */
+ void setStateType( StateType stateType );
+
+ /**
+ * Adds the given activity to the state.
+ */
+ bool addActivity( const QString &activity );
+
+ /**
+ * Removes the given activity from the state.
+ */
+ bool removeActivity( const QString &activity );
+
+ /**
+ * Renames the given activity.
+ */
+ bool renameActivity( const QString &activity, const QString &newName );
+
+ /**
+ * Sets the states activities to the ones given.
+ */
+ void setActivities( QStringList & list );
+
+ /**
+ * Returns the list of activities.
+ */
+ QStringList & getActivityList();
+
+ /**
+ * Show a properties dialog for a StateWidget.
+ */
+ void showProperties();
+
+ /**
+ * Returns true if the given toolbar button represents a State.
+ *
+ * @param tbb Input value of type WorkToolBar::ToolBar_Buttons.
+ * @param resultType Output value, the StateType that corresponds to tbb.
+ * Only set if the method returns true.
+ */
+ static bool isState( WorkToolBar::ToolBar_Buttons tbb,
+ StateType& resultType );
+
+ /**
+ * Creates the "statewidget" XMI element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads a "statewidget" XMI element.
+ */
+ bool loadFromXMI( QDomElement & qElement );
+
+protected:
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+
+ /**
+ * Type of state.
+ */
+ StateType m_StateType;
+
+ /**
+ * List of activities for the state.
+ */
+ QStringList m_Activities;
+
+public slots:
+
+ /**
+ * Captures any popup menu signals for menus it created.
+ */
+ void slotMenuSelection(int sel);
+};
+
+#endif
diff --git a/umbrello/umbrello/stereotype.cpp b/umbrello/umbrello/stereotype.cpp
new file mode 100644
index 00000000..5cd68f11
--- /dev/null
+++ b/umbrello/umbrello/stereotype.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "stereotype.h"
+
+// qt/kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kinputdialog.h>
+
+// local includes
+#include "umldoc.h"
+#include "uml.h"
+
+UMLStereotype::UMLStereotype(const QString &name, Uml::IDType id /* = Uml::id_None */)
+ : UMLObject( name, id ) {
+ m_BaseType = Uml::ot_Stereotype;
+ UMLStereotype * existing = UMLApp::app()->getDocument()->findStereotype(name);
+ if (existing) {
+ kError() << "UMLStereotype constructor: " << name << " already exists"
+ << kdBacktrace(25) << endl;
+ }
+ m_refCount = 0;
+}
+
+UMLStereotype::UMLStereotype() : UMLObject() {
+ m_BaseType = Uml::ot_Stereotype;
+ m_refCount = 0;
+}
+
+UMLStereotype::~UMLStereotype() {}
+
+bool UMLStereotype::operator==( UMLStereotype &rhs) {
+ if (this == &rhs) {
+ return true;
+ }
+
+ if ( !UMLObject::operator==( rhs ) ) {
+ return false;
+ }
+
+ return true;
+}
+
+void UMLStereotype::copyInto(UMLStereotype *rhs) const
+{
+ UMLObject::copyInto(rhs);
+}
+
+UMLObject* UMLStereotype::clone() const
+{
+ UMLStereotype *clone = new UMLStereotype();
+ copyInto(clone);
+
+ return clone;
+}
+
+
+void UMLStereotype::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ //FIXME: uml13.dtd compliance
+ QDomElement stereotypeElement = UMLObject::save("UML:Stereotype", qDoc);
+ qElement.appendChild( stereotypeElement );
+}
+
+bool UMLStereotype::showPropertiesDialog(QWidget* parent) {
+ bool ok;
+ QString name = KInputDialog::getText(i18n("Stereotype"), i18n("Enter name:"), getName(),&ok, parent);
+ if (ok) {
+ setName(name);
+ }
+ return ok;
+}
+
+void UMLStereotype::incrRefCount() {
+ m_refCount++;
+}
+
+void UMLStereotype::decrRefCount() {
+ m_refCount--;
+}
+
+int UMLStereotype::refCount() const {
+ return m_refCount;
+}
+
diff --git a/umbrello/umbrello/stereotype.h b/umbrello/umbrello/stereotype.h
new file mode 100644
index 00000000..a836952f
--- /dev/null
+++ b/umbrello/umbrello/stereotype.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef STEREOTYPE_H
+#define STEREOTYPE_H
+
+#include "umlobject.h"
+
+/**
+ * This class is used to set up information for a stereotype.
+ * Stereotypes are used essentially as properties of
+ * attributes and operations etc.
+ *
+ * @short Sets up stereotype information.
+ * @author Jonathan Riddell
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLStereotype : public UMLObject {
+public:
+ /**
+ * Sets up a stereotype.
+ *
+ * @param name The name of this UMLStereotype.
+ * @param id The unique id given to this UMLStereotype.
+ */
+ explicit UMLStereotype(const QString &name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Sets up a stereotype.
+ */
+ UMLStereotype();
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==(UMLStereotype &rhs);
+
+ /**
+ * destructor
+ */
+ virtual ~UMLStereotype();
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLStereotype *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Increments the reference count for this stereotype.
+ */
+ void incrRefCount();
+
+ /**
+ * Decrements the reference count for this stereotype.
+ */
+ void decrRefCount();
+
+ /**
+ * Returns the reference count for this stereotype.
+ */
+ int refCount() const;
+
+ /**
+ * Saves to the <UML:StereoType> XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Display the properties configuration dialog for the stereotype
+ * (just a line edit).
+ */
+ bool showPropertiesDialog(QWidget* parent);
+
+protected:
+ /**
+ * Each stereotype object is reference counted, i.e. client code
+ * manages it such that it comes into existence as soon as there is
+ * at least one user, and ceases existing when the number of users
+ * drops to 0.
+ * m_refCount reflects the number of users. It is externally managed,
+ * i.e. client code must take care to call incrRefCount() and
+ * decrRefCount() as appropriate.
+ */
+ int m_refCount;
+};
+
+#endif
diff --git a/umbrello/umbrello/template.cpp b/umbrello/umbrello/template.cpp
new file mode 100644
index 00000000..12d08fab
--- /dev/null
+++ b/umbrello/umbrello/template.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "template.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "dialogs/umltemplatedialog.h"
+
+UMLTemplate::UMLTemplate(const UMLObject *parent, const QString& name,
+ Uml::IDType id, const QString& type)
+ : UMLClassifierListItem( parent, name, id ) {
+ setTypeName( type );
+ m_BaseType = Uml::ot_Template;
+}
+
+UMLTemplate::UMLTemplate(const UMLObject *parent)
+ : UMLClassifierListItem( parent ) {
+ m_BaseType = Uml::ot_Template;
+}
+
+UMLTemplate::~UMLTemplate() {}
+
+QString UMLTemplate::toString(Uml::Signature_Type /*sig = st_NoSig*/) {
+ if (m_pSecondary == NULL || m_pSecondary->getName() == "class") {
+ return getName();
+ } else {
+ return getName() + " : " + m_pSecondary->getName();
+ }
+}
+
+QString UMLTemplate::getTypeName() {
+ if (m_pSecondary == NULL)
+ return "class";
+ return m_pSecondary->getName();
+}
+
+bool UMLTemplate::operator==(UMLTemplate &rhs) {
+ if (this == &rhs) {
+ return true;
+ }
+ if ( !UMLObject::operator==( rhs ) ) {
+ return false;
+ }
+ if (m_pSecondary != rhs.m_pSecondary) {
+ return false;
+ }
+ return true;
+}
+
+void UMLTemplate::copyInto(UMLTemplate *rhs) const
+{
+ UMLClassifierListItem::copyInto(rhs);
+}
+
+UMLObject* UMLTemplate::clone() const
+{
+ UMLTemplate *clone = new UMLTemplate( (UMLTemplate*) parent());
+ copyInto(clone);
+
+ return clone;
+}
+
+
+void UMLTemplate::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ //FIXME: uml13.dtd compliance
+ QDomElement attributeElement = UMLObject::save("UML:TemplateParameter", qDoc);
+ if (m_pSecondary)
+ attributeElement.setAttribute("type", ID2STR(m_pSecondary->getID()));
+ qElement.appendChild(attributeElement);
+}
+
+bool UMLTemplate::load(QDomElement& element) {
+ m_SecondaryId = element.attribute("type", "");
+ return true;
+}
+
+bool UMLTemplate::showPropertiesDialog(QWidget* parent) {
+ UMLTemplateDialog dialog(parent, this);
+ return dialog.exec();
+}
diff --git a/umbrello/umbrello/template.h b/umbrello/umbrello/template.h
new file mode 100644
index 00000000..1109411a
--- /dev/null
+++ b/umbrello/umbrello/template.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TEMPLATE_H
+#define TEMPLATE_H
+
+#include "classifierlistitem.h"
+
+/**
+ * This class holds information used by template classes, called
+ * paramaterised class in UML and a generic in Java. It has a
+ * type (usually just "class") and name.
+ *
+ * @short Sets up template information.
+ * @author Jonathan Riddell
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLTemplate : public UMLClassifierListItem {
+public:
+ /**
+ * Sets up a template.
+ *
+ * @param parent The parent of this UMLTemplate (i.e. its concept).
+ * @param name The name of this UMLTemplate.
+ * @param id The unique id given to this UMLTemplate.
+ * @param type The type of this UMLTemplate.
+ */
+ UMLTemplate(const UMLObject *parent, const QString& name,
+ Uml::IDType id = Uml::id_None, const QString& type = "class");
+
+ /**
+ * Sets up a template.
+ *
+ * @param parent The parent of this UMLTemplate (i.e. its concept).
+ */
+ UMLTemplate(const UMLObject *parent);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==(UMLTemplate &rhs);
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLTemplate *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * destructor
+ */
+ virtual ~UMLTemplate();
+
+ /**
+ * Returns a string representation of the UMLTemplate.
+ *
+ * @param sig Currently unused.
+ * @return Returns a string representation of the UMLTemplate.
+ */
+ QString toString(Uml::Signature_Type sig = Uml::st_NoSig);
+
+ /**
+ * Overrides method from UMLClassifierListItem.
+ * Returns the type name of the UMLTemplate.
+ * If the template parameter is a class, there is no separate
+ * type object. In this case, getTypeName() returns "class".
+ *
+ * @return The type name of the UMLClassifierListItem.
+ */
+ virtual QString getTypeName();
+
+ /**
+ * Display the properties configuration dialog for the template.
+ *
+ * @return Success status.
+ */
+ bool showPropertiesDialog(QWidget* parent);
+
+ /**
+ * Writes the <UML:TemplateParameter> XMI element.
+ */
+ void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
+
+protected:
+ /**
+ * Loads the <UML:TemplateParameter> XMI element.
+ */
+ bool load(QDomElement & element);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/textblock.cpp b/umbrello/umbrello/textblock.cpp
new file mode 100644
index 00000000..e9779875
--- /dev/null
+++ b/umbrello/umbrello/textblock.cpp
@@ -0,0 +1,320 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+// own header
+#include "textblock.h"
+
+// qt/kde includes
+#include <qregexp.h>
+
+// local includes
+#include "codedocument.h"
+#include "codegenerator.h"
+#include "codegenerationpolicy.h"
+#include "uml.h"
+
+// Constructors/Destructors
+//
+
+TextBlock::TextBlock ( CodeDocument * parent, const QString & text )
+ : QObject ( (QObject *)parent, "textBlock")
+{
+ initFields(parent);
+ setText(text);
+}
+
+TextBlock::~TextBlock ( ) { }
+
+//
+// Methods
+//
+
+
+// Accessor methods
+//
+
+
+/**
+ * Set the value of the parent code document
+ * @param new_var the new value of m_parentDocument
+ */
+void TextBlock::setParentDocument ( CodeDocument * new_var ) {
+ m_parentDocument = new_var;
+}
+
+bool TextBlock::canDelete ( ) {
+ return m_canDelete;
+}
+
+/**
+ * Get the value of m_parentDocument
+ * @return the value of m_parentDocument
+ */
+CodeDocument * TextBlock::getParentDocument ( ) {
+ return m_parentDocument;
+}
+
+/**
+ * Set the value of m_text
+ * The actual text of this code block.
+ * @param new_var the new value of m_text
+ */
+void TextBlock::setText ( const QString &new_var ) {
+ m_text = new_var;
+}
+
+/**
+ * Add text to this object.
+ *
+ */
+void TextBlock::appendText ( const QString &new_text ) {
+ m_text = m_text + new_text;
+}
+
+/**
+ * Get the value of m_text
+ * The actual text of this code block.
+ * @return the value of m_text
+ */
+QString TextBlock::getText ( ) const {
+ return m_text;
+}
+
+/**
+ * Get the tag of this text block. This tag
+ * may be used to find this text block in the code document
+ * to which it belongs.
+ */
+QString TextBlock::getTag( ) const {
+ return m_tag;
+}
+
+/**
+ * Set the tag of this text block. This tag
+ * may be used to find this text block in the code document
+ * to which it belongs.
+ */
+void TextBlock::setTag ( const QString &value ) {
+ m_tag = value;
+}
+
+/**
+ * Set the value of m_writeOutText
+ * Whether or not to include the text of this TextBlock into a file.
+ * @param new_var the new value of m_writeOutText
+ */
+void TextBlock::setWriteOutText ( bool new_var ) {
+ m_writeOutText = new_var;
+}
+
+/**
+ * Get the value of m_writeOutText
+ * Whether or not to include the text of this TextBlock into a file.
+ * @return the value of m_writeOutText
+ */
+bool TextBlock::getWriteOutText ( ) {
+ return m_writeOutText;
+}
+
+/** Set how many times to indent this text block.
+ */
+void TextBlock::setIndentationLevel ( int level ) {
+ m_indentationLevel = level;
+}
+
+/** Get how many times to indent this text block.
+ * The amount of each indenatation is determined from the parent
+ * codedocument codegeneration policy.
+ */
+int TextBlock::getIndentationLevel ( ) {
+ return m_indentationLevel;
+}
+
+QString TextBlock::getNewLineEndingChars ( ) {
+ CodeGenerationPolicy * policy = UMLApp::app()->getCommonPolicy();
+ return policy->getNewLineEndingChars();
+}
+
+QString TextBlock::getIndentation() {
+ CodeGenerationPolicy * policy = UMLApp::app()->getCommonPolicy();
+ return policy->getIndentation();
+}
+
+QString TextBlock::getIndentationString ( int level ) {
+ if (!level)
+ level = m_indentationLevel;
+ QString indentAmount = getIndentation();
+ QString indentation = "";
+ for(int i=0; i<level; i++)
+ indentation.append(indentAmount);
+ return indentation;
+}
+
+// Other methods
+//
+
+/** Ush. These are terrifically bad and must one day go away.
+ * Both methods indicate the range of lines in this textblock
+ * which may be edited by the codeeditor (assuming that any are
+ * actually editable). The default case is no lines are editable.
+ * The line numbering starts with '0' and a '-1' means no line
+ * qualifies.
+ */
+int TextBlock::firstEditableLine() { return 0; }
+int TextBlock::lastEditableLine() { return 0; }
+
+QString TextBlock::getNewEditorLine ( int amount ) {
+ return getIndentationString(amount);
+}
+
+// will remove indenation from this text block.
+QString TextBlock::unformatText ( const QString & text, const QString & indent )
+{
+ QString output = text;
+ QString myIndent = indent;
+ if(myIndent.isEmpty())
+ myIndent = getIndentationString();
+
+ if(!output.isEmpty())
+ output.remove(QRegExp('^'+myIndent));
+
+ return output;
+}
+
+void TextBlock::release () {
+ this->disconnect();
+ //this->deleteLater();
+}
+
+QString TextBlock::formatMultiLineText ( const QString &work, const QString &linePrefix,
+ const QString& breakStr, bool addBreak, bool lastLineHasBreak ) {
+ QString output = "";
+ QString text = work;
+ QString endLine = getNewLineEndingChars();
+ int matches = text.contains(QRegExp(breakStr));
+ if(matches)
+ {
+ // check that last part of string matches, if not, then
+ // we have to tack on extra match
+ if(!text.contains(QRegExp(breakStr+"\\$")))
+ matches++;
+
+ for(int i=0; i < matches; i++)
+ {
+ QString line = text.section(QRegExp(breakStr),i,i);
+ output += linePrefix + line;
+ if((i != matches-1) || lastLineHasBreak)
+ output += endLine; // add break to line
+ }
+ } else {
+ output = linePrefix + text;
+ if(addBreak)
+ output += breakStr;
+ }
+
+ return output;
+}
+
+void TextBlock::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement)
+{
+
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ if (&doc != 0 ) {
+
+ blockElement.setAttribute("tag",getTag());
+
+ // only write these if different from defaults
+ if(getIndentationLevel())
+ blockElement.setAttribute("indentLevel",QString::number(getIndentationLevel()));
+ if(!m_text.isEmpty())
+ blockElement.setAttribute("text",encodeText(m_text,endLine));
+ if(!getWriteOutText())
+ blockElement.setAttribute("writeOutText",getWriteOutText()?"true":"false");
+ if(!canDelete())
+ blockElement.setAttribute("canDelete",canDelete()?"true":"false");
+
+ }
+
+}
+
+void TextBlock::setAttributesFromObject(TextBlock * obj)
+{
+
+ // DONT set tag here.
+ setIndentationLevel(obj->getIndentationLevel());
+ setText(obj->getText());
+ setWriteOutText(obj->getWriteOutText());
+ m_canDelete = obj->canDelete();
+
+}
+
+void TextBlock::setAttributesFromNode (QDomElement & root ) {
+
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+
+ setIndentationLevel(root.attribute("indentLevel","0").toInt());
+ setTag(root.attribute("tag",""));
+ setText(decodeText(root.attribute("text",""),endLine));
+ setWriteOutText(root.attribute("writeOutText","true") == "true" ? true : false);
+ m_canDelete = root.attribute("canDelete","true") == "true" ? true : false;
+
+}
+
+// encode text for XML storage
+// we simply convert all types of newLines to the "\n" or &#010;
+// entity.
+QString TextBlock::encodeText(const QString& text, const QString &endLine) {
+ QString encoded = text;
+ encoded.replace(QRegExp(endLine),"&#010;");
+ return encoded;
+}
+
+// encode text for XML storage
+// we simply convert all types of newLines to the "\n" or &#010;
+// entity.
+QString TextBlock::decodeText(const QString& text, const QString &endLine) {
+ QString decoded = text;
+ decoded.replace(QRegExp("&#010;"),endLine);
+ return decoded;
+}
+
+/**
+ * @return QString
+ */
+QString TextBlock::toString ( )
+{
+
+ // simple output method
+ if(m_writeOutText && !m_text.isEmpty())
+ {
+ QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
+ return formatMultiLineText(m_text, getIndentationString(), endLine);
+ } else
+ return "";
+}
+
+void TextBlock::initFields ( CodeDocument * parent ) {
+ m_canDelete = true;
+ m_writeOutText = true;
+ m_parentDocument = parent;
+ m_text = "";
+ m_tag = "";
+ m_indentationLevel = 0;
+}
+
+#include "textblock.moc"
diff --git a/umbrello/umbrello/textblock.h b/umbrello/umbrello/textblock.h
new file mode 100644
index 00000000..16dcd910
--- /dev/null
+++ b/umbrello/umbrello/textblock.h
@@ -0,0 +1,241 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+/* This code generated by:
+ * Author : thomas
+ * Date : Wed Jun 18 2003
+ */
+
+
+
+#ifndef TEXTBLOCK_H
+#define TEXTBLOCK_H
+
+#include <qdom.h>
+#include <qobject.h>
+
+class CodeDocument;
+
+/**
+ * class TextBlock
+ * The fundemental unit of text within an output file containing code.
+ */
+
+class TextBlock : virtual public QObject {
+ friend class CodeGenObjectWithTextBlocks;
+ friend class ClassifierCodeDocument;
+ Q_OBJECT
+public:
+
+ // Constructors/Destructors
+ //
+
+ /**
+ * Constructors
+ */
+ explicit TextBlock ( CodeDocument * parent, const QString & text = "");
+
+ // destructor
+ ~TextBlock ( );
+
+ // Public attributes
+ //
+
+ // Public attribute accessor methods
+ //
+
+ /**
+ * Set the value of m_text
+ * The actual text of this code block.
+ * @param new_var the new value of m_text
+ */
+ void setText ( const QString &new_var );
+
+ /**
+ * Add text to this object.
+ *
+ */
+ void appendText ( const QString &new_text );
+
+ /**
+ * Get the value of m_text
+ * The actual text of this code block.
+ * @return the value of m_text
+ */
+ QString getText ( ) const;
+
+ /**
+ * Get the tag of this text block. This tag
+ * may be used to find this text block in the code document
+ * to which it belongs.
+ */
+ QString getTag( ) const;
+
+ /**
+ * Set the tag of this text block. This tag
+ * may be used to find this text block in the code document
+ * to which it belongs.
+ */
+ void setTag( const QString &value );
+
+ /**
+ * Get the value of m_parentDoc
+ * @return the value of m_parentDoc
+ */
+ CodeDocument * getParentDocument ( );
+
+ /**
+ * Set the value of m_writeOutText
+ * Whether or not to include the text of this TextBlock into a file.
+ * @param new_var the new value of m_writeOutText
+ */
+ void setWriteOutText ( bool new_var );
+
+ /**
+ * Get the value of m_writeOutText
+ * Whether or not to include the text of this TextBlock into a file.
+ * @return the value of m_writeOutText
+ */
+ bool getWriteOutText ( );
+
+ /** Set how many times to indent this text block.
+ * The amount of each indenatation is determined from the parent
+ * codedocument codegeneration policy.
+ */
+ void setIndentationLevel ( int level );
+
+ /** Get how many times to indent this text block.
+ * The amount of each indenatation is determined from the parent
+ * codedocument codegeneration policy.
+ */
+ int getIndentationLevel ( );
+
+ /** Get the actual amount of indentation for a given level of indentation.
+ */
+ QString getIndentationString ( int level = 0);
+
+ /** Get how much a single "level" of indentation will actually indent.
+ */
+ QString getIndentation();
+
+ QString getNewLineEndingChars ( );
+
+ /** Format a long text string to be more readable.
+ */
+ // should be static
+ QString formatMultiLineText ( const QString &text, const QString &linePrefix,
+ const QString& breakStr,
+ bool alwaysAddBreak = true, bool lastLineHasBreak = true);
+
+ /** UnFormat a long text string. Typically, this means removing
+ * the indentaion (linePrefix) and/or newline chars from each line.
+ * If an indentation isnt specified, then the current indentation is used.
+ */
+ virtual QString unformatText ( const QString & text, const QString & indent = "");
+
+ /**
+ * @return QString
+ */
+ virtual QString toString ( );
+
+ /** encode text for XML storage
+ * we simply convert all types of newLines to the "\n" or &#010;
+ * entity.
+ */
+ static QString encodeText(const QString& text , const QString &endChars);
+
+
+ /** decode text from XML storage
+ * We simply convert all newLine entity &#010; to chosen line ending.
+ */
+ static QString decodeText(const QString& text, const QString &endChars);
+
+ /**
+ * Save the XMI representation of this object
+ */
+ virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ) = 0;
+
+ /**
+ * load params from the appropriate XMI element node.
+ */
+ virtual void loadFromXMI ( QDomElement & root ) = 0;
+
+ /** Determine if its OK to delete this textblock from the document.
+ * Used by the text editor to know if deletion could cause a crash of
+ * the program.
+ */
+ bool canDelete ();
+
+ /** set the class attributes from a passed object
+ */
+ virtual void setAttributesFromObject (TextBlock * obj);
+
+ /** Used by the CodeEditor. It provides it with an appropriate
+ * starting string for a new line of text within the given textblock
+ * (for example a string with the proper indentation).
+ * If the indentation amount is '0' the current indentationString will
+ * be used.
+ */
+ virtual QString getNewEditorLine( int indentAmount = 0 );
+
+ /** Ush. These are terrifically bad and must one day go away.
+ * Both methods indicate the range of lines in this textblock
+ * which may be edited by the codeeditor (assuming that any are
+ * actually editable). The default case is no lines are editable.
+ * The line numbering starts with '0' and a '-1' means no line
+ * qualifies.
+ */
+ virtual int firstEditableLine();
+ virtual int lastEditableLine();
+
+protected:
+
+ /** causes the text block to release all of its connections
+ * and any other text blocks that it 'owns'.
+ * needed to be called prior to deletion of the textblock.
+ */
+ virtual void release ();
+
+ /**
+ * Set the value of m_parentDocument
+ * @param new_var the new value of m_parentDoc
+ */
+ void setParentDocument ( CodeDocument * new_var );
+
+ /** set attributes of the node that represents this class
+ * in the XMI document.
+ */
+ virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);
+
+ /** set the class attributes of this object from
+ * the passed element node.
+ */
+ virtual void setAttributesFromNode ( QDomElement & element);
+
+ bool m_canDelete;
+
+private:
+
+ // The actual text of this code block.
+ QString m_text;
+ QString m_tag;
+
+ // Whether or not to include the text of this TextBlock into a file.
+ bool m_writeOutText;
+
+ int m_indentationLevel;
+ CodeDocument * m_parentDocument;
+
+ void initFields ( CodeDocument * doc);
+
+};
+
+#endif // TEXTBLOCK_H
diff --git a/umbrello/umbrello/textblocklist.h b/umbrello/umbrello/textblocklist.h
new file mode 100644
index 00000000..48048b8b
--- /dev/null
+++ b/umbrello/umbrello/textblocklist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef _TEXTBLOCKLIST_H
+#define _TEXTBLOCKLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class TextBlock;
+
+typedef QPtrList<TextBlock> TextBlockList;
+typedef QPtrListIterator<TextBlock> TextBlockListIt;
+
+#endif
diff --git a/umbrello/umbrello/tips b/umbrello/umbrello/tips
new file mode 100644
index 00000000..504090f9
--- /dev/null
+++ b/umbrello/umbrello/tips
@@ -0,0 +1,129 @@
+<tip category="Umbrello">
+<html>
+<p>Welcome to Umbrello.</p>
+
+<p>UML diagrams let you design and document object oriented software. <a href="help:/umbrello">The Umbrello Handbook</a> is a good introduction to using UML.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Welcome to Umbrello 1.5. New in this version are association classes, Ruby code generation, externalizable folders, ability to change interfaces into classes, and more.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Tabbed Diagrams and Externalized Folders are mutually exclusive. If you need External Folders then deselect &quot;Use tabbed diagrams&quot; in the General Settings.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Most diagram items can not be resized, they will resize themselves to fit to their contents.
+Boxes, notes and sequence diagram messages can be resized, just click and drag on the red square.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>If you want to add an already existing class to a diagram just drag its entry from the tree view.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Umbrello's refactoring agent lets you move operations between a class and its derived and base
+classes.
+Right click a class to open the refactoring agent.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Sequence diagram objects can have a destructor box and be drawn as actors. Double click one for
+the Properties dialogue.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Sequence diagram messages can act as constructors. Click on the object box (rather than the vertical line) to make it a constructor.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Sequence diagrams support messages to self. Click on the same vertical line again to create an automessage.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>If on loading a foreign file nothing is displayed in the list view, try saving the model under a different name,
+closing, and reloading the saved file. Usually the list view is then properly populated.
+</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Cut and Copy will also export the image to a PNG clipboard which can be pasted into KWord
+and other applications.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Associations do not have to be in straight lines, double clicking on one will create a movable point.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>You can turn on autosaving in the Configure Umbrello dialog.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Is a feature missing that you need in Umbrello? Please let us know.
+Either add it to the bugs database with Report Bug from the Help menu
+or send it to the uml-devel mailing list.</p>
+<ul>
+<li><a href="http://uml.sf.net/contact.php">http://uml.sf.net/contact.php</a>.</li>
+</ul>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>You can delete all selected objects by pressing Del or Backspace.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>If you've found a bug in Umbrello, please let us know.
+You can submit bugs with the Report Bug tool in the Help menu.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>Pressing the Escape key sets the current tool to the select tool.
+Backspace jumps to the previously used tool.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>You can select all objects by pressing Ctrl-A.</p>
+</html>
+</tip>
+
+<tip category="Umbrello">
+<html>
+<p>You can create and setup a new class using the New Class Wizard in the Code menu.</p>
+</html>
+</tip>
diff --git a/umbrello/umbrello/toolbarstate.cpp b/umbrello/umbrello/toolbarstate.cpp
new file mode 100644
index 00000000..339214a8
--- /dev/null
+++ b/umbrello/umbrello/toolbarstate.cpp
@@ -0,0 +1,260 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstate.h"
+
+// qt includes
+#include <qwmatrix.h> // need for inverseWorldMatrix.map
+
+// app includes
+#include "associationwidget.h"
+#include "messagewidget.h"
+#include "uml.h"
+#include "umlview.h"
+#include "umlwidget.h"
+
+ToolBarState::~ToolBarState() {
+ delete m_pMouseEvent;
+}
+
+void ToolBarState::init() {
+ m_pUMLView->viewport()->setMouseTracking(false);
+ m_pMouseEvent = 0;
+ m_currentWidget = 0;
+ m_currentAssociation = 0;
+
+ connect(m_pUMLView, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
+ this, SLOT(slotAssociationRemoved(AssociationWidget*)));
+ connect(m_pUMLView, SIGNAL(sigWidgetRemoved(UMLWidget*)),
+ this, SLOT(slotWidgetRemoved(UMLWidget*)));
+}
+
+void ToolBarState::cleanBeforeChange() {
+ disconnect(m_pUMLView, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
+ this, SLOT(slotAssociationRemoved(AssociationWidget*)));
+ disconnect(m_pUMLView, SIGNAL(sigWidgetRemoved(UMLWidget*)),
+ this, SLOT(slotWidgetRemoved(UMLWidget*)));
+}
+
+void ToolBarState::mousePress(QMouseEvent* ome) {
+ setMouseEvent(ome, QEvent::MouseButtonPress);
+
+ m_pUMLView->viewport()->setMouseTracking(true);
+
+ //TODO Doesn't another way of emiting the signal exist? A method only for
+ //that seems a bit dirty.
+ m_pUMLView->emitRemovePopupMenu();
+
+ // TODO: Check who needs this.
+ m_pUMLView->setPos(m_pMouseEvent->pos());
+
+ //TODO check why
+ m_pUMLView->setPaste(false);
+
+ setCurrentElement();
+
+ if (getCurrentWidget()) {
+ mousePressWidget();
+ } else if (getCurrentAssociation()) {
+ mousePressAssociation();
+ } else {
+ mousePressEmpty();
+ }
+}
+
+void ToolBarState::mouseRelease(QMouseEvent* ome) {
+ setMouseEvent(ome, QEvent::MouseButtonRelease);
+
+ // Set the position of the mouse
+ // TODO, should only be available in this state?
+ m_pUMLView->setPos(m_pMouseEvent->pos());
+
+ m_pUMLView->viewport()->setMouseTracking(false);
+
+ if (getCurrentWidget()) {
+ mouseReleaseWidget();
+ setCurrentWidget(0);
+ } else if (getCurrentAssociation()) {
+ mouseReleaseAssociation();
+ setCurrentAssociation(0);
+ } else {
+ mouseReleaseEmpty();
+ }
+
+ // Default, rightbutton changes the tool.
+ // The arrow tool overrides the changeTool() function.
+ changeTool();
+}
+
+void ToolBarState::mouseDoubleClick(QMouseEvent* ome) {
+ setMouseEvent(ome, QEvent::MouseButtonDblClick);
+
+ UMLWidget* currentWidget = m_pUMLView->getWidgetAt(m_pMouseEvent->pos());
+ AssociationWidget* currentAssociation = getAssociationAt(m_pMouseEvent->pos());
+ if (currentWidget) {
+ setCurrentWidget(currentWidget);
+ mouseDoubleClickWidget();
+ setCurrentWidget(0);
+ } else if (currentAssociation) {
+ setCurrentAssociation(currentAssociation);
+ mouseDoubleClickAssociation();
+ setCurrentAssociation(0);
+ } else {
+ mouseDoubleClickEmpty();
+ }
+}
+
+void ToolBarState::mouseMove(QMouseEvent* ome) {
+ setMouseEvent(ome, QEvent::MouseMove);
+
+ if (getCurrentWidget()) {
+ mouseMoveWidget();
+ } else if (getCurrentAssociation()) {
+ mouseMoveAssociation();
+ } else {
+ mouseMoveEmpty();
+ }
+
+ //Scrolls the view
+ int vx = ome->x();
+ int vy = ome->y();
+ int contsX = m_pUMLView->contentsX();
+ int contsY = m_pUMLView->contentsY();
+ int visw = m_pUMLView->visibleWidth();
+ int vish = m_pUMLView->visibleHeight();
+ int dtr = visw - (vx-contsX);
+ int dtb = vish - (vy-contsY);
+ int dtt = (vy-contsY);
+ int dtl = (vx-contsX);
+ if (dtr < 30) m_pUMLView->scrollBy(30-dtr,0);
+ if (dtb < 30) m_pUMLView->scrollBy(0,30-dtb);
+ if (dtl < 30) m_pUMLView->scrollBy(-(30-dtl),0);
+ if (dtt < 30) m_pUMLView->scrollBy(0,-(30-dtt));
+}
+
+void ToolBarState::slotAssociationRemoved(AssociationWidget* association) {
+ if (association == getCurrentAssociation()) {
+ setCurrentAssociation(0);
+ }
+}
+
+void ToolBarState::slotWidgetRemoved(UMLWidget* widget) {
+ if (widget == getCurrentWidget()) {
+ setCurrentWidget(0);
+ }
+}
+
+ToolBarState::ToolBarState(UMLView *umlView) : QObject(umlView), m_pUMLView(umlView) {
+ m_pMouseEvent = NULL;
+ init();
+}
+
+void ToolBarState::setCurrentElement() {
+ // Check associations.
+ AssociationWidget* association = getAssociationAt(m_pMouseEvent->pos());
+ if (association) {
+ setCurrentAssociation(association);
+ return;
+ }
+
+ // Check messages.
+ //TODO check why message widgets are treated different
+ MessageWidget* message = getMessageAt(m_pMouseEvent->pos());
+ if (message) {
+ setCurrentWidget(message);
+ return;
+ }
+
+ // Check widgets.
+ UMLWidget *widget = m_pUMLView->getWidgetAt(m_pMouseEvent->pos());
+ if (widget) {
+ setCurrentWidget(widget);
+ return;
+ }
+}
+
+void ToolBarState::mousePressAssociation() {
+}
+
+void ToolBarState::mousePressWidget() {
+}
+
+void ToolBarState::mousePressEmpty() {
+ m_pUMLView->clearSelected();
+}
+
+void ToolBarState::mouseReleaseAssociation() {
+}
+
+void ToolBarState::mouseReleaseWidget() {
+}
+
+void ToolBarState::mouseReleaseEmpty() {
+}
+
+void ToolBarState::mouseDoubleClickAssociation() {
+}
+
+void ToolBarState::mouseDoubleClickWidget() {
+}
+
+void ToolBarState::mouseDoubleClickEmpty() {
+ m_pUMLView->clearSelected();
+}
+
+void ToolBarState::mouseMoveAssociation() {
+}
+
+void ToolBarState::mouseMoveWidget() {
+}
+
+void ToolBarState::mouseMoveEmpty() {
+}
+
+void ToolBarState::changeTool() {
+ if (m_pMouseEvent->state() == Qt::RightButton) {
+ UMLApp::app()->getWorkToolBar()->setDefaultTool();
+ }
+}
+
+void ToolBarState::setMouseEvent(QMouseEvent* ome, const QEvent::Type &type) {
+ if (m_pMouseEvent) delete m_pMouseEvent;
+
+ m_pMouseEvent = new QMouseEvent(type, m_pUMLView->inverseWorldMatrix().map(ome->pos()),
+ ome->button(),ome->state());
+}
+
+MessageWidget* ToolBarState::getMessageAt(const QPoint& pos) {
+ MessageWidget* message = 0;
+ for (MessageWidgetListIt it(m_pUMLView->getMessageList());
+ (message = it.current()) != 0; ++it) {
+ if (message->isVisible() && message->onWidget(pos)) {
+ return message;
+ }
+ }
+
+ return message;
+}
+
+AssociationWidget* ToolBarState::getAssociationAt(const QPoint& pos) {
+ AssociationWidget* association = 0;
+ for (AssociationWidgetListIt it(m_pUMLView->getAssociationList());
+ (association = it.current()) != 0; ++it) {
+ if (association->onAssociation(pos)) {
+ return association;
+ }
+ }
+
+ return association;
+}
+
+#include "toolbarstate.moc"
diff --git a/umbrello/umbrello/toolbarstate.h b/umbrello/umbrello/toolbarstate.h
new file mode 100644
index 00000000..e005c021
--- /dev/null
+++ b/umbrello/umbrello/toolbarstate.h
@@ -0,0 +1,365 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATE_H
+#define TOOLBARSTATE_H
+
+#include <qevent.h>
+#include <qobject.h>
+
+class QEvent;
+class QMouseEvent;
+
+class AssociationWidget;
+class MessageWidget;
+class UMLView;
+class UMLWidget;
+
+
+/**
+ * Base class for toolbar states.
+ * All toolbar states inherit directly or indirectly from this class. Toolbar
+ * states represent tools that work with the diagram (for example, to create
+ * widgets, make associations...). All the mouse events received in the diagram
+ * are delivered to the toolbar state currently active. The events are handled
+ * in the tool and it executes the needed actions.
+ *
+ * All the mouse event handlers can be overridden in subclasses. However, the
+ * behaviour of the main handlers shouldn't be modified (apart from extend it,
+ * that is, call the base implementation before any other actions in the derived
+ * method).
+ *
+ * In order to handle the events, each main handler has three protected
+ * "sub-handlers" named like the main handler with the suffixes "Association",
+ * "Wdiget" and "Empty". The events received in the main handlers are delivered
+ * to the suitable handler, depending on if the event happened on an association,
+ * on a widget or on an empty space of the diagram. Those methods are the ones to
+ * override or extend to specify the behaviour of the toolbar state.
+ *
+ * The mouse events received in main handlers are tweaked to use the inverse
+ * position. The modified event is saved in m_pMouseEvent. This is the event that
+ * must be used everywhere.
+ *
+ * The association or widget that will receive the events is set in press event.
+ * How they are set can be tweaked in subclasses overriding setCurrentElement().
+ * Once a press event happens, all the mouse events and the release event are sent
+ * to the same widget or association. Mouse events are delivered only when mouse
+ * tracking is enabled. It is enabled in press event, and disabled in release
+ * event. Also, it is disabled in the toolbar state initialization. Additionally,
+ * it can be enabled or disabled in other situations by subclasses if needed.
+ *
+ * After handling a release event, the tool is changed if needed. Default
+ * implementation sets the default tool if the button released was the right
+ * button. Subclasses can override this behaviour if needed.
+ *
+ * When a toolbar state is selected, method init is called to revert its state
+ * to the initial. Subclasses should extend that method as needed. Also, method
+ * cleanBeforeChange() is called before changing it to the new tool. Subclasses
+ * should extend that method as needed.
+ *
+ * @todo Handle, for example, left press, right press, left release, right
+ * release and other similar strange combinations?
+ */
+class ToolBarState: public QObject {
+ Q_OBJECT
+public:
+
+ /**
+ * Destroys this ToolBarState.
+ * Frees m_pMouseEvent.
+ */
+ virtual ~ToolBarState();
+
+ /**
+ * Goes back to the initial state.
+ * Subclasses can extend, but not override, this method as needed.
+ */
+ virtual void init();
+
+ /**
+ * Called when the current tool is changed to use another tool.
+ * Subclasses can extend, but not override, this method as needed.
+ * Default implementation does nothing.
+ */
+ virtual void cleanBeforeChange();
+
+ /**
+ * Handler for mouse press events.
+ * Mouse tracking is enabled, any pop up menu removed, the position of the
+ * cursor set and paste state disabled.
+ * Then, the current association or widget are set (if any), and events are
+ * delivered to the specific methods, depending on where the cursor was
+ * pressed.
+ *
+ * @param ome The received event.
+ * @see setCurrentElement()
+ */
+ virtual void mousePress(QMouseEvent *ome);
+
+ /**
+ * Handler for mouse release events.
+ * Mouse tracking is disabled and the position of the cursor set.
+ * The events are delivered to the specific methods, depending on where the
+ * cursor was released, and the current association or widget cleaned.
+ * Finally, the current tool is changed if needed.
+ *
+ * @param ome The received event.
+ */
+ virtual void mouseRelease(QMouseEvent* ome);
+
+ /**
+ * Handler for mouse double click events.
+ * The current association or widget is set (if any), and events are
+ * delivered to the specific methods, depending on where the cursor was pressed.
+ * After delivering the events, the current association or widget is cleaned.
+ *
+ * @param ome The received event.
+ */
+ virtual void mouseDoubleClick(QMouseEvent* ome);
+
+ /**
+ * Handler for mouse double click events.
+ * Events are delivered to the specific methods, depending on where the cursor
+ * was pressed. It uses the current widget or association set in press event,
+ * if any.
+ * Then, the view is scrolled if needed (if the cursor is moved in any of the
+ * 30 pixels width area from left, top, right or bottom sides, and there is
+ * more diagram currently not being shown in that direction).
+ * This method is only called when mouse tracking is enabled and the mouse
+ * is moved.
+ *
+ * @param ome The received event.
+ */
+ virtual void mouseMove(QMouseEvent* ome);
+
+public slots:
+
+ /**
+ * An association was removed from the UMLView.
+ * If the association removed was the current association, the current
+ * association is set to 0.
+ * It can be extended in subclasses if needed.
+ */
+ virtual void slotAssociationRemoved(AssociationWidget* association);
+
+ /**
+ * A widget was removed from the UMLView.
+ * If the widget removed was the current widget, the current widget is set
+ * to 0.
+ * It can be extended in subclasses if needed.
+ */
+ virtual void slotWidgetRemoved(UMLWidget* widget);
+
+protected:
+
+ /**
+ * Creates a new ToolBarState.
+ * UMLView is set as parent of this QObject, and name is left empty.
+ * Protected to avoid classes other than derived to create objects of this
+ * class.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarState(UMLView *umlView);
+
+ /**
+ * Sets the current association or widget.
+ * It sets the current element when a press event happened. The element will
+ * be used until the next release event.
+ * Default implementation first checks for associations, then message widgets
+ * and then any other widgets.
+ * It can be overridden in subclasses if needed.
+ */
+ virtual void setCurrentElement();
+
+ /**
+ * Called when the press event happened on an association.
+ * Default implementation does nothing.
+ */
+ virtual void mousePressAssociation();
+
+ /**
+ * Called when the press event happened on a widget.
+ * Default implementation does nothing.
+ */
+ virtual void mousePressWidget();
+
+ /**
+ * Called when the press event happened on an empty space.
+ * Default implementation cleans the selection.
+ */
+ virtual void mousePressEmpty();
+
+ /**
+ * Called when the release event happened on an association.
+ * Default implementation does nothing.
+ */
+ virtual void mouseReleaseAssociation();
+
+ /**
+ * Called when the release event happened on a widget.
+ * Default implementation does nothing.
+ */
+ virtual void mouseReleaseWidget();
+
+ /**
+ * Called when the release event happened on an empty space.
+ * Default implementation does nothing.
+ */
+ virtual void mouseReleaseEmpty();
+
+ /**
+ * Called when the double click event happened on an association.
+ * Default implementation does nothing.
+ */
+ virtual void mouseDoubleClickAssociation();
+
+ /**
+ * Called when the double click event happened on a widget.
+ * Default implementation does nothing.
+ */
+ virtual void mouseDoubleClickWidget();
+
+ /**
+ * Called when the double click event happened on an empty space.
+ * Default implementation cleans the selection.
+ */
+ virtual void mouseDoubleClickEmpty();
+
+ /**
+ * Called when the move event happened when an association is
+ * currently available.
+ * Default implementation does nothing.
+ */
+ virtual void mouseMoveAssociation();
+
+ /**
+ * Called when the move event happened when a widget is
+ * currently available.
+ * Default implementation does nothing.
+ */
+ virtual void mouseMoveWidget();
+
+ /**
+ * Called when the move event happened when no association nor
+ * widget are currently available.
+ * Default implementation does nothing.
+ */
+ virtual void mouseMoveEmpty();
+
+ /**
+ * Changes the current tool to the default one if the right button was released.
+ * It can be overridden in subclasses if needed.
+ */
+ virtual void changeTool();
+
+ /**
+ * Returns the widget currently in use.
+ *
+ * @return The widget currently in use.
+ */
+ virtual UMLWidget* getCurrentWidget() {
+ return m_currentWidget;
+ }
+
+ /**
+ * Sets the widget currently in use.
+ * This method is called in main press events handler just before calling
+ * the press event for widgets handler.
+ * Default implementation is set the specified widget, although this
+ * behaviour can be overridden in subclasses if needed.
+ *
+ * @param currentWidget The widget to be set.
+ */
+ virtual void setCurrentWidget(UMLWidget* currentWidget) {
+ m_currentWidget = currentWidget;
+ }
+
+ /**
+ * Returns the association currently in use.
+ *
+ * @return The association currently in use.
+ */
+ virtual AssociationWidget* getCurrentAssociation() {
+ return m_currentAssociation;
+ }
+
+ /**
+ * Sets the association currently in use.
+ * This method is called in main press events handler just before calling
+ * the press event for associations handler.
+ * Default implementation is set the specified association, although this
+ * behaviour can be overridden in subclasses if needed.
+ *
+ * @param currentAssociation The association to be set.
+ */
+ virtual void setCurrentAssociation(AssociationWidget* currentAssociation) {
+ m_currentAssociation = currentAssociation;
+ }
+
+ /**
+ * Sets m_pMouseEvent as the equivalent of the received event after transforming it
+ * using the inverse world matrix in the UMLView.
+ * This method is called at the beginning of the main event handler methods.
+ *
+ * @param ome The mouse event to transform.
+ * @param type The type of the event.
+ */
+ void setMouseEvent(QMouseEvent* ome, const QEvent::Type &type);
+
+ /**
+ * Returns the AssociationWidget at the specified position, or null if there is none.
+ * If there are more than one association at this point, it returns the first found.
+ *
+ * @param pos The position to get the association.
+ * @return The AssociationWidget at the specified position, or null if there is none.
+ * @todo Better handling for associations at the same point
+ */
+ AssociationWidget* getAssociationAt(const QPoint& pos);
+
+ /**
+ * Returns the MessageWidget at the specified position, or null if there is none.
+ * The message is only returned if it is visible.
+ * If there are more than one message at this point, it returns the first found.
+ *
+ * @param pos The position to get the message.
+ * @return The MessageWidget at the specified position, or null if there is none.
+ * @todo Better handling for messages at the same point
+ */
+ MessageWidget* getMessageAt(const QPoint& pos);
+
+ /**
+ * The UMLView.
+ */
+ UMLView* m_pUMLView;
+
+ /**
+ * The mouse event currently in use.
+ * This event is the equivalent of the received event after transforming it
+ * using the inverse world matrix in the UMLView.
+ */
+ QMouseEvent* m_pMouseEvent;
+
+private:
+
+ /**
+ * The widget currently in use, if any.
+ */
+ UMLWidget* m_currentWidget;
+
+ /**
+ * The association currently in use, if any.
+ */
+ AssociationWidget* m_currentAssociation;
+
+};
+
+#endif //TOOLBARSTATE_H
diff --git a/umbrello/umbrello/toolbarstatearrow.cpp b/umbrello/umbrello/toolbarstatearrow.cpp
new file mode 100644
index 00000000..d8205350
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatearrow.cpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstatearrow.h"
+
+// app includes
+#include "associationwidget.h"
+#include "uml.h"
+#include "umlview.h"
+#include "umlwidget.h"
+
+ToolBarStateArrow::ToolBarStateArrow(UMLView *umlView): ToolBarState(umlView) {
+ m_selectionRect.setAutoDelete(true);
+
+ init();
+}
+
+ToolBarStateArrow::~ToolBarStateArrow() {
+}
+
+void ToolBarStateArrow::init() {
+ ToolBarState::init();
+
+ m_selectionRect.clear();
+}
+
+void ToolBarStateArrow::mousePressAssociation() {
+ getCurrentAssociation()->mousePressEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mousePressWidget() {
+ getCurrentWidget()->mousePressEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mousePressEmpty() {
+ if (m_pMouseEvent->button() != Qt::LeftButton) {
+ // Leave widgets selected upon RMB press on empty diagram area.
+ // The popup menu is activated upon RMB release.
+ return;
+ }
+ ToolBarState::mousePressEmpty();
+
+ // Starts the selection rectangle
+ if (m_selectionRect.count() == 0) {
+ m_startPosition = m_pMouseEvent->pos();
+
+ for (int i = 0; i < 4; i++) {
+ QCanvasLine* line = new QCanvasLine(m_pUMLView->canvas());
+ line->setPoints(m_pMouseEvent->x(), m_pMouseEvent->y(),
+ m_pMouseEvent->x(), m_pMouseEvent->y());
+ line->setPen(QPen(QColor("grey"), 0, Qt::DotLine));
+ line->setVisible(true);
+ line->setZ(100);
+ m_selectionRect.append(line);
+ }
+ }
+}
+
+void ToolBarStateArrow::mouseReleaseAssociation() {
+ getCurrentAssociation()->mouseReleaseEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseReleaseWidget() {
+ getCurrentWidget()->mouseReleaseEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseReleaseEmpty() {
+ if (m_selectionRect.count() == 4) {
+ m_selectionRect.clear();
+ } else if (m_pMouseEvent->button() == Qt::RightButton) {
+ m_pUMLView->setMenu();
+ }
+}
+
+void ToolBarStateArrow::mouseDoubleClickAssociation() {
+ getCurrentAssociation()->mouseDoubleClickEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseDoubleClickWidget() {
+ getCurrentWidget()->mouseDoubleClickEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseMoveAssociation() {
+ getCurrentAssociation()->mouseMoveEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseMoveWidget() {
+ getCurrentWidget()->mouseMoveEvent(m_pMouseEvent);
+}
+
+void ToolBarStateArrow::mouseMoveEmpty() {
+ if (m_selectionRect.count() == 4) {
+ QCanvasLine* line = m_selectionRect.at(0);
+ line->setPoints(m_startPosition.x(), m_startPosition.y(),
+ m_pMouseEvent->x(), m_startPosition.y());
+
+ line = m_selectionRect.at(1);
+ line->setPoints(m_pMouseEvent->x(), m_startPosition.y(),
+ m_pMouseEvent->x(), m_pMouseEvent->y());
+
+ line = m_selectionRect.at(2);
+ line->setPoints(m_pMouseEvent->x(), m_pMouseEvent->y(),
+ m_startPosition.x(), m_pMouseEvent->y());
+
+ line = m_selectionRect.at(3);
+ line->setPoints(m_startPosition.x(), m_pMouseEvent->y(),
+ m_startPosition.x(), m_startPosition.y());
+
+ m_pUMLView->selectWidgets(m_startPosition.x(), m_startPosition.y(),
+ m_pMouseEvent->x(), m_pMouseEvent->y());
+ }
+}
+
+void ToolBarStateArrow::changeTool() {
+}
+
+void ToolBarStateArrow::setCurrentWidget(UMLWidget* currentWidget) {
+ if (currentWidget != 0 && getCurrentWidget() != 0) {
+ return;
+ }
+
+ ToolBarState::setCurrentWidget(currentWidget);
+}
+
+#include "toolbarstatearrow.moc"
diff --git a/umbrello/umbrello/toolbarstatearrow.h b/umbrello/umbrello/toolbarstatearrow.h
new file mode 100644
index 00000000..a2fab59f
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatearrow.h
@@ -0,0 +1,158 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEARROW_H
+#define TOOLBARSTATEARROW_H
+
+
+#include "toolbarstate.h"
+
+#include "worktoolbar.h"
+
+class QMouseEvent;
+class UMLView;
+
+class QCanvasLine;
+
+/**
+ * Arrow tool for select, move and resize widgets and associations.
+ * Arrow tool delegates the event handling in the widgets and associations. When
+ * no widget nor association is being used,the arrow tool acts as a selecting
+ * tool that selects all the elements in the rectangle created when dragging the
+ * mouse.
+ *
+ * This is the default tool.
+ */
+class ToolBarStateArrow : public ToolBarState {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a new ToolBarStateArrow.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarStateArrow(UMLView *umlView);
+
+ /**
+ * Destroys this ToolBarStateArrow.
+ */
+ virtual ~ToolBarStateArrow();
+
+ /**
+ * Goes back to the inital state.
+ */
+ virtual void init();
+
+protected:
+
+ /**
+ * Called when the press event happened on an association.
+ * Delivers the event to the association.
+ */
+ virtual void mousePressAssociation();
+
+ /**
+ * Called when the press event happened on a widget.
+ * Delivers the event to the widget.
+ */
+ virtual void mousePressWidget();
+
+ /**
+ * Called when the press event happened on an empty space.
+ * Calls base method and, if left button was pressed, prepares the selection
+ * rectangle.
+ */
+ virtual void mousePressEmpty();
+
+ /**
+ * Called when the release event happened on an association.
+ * Delivers the event to the association.
+ */
+ virtual void mouseReleaseAssociation();
+
+ /**
+ * Called when the release event happened on a widget.
+ * Delivers the event to the widget.
+ */
+ virtual void mouseReleaseWidget();
+
+ /**
+ * Called when the release event happened on an empty space.
+ * If selection rectangle is active, it is cleared. Else, if the right
+ * button was released, it shows the pop up menu for the diagram.
+ */
+ virtual void mouseReleaseEmpty();
+
+ /**
+ * Called when the double click event happened on an association.
+ * Delivers the event to the association.
+ */
+ virtual void mouseDoubleClickAssociation();
+
+ /**
+ * Called when the double click event happened on a widget.
+ * Delivers the event to the widget.
+ */
+ virtual void mouseDoubleClickWidget();
+
+ /**
+ * Called when the move event happened when an association is
+ * currently available.
+ * Delivers the event to the association.
+ */
+ virtual void mouseMoveAssociation();
+
+ /**
+ * Called when the move event happened when a widget is
+ * currently available.
+ * Delivers the event to the widget.
+ */
+ virtual void mouseMoveWidget();
+
+ /**
+ * Called when the move event happened when no association nor
+ * widget are currently available.
+ * Updates the selection rectangle to the new position and selectes all the
+ * widgets in the rectangle.
+ *
+ * @todo Fix selection
+ */
+ virtual void mouseMoveEmpty();
+
+ /**
+ * Sets the widget currently in use.
+ * It ensures that the widget is only set if there is no other widget set
+ * already.
+ * It avoids things like moving a big widget over a little one, clicking
+ * right button to cancel the movement and the little widget getting the
+ * event, thus not cancelling the movement in the big widget.
+ */
+ virtual void setCurrentWidget(UMLWidget* currentWidget);
+
+ /**
+ * Overriden from base class to do nothing, as arrow is the default tool.
+ */
+ virtual void changeTool();
+
+ /**
+ * The selection rectangle that contains the four lines of its borders.
+ */
+ QPtrList<QCanvasLine> m_selectionRect;
+
+ /**
+ * The start position of the selection rectangle.
+ */
+ QPoint m_startPosition;
+
+};
+
+#endif //TOOLBARSTATEARROW_H
diff --git a/umbrello/umbrello/toolbarstateassociation.cpp b/umbrello/umbrello/toolbarstateassociation.cpp
new file mode 100644
index 00000000..d36647dd
--- /dev/null
+++ b/umbrello/umbrello/toolbarstateassociation.cpp
@@ -0,0 +1,232 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstateassociation.h"
+
+// kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// app includes
+#include "assocrules.h"
+#include "association.h"
+#include "associationwidget.h"
+#include "classifierwidget.h"
+#include "folder.h"
+#include "model_utils.h"
+#include "uml.h"
+#include "umlobject.h"
+#include "umlview.h"
+#include "umllistview.h"
+#include "umldoc.h"
+#include "umlwidget.h"
+
+using namespace Uml;
+
+ToolBarStateAssociation::ToolBarStateAssociation(UMLView *umlView) : ToolBarStatePool(umlView) {
+ m_firstWidget = 0;
+ m_associationLine = 0;
+}
+
+ToolBarStateAssociation::~ToolBarStateAssociation() {
+ delete m_associationLine;
+}
+
+void ToolBarStateAssociation::init() {
+ ToolBarStatePool::init();
+
+ cleanAssociation();
+}
+
+void ToolBarStateAssociation::cleanBeforeChange() {
+ ToolBarStatePool::cleanBeforeChange();
+
+ cleanAssociation();
+}
+
+void ToolBarStateAssociation::mouseMove(QMouseEvent* ome) {
+ ToolBarStatePool::mouseMove(ome);
+
+ if (m_associationLine) {
+ QPoint sp = m_associationLine->startPoint();
+ m_associationLine->setPoints(sp.x(), sp.y(), m_pMouseEvent->x(), m_pMouseEvent->y());
+ }
+}
+
+void ToolBarStateAssociation::slotWidgetRemoved(UMLWidget* widget) {
+ ToolBarState::slotWidgetRemoved(widget);
+
+ if (widget == m_firstWidget) {
+ cleanAssociation();
+ }
+}
+
+void ToolBarStateAssociation::mouseReleaseAssociation() {
+ if (m_pMouseEvent->button() != Qt::LeftButton ||
+ !m_firstWidget || m_firstWidget->getBaseType() != Uml::wt_Class) {
+ cleanAssociation();
+ return;
+ }
+
+ getCurrentAssociation()->createAssocClassLine(
+ static_cast<ClassifierWidget*>(m_firstWidget),
+ getCurrentAssociation()->getLinePath()->onLinePath(m_pMouseEvent->pos()));
+ cleanAssociation();
+}
+
+void ToolBarStateAssociation::mouseReleaseWidget() {
+ if (m_pMouseEvent->button() != Qt::LeftButton) {
+ cleanAssociation();
+ return;
+ }
+
+ // TODO In old code in ToolBarState there was a TODO that said: Should not
+ //be called by a Sequence message Association. Here's the check for that,
+ //although I don't know why it is needed, but it seems that it's not needed,
+ //as the old code worked fine without it...
+ if (getAssociationType() == at_Seq_Message) {
+ return;
+ }
+
+ if (!m_firstWidget) {
+ setFirstWidget();
+ } else {
+ setSecondWidget();
+ }
+}
+
+void ToolBarStateAssociation::mouseReleaseEmpty() {
+ cleanAssociation();
+}
+
+void ToolBarStateAssociation::setFirstWidget() {
+ UMLWidget* widget = getCurrentWidget();
+ Association_Type type = getAssociationType();
+
+ if (!AssocRules::allowAssociation(type, widget)) {
+ //TODO improve error feedback: tell the user what are the valid type of associations for
+ //that widget
+ KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error"));
+ return;
+ }
+ //set up position
+ QPoint pos;
+ pos.setX(widget->getX() + (widget->getWidth() / 2));
+ pos.setY(widget->getY() + (widget->getHeight() / 2));
+ //TODO why is this needed?
+ m_pUMLView->setPos(pos);
+
+ m_firstWidget = widget;
+
+ m_associationLine = new QCanvasLine(m_pUMLView->canvas());
+ m_associationLine->setPoints(pos.x(), pos.y(), pos.x(), pos.y());
+ m_associationLine->setPen(QPen(m_pUMLView->getLineColor(), m_pUMLView->getLineWidth(), Qt::DashLine));
+
+ m_associationLine->setVisible(true);
+
+ m_pUMLView->viewport()->setMouseTracking(true);
+}
+
+void ToolBarStateAssociation::setSecondWidget() {
+ Association_Type type = getAssociationType();
+ UMLWidget* widgetA = m_firstWidget;
+ UMLWidget* widgetB = getCurrentWidget();
+ Widget_Type at = widgetA->getBaseType();
+ bool valid = true;
+ if (type == at_Generalization) {
+ type = AssocRules::isGeneralisationOrRealisation(widgetA, widgetB);
+ }
+ if (widgetA == widgetB) {
+ valid = AssocRules::allowSelf(type, at);
+ if (valid && type == at_Association) {
+ type = at_Association_Self;
+ }
+ } else {
+ valid = AssocRules::allowAssociation(type, widgetA, widgetB);
+ }
+ if (valid) {
+ AssociationWidget *temp = new AssociationWidget(m_pUMLView, widgetA, type, widgetB);
+ addAssociationInViewAndDoc(temp);
+ if (type == at_Containment) {
+ UMLListView *lv = UMLApp::app()->getListView();
+ UMLObject *newContainer = widgetA->getUMLObject();
+ UMLObject *objToBeMoved = widgetB->getUMLObject();
+ if (newContainer && objToBeMoved) {
+ UMLListViewItem *newLVParent = lv->findUMLObject(newContainer);
+ lv->moveObject(objToBeMoved->getID(),
+ Model_Utils::convert_OT_LVT(objToBeMoved),
+ newLVParent);
+ }
+ }
+ UMLApp::app()->getDocument()->setModified();
+ } else {
+ //TODO improve error feedback: tell the user what are the valid type of associations for
+ //the second widget using the first widget
+ KMessageBox::error(0, i18n("Incorrect use of associations."), i18n("Association Error"));
+ }
+
+ cleanAssociation();
+}
+
+Association_Type ToolBarStateAssociation::getAssociationType() {
+ Association_Type at;
+
+ switch(getButton()) {
+ case WorkToolBar::tbb_Anchor: at = at_Anchor; break;
+ case WorkToolBar::tbb_Association: at = at_Association; break;
+ case WorkToolBar::tbb_UniAssociation: at = at_UniAssociation; break;
+ case WorkToolBar::tbb_Generalization: at = at_Generalization; break;
+ case WorkToolBar::tbb_Composition: at = at_Composition; break;
+ case WorkToolBar::tbb_Aggregation: at = at_Aggregation; break;
+ case WorkToolBar::tbb_Relationship: at = at_Relationship; break;
+ case WorkToolBar::tbb_Dependency: at = at_Dependency; break;
+ case WorkToolBar::tbb_Containment: at = at_Containment; break;
+ case WorkToolBar::tbb_Seq_Message_Synchronous:
+ case WorkToolBar::tbb_Seq_Message_Asynchronous: at = at_Seq_Message; break;
+ case WorkToolBar::tbb_Coll_Message: at = at_Coll_Message; break;
+ case WorkToolBar::tbb_State_Transition: at = at_State; break;
+ case WorkToolBar::tbb_Activity_Transition: at = at_Activity; break;
+
+ default: at = at_Unknown; break;
+ }
+
+ return at;
+}
+
+void ToolBarStateAssociation::addAssociationInViewAndDoc(AssociationWidget* a) {
+ // append in view
+ if (m_pUMLView->addAssociation(a, false)) {
+ // if view went ok, then append in document
+ UMLAssociation *umla = a->getAssociation();
+ if (umla == NULL) {
+ // association without model representation in UMLDoc
+ return;
+ }
+ Uml::Model_Type m = Model_Utils::convert_DT_MT(m_pUMLView->getType());
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ umla->setUMLPackage(umldoc->getRootFolder(m));
+ UMLApp::app()->getDocument()->addAssociation(umla);
+ } else {
+ kError() << "cannot addAssocInViewAndDoc(), deleting" << endl;
+ delete a;
+ }
+}
+
+void ToolBarStateAssociation::cleanAssociation() {
+ m_firstWidget = 0;
+
+ delete m_associationLine;
+ m_associationLine = 0;
+}
+
+#include "toolbarstateassociation.moc"
diff --git a/umbrello/umbrello/toolbarstateassociation.h b/umbrello/umbrello/toolbarstateassociation.h
new file mode 100644
index 00000000..1d6c5174
--- /dev/null
+++ b/umbrello/umbrello/toolbarstateassociation.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEASSOCIATION_H
+#define TOOLBARSTATEASSOCIATION_H
+
+#include "toolbarstatepool.h"
+
+class QCanvasLine;
+
+/**
+ * Association tool to create associations between widgets.
+ * With association tool, two widgets are selected clicking with left button on
+ * them and an association of the needed type (depending on the association
+ * button selected) is created between the widgets. When the first widget is
+ * selected, a temporal visual association that follows the cursor movement is
+ * created until the second widget is selected or the association cancelled.
+ *
+ * Also, association tool can create association class: a classifier widget
+ * which is linked to an association. To do this, the classifier must be
+ * selected first and then the association must be selected. The association
+ * can't be selected first.
+ *
+ * An association can be cancelled using right button, which also returns to
+ * default tool, or with middle button, which only cancels the association
+ * without changing the tool being used.
+ *
+ * @todo refactor with common code in ToolBarStateMessages?
+ */
+class ToolBarStateAssociation : public ToolBarStatePool {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a new ToolBarStateAssociation.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarStateAssociation(UMLView *umlView);
+
+ /**
+ * Destroys this ToolBarStateAssociation.
+ * Deletes the association line.
+ */
+ virtual ~ToolBarStateAssociation();
+
+ /**
+ * Goes back to the initial state.
+ */
+ virtual void init();
+
+ /**
+ * Called when the current tool is changed to use another tool.
+ * Executes base method and cleans the association.
+ */
+ virtual void cleanBeforeChange();
+
+ /**
+ * Called when a mouse event happened.
+ * It executes the base method and then updates the position of the
+ * association line, if any.
+ */
+ virtual void mouseMove(QMouseEvent* ome);
+
+public slots:
+
+ /**
+ * A widget was removed from the UMLView.
+ * If the widget removed was the current widget, the current widget is set
+ * to 0.
+ * Also, if it was the first widget, the association is cleaned.
+ */
+ virtual void slotWidgetRemoved(UMLWidget* widget);
+
+protected:
+
+ /**
+ * Called when the release event happened on an association.
+ * If the button pressed isn't left button, the association being created is
+ * cleaned. If it is left button, and the first widget is set and is a
+ * classifier widget, it creates an association class. Otherwise, the
+ * association being created is cleaned.
+ */
+ virtual void mouseReleaseAssociation();
+
+ /**
+ * Called when the release event happened on a widget.
+ * If the button pressed isn't left button, the association is cleaned. If
+ * it is left button, sets the first widget or the second, depending on
+ * whether the first widget is already set or not.
+ */
+ virtual void mouseReleaseWidget();
+
+ /**
+ * Called when the release event happened on an empty space.
+ * Cleans the association.
+ */
+ virtual void mouseReleaseEmpty();
+
+private:
+
+ /**
+ * Sets the first widget in the association using the current widget.
+ * If the widget can't be associated using the current type of association,
+ * an error is shown and the widget isn't set.
+ * Otherwise, the temporal visual association is created and the mouse
+ * tracking is enabled, so move events will be delivered.
+ */
+ void setFirstWidget();
+
+ /**
+ * Sets the second widget in the association using the current widget and
+ * creates the association.
+ * If the association between the two widgets using the current type of
+ * association, an error is shown and the association cancelled.
+ * Otherwise, the association is created and added to the view, and the tool
+ * is changed to the default tool.
+ *
+ * @todo Why change to the default tool? Shouldn't it better to stay on
+ * association and let the user change with a right click? The tool to
+ * create widgets doesn't change to default after creating a widget
+ */
+ void setSecondWidget();
+
+ /**
+ * Returns the association type of this tool.
+ *
+ * @return The association type of this tool.
+ */
+ Uml::Association_Type getAssociationType();
+
+ /**
+ * Adds an AssociationWidget to the association list and creates the
+ * corresponding UMLAssociation in the current UMLDoc.
+ * If the association can't be added, is deleted.
+ *
+ * @param association The AssociationWidget to add.
+ */
+ void addAssociationInViewAndDoc(AssociationWidget* association);
+
+ /**
+ * Cleans the first widget and the temporal association line, if any.
+ * Both are set to null, and the association line is also deleted.
+ */
+ void cleanAssociation();
+
+ /**
+ * The first widget in the association.
+ */
+ UMLWidget* m_firstWidget;
+
+ /**
+ * The association line shown while the first widget is selected and the
+ * second one wasn't selected yet.
+ */
+ QCanvasLine* m_associationLine;
+
+};
+
+#endif //TOOLBARSTATEASSOCIATION_H
diff --git a/umbrello/umbrello/toolbarstatefactory.cpp b/umbrello/umbrello/toolbarstatefactory.cpp
new file mode 100644
index 00000000..66cf89bb
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatefactory.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+#include "toolbarstatefactory.h"
+
+#include "toolbarstate.h"
+#include "toolbarstatepool.h"
+#include "toolbarstateother.h"
+#include "toolbarstatearrow.h"
+#include "toolbarstatemessages.h"
+#include "toolbarstateassociation.h"
+
+#include "umlview.h"
+
+ToolBarStateFactory::ToolBarStateFactory(UMLView *umlView)
+{
+ m_pUMLView = umlView;
+
+ for (int i = 0; i < NR_OF_TOOLBAR_STATES; i++)
+ {
+ states[i] = NULL;
+ }
+}
+
+ToolBarStateFactory::~ToolBarStateFactory()
+{
+ for (int i = 0; i < NR_OF_TOOLBAR_STATES; i++)
+ {
+ if (states[i] != NULL) delete states[i];
+ }
+}
+
+
+ToolBarState* ToolBarStateFactory::getState(const WorkToolBar::ToolBar_Buttons &toolbarButton)
+{
+ int key = getKey(toolbarButton);
+
+ if (states[key] == NULL)
+ {
+ switch (key)
+ {
+ // When you add a new state, make sure you also increase the
+ // NR_OF_TOOLBAR_STATES
+ case 0: states[0] = new ToolBarStateOther(m_pUMLView); break;
+ case 1: states[1] = new ToolBarStateAssociation(m_pUMLView); break;
+ case 2: states[2] = new ToolBarStateMessages(m_pUMLView); break;
+
+ // This case has no pool.
+ case 3: states[3] = new ToolBarStateArrow(m_pUMLView); break;
+ }
+ }
+
+ // Make explicit the selected button. This is only necessary for states with a pool.
+ if (key <= 2) ((ToolBarStatePool *) states[key])->setButton(toolbarButton);
+
+ return states[key];
+}
+
+
+int ToolBarStateFactory::getKey(const WorkToolBar::ToolBar_Buttons &toolbarButton) const
+{
+ switch (toolbarButton)
+ {
+ // Associations
+ case WorkToolBar::tbb_Dependency: return 1;
+ case WorkToolBar::tbb_Aggregation: return 1;
+ case WorkToolBar::tbb_Relationship: return 1;
+ case WorkToolBar::tbb_Generalization: return 1;
+ case WorkToolBar::tbb_Association: return 1;
+ case WorkToolBar::tbb_UniAssociation: return 1;
+ case WorkToolBar::tbb_Composition: return 1;
+ case WorkToolBar::tbb_Containment: return 1;
+ case WorkToolBar::tbb_Anchor: return 1;
+ case WorkToolBar::tbb_Coll_Message: return 1;
+ case WorkToolBar::tbb_State_Transition: return 1;
+ case WorkToolBar::tbb_Activity_Transition: return 1;
+
+ // Messages
+ case WorkToolBar::tbb_Seq_Message_Synchronous: return 2;
+ case WorkToolBar::tbb_Seq_Message_Asynchronous: return 2;
+
+ // Arrow pointer
+ case WorkToolBar::tbb_Arrow: return 3;
+
+ // Other.
+ default: return 0;
+ }
+
+}
diff --git a/umbrello/umbrello/toolbarstatefactory.h b/umbrello/umbrello/toolbarstatefactory.h
new file mode 100644
index 00000000..b5c1ee4c
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatefactory.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEFACTORY_H
+#define TOOLBARSTATEFACTORY_H
+
+#include "toolbarstate.h"
+
+#include "worktoolbar.h"
+
+#define NR_OF_TOOLBAR_STATES 4
+
+class UMLView;
+
+
+/**
+ * The ToolBarStateFactory keeps track of all the toolbar states. For the first
+ * request, the factory creates a new state object. The next requests to this
+ * object, this factory will return the existing object.
+ *
+ * States that inherit from the ToolBarStatePool share multiple toolbar states.
+ * Therefore the setButton function is called. Internally the shared state object
+ * determines the exact behavior by itself.
+ */
+class ToolBarStateFactory
+{
+public:
+ // constructor.
+ ToolBarStateFactory(UMLView* umlView);
+
+ // Destructor
+ virtual ~ToolBarStateFactory();
+
+ ToolBarState* getState(const WorkToolBar::ToolBar_Buttons &toolbarButton);
+
+protected:
+ int getKey(const WorkToolBar::ToolBar_Buttons &toolbarButton) const;
+
+protected:
+ ToolBarState* states[NR_OF_TOOLBAR_STATES];
+
+ UMLView* m_pUMLView;
+};
+
+#endif //TOOLBARSTATEFACTORY_H
diff --git a/umbrello/umbrello/toolbarstatemessages.cpp b/umbrello/umbrello/toolbarstatemessages.cpp
new file mode 100644
index 00000000..36ffb005
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatemessages.cpp
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstatemessages.h"
+
+// kde includes
+#include <kdebug.h>
+
+// local includes
+#include "floatingtextwidget.h"
+#include "messagewidget.h"
+#include "objectwidget.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+
+ToolBarStateMessages::ToolBarStateMessages(UMLView *umlView) : ToolBarStatePool(umlView) {
+ m_firstObject = 0;
+ m_messageLine = 0;
+}
+
+ToolBarStateMessages::~ToolBarStateMessages() {
+ delete m_messageLine;
+}
+
+void ToolBarStateMessages::init() {
+ ToolBarStatePool::init();
+
+ cleanMessage();
+}
+
+void ToolBarStateMessages::cleanBeforeChange() {
+ ToolBarStatePool::cleanBeforeChange();
+
+ cleanMessage();
+}
+
+void ToolBarStateMessages::mouseMove(QMouseEvent* ome) {
+ ToolBarStatePool::mouseMove(ome);
+
+ if (m_messageLine) {
+ QPoint sp = m_messageLine->startPoint();
+ m_messageLine->setPoints(sp.x(), sp.y(), m_pMouseEvent->x(), m_pMouseEvent->y());
+ }
+}
+
+void ToolBarStateMessages::slotWidgetRemoved(UMLWidget* widget) {
+ ToolBarState::slotWidgetRemoved(widget);
+
+ if (widget == m_firstObject) {
+ cleanMessage();
+ }
+}
+
+void ToolBarStateMessages::setCurrentElement() {
+ m_isObjectWidgetLine = false;
+
+ ObjectWidget* objectWidgetLine = m_pUMLView->onWidgetLine(m_pMouseEvent->pos());
+ if (objectWidgetLine) {
+ setCurrentWidget(objectWidgetLine);
+ m_isObjectWidgetLine = true;
+ return;
+ }
+
+ //commit 515177 fixed a setting creation messages only working properly at 100% zoom
+ //However, the applied patch doesn't seem to be necessary no more, so it was removed
+ //The widgets weren't got from UMLView, but from a method in this class similarto the
+ //one in UMLView but containing special code to handle the zoom
+ UMLWidget *widget = m_pUMLView->getWidgetAt(m_pMouseEvent->pos());
+ if (widget) {
+ setCurrentWidget(widget);
+ return;
+ }
+}
+
+void ToolBarStateMessages::mouseReleaseWidget() {
+ //TODO When an association between UMLObjects of invalid types is made, an error message
+ //is shown. Shouldn't also a message be used here?
+ if (m_pMouseEvent->button() != Qt::LeftButton ||
+ getCurrentWidget()->getBaseType() != Uml::wt_Object) {
+ cleanMessage();
+ return;
+ }
+
+ if (!m_isObjectWidgetLine && !m_firstObject) {
+ return;
+ }
+
+ if (!m_isObjectWidgetLine) {
+ setSecondWidget(static_cast<ObjectWidget*>(getCurrentWidget()), CreationMessage);
+ return;
+ }
+
+ if (!m_firstObject) {
+ setFirstWidget(static_cast<ObjectWidget*>(getCurrentWidget()));
+ } else {
+ setSecondWidget(static_cast<ObjectWidget*>(getCurrentWidget()), NormalMessage);
+ }
+}
+
+void ToolBarStateMessages::mouseReleaseEmpty() {
+ cleanMessage();
+}
+
+void ToolBarStateMessages::setFirstWidget(ObjectWidget* firstObject) {
+ m_firstObject = firstObject;
+
+ m_messageLine = new QCanvasLine(m_pUMLView->canvas());
+ m_messageLine->setPoints(m_pMouseEvent->x(), m_pMouseEvent->y(), m_pMouseEvent->x(), m_pMouseEvent->y());
+ m_messageLine->setPen(QPen(m_pUMLView->getLineColor(), m_pUMLView->getLineWidth(), Qt::DashLine));
+
+ m_messageLine->setVisible(true);
+
+ m_pUMLView->viewport()->setMouseTracking(true);
+}
+
+void ToolBarStateMessages::setSecondWidget(ObjectWidget* secondObject, MessageType messageType) {
+ Uml::Sequence_Message_Type msgType = getMessageType();
+
+ //TODO shouldn't start position in the first widget be used also for normal messages
+ //and not only for creation?
+ int y = m_pMouseEvent->y();
+ if (messageType == CreationMessage) {
+ msgType = Uml::sequence_message_creation;
+ y = m_messageLine->startPoint().y();
+ }
+
+ MessageWidget* message = new MessageWidget(m_pUMLView, m_firstObject,
+ secondObject, y, msgType);
+
+ cleanMessage();
+
+ m_pUMLView->getMessageList().append(message);
+
+ FloatingTextWidget *ft = message->getFloatingTextWidget();
+ //TODO cancel doesn't cancel the creation of the message, only cancels setting an operation.
+ //Shouldn't it cancel also the whole creation?
+ ft->showOpDlg();
+ message->setTextPosition();
+ m_pUMLView->getWidgetList().append(ft);
+
+ UMLApp::app()->getDocument()->setModified();
+}
+
+Uml::Sequence_Message_Type ToolBarStateMessages::getMessageType() {
+ if (getButton() == WorkToolBar::tbb_Seq_Message_Synchronous) {
+ return Uml::sequence_message_synchronous;
+ }
+
+ return Uml::sequence_message_asynchronous;
+}
+
+void ToolBarStateMessages::cleanMessage() {
+ m_firstObject = 0;
+
+ delete m_messageLine;
+ m_messageLine = 0;
+}
+
+#include "toolbarstatemessages.moc"
diff --git a/umbrello/umbrello/toolbarstatemessages.h b/umbrello/umbrello/toolbarstatemessages.h
new file mode 100644
index 00000000..f6b2cb79
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatemessages.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEMESSAGES_H
+#define TOOLBARSTATEMESSAGES_H
+
+#include "toolbarstatepool.h"
+#include <qpoint.h>
+
+class QCanvasLine;
+class ObjectWidget;
+
+/**
+ * Messages tool to create messages between objects in sequence diagrams.
+ * With messages tool, two objects are selected clicking with left button on
+ * them and a message of the needed type (depending on the message button
+ * selected) is created between the objects. When the first object is selected,
+ * a temporal visual message that follows the cursor movement is created until
+ * the second object is selected or the message cancelled.
+ *
+ * A message can be cancelled using right button, which also returns to default
+ * tool, or with middle button, which only cancels the message without changing
+ * the tool being used.
+ *
+ * The messages to create can be normal messages or creation messages. Normal
+ * messages are created clicking on the line of the two objects. Creation
+ * messages are created clicking in the line of the first object, and on the
+ * second object itself (not in its line).
+ *
+ * Associations aren't taken into account, and are treated as empty spaces.
+ * Moreover, widgets other than objects aren't neither taken into account.
+ *
+ * @todo refactor with common code in ToolBarStateAssociation?
+ * @todo sequence message lines should be handled by object widgets. Right now,
+ * they aren't taken into account in testOnWidget and an explicit check is
+ * needed. However, if onWidget in object widgets is changed to also check for
+ * the line, a way to make them prioritaries over other widgets in testOnWidget
+ * will be needed. For example, when creating a message clicking on an already
+ * created message,the message line must be got instead of the message, even if
+ * the message is smaller than the line.
+ */
+class ToolBarStateMessages : public ToolBarStatePool {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a new ToolBarStateMessages.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarStateMessages(UMLView *umlView);
+
+ /**
+ * Destroys this ToolBarStateMessages.
+ */
+ virtual ~ToolBarStateMessages();
+
+ /**
+ * Goes back to the initial state.
+ */
+ virtual void init();
+
+ /**
+ * Called when the current tool is changed to use another tool.
+ * Executes base method and cleans the message.
+ */
+ virtual void cleanBeforeChange();
+
+ /**
+ * Called when a mouse event happened.
+ * It executes the base method and then updates the position of the
+ * message line, if any.
+ */
+ virtual void mouseMove(QMouseEvent* ome);
+
+public slots:
+
+ /**
+ * A widget was removed from the UMLView.
+ * If the widget removed was the current widget, the current widget is set
+ * to 0.
+ * Also, if it was the first object, the message is cleaned.
+ */
+ virtual void slotWidgetRemoved(UMLWidget* widget);
+
+protected:
+
+ /**
+ * Selects only widgets, but no associations.
+ * Overrides base class method.
+ * If the press event happened on the line of an object, the object is set
+ * as current widget. If the press event happened on a widget, the widget is
+ * set as current widget.
+ */
+ virtual void setCurrentElement();
+
+ /**
+ * Called when the release event happened on a widget.
+ * If the button pressed isn't left button or the widget isn't an object
+ * widget, the message is cleaned.
+ * If the release event didn't happen on the line of an object and the first
+ * object wasn't selected, nothing is done. If the first object was already
+ * selected, a creation message is made.
+ * If the event happened on the line of an object, the first object or the
+ * second are set, depending on whether the first object was already set or
+ * not.
+ */
+ virtual void mouseReleaseWidget();
+
+ /**
+ * Called when the release event happened on an empty space.
+ * Cleans the message.
+ * Empty spaces are not only actual empty spaces, but also associations.
+ */
+ virtual void mouseReleaseEmpty();
+
+protected:
+
+ /**
+ * The type of the message to create.
+ */
+ enum MessageType {
+ NormalMessage,
+ CreationMessage
+ };
+
+ /**
+ * Sets the first object of the message using the specified object.
+ * The temporal visual message is created and mouse tracking enabled, so
+ * mouse events will be delivered.
+ *
+ * @param firstObject The first object of the message.
+ */
+ void setFirstWidget(ObjectWidget* firstObject);
+
+ /**
+ * Sets the second object of the message using the specified widget and
+ * creates the message.
+ * The association is created and added to the view. The dialog to select
+ * the operation of the message is shown.
+ *
+ * @param secondObject The second object of the message.
+ * @param messageType The type of the message to create.
+ */
+ void setSecondWidget(ObjectWidget* secondObject, MessageType messageType);
+
+ /**
+ * Returns the message type of this tool.
+ *
+ * @return The message type of this tool.
+ */
+ Uml::Sequence_Message_Type getMessageType();
+
+ /**
+ * Cleans the first widget and the temporal message line, if any.
+ * Both are set to null, and the message line is also deleted.
+ */
+ void cleanMessage();
+
+ /**
+ * The first object in the message.
+ */
+ ObjectWidget* m_firstObject;
+
+ /**
+ * The message line shown while the first widget is selected and the
+ * second one wasn't selected yet.
+ */
+ QCanvasLine* m_messageLine;
+
+ /**
+ * If there is a current widget, it is true if the press event happened on
+ * the line of an object, or false if it happened on a normal UMLWidget.
+ */
+ bool m_isObjectWidgetLine;
+
+};
+
+#endif //TOOLBARSTATEMESSAGES_H
diff --git a/umbrello/umbrello/toolbarstateother.cpp b/umbrello/umbrello/toolbarstateother.cpp
new file mode 100644
index 00000000..f6161dbd
--- /dev/null
+++ b/umbrello/umbrello/toolbarstateother.cpp
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstateother.h"
+
+// kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "activitywidget.h"
+#include "boxwidget.h"
+#include "dialog_utils.h"
+#include "floatingtextwidget.h"
+#include "forkjoinwidget.h"
+#include "notewidget.h"
+#include "object_factory.h"
+#include "statewidget.h"
+#include "uml.h"
+#include "umlview.h"
+#include "umldoc.h"
+
+using namespace Uml;
+
+ToolBarStateOther::ToolBarStateOther(UMLView *umlView) : ToolBarStatePool(umlView) {
+}
+
+ToolBarStateOther::~ToolBarStateOther() {
+}
+
+void ToolBarStateOther::setCurrentElement() {
+}
+
+void ToolBarStateOther::mouseReleaseEmpty() {
+ if (m_pMouseEvent->button() == Qt::LeftButton) {
+ if (!newWidget()) {
+ // Is UMLObject?
+
+ m_pUMLView->setCreateObject(true);
+ Object_Factory::createUMLObject(getObjectType());
+ }
+
+ m_pUMLView->resizeCanvasToItems();
+ }
+}
+
+Uml::Object_Type ToolBarStateOther::getObjectType() {
+ Object_Type ot;
+
+ switch(getButton()) {
+ case WorkToolBar::tbb_Actor: ot = ot_Actor; break;
+ case WorkToolBar::tbb_UseCase: ot = ot_UseCase; break;
+ case WorkToolBar::tbb_Class: ot = ot_Class; break;
+ case WorkToolBar::tbb_Object: ot = ot_Class; break; // Object is a class.
+ case WorkToolBar::tbb_Package: ot = ot_Package; break;
+ case WorkToolBar::tbb_Component: ot = ot_Component; break;
+ case WorkToolBar::tbb_Node: ot = ot_Node; break;
+ case WorkToolBar::tbb_Artifact: ot = ot_Artifact; break;
+ case WorkToolBar::tbb_Interface: ot = ot_Interface; break;
+ case WorkToolBar::tbb_Enum: ot = ot_Enum; break;
+ case WorkToolBar::tbb_Entity: ot = ot_Entity; break;
+ case WorkToolBar::tbb_Datatype: ot = ot_Datatype; break;
+
+ default: ot = ot_UMLObject; break;
+ }
+
+ return ot;
+}
+
+// TODO: The name is a bit confusing.
+bool ToolBarStateOther::newWidget() {
+ UMLWidget* umlWidget = NULL;
+
+ switch (getButton()) {
+ case WorkToolBar::tbb_Note:
+ umlWidget = new NoteWidget(m_pUMLView);
+ break;
+
+ case WorkToolBar::tbb_Box:
+ umlWidget = new BoxWidget(m_pUMLView);
+ break;
+
+ case WorkToolBar::tbb_Text:
+ umlWidget = new FloatingTextWidget(m_pUMLView, tr_Floating, "");
+ break;
+
+ // Activity buttons
+ case WorkToolBar::tbb_Initial_Activity:
+ umlWidget = new ActivityWidget(m_pUMLView, ActivityWidget::Initial);
+ break;
+
+ case WorkToolBar::tbb_Activity:
+ umlWidget = new ActivityWidget(m_pUMLView, ActivityWidget::Normal);
+ break;
+
+ case WorkToolBar::tbb_End_Activity:
+ umlWidget = new ActivityWidget(m_pUMLView, ActivityWidget::End);
+ break;
+
+ case WorkToolBar::tbb_Branch:
+ umlWidget = new ActivityWidget(m_pUMLView, ActivityWidget::Branch);
+ break;
+
+ case WorkToolBar::tbb_Fork:
+ case WorkToolBar::tbb_StateFork:
+ umlWidget = new ForkJoinWidget(m_pUMLView);
+ break;
+
+ case WorkToolBar::tbb_Initial_State:
+ umlWidget = new StateWidget(m_pUMLView, StateWidget::Initial);
+ break;
+
+ case WorkToolBar::tbb_State:
+ umlWidget = new StateWidget(m_pUMLView, StateWidget::Normal);
+ break;
+
+ case WorkToolBar::tbb_End_State:
+ umlWidget = new StateWidget(m_pUMLView, StateWidget::End);
+ break;
+
+ default:
+ break;
+ }
+
+ // Return false if we didn't find a suitable widget.
+ if (umlWidget == NULL) {
+ return false;
+ }
+
+ // Special treatment for some buttons
+ if (getButton() == WorkToolBar::tbb_Activity) {
+ Dialog_Utils::askNameForWidget(
+ umlWidget, i18n("Enter Activity Name"),
+ i18n("Enter the name of the new activity:"), i18n("new activity"));
+ } else if (getButton() == WorkToolBar::tbb_State) {
+ Dialog_Utils::askNameForWidget(
+ umlWidget, i18n("Enter State Name"),
+ i18n("Enter the name of the new state:"), i18n("new state"));
+ } else if (getButton() == WorkToolBar::tbb_Text) {
+ // It is pretty invisible otherwise.
+ FloatingTextWidget* ft = (FloatingTextWidget*) umlWidget;
+ ft->changeTextDlg();
+ }
+
+ // Create the widget. Some setup functions can remove the widget.
+ if (umlWidget != NULL) {
+ m_pUMLView->setupNewWidget(umlWidget);
+ }
+
+ return true;
+}
+
+#include "toolbarstateother.moc"
diff --git a/umbrello/umbrello/toolbarstateother.h b/umbrello/umbrello/toolbarstateother.h
new file mode 100644
index 00000000..d5c6f412
--- /dev/null
+++ b/umbrello/umbrello/toolbarstateother.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEOTHER_H
+#define TOOLBARSTATEOTHER_H
+
+#include "toolbarstatepool.h"
+
+/**
+ * Other tool creates almost all the objects (except associations and messages).
+ * Objects are created when left button is released, no matter if it was
+ * released on an association, on a widget or on an empty space.
+ *
+ * Associations and widgets aren't taken into account, and are treated as empty
+ * spaces.
+ */
+class ToolBarStateOther : public ToolBarStatePool {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a new ToolBarStateOther.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarStateOther(UMLView *umlView);
+
+ /**
+ * Destroys this ToolBarStateOther.
+ */
+ virtual ~ToolBarStateOther();
+
+private:
+
+ /**
+ * Sets nothing.
+ * Overriden from base class to ignore associations and widgets and treat
+ * them as empty spaces to create widgets on it.
+ */
+ virtual void setCurrentElement();
+
+ /**
+ * Called when the release event happened on an empty space.
+ * Associations, widgets and actual empty spaces are all treated as empty
+ * spaces. It creates a new widget if the left button was released.
+ * The widget to create depends on the type of the toolbar button selected.
+ * If the widget is the visual representation of an UMLObject, the object
+ * factory handles its creation. Otherwise, the widget is created using
+ * newWidget().
+ * The UMLView is resized to fit on all the items.
+ */
+ virtual void mouseReleaseEmpty();
+
+ /**
+ * Returns the object type of this tool.
+ *
+ * @return The object type of this tool.
+ */
+ Uml::Object_Type getObjectType();
+
+ /**
+ * Creates and adds a new widget to the UMLView (if widgets of that type
+ * don't have an associated UMLObject).
+ * If the type of the widget doesn't use an UMLObject (for example, a note
+ * or a box), it creates the widget, adds it to the view and returns true.
+ * Otherwise, it returns false.
+ *
+ * @return True if the widget was created, false otherwise.
+ * @todo rename to something more clear
+ */
+ bool newWidget();
+
+};
+
+#endif //TOOLBARSTATEOTHER_H
diff --git a/umbrello/umbrello/toolbarstatepool.cpp b/umbrello/umbrello/toolbarstatepool.cpp
new file mode 100644
index 00000000..3bb2d04a
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatepool.cpp
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "toolbarstatepool.h"
+
+ToolBarStatePool::~ToolBarStatePool() {
+}
+
+void ToolBarStatePool::setButton(const WorkToolBar::ToolBar_Buttons &button) {
+ if (button != m_ToolBarButton) {
+ m_ToolBarButton = button;
+
+ init(); // Go back to the initial state.
+ }
+}
+
+ToolBarStatePool::ToolBarStatePool(UMLView *umlView): ToolBarState(umlView) {
+ m_ToolBarButton = WorkToolBar::tbb_Arrow;
+}
+
+#include "toolbarstatepool.moc"
diff --git a/umbrello/umbrello/toolbarstatepool.h b/umbrello/umbrello/toolbarstatepool.h
new file mode 100644
index 00000000..6b33f9ea
--- /dev/null
+++ b/umbrello/umbrello/toolbarstatepool.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef TOOLBARSTATEPOOL_H
+#define TOOLBARSTATEPOOL_H
+
+#include "toolbarstate.h"
+
+#include "worktoolbar.h"
+
+/**
+ * Base class for tools that can use the same state but with different button.
+ * This class only adds support to specify the button currently in use for a
+ * tool bar state.
+ */
+class ToolBarStatePool : public ToolBarState {
+ Q_OBJECT
+public:
+
+ /**
+ * Destroys this ToolBarStatePool.
+ */
+ virtual ~ToolBarStatePool();
+
+ /**
+ * Sets the current button and inits the tool.
+ * If the current button is the same to the button to set, the tool isn't
+ * initialized.
+ *
+ * @param button The button to set.
+ */
+ void setButton(const WorkToolBar::ToolBar_Buttons &button);
+
+ /**
+ * Returns the current button.
+ *
+ * @return The current button.
+ */
+ WorkToolBar::ToolBar_Buttons getButton() const {
+ return m_ToolBarButton;
+ }
+
+protected:
+
+ /**
+ * Creates a new ToolBarStatePool.
+ * Protected to avoid classes other than derived to create objects of this
+ * class.
+ *
+ * @param umlView The UMLView to use.
+ */
+ ToolBarStatePool(UMLView *umlView);
+
+private:
+
+ /**
+ * The current button of the tool.
+ */
+ WorkToolBar::ToolBar_Buttons m_ToolBarButton;
+
+};
+
+#endif //TOOLBARSTATEPOOL_H
diff --git a/umbrello/umbrello/umbrello.desktop b/umbrello/umbrello/umbrello.desktop
new file mode 100644
index 00000000..e414a8da
--- /dev/null
+++ b/umbrello/umbrello/umbrello.desktop
@@ -0,0 +1,57 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+Exec=umbrello -caption "%c" %i %m
+Icon=umbrello
+DocPath=umbrello/index.html
+Terminal=false
+Name=Umbrello
+Name[hi]=अमà¥à¤¬à¤°à¥ˆà¤²à¥‹
+Name[ne]=अमà¥à¤¬à¥à¤°à¥‡à¤²à¥‹
+Name[pa]=ਉਮਬਰਿੱਲਓ
+Name[ta]= à®…à®®à¯à®°à®²à¯à®²à¯‹
+GenericName=UML Modeller
+GenericName[bs]=UML modeler
+GenericName[ca]=Modelador UML
+GenericName[cs]=UML modelář
+GenericName[cy]=Modelydd UML
+GenericName[da]=UML Modellering
+GenericName[de]=UML-Modellierer
+GenericName[el]=Μοντελοποιητής UML
+GenericName[eo]=UML-Modelilo
+GenericName[es]=Modelador de UML
+GenericName[et]=UML-i modelleerimise rakendus
+GenericName[eu]=UML modelatzailea
+GenericName[fa]=مدل‌ساز UML
+GenericName[fi]=UML-mallintaja
+GenericName[fr]=Modeleur UML
+GenericName[ga]=Múnlóir UML
+GenericName[gl]=Modelador de UML
+GenericName[hi]=यूà¤à¤®à¤à¤² मॉडलर
+GenericName[hu]=UML-modellező
+GenericName[it]=Modellatore UML
+GenericName[ja]=UML モデラー
+GenericName[ka]=UML მáƒáƒ“ელერი
+GenericName[kk]=UML үлгілегіші
+GenericName[ms]=Pemodel UML
+GenericName[nb]=UML-modelleringsprogram
+GenericName[nds]=UML-Modellmaker
+GenericName[ne]=यूà¤à¤®à¤à¤² मोडेलर
+GenericName[nl]=UML-modeller
+GenericName[nn]=UML-modelleringsprogram
+GenericName[pl]=Program do modelowania UML
+GenericName[pt]=Modelador de UML
+GenericName[pt_BR]=Modelador UML
+GenericName[ru]=СредÑтво UML моделированиÑ
+GenericName[sk]=Modelár UML
+GenericName[sl]=Mofdelirnik UML
+GenericName[sr]=UML моделар
+GenericName[sr@Latn]=UML modelar
+GenericName[sv]=UML-modellering
+GenericName[ta]=UML மோடெலà¯à®²à®¾à®°à¯
+GenericName[tg]=ВоÑитаи UML моделкунонӣ
+GenericName[tr]=UML Modelleyici
+GenericName[uk]=ЗаÑіб Ð¼Ð¾Ð´ÐµÐ»ÑŽÐ²Ð°Ð½Ð½Ñ UML
+GenericName[zh_CN]=UML 建模工具
+MimeType=application/x-uml;
+Categories=Qt;KDE;Development;
diff --git a/umbrello/umbrello/umbrelloui.rc b/umbrello/umbrello/umbrelloui.rc
new file mode 100644
index 00000000..f14efddd
--- /dev/null
+++ b/umbrello/umbrello/umbrelloui.rc
@@ -0,0 +1,58 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="umbrello" version="11">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_docbook"/>
+ <Action name="file_export_xhtml"/>
+ </Menu>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="delete_selected"/>
+ </Menu>
+ <Menu name="views"><text>&amp;Diagram</text>
+ <Menu name="new_view"><text>&amp;New</text>
+ <Action name="new_class_diagram"/>
+ <Action name="new_sequence_diagram"/>
+ <Action name="new_collaboration_diagram"/>
+ <Action name="new_use_case_diagram"/>
+ <Action name="new_state_diagram"/>
+ <Action name="new_activity_diagram"/>
+ <Action name="new_component_diagram"/>
+ <Action name="new_deployment_diagram"/>
+ <Action name="new_entityrelationship_diagram"/>
+ </Menu>
+ <Action name="view_clear_diagram"/>
+ <Action name="view_delete"/>
+ <Action name="view_export_image"/>
+ <Action name="view_export_image_all"/>
+ <Action name="autolayout" />
+ <Separator/>
+ <Menu name="show_view"><text>Sh&amp;ow</text>
+ <ActionList name="view_list">
+ </ActionList>
+ </Menu>
+ <Menu name="zoom_menu"><text>&amp;Zoom</text>
+ </Menu>
+ <Separator/>
+ <Action name="view_snap_to_grid"/>
+ <Action name="view_show_grid"/>
+ <Action name="view_properties"/>
+ </Menu>
+
+ <Menu name="code"><text>&amp;Code</text>
+ <Action name="import_class"/>
+ <Action name="generation_wizard"/>
+ <Action name="generate_all"/>
+ <Menu name="active_lang_menu"><text>Active &amp;Language</text>
+ </Menu>
+ <Separator/>
+ <Action name="create_default_datatypes"/>
+ <Action name="class_wizard"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar">
+ <Action name="popup_zoom"/>
+ <Action name="zoom100"/>
+</ToolBar>
+</kpartgui>
diff --git a/umbrello/umbrello/uml.cpp b/umbrello/umbrello/uml.cpp
new file mode 100644
index 00000000..11a5b32a
--- /dev/null
+++ b/umbrello/umbrello/uml.cpp
@@ -0,0 +1,1708 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "uml.h"
+
+// qt includes
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+#include <qtimer.h>
+#include <qwidgetstack.h>
+#include <qslider.h>
+#include <qregexp.h>
+#include <qtoolbutton.h>
+
+// kde includes
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kprinter.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <ktip.h>
+#include <ktabwidget.h>
+#include <ktoolbarbutton.h>
+#include <kpopupmenu.h>
+
+// app includes
+#include "aligntoolbar.h"
+#include "codeimport/classimport.h"
+#include "docwindow.h"
+#include "codegenerator.h"
+#include "codegenerationpolicy.h"
+#include "codegenerators/codegenfactory.h"
+#include "codegenerators/codegenpolicyext.h"
+#include "optionstate.h"
+#include "widget_utils.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umlviewlist.h"
+#include "worktoolbar.h"
+#ifdef HAVE_DOT
+# include "autolayout/autolayoutdlg.h" //dimitri
+#endif
+#include "model_utils.h"
+#include "clipboard/umlclipboard.h"
+#include "dialogs/classwizard.h"
+#include "dialogs/codegenerationwizard.h"
+#include "dialogs/codeviewerdialog.h"
+#include "dialogs/diagramprintpage.h"
+
+#include "refactoring/refactoringassistant.h"
+#include "codegenerators/simplecodegenerator.h"
+#include "umlviewimageexporter.h"
+#include "umlviewimageexporterall.h"
+
+#include "kplayerslideraction.h"
+
+#include "configurable.h"
+
+#include "cmdlineexportallviewsevent.h"
+
+#include "docgenerators/docbookgenerator.h"
+#include "docgenerators/xhtmlgenerator.h"
+
+UMLApp::UMLApp(QWidget* , const char* name):KDockMainWindow(0, name) {
+ s_instance = this;
+ m_pDocWindow = 0;
+ m_config = kapp->config();
+ m_listView = 0;
+ m_langSelect = NULL;
+ m_zoomSelect = NULL;
+ m_loading = false;
+ m_clipTimer = 0;
+ m_copyTimer = 0;
+ m_codegen = 0;
+ m_policyext = 0;
+ m_commoncodegenpolicy = 0;
+ m_xhtmlGenerator = 0;
+ m_activeLanguage = Uml::pl_Reserved;
+ ///////////////////////////////////////////////////////////////////
+ // call inits to invoke all other construction parts
+ readOptionState();
+ m_doc = new UMLDoc();
+ m_doc->init();
+ initActions(); //now calls initStatusBar() because it is affected by setupGUI()
+ initView();
+ initClip();
+ readOptions();
+ ///////////////////////////////////////////////////////////////////
+ // disable actions at startup
+ fileSave->setEnabled(true);
+ fileSaveAs->setEnabled(true);
+ enablePrint(false);
+ editCut->setEnabled(false);
+ editCopy->setEnabled(false);
+ editPaste->setEnabled(false);
+ editUndo->setEnabled(false);
+ editRedo->setEnabled(false);
+
+ //get a reference to the Code->Active Language and to the Diagram->Zoom menu
+ QPopupMenu* menu = findMenu( menuBar(), QString("code") );
+ m_langSelect = findMenu( menu, QString("active_lang_menu") );
+
+ //in case langSelect hasn't been initialized we create the Popup menu.
+ //it will be hidden, but at least we wont crash if someone takes the entry away from the ui.rc file
+ if (m_langSelect == NULL) {
+ m_langSelect = new QPopupMenu(this);
+ }
+
+ menu = findMenu( menuBar(), QString("views") );
+ m_zoomSelect = findMenu( menu, QString("zoom_menu") );
+
+ //in case zoomSelect hasn't been initialized we create the Popup menu.
+ //it will be hidden, but at least we wont crash if some one takes the entry away from the ui.rc file
+ if (m_zoomSelect == NULL) {
+ m_zoomSelect = new QPopupMenu(this);
+ }
+
+ //connect zoomSelect menu
+ m_zoomSelect->setCheckable(true);
+ connect(m_zoomSelect,SIGNAL(aboutToShow()),this,SLOT(setupZoomMenu()));
+ connect(m_zoomSelect,SIGNAL(activated(int)),this,SLOT(setZoom(int)));
+
+ m_refactoringAssist = 0L;
+
+ m_commoncodegenpolicy = new CodeGenerationPolicy(m_config);
+
+ m_imageExporterAll = new UMLViewImageExporterAll();
+}
+
+UMLApp::~UMLApp() {
+ delete m_imageExporterAll;
+
+ delete m_clipTimer;
+ delete m_copyTimer;
+
+ delete m_statusLabel;
+ delete m_refactoringAssist;
+}
+
+UMLApp* UMLApp::app()
+{
+ return s_instance;
+}
+
+void UMLApp::initActions() {
+ fileNew = KStdAction::openNew(this, SLOT(slotFileNew()), actionCollection());
+ fileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
+ fileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection());
+ fileSave = KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
+ fileSaveAs = KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
+ fileClose = KStdAction::close(this, SLOT(slotFileClose()), actionCollection());
+ filePrint = KStdAction::print(this, SLOT(slotFilePrint()), actionCollection());
+ fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
+ editUndo = KStdAction::undo(this, SLOT(slotEditUndo()), actionCollection());
+ editRedo = KStdAction::redo(this, SLOT(slotEditRedo()), actionCollection());
+ editCut = KStdAction::cut(this, SLOT(slotEditCut()), actionCollection());
+ editCopy = KStdAction::copy(this, SLOT(slotEditCopy()), actionCollection());
+ editPaste = KStdAction::paste(this, SLOT(slotEditPaste()), actionCollection());
+ createStandardStatusBarAction();
+ setStandardToolBarMenuEnabled(true);
+ selectAll = KStdAction::selectAll(this, SLOT( slotSelectAll() ), actionCollection());
+ fileExportDocbook = new KAction(i18n("&Export model to DocBook"), 0,
+ this, SLOT( slotFileExportDocbook() ),
+ actionCollection(), "file_export_docbook");
+ fileExportXhtml = new KAction(i18n("&Export model to XHTML"), 0,
+ this, SLOT( slotFileExportXhtml() ),
+ actionCollection(), "file_export_xhtml");
+
+ classWizard = new KAction(i18n("&New Class Wizard..."),0,this,SLOT(slotClassWizard()),
+ actionCollection(),"class_wizard");
+ new KAction(i18n("&Add Default Datatypes for Active Language"), 0, this,
+ SLOT(slotAddDefaultDatatypes()), actionCollection(), "create_default_datatypes");
+
+ preferences = KStdAction::preferences(this, SLOT( slotPrefs() ), actionCollection());
+
+ genWizard = new KAction(i18n("&Code Generation Wizard..."),0,this,SLOT(generationWizard()),
+ actionCollection(),"generation_wizard");
+ genAll = new KAction(i18n("&Generate All Code"),0,this,SLOT(generateAllCode()),
+ actionCollection(),"generate_all");
+
+ importClasses = new KAction(i18n("&Import Classes..."), SmallIconSet("source_cpp"), 0,
+ this,SLOT(slotImportClasses()), actionCollection(),"import_class");
+
+ fileNew->setToolTip(i18n("Creates a new document"));
+ fileOpen->setToolTip(i18n("Opens an existing document"));
+ fileOpenRecent->setToolTip(i18n("Opens a recently used file"));
+ fileSave->setToolTip(i18n("Saves the document"));
+ fileSaveAs->setToolTip(i18n("Saves the document as..."));
+ fileClose->setToolTip(i18n("Closes the document"));
+ filePrint ->setToolTip(i18n("Prints out the document"));
+ fileQuit->setToolTip(i18n("Quits the application"));
+ fileExportDocbook->setToolTip(i18n("Exports the model to the docbook format"));
+ fileExportXhtml->setToolTip(i18n("Exports the model to the XHTML format"));
+ editCut->setToolTip(i18n("Cuts the selected section and puts it to the clipboard"));
+ editCopy->setToolTip(i18n("Copies the selected section to the clipboard"));
+ editPaste->setToolTip(i18n("Pastes the contents of the clipboard"));
+ preferences->setToolTip( i18n( "Set the default program preferences") );
+
+ deleteSelectedWidget = new KAction( i18n("Delete &Selected"),
+ SmallIconSet("editdelete"),
+ KShortcut(Qt::Key_Delete), this,
+ SLOT( slotDeleteSelectedWidget() ), actionCollection(),
+ "delete_selected" );
+
+ // The different views
+ newDiagram = new KActionMenu(0, SmallIconSet("filenew"), actionCollection(), "new_view");
+ classDiagram = new KAction( i18n( "&Class Diagram..." ), SmallIconSet("umbrello_diagram_class"), 0,
+ this, SLOT( slotClassDiagram() ), actionCollection(), "new_class_diagram" );
+
+#if defined (HAVE_DOT)
+ autolayout = new KAction(i18n("&Autolayout..."),0,0,this,SLOT(slotAutolayout()),
+ actionCollection(),"autolayout");
+#endif
+ sequenceDiagram= new KAction( i18n( "&Sequence Diagram..." ), SmallIconSet("umbrello_diagram_sequence"), 0,
+ this, SLOT( slotSequenceDiagram() ), actionCollection(), "new_sequence_diagram" );
+
+ collaborationDiagram = new KAction( i18n( "C&ollaboration Diagram..." ), SmallIconSet("umbrello_diagram_collaboration"), 0,
+ this, SLOT( slotCollaborationDiagram() ), actionCollection(), "new_collaboration_diagram" );
+
+ useCaseDiagram= new KAction( i18n( "&Use Case Diagram..." ), SmallIconSet("umbrello_diagram_usecase"), 0,
+ this, SLOT( slotUseCaseDiagram() ), actionCollection(), "new_use_case_diagram" );
+
+ stateDiagram= new KAction( i18n( "S&tate Diagram..." ), SmallIconSet("umbrello_diagram_state"), 0,
+ this, SLOT( slotStateDiagram() ), actionCollection(), "new_state_diagram" );
+
+ activityDiagram= new KAction( i18n( "&Activity Diagram..." ), SmallIconSet("umbrello_diagram_activity"), 0,
+ this, SLOT( slotActivityDiagram() ), actionCollection(), "new_activity_diagram" );
+
+ componentDiagram = new KAction( i18n("Co&mponent Diagram..."), SmallIconSet("umbrello_diagram_component"), 0,
+ this, SLOT( slotComponentDiagram() ), actionCollection(),
+ "new_component_diagram" );
+
+ deploymentDiagram = new KAction( i18n("&Deployment Diagram..."), SmallIconSet("umbrello_diagram_deployment"), 0,
+ this, SLOT( slotDeploymentDiagram() ), actionCollection(),
+ "new_deployment_diagram" );
+
+ entityRelationshipDiagram = new KAction( i18n("&Entity Relationship Diagram..."), SmallIconSet("umbrello_diagram_entityrelationship"), 0,
+ this, SLOT( slotEntityRelationshipDiagram() ), actionCollection(),
+ "new_entityrelationship_diagram" );
+
+ viewClearDiagram = new KAction(i18n("&Clear Diagram"), SmallIconSet("editclear"), 0,
+ this, SLOT( slotCurrentViewClearDiagram() ), actionCollection(), "view_clear_diagram");
+ viewSnapToGrid = new KToggleAction(i18n("&Snap to Grid"), 0,
+ this, SLOT( slotCurrentViewToggleSnapToGrid() ), actionCollection(), "view_snap_to_grid");
+ viewShowGrid = new KToggleAction(i18n("S&how Grid"), 0,
+ this, SLOT( slotCurrentViewToggleShowGrid() ), actionCollection(), "view_show_grid");
+#if (KDE_VERSION_MINOR>=3) && (KDE_VERSION_MAJOR>=3)
+ viewShowGrid->setCheckedState(i18n("&Hide Grid"));
+#endif
+ deleteDiagram = new KAction(i18n("&Delete"), SmallIconSet("editdelete"), 0,
+ this, SLOT( slotDeleteDiagram() ), actionCollection(), "view_delete");
+ viewExportImage = new KAction(i18n("&Export as Picture..."), SmallIconSet("image"), 0,
+ this, SLOT( slotCurrentViewExportImage() ), actionCollection(), "view_export_image");
+ viewExportImageAll = new KAction(i18n("Export &All Diagrams as Pictures..."), SmallIconSet("image"), 0,
+ this, SLOT( slotAllViewsExportImage() ), actionCollection(), "view_export_image_all");
+ viewProperties = new KAction(i18n("&Properties"), SmallIconSet("info"), 0,
+ this, SLOT( slotCurrentViewProperties() ), actionCollection(), "view_properties");
+
+ viewSnapToGrid->setChecked(false);
+ viewShowGrid->setChecked(false);
+
+ viewClearDiagram->setEnabled(false);
+ viewSnapToGrid->setEnabled(false);
+ viewShowGrid->setEnabled(false);
+ deleteDiagram->setEnabled(false);
+ viewExportImage->setEnabled(false);
+ viewProperties->setEnabled(false);
+
+ zoomAction = new KPlayerPopupSliderAction(i18n("&Zoom Slider"), "viewmag", Key_F9,
+ this, SLOT(slotZoomSliderMoved(int)),
+ actionCollection(), "popup_zoom");
+ zoom100Action = new KAction(i18n( "Z&oom to 100%" ), "viewmag1", 0,
+ this, SLOT( slotZoom100() ), actionCollection(),
+ "zoom100");
+
+ KStdAction::tipOfDay( this, SLOT( tipOfTheDay() ), actionCollection() );
+
+ QString moveTabLeftString = i18n("&Move Tab Left");
+ QString moveTabRightString = i18n("&Move Tab Right");
+ moveTabLeft = new KAction(QApplication::reverseLayout() ? moveTabRightString : moveTabLeftString,
+ QApplication::reverseLayout() ? "forward" : "back",
+ QApplication::reverseLayout() ? Qt::CTRL+Qt::SHIFT+Qt::Key_Right : Qt::CTRL+Qt::SHIFT+Qt::Key_Left,
+ this, SLOT(slotMoveTabLeft()), actionCollection(),
+ "move_tab_left");
+ moveTabRight = new KAction(QApplication::reverseLayout() ? moveTabLeftString : moveTabRightString,
+ QApplication::reverseLayout() ? "back" : "forward",
+ QApplication::reverseLayout() ? Qt::CTRL+Qt::SHIFT+Qt::Key_Left : Qt::CTRL+Qt::SHIFT+Qt::Key_Right,
+ this, SLOT(slotMoveTabRight()), actionCollection(),
+ "move_tab_right");
+
+ QString selectTabLeftString = i18n("Select Diagram on Left");
+ QString selectTabRightString = i18n("Select Diagram on Right");
+ changeTabLeft = new KAction(QApplication::reverseLayout() ? selectTabRightString : selectTabLeftString,
+ QApplication::reverseLayout() ? Qt::SHIFT+Qt::Key_Right : Qt::SHIFT+Qt::Key_Left,
+ this, SLOT(slotChangeTabLeft()), actionCollection(), "previous_tab");
+ changeTabRight = new KAction(QApplication::reverseLayout() ? selectTabLeftString : selectTabRightString,
+ QApplication::reverseLayout() ? Qt::SHIFT+Qt::Key_Left : Qt::SHIFT+Qt::Key_Right,
+ this, SLOT(slotChangeTabRight()), actionCollection(), "next_tab");
+
+
+ initStatusBar(); //call this here because the statusBar is shown/hidden by setupGUI()
+
+ // use the absolute path to your umbrelloui.rc file for testing purpose in setupGUI();
+#if KDE_IS_VERSION(3,2,90)
+ setupGUI();
+#else
+ createGUI();
+#endif
+ QPopupMenu* menu = findMenu( menuBar(), QString("settings") );
+ menu->insertItem(i18n("&Windows"), dockHideShowMenu(), -1, 0);
+}
+
+void UMLApp::slotZoomSliderMoved(int value) {
+ int zoom = (int)(value*0.01);
+ getCurrentView()->setZoom(zoom*zoom);
+}
+
+void UMLApp::slotZoom100() {
+ setZoom(100);
+}
+
+void UMLApp::setZoom(int zoom) {
+ getCurrentView()->setZoom(zoom);
+}
+
+void UMLApp::setupZoomMenu() {
+ m_zoomSelect->clear();
+
+ //IMPORTANT: The ID's must match the zoom value (text)
+ m_zoomSelect->insertItem(i18n(" &33%"),33);
+ m_zoomSelect->insertItem(i18n(" &50%"),50);
+ m_zoomSelect->insertItem(i18n(" &75%"),75);
+ m_zoomSelect->insertItem(i18n("&100%"),100);
+ m_zoomSelect->insertItem(i18n("1&50%"),150);
+ m_zoomSelect->insertItem(i18n("&200%"),200);
+ m_zoomSelect->insertItem(i18n("3&00%"),300);
+
+
+ int zoom = getCurrentView()->currentZoom();
+ //if current zoom is not a "standard zoom" (because of zoom in / zoom out step
+ //we add it for information
+ switch(zoom){
+ case 33:
+ case 50:
+ case 75:
+ case 100:
+ case 150:
+ case 200:
+ case 300:
+ break;
+ default:
+ m_zoomSelect->insertSeparator();
+ m_zoomSelect->insertItem(QString::number(zoom)+" %",zoom);
+ }
+ m_zoomSelect->setItemChecked(zoom, true);
+}
+
+void UMLApp::initStatusBar() {
+ m_statusLabel = new KStatusBarLabel( i18n("Ready."), 0, statusBar() );
+ m_statusLabel->setFixedHeight( m_statusLabel->sizeHint().height() );
+
+ m_statusLabel->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
+ m_statusLabel->setMargin( 0 );
+ m_statusLabel->setLineWidth(0);
+
+ statusBar()->addWidget( m_statusLabel, 1, false );
+
+ m_statusLabel->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
+
+ connect(m_doc, SIGNAL( sigWriteToStatusBar(const QString &) ), this, SLOT( slotStatusMsg(const QString &) ));
+}
+
+void UMLApp::initView() {
+ setCaption(m_doc->URL().fileName(),false);
+ m_view = NULL;
+ toolsbar = new WorkToolBar(this, "");
+ toolsbar->setLabel(i18n("Diagram Toolbar"));
+ addToolBar(toolsbar, Qt::DockTop, false);
+
+ m_alignToolBar = new AlignToolBar(this, "");
+ m_alignToolBar->setLabel(i18n("Alignment Toolbar"));
+ addToolBar(m_alignToolBar, Qt::DockTop, false);
+
+ m_mainDock = createDockWidget("maindock", 0L, 0L, "main dock");
+ m_newSessionButton = NULL;
+ m_diagramMenu = NULL;
+ m_closeDiagramButton = NULL;
+ Settings::OptionState& optionState = Settings::getOptionState();
+ if (optionState.generalState.tabdiagrams) {
+ m_viewStack = NULL;
+ m_tabWidget = new KTabWidget(m_mainDock, "tab_widget");
+
+#if KDE_IS_VERSION(3,3,89)
+ m_tabWidget->setAutomaticResizeTabs( true );
+#endif
+
+ m_newSessionButton = new KToolBarButton("tab_new", 0, m_tabWidget);
+ m_newSessionButton->setIconSet( SmallIcon( "tab_new" ) );
+ m_newSessionButton->adjustSize();
+ m_newSessionButton->setAutoRaise(true);
+ m_diagramMenu = new KPopupMenu(m_newSessionButton);
+
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Class), i18n("Class Diagram..."), this, SLOT(slotClassDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Sequence), i18n("Sequence Diagram..."), this, SLOT(slotSequenceDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Collaboration), i18n("Collaboration Diagram..."), this, SLOT(slotCollaborationDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_UseCase), i18n("Use Case Diagram..."), this, SLOT(slotUseCaseDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_State), i18n("State Diagram..."), this, SLOT(slotStateDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Activity), i18n("Activity Diagram..."), this, SLOT(slotActivityDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Component), i18n("Component Diagram..."), this, SLOT(slotComponentDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_Deployment), i18n("Deployment Diagram..."), this, SLOT(slotDeploymentDiagram()) );
+ m_diagramMenu->insertItem(Widget_Utils::iconSet(Uml::dt_EntityRelationship), i18n("Entity Relationship Diagram..."), this, SLOT(slotEntityRelationshipDiagram()) );
+ m_newSessionButton->setPopup(m_diagramMenu);
+ //FIXME why doesn't this work?
+ //m_newSessionButton->setPopup(newDiagram->popupMenu());
+
+ //m_closeDiagramButton = new KToolBarButton("tab_remove", 0, m_tabWidget);
+ m_closeDiagramButton = new QToolButton(m_tabWidget);
+ m_closeDiagramButton->setIconSet( SmallIcon("tab_remove") );
+ m_closeDiagramButton->adjustSize();
+
+ connect(m_closeDiagramButton, SIGNAL(clicked()), SLOT(slotDeleteDiagram()));
+ connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), SLOT(slotTabChanged(QWidget*)));
+ connect(m_tabWidget, SIGNAL(contextMenu(QWidget*,const QPoint&)), m_doc, SLOT(slotDiagramPopupMenu(QWidget*,const QPoint&)));
+ m_tabWidget->setCornerWidget( m_newSessionButton, TopLeft );
+ m_tabWidget->setCornerWidget( m_closeDiagramButton, TopRight );
+ m_newSessionButton->installEventFilter(this);
+
+ m_mainDock->setWidget(m_tabWidget);
+ }
+ else
+ {
+ m_tabWidget = NULL;
+ m_viewStack = new QWidgetStack(m_mainDock, "viewstack");
+ m_mainDock->setWidget(m_viewStack);
+ }
+ m_mainDock->setDockSite(KDockWidget::DockCorner);
+ m_mainDock->setEnableDocking(KDockWidget::DockNone);
+ setView(m_mainDock);
+ setMainDockWidget(m_mainDock);
+
+ m_listDock = createDockWidget( "Model", 0L, 0L, i18n("&Tree View") );
+ m_listView = new UMLListView(m_listDock ,"LISTVIEW");
+ //m_listView->setSorting(-1);
+ m_listView->setDocument(m_doc);
+ m_listView->init();
+ m_listDock->setWidget(m_listView);
+ m_listDock->setDockSite(KDockWidget::DockCorner);
+ m_listDock->manualDock(m_mainDock, KDockWidget::DockLeft, 20);
+
+ m_documentationDock = createDockWidget( "Documentation", 0L, 0L, i18n("&Documentation") );
+ m_pDocWindow = new DocWindow(m_doc, m_documentationDock, "DOCWINDOW");
+ m_documentationDock->setWidget(m_pDocWindow);
+ m_documentationDock->setDockSite(KDockWidget::DockCorner);
+ m_documentationDock->manualDock(m_listDock, KDockWidget::DockBottom, 80);
+
+ m_doc->setupSignals();//make sure gets signal from list view
+
+ readDockConfig(); //reposition all the DockWindows to their saved positions
+}
+
+void UMLApp::openDocumentFile(const KURL& url) {
+ slotStatusMsg(i18n("Opening file..."));
+
+ m_doc->openDocument( url);
+ fileOpenRecent->addURL( url );
+ slotStatusMsg(i18n("Ready."));
+ setCaption(m_doc->URL().fileName(), false);
+ enablePrint(true);
+}
+
+UMLDoc *UMLApp::getDocument() const {
+ return m_doc;
+}
+
+UMLListView* UMLApp::getListView() {
+ return m_listView;
+}
+
+
+void UMLApp::saveOptions() {
+ toolBar("mainToolBar")->saveSettings(m_config, "toolbar");
+ toolsbar->saveSettings(m_config, "workbar");
+ m_alignToolBar->saveSettings(m_config, "aligntoolbar");
+ fileOpenRecent->saveEntries(m_config,"Recent Files");
+ m_config->setGroup( "General Options" );
+ m_config->writeEntry( "Geometry", size() );
+
+ Settings::OptionState& optionState = Settings::getOptionState();
+ m_config->writeEntry( "undo", optionState.generalState.undo );
+ m_config->writeEntry( "tabdiagrams", optionState.generalState.tabdiagrams );
+ m_config->writeEntry( "newcodegen", optionState.generalState.newcodegen );
+ m_config->writeEntry( "angularlines", optionState.generalState.angularlines );
+ m_config->writeEntry( "autosave", optionState.generalState.autosave );
+ m_config->writeEntry( "time", optionState.generalState.time );
+ m_config->writeEntry( "autosavetime", optionState.generalState.autosavetime );
+ m_config->writeEntry( "autosavesuffix", optionState.generalState.autosavesuffix );
+
+ m_config->writeEntry( "logo", optionState.generalState.logo );
+ m_config->writeEntry( "loadlast", optionState.generalState.loadlast );
+
+ m_config->writeEntry( "diagram", optionState.generalState.diagram );
+ if( m_doc->URL().fileName() == i18n( "Untitled" ) ) {
+ m_config -> writeEntry( "lastFile", "" );
+ } else {
+ m_config -> writePathEntry( "lastFile", m_doc -> URL().prettyURL() );
+ }
+ m_config->writeEntry( "imageMimeType", getImageMimeType() );
+
+ m_config->setGroup( "TipOfDay");
+ optionState.generalState.tip = m_config -> readBoolEntry( "RunOnStart", true );
+ m_config->writeEntry( "RunOnStart", optionState.generalState.tip );
+
+ m_config->setGroup( "UI Options" );
+ m_config->writeEntry( "useFillColor", optionState.uiState.useFillColor );
+ m_config->writeEntry( "fillColor", optionState.uiState.fillColor );
+ m_config->writeEntry( "lineColor", optionState.uiState.lineColor );
+ m_config->writeEntry( "lineWidth", optionState.uiState.lineWidth );
+ m_config->writeEntry( "showDocWindow", m_documentationDock->isVisible() );
+ m_config->writeEntry( "font", optionState.uiState.font );
+
+ m_config->setGroup( "Class Options" );
+ m_config->writeEntry( "showVisibility", optionState.classState.showVisibility );
+ m_config->writeEntry( "showAtts", optionState.classState.showAtts);
+ m_config->writeEntry( "showOps", optionState.classState.showOps );
+ m_config->writeEntry( "showStereoType", optionState.classState.showStereoType );
+ m_config->writeEntry( "showAttSig", optionState.classState.showAttSig );
+ m_config->writeEntry( "ShowOpSig", optionState.classState.showOpSig );
+ m_config->writeEntry( "showPackage", optionState.classState.showPackage );
+ m_config->writeEntry( "defaultAttributeScope", optionState.classState.defaultAttributeScope);
+ m_config->writeEntry( "defaultOperationScope", optionState.classState.defaultOperationScope);
+
+ m_config -> setGroup( "Code Viewer Options" );
+ m_config->writeEntry( "height", optionState.codeViewerState.height );
+ m_config->writeEntry( "width", optionState.codeViewerState.width);
+ m_config->writeEntry( "font", optionState.codeViewerState.font);
+ m_config->writeEntry( "fontColor", optionState.codeViewerState.fontColor);
+ m_config->writeEntry( "paperColor", optionState.codeViewerState.paperColor);
+ m_config->writeEntry( "selectedColor", optionState.codeViewerState.selectedColor);
+ m_config->writeEntry( "editBlockColor", optionState.codeViewerState.editBlockColor);
+ m_config->writeEntry( "nonEditBlockColor", optionState.codeViewerState.nonEditBlockColor);
+ m_config->writeEntry( "umlObjectBlockColor", optionState.codeViewerState.umlObjectColor);
+ m_config->writeEntry( "blocksAreHighlighted", optionState.codeViewerState.blocksAreHighlighted);
+ m_config->writeEntry( "showHiddenBlocks", optionState.codeViewerState.showHiddenBlocks);
+ m_config->writeEntry( "hiddenColor", optionState.codeViewerState.hiddenColor);
+
+ // write the config for a language-specific code gen policy
+ if (m_policyext)
+ m_policyext->writeConfig(m_config);
+
+ // now write the basic defaults to the m_config file
+ m_commoncodegenpolicy->writeConfig(m_config);
+
+ // next, we record the activeLanguage in the Code Generation Group
+ if (m_codegen) {
+ m_config->setGroup("Code Generation");
+ m_config->writeEntry("activeLanguage", Model_Utils::progLangToString(m_codegen->getLanguage()));
+ }
+}
+
+void UMLApp::readOptions() {
+ // bar status settings
+ toolBar("mainToolBar")->applySettings(m_config, "toolbar");
+ // do config for work toolbar
+ toolsbar->applySettings(m_config, "workbar");
+ m_alignToolBar->applySettings(m_config, "aligntoolbar");
+ fileOpenRecent->loadEntries(m_config,"Recent Files");
+ m_config->setGroup("General Options");
+ setImageMimeType(m_config->readEntry("imageMimeType","image/png"));
+ QSize tmpQSize(630,460);
+ resize( m_config->readSizeEntry("Geometry", & tmpQSize) );
+}
+
+void UMLApp::saveProperties(KConfig *_config) {
+ if(m_doc->URL().fileName()!=i18n("Untitled") && !m_doc->isModified()) {
+ // saving to tempfile not necessary
+
+ } else {
+ KURL url=m_doc->URL();
+ _config->writePathEntry("filename", url.url());
+ _config->writeEntry("modified", m_doc->isModified());
+ QString tempname = kapp->tempSaveName(url.url());
+ QString tempurl= KURL::encode_string(tempname);
+
+ KURL _url(tempurl);
+ m_doc->saveDocument(_url);
+ }
+}
+
+void UMLApp::readProperties(KConfig* _config) {
+ QString filename = _config->readPathEntry("filename");
+ KURL url(filename);
+ bool modified = _config->readBoolEntry("modified", false);
+ if(modified) {
+ bool canRecover;
+ QString tempname = kapp->checkRecoverFile(filename, canRecover);
+ KURL _url(tempname);
+
+
+ if(canRecover) {
+ m_doc->openDocument(_url);
+ m_doc->setModified();
+ enablePrint(true);
+ setCaption(_url.fileName(),true);
+ QFile::remove
+ (tempname);
+ } else {
+ enablePrint(false);
+ }
+ } else {
+ if(!filename.isEmpty()) {
+ m_doc->openDocument(url);
+ enablePrint(true);
+ setCaption(url.fileName(),false);
+
+ } else {
+ enablePrint(false);
+ }
+ }
+}
+
+bool UMLApp::queryClose() {
+ writeDockConfig();
+ return m_doc->saveModified();
+}
+
+bool UMLApp::queryExit() {
+ saveOptions();
+ m_doc -> closeDocument();
+ return true;
+}
+
+void UMLApp::slotFileNew() {
+ slotStatusMsg(i18n("Creating new document..."));
+ if(m_doc->saveModified()) {
+ setDiagramMenuItemsState(false);
+ m_doc->newDocument();
+ setCaption(m_doc->URL().fileName(), false);
+ fileOpenRecent->setCurrentItem( -1 );
+ setModified(false);
+ enablePrint(false);
+ }
+ slotUpdateViews();
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotFileOpen() {
+ slotStatusMsg(i18n("Opening file..."));
+ m_loading = true;
+
+ if(!m_doc->saveModified()) {
+
+ // here saving wasn't successful
+
+ } else {
+ KURL url=KFileDialog::getOpenURL(":open-umbrello-file",
+ i18n("*.xmi *.xmi.tgz *.xmi.tar.bz2 *.mdl|All Supported Files (*.xmi, *.xmi.tgz, *.xmi.tar.bz2, *.mdl)\n"
+ "*.xmi|Uncompressed XMI Files (*.xmi)\n"
+ "*.xmi.tgz|Gzip Compressed XMI Files (*.xmi.tgz)\n"
+ "*.xmi.tar.bz2|Bzip2 Compressed XMI Files (*.xmi.tar.bz2)\n"
+ "*.mdl|Rose model files"), this, i18n("Open File"));
+ if(!url.isEmpty()) {
+ if(m_doc->openDocument(url))
+ fileOpenRecent->addURL( url );
+ enablePrint(true);
+ setCaption(m_doc->URL().fileName(), false);
+ }
+
+ }
+ slotUpdateViews();
+ m_loading = false;
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotFileOpenRecent(const KURL& url) {
+ slotStatusMsg(i18n("Opening file..."));
+ m_loading = true;
+
+ KURL oldURL = m_doc->URL();
+
+ if(!m_doc->saveModified()) {
+ // here saving wasn't successful
+ } else {
+ if(!m_doc->openDocument(url)) {
+ fileOpenRecent->removeURL(url);
+ fileOpenRecent->setCurrentItem( -1 );
+ } else {
+ fileOpenRecent->addURL(url);
+ }
+ enablePrint(true);
+ setCaption(m_doc->URL().fileName(), false);
+ }
+
+ m_loading = false;
+ slotUpdateViews();
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotFileSave() {
+ slotStatusMsg(i18n("Saving file..."));
+ if(m_doc->URL().fileName() == i18n("Untitled"))
+ slotFileSaveAs();
+ else
+ m_doc->saveDocument(m_doc -> URL());
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+bool UMLApp::slotFileSaveAs()
+{
+ slotStatusMsg(i18n("Saving file with a new filename..."));
+ bool cont = true;
+ KURL url;
+ QString ext;
+ while(cont) {
+ url=KFileDialog::getSaveURL(":save-umbrello-file", i18n("*.xmi|XMI File\n*.xmi.tgz|Gzip Compressed XMI File\n*.xmi.tar.bz2|Bzip2 Compressed XMI File\n*|All Files"), this, i18n("Save As"));
+
+ if(url.isEmpty())
+ cont = false;
+ else {
+ QDir d = url.path(-1);
+
+ if(QFile::exists(d.path())) {
+ int want_save = KMessageBox::warningContinueCancel(this, i18n("The file %1 exists.\nDo you wish to overwrite it?").arg(url.path()), i18n("Warning"), i18n("Overwrite"));
+ if(want_save == KMessageBox::Continue)
+ cont = false;
+ } else
+ cont = false;
+
+ }
+ }
+ if(!url.isEmpty()) {
+ bool b = m_doc->saveDocument(url);
+ if (b) {
+ fileOpenRecent->addURL(url);
+ setCaption(url.fileName(),m_doc->isModified());
+ slotStatusMsg(i18n("Ready."));
+ }
+ return b;
+
+ } else {
+ slotStatusMsg(i18n("Ready."));
+ return false;
+ }
+}
+
+void UMLApp::slotFileClose() {
+ slotStatusMsg(i18n("Closing file..."));
+
+ slotFileNew();
+
+}
+
+void UMLApp::slotFilePrint()
+{
+ slotStatusMsg(i18n("Printing..."));
+
+ KPrinter printer;
+ printer.setFullPage(true);
+ DiagramPrintPage * selectPage = new DiagramPrintPage(0, m_doc);
+ printer.addDialogPage(selectPage);
+ QString msg;
+ if (printer.setup(this, i18n("Print %1").arg(m_doc->URL().prettyURL()))) {
+
+ m_doc -> print(&printer);
+ }
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotFileQuit() {
+ slotStatusMsg(i18n("Exiting..."));
+ if(m_doc->saveModified()) {
+ writeDockConfig();
+ saveOptions();
+ kapp->quit();
+ }
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotFileExportDocbook()
+{
+ DocbookGenerator().generateDocbookForProject();
+}
+
+void UMLApp::slotFileExportXhtml()
+{
+ if (m_xhtmlGenerator != 0)
+ {
+ return;
+ }
+ m_xhtmlGenerator = new XhtmlGenerator();
+ m_xhtmlGenerator->generateXhtmlForProject();
+ connect(m_xhtmlGenerator,SIGNAL(finished()),this,SLOT(slotXhtmlDocGenerationFinished()));
+}
+
+void UMLApp::slotEditUndo() {
+ m_doc->loadUndoData();
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotEditRedo() {
+ m_doc->loadRedoData();
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotEditCut() {
+ slotStatusMsg(i18n("Cutting selection..."));
+ //FIXME bug 59774 this fromview isn't very reliable.
+ //when cutting diagrams it is set to true even though it shouldn't be
+ bool fromview = (getCurrentView() && getCurrentView()->getSelectCount());
+ if ( editCutCopy(fromview) ) {
+ emit sigCutSuccessful();
+ slotDeleteSelectedWidget();
+ m_doc->setModified(true);
+ }
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotEditCopy() {
+ slotStatusMsg(i18n("Copying selection to clipboard..."));
+ bool fromview = (getCurrentView() && getCurrentView()->getSelectCount());
+ editCutCopy( fromview );
+ slotStatusMsg(i18n("Ready."));
+ m_doc -> setModified( true );
+}
+
+void UMLApp::slotEditPaste() {
+ slotStatusMsg(i18n("Inserting clipboard contents..."));
+ QMimeSource* data = QApplication::clipboard()->data();
+ UMLClipboard clipboard;
+ setCursor(KCursor::waitCursor());
+ if(!clipboard.paste(data)) {
+ KMessageBox::sorry( this, i18n("Umbrello could not paste the clipboard contents. "
+ "The objects in the clipboard may be of the wrong "
+ "type to be pasted here."), i18n("Paste Error") );
+ }
+ slotStatusMsg(i18n("Ready."));
+ setCursor(KCursor::arrowCursor());
+ editPaste->setEnabled(false);
+ m_doc -> setModified( true );
+}
+
+//Remove these once we stop supporting KDE 3.1
+// #if !KDE_IS_VERSION(3,1,90)
+
+void UMLApp::slotViewToolBar() {
+ slotStatusMsg(i18n("Toggling toolbar..."));
+
+ ///////////////////////////////////////////////////////////////////
+ // turn Toolbar on or off
+
+ if(!viewToolBar->isChecked()) {
+ toolBar("mainToolBar")->hide();
+ } else {
+ toolBar("mainToolBar")->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void UMLApp::slotViewStatusBar() {
+ slotStatusMsg(i18n("Toggle the statusbar..."));
+ ///////////////////////////////////////////////////////////////////
+ //turn Statusbar on or off
+ if(!viewStatusBar->isChecked()) {
+ statusBar()->hide();
+ } else {
+ statusBar()->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+// #endif
+
+
+void UMLApp::slotStatusMsg(const QString &text) {
+ ///////////////////////////////////////////////////////////////////
+ // change status message permanently
+ statusBar()->clear();
+ m_statusLabel->setText( text );
+
+ m_statusLabel->repaint();
+}
+
+void UMLApp::slotClassDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Logical);
+ getDocument()->createDiagram(root, Uml::dt_Class);
+}
+
+
+void UMLApp::slotSequenceDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Logical);
+ m_doc->createDiagram(root, Uml::dt_Sequence);
+}
+
+void UMLApp::slotCollaborationDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Logical);
+ m_doc->createDiagram(root, Uml::dt_Collaboration);
+}
+
+void UMLApp::slotUseCaseDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_UseCase);
+ m_doc->createDiagram(root, Uml::dt_UseCase);
+}
+
+void UMLApp::slotStateDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Logical);
+ m_doc->createDiagram(root, Uml::dt_State);
+}
+
+void UMLApp::slotActivityDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Logical);
+ m_doc->createDiagram(root, Uml::dt_Activity);
+}
+
+void UMLApp::slotComponentDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Component);
+ m_doc->createDiagram(root, Uml::dt_Component );
+}
+
+void UMLApp::slotDeploymentDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_Deployment);
+ m_doc->createDiagram(root, Uml::dt_Deployment);
+}
+
+void UMLApp::slotEntityRelationshipDiagram() {
+ UMLFolder *root = m_doc->getRootFolder(Uml::mt_EntityRelationship);
+ m_doc->createDiagram(root, Uml::dt_EntityRelationship);
+}
+
+WorkToolBar* UMLApp::getWorkToolBar() {
+ return toolsbar;
+}
+
+void UMLApp::setModified(bool modified) {
+ //fileSave -> setEnabled(modified);
+
+ //if anything else needs to be done on a mofication, put it here
+
+ // printing should be possible whenever there is something to print
+ if ( m_loading == false && modified == true && getCurrentView() ) {
+ enablePrint(true);
+ }
+
+ if (m_loading == false) {
+ setCaption(m_doc->URL().fileName(), modified); //add disk icon to taskbar if modified
+ }
+}
+
+void UMLApp::enablePrint(bool enable) {
+ filePrint->setEnabled(enable);
+}
+
+void UMLApp::enableUndo(bool enable) {
+ editUndo->setEnabled(enable);
+}
+
+void UMLApp::enableRedo(bool enable) {
+ editRedo->setEnabled(enable);
+}
+
+/** initialize the QT's global clipboard support for the application */
+void UMLApp::initClip() {
+ QClipboard* clip = QApplication::clipboard();
+ connect(clip, SIGNAL(dataChanged()), this, SLOT(slotClipDataChanged()));
+
+ // Don't poll the X11 clipboard every second. This is a little expensive and resulted
+ // in very annoying umbrello slowdowns / hangs. Qt will notify us about clipboard
+ // changes anyway (see dataChanged() signal above), albeit only when a Qt application
+ // changes the clipboard. Work is in progress to make this work with other toolkits
+ // as well. (pfeiffer)
+ // m_clipTimer = new QTimer(this, "timer");
+ // m_clipTimer->start(1000, false);
+ // connect(m_clipTimer, SIGNAL(timeout()), this, SLOT(slotClipDataChanged()));
+
+ m_copyTimer = new QTimer(this, "copytimer");
+ m_copyTimer->start(500, false);
+ connect(m_copyTimer, SIGNAL(timeout()), this, SLOT(slotCopyChanged()));
+}
+
+bool UMLApp::canDecode(const QMimeSource* mimeSource) {
+ const char* f;
+ for (int i=0; (f=mimeSource->format(i)); i++) {
+ if ( !qstrnicmp(f,"application/x-uml-clip", 22) ) {
+ //FIXME need to test for clip1, clip2, clip3, clip4 or clip5
+ //(the only valid clip types)
+ return true;
+ }
+ }
+ return false;
+}
+
+void UMLApp::slotClipDataChanged() {
+ QMimeSource * data = QApplication::clipboard()->data();
+
+ //Pass the MimeSource to the Doc
+ editPaste->setEnabled( data && canDecode(data) );
+}
+
+void UMLApp::slotCopyChanged() {
+ if(m_listView->getSelectedCount() || (getCurrentView() && getCurrentView()->getSelectCount())) {
+ editCopy->setEnabled(true);
+ editCut->setEnabled(true);
+ } else {
+ editCopy->setEnabled(false);
+ editCut->setEnabled(false);
+ }
+}
+
+void UMLApp::slotPrefs() {
+ /* the KTipDialog may have changed the value */
+ m_config->setGroup("TipOfDay");
+ Settings::OptionState& optionState = Settings::getOptionState();
+ optionState.generalState.tip = m_config->readBoolEntry( "RunOnStart", true );
+
+ m_dlg = new SettingsDlg(this, &optionState);
+ connect(m_dlg, SIGNAL( applyClicked() ), this, SLOT( slotApplyPrefs() ) );
+
+ if ( m_dlg->exec() == QDialog::Accepted && m_dlg->getChangesApplied() ) {
+ slotApplyPrefs();
+ }
+
+ delete m_dlg;
+ m_dlg = NULL;
+}
+
+void UMLApp::slotApplyPrefs() {
+ if (m_dlg) {
+ /* we need this to sync both values */
+ m_config -> setGroup( "TipOfDay");
+ Settings::OptionState& optionState = Settings::getOptionState();
+ m_config -> writeEntry( "RunOnStart", optionState.generalState.tip );
+
+ m_doc -> settingsChanged( optionState );
+ const QString plStr = m_dlg->getCodeGenerationLanguage();
+ Uml::Programming_Language pl = Model_Utils::stringToProgLang(plStr);
+ setGenerator(pl);
+ }
+}
+
+bool UMLApp::getUndoEnabled() {
+ return editUndo->isEnabled();
+}
+
+bool UMLApp::getRedoEnabled() {
+ return editRedo->isEnabled();
+}
+
+bool UMLApp::getPasteState() {
+ return editPaste -> isEnabled();
+}
+
+bool UMLApp::getCutCopyState() {
+ return editCopy -> isEnabled();
+}
+
+bool UMLApp::editCutCopy( bool bFromView ) {
+ UMLClipboard clipboard;
+ QMimeSource * clipdata = 0;
+
+ if ((clipdata = clipboard.copy(bFromView)) != 0) {
+ QClipboard* clip = QApplication::clipboard();
+ clip->setData(clipdata);//the global clipboard takes ownership of the clipdata memory
+ connect(clip, SIGNAL(dataChanged()), this, SLOT(slotClipDataChanged()));
+ return true;
+ }
+ return false;
+}
+
+void UMLApp::readOptionState() {
+ m_config -> setGroup( "General Options" );
+ Settings::OptionState& optionState = Settings::getOptionState();
+ optionState.generalState.undo = m_config -> readBoolEntry( "undo", true );
+ optionState.generalState.tabdiagrams = m_config -> readBoolEntry("tabdiagrams", false);
+#if defined (WORK_ON_BUG_126262)
+ optionState.generalState.newcodegen = m_config -> readBoolEntry("newcodegen", false);
+#else
+ optionState.generalState.newcodegen = false;
+#endif
+ optionState.generalState.angularlines = m_config->readBoolEntry("angularlines", false);
+ optionState.generalState.autosave = m_config -> readBoolEntry( "autosave", true );
+ optionState.generalState.time = m_config -> readNumEntry( "time", 0 ); //old autosavetime value kept for compatibility
+ optionState.generalState.autosavetime = m_config -> readNumEntry( "autosavetime", 0 );
+ //if we don't have a "new" autosavetime value, convert the old one
+ if (optionState.generalState.autosavetime == 0) {
+ switch (optionState.generalState.time) {
+ case 0: optionState.generalState.autosavetime = 5; break;
+ case 1: optionState.generalState.autosavetime = 10; break;
+ case 2: optionState.generalState.autosavetime = 15; break;
+ case 3: optionState.generalState.autosavetime = 20; break;
+ case 4: optionState.generalState.autosavetime = 25; break;
+ default: optionState.generalState.autosavetime = 5; break;
+ }
+ }
+ // 2004-05-17 Achim Spangler: read new config entry for autosave sufix
+ optionState.generalState.autosavesuffix = m_config -> readEntry( "autosavesuffix", ".xmi" );
+
+ optionState.generalState.logo = m_config -> readBoolEntry( "logo", true );
+ optionState.generalState.loadlast = m_config -> readBoolEntry( "loadlast", true );
+
+ optionState.generalState.diagram = (Uml::Diagram_Type) m_config->readNumEntry("diagram", 1);
+ m_config -> setGroup( "TipOfDay");
+
+ optionState.generalState.tip = m_config -> readBoolEntry( "RunOnStart", true );
+
+ m_config -> setGroup( "UI Options" );
+ optionState.uiState.useFillColor = m_config -> readBoolEntry( "useFillColor", true );
+ QColor defaultYellow = QColor( 255, 255, 192 );
+ QColor red ( Qt::red );
+
+ optionState.uiState.fillColor = m_config -> readColorEntry( "fillColor", &defaultYellow );
+ optionState.uiState.lineColor = m_config -> readColorEntry( "lineColor", &red );
+ optionState.uiState.lineWidth = m_config -> readNumEntry( "lineWidth", 0 );
+ QFont font = ((QWidget *) this)->font() ;
+ optionState.uiState.font = m_config -> readFontEntry("font", &font );
+
+ m_config -> setGroup( "Class Options" );
+
+ optionState.classState.showVisibility = m_config -> readBoolEntry("showVisibility", true);
+ optionState.classState.showAtts = m_config -> readBoolEntry("showAtts", true);
+ optionState.classState.showOps = m_config -> readBoolEntry("showOps", true);
+ optionState.classState.showStereoType = m_config -> readBoolEntry("showStereoType", false);
+ optionState.classState.showAttSig = m_config -> readBoolEntry("showAttSig", true);
+ optionState.classState.showOpSig = m_config -> readBoolEntry("ShowOpSig", true);
+ optionState.classState.showPackage = m_config -> readBoolEntry("showPackage", false);
+ optionState.classState.defaultAttributeScope = (Uml::Visibility::Value) m_config -> readNumEntry("defaultAttributeScope", Uml::Visibility::Private);
+ optionState.classState.defaultOperationScope = (Uml::Visibility::Value) m_config -> readNumEntry("defaultOperationScope", Uml::Visibility::Public);
+
+ m_config -> setGroup( "Code Viewer Options" );
+
+ QColor defaultWhite = QColor( "white" );
+ QColor defaultBlack = QColor( "black" );
+ QColor defaultPink = QColor( "pink" );
+ QColor defaultGrey = QColor( "grey" );
+
+ optionState.codeViewerState.height = m_config -> readNumEntry( "height", 40 );
+ optionState.codeViewerState.width = m_config -> readNumEntry( "width", 80 );
+ optionState.codeViewerState.font = m_config -> readFontEntry("font", &font );
+ optionState.codeViewerState.showHiddenBlocks = m_config -> readBoolEntry( "showHiddenBlocks", false);
+ optionState.codeViewerState.blocksAreHighlighted = m_config -> readBoolEntry( "blocksAreHighlighted", false);
+ optionState.codeViewerState.selectedColor = m_config -> readColorEntry( "selectedColor", &defaultYellow );
+ optionState.codeViewerState.paperColor = m_config -> readColorEntry( "paperColor", &defaultWhite);
+ optionState.codeViewerState.fontColor = m_config -> readColorEntry( "fontColor", &defaultBlack);
+ optionState.codeViewerState.editBlockColor = m_config -> readColorEntry( "editBlockColor", &defaultPink);
+ optionState.codeViewerState.umlObjectColor = m_config -> readColorEntry( "umlObjectBlockColor", &defaultPink);
+ optionState.codeViewerState.nonEditBlockColor = m_config -> readColorEntry( "nonEditBlockColor", &defaultGrey);
+ optionState.codeViewerState.hiddenColor = m_config -> readColorEntry( "hiddenColor", &defaultGrey);
+
+}
+
+
+/** Call the code viewing assistant on a code document */
+void UMLApp::viewCodeDocument(UMLClassifier* classifier) {
+
+ CodeGenerator * currentGen = getGenerator();
+ if(currentGen && classifier) {
+ if(!dynamic_cast<SimpleCodeGenerator*>(currentGen))
+ {
+ CodeDocument *cdoc = currentGen->findCodeDocumentByClassifier(classifier);
+
+ if (cdoc) {
+ Settings::OptionState& optionState = Settings::getOptionState();
+ CodeViewerDialog * dialog = currentGen->getCodeViewerDialog(this,cdoc,optionState.codeViewerState);
+ dialog->exec();
+ optionState.codeViewerState = dialog->getState();
+ delete dialog;
+ dialog = NULL;
+ } else {
+ // shouldn't happen..
+ KMessageBox::sorry(0, i18n("Cannot view code until you generate some first."),i18n("Cannot View Code"));
+ }
+ } else {
+ KMessageBox::sorry(0, i18n("Cannot view code from simple code writer."),i18n("Cannot View Code"));
+ }
+ }
+
+}
+
+void UMLApp::refactor(UMLClassifier* classifier) {
+ if (!m_refactoringAssist) {
+ m_refactoringAssist = new RefactoringAssistant( m_doc, 0, 0, "refactoring_assistant" );
+ }
+ m_refactoringAssist->refactor(classifier);
+ m_refactoringAssist->show();
+}
+
+CodeGenerationPolicy *UMLApp::getCommonPolicy() {
+ return m_commoncodegenpolicy;
+}
+
+void UMLApp::setPolicyExt(CodeGenPolicyExt *policy) {
+ m_policyext = policy;
+}
+
+CodeGenPolicyExt *UMLApp::getPolicyExt() {
+ return m_policyext;
+}
+
+CodeGenerator *UMLApp::setGenerator(Uml::Programming_Language pl) {
+ if (pl == Uml::pl_Reserved) {
+ if (m_codegen) {
+ delete m_codegen;
+ m_codegen = NULL;
+ }
+ return NULL;
+ }
+ // does the code generator already exist?
+ // then simply return that
+ if (m_codegen) {
+ if (m_codegen->getLanguage() == pl)
+ return m_codegen;
+ delete m_codegen; // ATTENTION! remove all refs to it or its policy first
+ m_codegen = NULL;
+ }
+ m_activeLanguage = pl;
+ m_codegen = CodeGenFactory::createObject(pl);
+ updateLangSelectMenu(pl);
+
+ if (m_policyext)
+ m_policyext->setDefaults(m_config, false); // picks up language specific stuff
+ return m_codegen;
+}
+
+CodeGenerator* UMLApp::getGenerator() {
+ return m_codegen;
+}
+
+void UMLApp::generateAllCode() {
+ if (m_codegen) {
+ m_codegen->writeCodeToFile();
+ }
+}
+
+void UMLApp::generationWizard() {
+ CodeGenerationWizard wizard(0 /*classList*/);
+ wizard.exec();
+}
+
+void UMLApp::setActiveLanguage(int menuId) {
+
+ // only change the active language IF different from one we currently have
+ if (!m_langSelect->isItemChecked(menuId))
+ {
+ uint index = 0;
+ for(unsigned int i=0; i < m_langSelect->count(); i++) {
+ int id = m_langSelect->idAt(i);
+ m_langSelect->setItemChecked(id, false); //uncheck everything
+ if (id == menuId)
+ index = i;
+ }
+
+ m_langSelect->setItemChecked(menuId,true);
+ m_activeLanguage = (Uml::Programming_Language)index;
+
+ // update the generator
+ setGenerator(m_activeLanguage);
+ }
+}
+
+void UMLApp::setActiveLanguage( const QString &activeLanguage ) {
+
+ for(unsigned int j=0; j < m_langSelect->count(); j++) {
+ int id = m_langSelect->idAt(j);
+
+ if (m_langSelect->text(id) == activeLanguage &&
+ m_langSelect->isItemChecked(id))
+ return; // already set.. no need to do anything
+ }
+
+ for(unsigned int i=0; i < m_langSelect->count(); i++) {
+ bool isActiveLang = (m_langSelect->text(m_langSelect->idAt(i)) == activeLanguage);
+ //uncheck everything except the active language
+ m_langSelect->setItemChecked(m_langSelect->idAt(i), isActiveLang);
+ }
+
+ setGenerator(Model_Utils::stringToProgLang(activeLanguage));
+}
+
+Uml::Programming_Language UMLApp::getActiveLanguage() {
+ return m_activeLanguage;
+}
+
+bool UMLApp::activeLanguageIsCaseSensitive() {
+ return (m_activeLanguage != Uml::pl_Pascal &&
+ m_activeLanguage != Uml::pl_Ada &&
+ m_activeLanguage != Uml::pl_SQL);
+}
+
+QString UMLApp::activeLanguageScopeSeparator() {
+ Uml::Programming_Language pl = getActiveLanguage();
+ if (pl == Uml::pl_Ada ||
+ pl == Uml::pl_CSharp ||
+ pl == Uml::pl_Pascal ||
+ pl == Uml::pl_Java ||
+ pl == Uml::pl_JavaScript ||
+ pl == Uml::pl_Python) // CHECK: more?
+ return ".";
+ return "::";
+}
+
+void UMLApp::slotCurrentViewClearDiagram() {
+ getCurrentView()->clearDiagram();
+}
+
+void UMLApp::slotCurrentViewToggleSnapToGrid() {
+ getCurrentView()->toggleSnapToGrid();
+ viewSnapToGrid->setChecked( getCurrentView()->getSnapToGrid() );
+}
+
+void UMLApp::slotCurrentViewToggleShowGrid() {
+ getCurrentView()->toggleShowGrid();
+ viewShowGrid->setChecked( getCurrentView()->getShowSnapGrid() );
+}
+
+void UMLApp::slotCurrentViewExportImage() {
+ getCurrentView()->getImageExporter()->exportView();
+}
+
+void UMLApp::slotAllViewsExportImage() {
+ m_imageExporterAll->exportAllViews();
+}
+
+void UMLApp::slotCurrentViewProperties() {
+ getCurrentView()->showPropDialog();
+}
+
+void UMLApp::setDiagramMenuItemsState(bool bState) {
+ viewClearDiagram->setEnabled( bState );
+ viewSnapToGrid->setEnabled( bState );
+ viewShowGrid->setEnabled( bState );
+ deleteDiagram->setEnabled(bState);
+ viewExportImage->setEnabled( bState );
+ viewProperties->setEnabled( bState );
+ filePrint->setEnabled( bState );
+ if ( getCurrentView() ) {
+ viewSnapToGrid->setChecked( getCurrentView()->getSnapToGrid() );
+ viewShowGrid->setChecked( getCurrentView()->getShowSnapGrid() );
+ }
+}
+
+void UMLApp::slotUpdateViews() {
+ QPopupMenu* menu = findMenu( menuBar(), QString("views") );
+ if (!menu) {
+ kWarning() << "view menu not found" << endl;
+ return;
+ }
+
+ menu = findMenu( menu, QString("show_view") );
+ if (!menu) {
+ kWarning() << "show menu not found" << endl;
+ return;
+ }
+
+ menu->clear();
+
+ UMLViewList views = getDocument()->getViewIterator();
+ for(UMLView *view = views.first(); view; view = views.next()) {
+ menu->insertItem( view->getName(), view, SLOT( slotShowView() ) );
+ view->fileLoaded();
+ }
+}
+
+void UMLApp::slotImportClasses() {
+ m_doc->setLoading(true);
+ // File selection is separated from invocation of ClassImport::import()
+ // because the user might decide to choose a language different from
+ // the active language (by using the "All Files" option).
+ QString preselectedExtension;
+ const Uml::Programming_Language pl = m_codegen->getLanguage();
+ if (pl == Uml::pl_IDL) {
+ preselectedExtension = i18n("*.idl|IDL Files (*.idl)");
+ } else if (pl == Uml::pl_Python) {
+ preselectedExtension = i18n("*.py|Python Files (*.py)");
+ } else if (pl == Uml::pl_Java) {
+ preselectedExtension = i18n("*.java|Java Files (*.java)");
+ } else if (pl == Uml::pl_Pascal) {
+ preselectedExtension = i18n("*.pas|Pascal Files (*.pas)");
+ } else if (pl == Uml::pl_Ada) {
+ preselectedExtension = i18n("*.ads *.ada|Ada Files (*.ads *.ada)");
+ } else {
+ preselectedExtension = i18n("*.h *.hh *.hpp *.hxx *.H|Header Files (*.h *.hh *.hpp *.hxx *.H)");
+ }
+ preselectedExtension.append("\n*|" + i18n("All Files"));
+ QStringList fileList = KFileDialog::getOpenFileNames(":import-classes", preselectedExtension,
+ this, i18n("Select Code to Import") );
+ const QString& firstFile = fileList.first();
+ ClassImport *classImporter = ClassImport::createImporterByFileExt(firstFile);
+ classImporter->importFiles(fileList);
+ delete classImporter;
+ m_doc->setLoading(false);
+ //Modification is set after the import is made, because the file was modified when adding the classes
+ //Allowing undo of the whole class importing. I think it eats a lot of memory
+ //m_doc->setModified(true);
+ //Setting the modification, but without allowing undo
+ m_doc->setModified(true, false);
+}
+
+void UMLApp::slotClassWizard() {
+ ClassWizard dlg( m_doc );
+ dlg.exec();
+}
+
+void UMLApp::slotAddDefaultDatatypes() {
+ m_doc->addDefaultDatatypes();
+}
+
+void UMLApp::slotCurrentViewChanged() {
+ UMLView *view = getCurrentView();
+ if (view) {
+ connect(view, SIGNAL( sigShowGridToggled(bool) ),
+ this, SLOT( slotShowGridToggled(bool) ) );
+ connect(view, SIGNAL( sigSnapToGridToggled(bool) ),
+ this, SLOT( slotSnapToGridToggled(bool) ) );
+ }
+}
+void UMLApp::slotSnapToGridToggled(bool gridOn) {
+ viewSnapToGrid->setChecked(gridOn);
+}
+
+void UMLApp::slotShowGridToggled(bool gridOn) {
+ viewShowGrid->setChecked(gridOn);
+}
+
+void UMLApp::slotSelectAll() {
+ getCurrentView()->selectAll();
+}
+
+void UMLApp::slotDeleteSelectedWidget() {
+ if ( getCurrentView() ) {
+ getCurrentView()->deleteSelection();
+ } else {
+ kWarning() << " trying to delete widgets when there is no current view (see bug 59774)" << endl;
+ }
+}
+
+void UMLApp::slotDeleteDiagram() {
+ m_doc->removeDiagram( getCurrentView()->getID() );
+}
+
+Uml::Programming_Language UMLApp::getDefaultLanguage() {
+ m_config->setGroup("Code Generation");
+ QString activeLanguage = m_config->readEntry("activeLanguage", "C++");
+ return Model_Utils::stringToProgLang(activeLanguage);
+}
+
+void UMLApp::initGenerator() {
+ if (m_codegen) {
+ delete m_codegen;
+ m_codegen = NULL;
+ }
+ Uml::Programming_Language defaultLanguage = getDefaultLanguage();
+ setActiveLanguage(Model_Utils::progLangToString(defaultLanguage));
+ if (m_codegen == NULL)
+ setGenerator(defaultLanguage);
+ updateLangSelectMenu(defaultLanguage);
+}
+
+void UMLApp::updateLangSelectMenu(Uml::Programming_Language activeLanguage) {
+ m_langSelect->clear();
+ m_langSelect->setCheckable(true);
+ for (int i = 0; i < Uml::pl_Reserved; i++) {
+ QString language = Model_Utils::progLangToString((Uml::Programming_Language) i);
+ int id = m_langSelect->insertItem(language,this,SLOT(setActiveLanguage(int)));
+ const bool isActiveLanguage = (activeLanguage == i);
+ m_langSelect->setItemChecked(id, isActiveLanguage);
+ }
+}
+
+void UMLApp::tipOfTheDay()
+{
+ KTipDialog::showTip(this ,QString::null, true);
+}
+
+void UMLApp::keyPressEvent(QKeyEvent *e) {
+ switch(e->key()) {
+ case Qt::Key_Shift:
+ //toolsbar->setOldTool();
+ e->accept();
+ break;
+
+ default:
+ e->ignore();
+ }
+
+}
+
+void UMLApp::customEvent(QCustomEvent* e) {
+ if (e->type() == CmdLineExportAllViewsEvent::getType()) {
+ CmdLineExportAllViewsEvent* exportAllViewsEvent = static_cast<CmdLineExportAllViewsEvent*>(e);
+ exportAllViewsEvent->exportAllViews();
+ }
+}
+
+//TODO Move this to UMLWidgetController?
+void UMLApp::handleCursorKeyReleaseEvent(QKeyEvent* e) {
+ // in case we have selected something in the diagram, move it by one pixel
+ // to the direction pointed by the cursor key
+ if (m_view == NULL || !m_view->getSelectCount() || e->state() != Qt::AltButton) {
+ e->ignore();
+ return;
+ }
+ int dx = 0;
+ int dy = 0;
+ switch (e->key()) {
+ case Qt::Key_Left:
+ dx = -1;
+ break;
+ case Qt::Key_Right:
+ dx = 1;
+ break;
+ case Qt::Key_Up:
+ dy = -1;
+ break;
+ case Qt::Key_Down:
+ dy = 1;
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ m_view->moveSelectedBy(dx, dy);
+
+ // notify about modification only at the first key release of possible sequence of auto repeat key releases,
+ // this reduces the slow down caused by setModified() and makes the cursor moving of widgets smoother
+ if (!e->isAutoRepeat()) {
+ m_doc->setModified();
+ }
+ e->accept();
+}
+
+void UMLApp::keyReleaseEvent(QKeyEvent *e) {
+ switch(e->key()) {
+ case Qt::Key_Backspace:
+ if (!m_pDocWindow->isTyping())
+ toolsbar->setOldTool();
+ e->accept();
+ break;
+ case Qt::Key_Escape:
+ toolsbar->setDefaultTool();
+ e->accept();
+ break;
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ handleCursorKeyReleaseEvent(e);
+ break;
+ default:
+ e->ignore();
+ }
+
+}
+
+void UMLApp::newDocument() {
+ m_doc->newDocument();
+ Uml::Programming_Language defaultLanguage = getDefaultLanguage();
+ if (m_codegen) {
+ defaultLanguage = m_codegen->getLanguage();
+ delete m_codegen;
+ m_codegen = NULL;
+ }
+ setGenerator(defaultLanguage);
+ slotUpdateViews();
+}
+
+QWidget* UMLApp::getMainViewWidget() {
+ Settings::OptionState& optionState = Settings::getOptionState();
+ if (optionState.generalState.tabdiagrams)
+ return m_tabWidget;
+ return m_viewStack;
+}
+
+void UMLApp::setCurrentView(UMLView* view) {
+ m_view = view;
+ if (m_viewStack == NULL) {
+ kError() << "UMLApp::setCurrentView: m_viewStack is NULL" << endl;
+ return;
+ }
+ if (view == NULL) {
+ kDebug() << "UMLApp::setCurrentView: view is NULL" << endl;
+ return;
+ }
+ if (m_viewStack->id(view) < 0)
+ m_viewStack->addWidget(view);
+ m_viewStack->raiseWidget(view);
+ slotStatusMsg(view->getName());
+ UMLListViewItem* lvitem = m_listView->findView(view);
+ if (lvitem)
+ m_listView->setCurrentItem(lvitem);
+}
+
+UMLView* UMLApp::getCurrentView() {
+ return m_view;
+}
+
+QPopupMenu* UMLApp::findMenu(QMenuData* menu, const QString &name) {
+
+ if (menu) {
+ int menuCount = menu->count();
+
+ for (int i=0; i<menuCount; i++) {
+ int idAt = menu->idAt(i);
+ QPopupMenu* popupMenu = menu->findItem(idAt)->popup();
+ if (popupMenu) {
+ QString menuName = popupMenu->name();
+ if( menuName == name) {
+ return popupMenu;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void UMLApp::slotTabChanged(QWidget* view) {
+ UMLView* umlview = ( UMLView* )view;
+ m_doc->changeCurrentView( umlview->getID() );
+}
+
+void UMLApp::slotChangeTabLeft() {
+ if (m_tabWidget) {
+ m_tabWidget->setCurrentPage( m_tabWidget->currentPageIndex() - 1 );
+ return;
+ }
+ UMLViewList views = m_doc->getViewIterator();
+ UMLView *currView = m_view;
+ if (views.find(currView) < 0) {
+ kError() << "UMLApp::slotChangeTabLeft(): currView not found in viewlist" << endl;
+ return;
+ }
+ if ((currView = views.prev()) != NULL)
+ setCurrentView(currView);
+ else
+ setCurrentView(views.last());
+}
+
+void UMLApp::slotChangeTabRight() {
+ if (m_tabWidget) {
+ m_tabWidget->setCurrentPage( m_tabWidget->currentPageIndex() + 1 );
+ return;
+ }
+ UMLViewList views = m_doc->getViewIterator();
+ UMLView *currView = m_view;
+ if (views.find(currView) < 0) {
+ kError() << "UMLApp::slotChangeTabRight(): currView not found in viewlist" << endl;
+ return;
+ }
+ if ((currView = views.next()) != NULL)
+ setCurrentView(currView);
+ else
+ setCurrentView(views.first());
+}
+
+void UMLApp::slotMoveTabLeft() {
+ //causes problems
+ //does strange things when moving right most diagram to the right
+ //doesn't save order in file
+ //m_tabWidget->moveTab( m_tabWidget->currentPageIndex(), m_tabWidget->currentPageIndex() - 1 );
+}
+
+void UMLApp::slotMoveTabRight() {
+ //causes problems
+ //m_tabWidget->moveTab( m_tabWidget->currentPageIndex(), m_tabWidget->currentPageIndex() + 1 );
+}
+
+void UMLApp::slotAutolayout(){
+#ifdef HAVE_DOT
+/*
+ QDialog* d = new AutolayoutDlg(getCurrentView());
+ d->show();
+ */
+#endif
+}
+
+void UMLApp::slotXhtmlDocGenerationFinished()
+{
+ delete m_xhtmlGenerator;
+ m_xhtmlGenerator = 0;
+}
+
+KTabWidget* UMLApp::tabWidget() {
+ return m_tabWidget;
+}
+
+QString UMLApp::getStatusBarMsg() {
+ return m_statusLabel->text();
+}
+
+//static pointer, holding the unique instance
+UMLApp* UMLApp::s_instance;
+
+#include "uml.moc"
diff --git a/umbrello/umbrello/uml.h b/umbrello/umbrello/uml.h
new file mode 100644
index 00000000..ee669d88
--- /dev/null
+++ b/umbrello/umbrello/uml.h
@@ -0,0 +1,1026 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UML_H
+#define UML_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "umlnamespace.h"
+
+#include <qmap.h>
+#include <qdict.h>
+
+#include <kdockwidget.h>
+#include <kdeversion.h>
+#include <kurl.h>
+
+// forward declaration of the UML classes
+class AlignToolBar;
+class CodeDocument;
+class CodeGenerator;
+class CodeGenerationPolicy;
+class CodeGenPolicyExt;
+class DocWindow;
+class UMLClassifier;
+class UMLDoc;
+class UMLListView;
+class UMLView;
+class WorkToolBar;
+class SettingsDlg;
+class UMLViewImageExporterAll;
+class RefactoringAssistant;
+class KPlayerPopupSliderAction;
+class XhtmlGenerator;
+
+// KDE forward declarations
+class KActionMenu;
+class KRecentFilesAction;
+class KStatusBarLabel;
+class KToggleAction;
+class KDockWidget;
+class KTabWidget;
+class KToolBarButton;
+class KPopupMenu;
+
+// Qt forward declarations
+class QWidgetStack;
+class QMenuData;
+class QClipboard;
+class QToolButton;
+class QCustomEvent;
+
+/**
+ * The base class for UML application windows. It sets up the main
+ * window and reads the config file as well as providing a menubar, toolbar
+ * and statusbar. An instance of UMLView creates your center view, which is connected
+ * to the window's Doc object.
+ * UMLApp reimplements the methods that KMainWindow provides for main window handling and supports
+ * full session management as well as using KActions.
+ * @see KMainWindow
+ * @see KApplication
+ * @see KConfig
+ *
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLApp : public KDockMainWindow {
+ Q_OBJECT
+public:
+ /**
+ * Constructor. Calls all init functions to create the application.
+ */
+ UMLApp(QWidget* parent=0, const char* name=0);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~UMLApp();
+
+ static UMLApp* app();
+
+ /**
+ * Opens a file specified by commandline option.
+ */
+ void openDocumentFile(const KURL& url=KURL());
+
+ /**
+ * Calls the UMLDoc method to create a new Document.
+ */
+ void newDocument();
+
+ /**
+ * Returns a pointer to the current document connected to the
+ * KMainWindow instance.
+ * Used by the View class to access the document object's methods.
+ */
+ UMLDoc *getDocument() const;
+
+ /**
+ * Returns a pointer to the list view.
+ *
+ * @return The listview being used.
+ */
+ UMLListView* getListView();
+
+ /**
+ * Returns the toolbar being used.
+ *
+ * @return The toolbar being used.
+ */
+ WorkToolBar* getWorkToolBar();
+
+ /**
+ * Sets whether the program has been modified.
+ * This will change how the program saves/exits.
+ *
+ * @param _m true - modified.
+ */
+ void setModified(bool _m);
+
+ /**
+ * Set whether to allow printing.
+ * It will enable/disable the menu/toolbar options.
+ *
+ * @param enable Set whether to allow printing.
+ */
+ void enablePrint(bool enable);
+
+ /**
+ * Set whether to allow printing.
+ * It will enable/disable the menu/toolbar options.
+ *
+ * @param enable Set whether to allow printing.
+ */
+ void enableUndo(bool enable);
+
+ /**
+ * Set whether to allow printing.
+ * It will enable/disable the menu/toolbar options.
+ *
+ * @param enable Set whether to allow printing.
+ */
+ void enableRedo(bool enable);
+
+ /**
+ * Returns a pointer to the documentation window.
+ *
+ * @return Pointer to the DocWindow.
+ */
+ DocWindow * getDocWindow() {
+ return m_pDocWindow;
+ }
+
+ /**
+ * Returns the undo state.
+ *
+ * @return True if Undo is enabled.
+ */
+ bool getUndoEnabled();
+
+ /**
+ * Returns the redo state.
+ *
+ * @return True if Redo is enabled.
+ */
+ bool getRedoEnabled();
+
+ /**
+ * Returns the paste state.
+ *
+ * @return True if Paste is enabled.
+ */
+ bool getPasteState();
+
+ /**
+ * Returns the state on Cut/Copy.
+ *
+ * @return True if Cut/Copy is enabled.
+ */
+ bool getCutCopyState();
+
+ /**
+ * Gets the appropriate CodeGenerator.
+ *
+ * @return Pointer to the CodeGenerator.
+ */
+ CodeGenerator* getGenerator();
+
+ /**
+ * Set the current generator for this app.
+ * If giveWarning is true, then a popup box warning that the
+ * code generation library is out-of-date will show if you
+ * attempt to set the generator to NULL.
+ *
+ * @param gen Pointer to the CodeGenerator to set.
+ * @param giveWarning True to enable out-of-date warning.
+ */
+ void setGenerator(CodeGenerator* gen, bool giveWarning = true);
+
+ /**
+ * Creates a new code generator for the given active language.
+ *
+ * @return Pointer to the CodeGenerator created.
+ */
+ CodeGenerator* createGenerator();
+
+ /**
+ * Auxiliary function for UMLDoc::loadExtensionsFromXMI():
+ * Return the code generator of the given language if it already
+ * exists; if it does not yet exist then create it and return
+ * the newly created generator. It is the caller's responsibility
+ * to load XMI into the newly created generator.
+ */
+ CodeGenerator *setGenerator(Uml::Programming_Language pl);
+
+ /**
+ * Call the refactoring assistant on a classifier.
+ *
+ * @param classifier Pointer to the classifier to refactor.
+ */
+ void refactor(UMLClassifier* classifier);
+
+ /**
+ * Call the code viewing assistant on a given UMLClassifier.
+ *
+ * @param classifier Pointer to the classifier to view.
+ */
+ void viewCodeDocument(UMLClassifier* classifier);
+
+ /**
+ * Sets the state of the view properties menu item.
+ *
+ * @param bState Boolean, true to enable the view properties item.
+ */
+ void setDiagramMenuItemsState(bool bState);
+
+ /**
+ * Returns the widget used as the parent for UMLViews.
+ * @return The main view widget.
+ */
+ QWidget* getMainViewWidget();
+
+ /**
+ * Puts this view to the top of the viewStack, i.e. makes it
+ * visible to the user.
+ *
+ * @param view Pointer to the UMLView to push.
+ */
+ void setCurrentView(UMLView* view);
+
+ /**
+ * Get the current view.
+ * This may return a null pointer (when no view was previously
+ * specified.)
+ *
+ */
+ UMLView* getCurrentView();
+
+ /**
+ * Sets the default mime type for all diagrams that are exported as
+ * images.
+ *
+ * @param mimeType The MIME type to set as the default.
+ */
+ void setImageMimeType(QString const & mimeType){m_imageMimeType=mimeType;};
+
+ /**
+ * Gets the default mime type for all diagrams that are exported as
+ * images.
+ *
+ * @return The default MIME type for images.
+ */
+ QString const & getImageMimeType()const{return m_imageMimeType;};
+
+ /**
+ * Carries out the cut/copy command with different action performed
+ * depending on if from view or list view.
+ * Cut/Copy are the same. It is up to the caller to delete/cut the selection..
+ *
+ * If the operation is successful, the signal sigCutSuccessful() is emitted.
+ *
+ * Callers should connect to this signal to know what to do next.
+ */
+ bool editCutCopy( bool bFromView );
+
+ /**
+ * Return the tab widget.
+ */
+ KTabWidget *tabWidget();
+
+ /**
+ * Returns the current text in the status bar.
+ *
+ * @return The text in the status bar.
+ */
+ QString getStatusBarMsg();
+
+ /**
+ * Returns the default code generation policy.
+ */
+ CodeGenerationPolicy *getCommonPolicy();
+
+ /**
+ * Sets the CodeGenPolicyExt object.
+ */
+ void setPolicyExt(CodeGenPolicyExt *policy);
+
+ /**
+ * Returns the CodeGenPolicyExt object.
+ */
+ CodeGenPolicyExt *getPolicyExt();
+
+protected:
+ virtual void keyPressEvent(QKeyEvent* e);
+ virtual void keyReleaseEvent(QKeyEvent* e);
+
+ /**
+ * Event handler to receive custom events.
+ * It handles events such as exporting all views from command line (in
+ * that case, it executes the exportAllViews method in the event).
+ */
+ virtual void customEvent(QCustomEvent* e);
+
+ /**
+ * Helper method for handling cursor key release events (refactoring).
+ */
+ void handleCursorKeyReleaseEvent(QKeyEvent* e);
+
+ /**
+ * Save general Options like all bar positions and status
+ * as well as the geometry and the recent file list to
+ * the configuration file.
+ */
+ void saveOptions();
+
+ /**
+ * Read general Options again and initialize all variables
+ * like the recent file list.
+ */
+ void readOptions();
+
+ /**
+ * Initializes the KActions of the application.
+ */
+ void initActions();
+
+ /**
+ * Sets up the statusbar for the main window by
+ * initialzing a statuslabel.
+ */
+ void initStatusBar();
+
+ /**
+ * Creates the centerwidget of the KMainWindow instance and
+ * sets it as the view.
+ */
+ void initView();
+
+ /**
+ * queryClose is called by KMainWindow on each closeEvent of a
+ * window. Counter to the default implementation (which only
+ * returns true), this calls saveModified() on the document object
+ * to ask if the document shall be saved if Modified; on cancel
+ * the closeEvent is rejected.
+ * @see KMainWindow#queryClose
+ * @see KMainWindow#closeEvent
+ *
+ * @return True if window may be closed.
+ */
+ virtual bool queryClose();
+
+ /**
+ * queryExit is called by KMainWindow when the last
+ * window of the application is going to be closed during
+ * the closeEvent(). In contrast to the default
+ * implementation that just returns true, this calls
+ * saveOptions() to save the settings of the last
+ * window's properties.
+ * @see KMainWindow#queryExit
+ * @see KMainWindow#closeEvent
+ *
+ * @return True if window may be closed.
+ */
+ virtual bool queryExit();
+
+ /**
+ * Saves the window properties for each open window
+ * during session end to the session config file,
+ * including saving the currently opened file by a
+ * temporary filename provided by KApplication.
+ * @see KMainWindow#saveProperties
+ */
+ virtual void saveProperties(KConfig *_cfg);
+
+ /**
+ * Reads the session config file and restores the
+ * application's state including the last opened files and
+ * documents by reading the temporary files saved by
+ * saveProperties()
+ * @see KMainWindow#readProperties
+ */
+ virtual void readProperties(KConfig *_cfg);
+
+ CodeGenerationPolicy * m_commoncodegenpolicy;
+
+ /**
+ * Updates the Menu for language selection and sets the
+ * active lanugage. If no active lanugage is found or if it is
+ * not one of the registered languages it tries to fall back
+ * to Cpp
+ */
+ void updateLangSelectMenu(Uml::Programming_Language activeLanguage);
+
+protected slots:
+
+ /**
+ * Show "Tip of the Day" dialog
+ */
+ void tipOfTheDay();
+
+public slots:
+
+ /**
+ * Reads the activeLanguage from the KConfig and calls updateLangSelectMenu()
+ */
+ void initGenerator();
+
+ /**
+ * Runs the code generation wizard.
+ */
+ void generationWizard();
+
+ /**
+ * Clears the document in the actual view to reuse it as the new
+ * document.
+ */
+ void slotFileNew();
+
+ /**
+ * Open a file and load it into the document.
+ */
+ void slotFileOpen();
+
+ /**
+ * Opens a file from the recent files menu.
+ */
+ void slotFileOpenRecent(const KURL& url);
+
+ /**
+ * Save a document.
+ */
+ void slotFileSave();
+
+ /**
+ * Save a document by a new filename.
+ */
+ bool slotFileSaveAs();
+
+ /**
+ * Asks for saving if the file is modified, then closes the current
+ * file and window.
+ */
+ void slotFileClose();
+
+ /**
+ * Print the current file.
+ */
+ void slotFilePrint();
+
+ /**
+ * Closes all open windows by calling close() on each
+ * memberList item until the list is empty, then quits the
+ * application. If queryClose() returns false because the
+ * user canceled the saveModified() dialog, the closing
+ * aborts.
+ */
+ void slotFileQuit();
+
+ /**
+ * Exports the current model to docbook in a subdir of the
+ * current model directory named from the model name.
+ * @todo Let the user chose the destination directory and
+ * name, using network transparency.
+ */
+ void slotFileExportDocbook();
+
+ /**
+ * Exports the current model to XHTML in a subdir of the
+ * current model directory named from the model name.
+ * @todo Let the user chose the destination directory and
+ * name, using network transparency.
+ */
+ void slotFileExportXhtml();
+
+ /**
+ * Put the marked text/object into the clipboard and remove
+ * it from the document.
+ */
+ void slotEditCut();
+
+ /**
+ * Put the marked text/object into the clipboard.
+ */
+ void slotEditCopy();
+
+ /**
+ * Paste the clipboard into the document.
+ */
+ void slotEditPaste();
+
+ /**
+ * Toggles the toolbar.
+ * Deprecated. For compatibility with KDE 3.1, remove if we stop supporting KDE 3.1
+ */
+ void slotViewToolBar();
+
+ /**
+ * Toggles the statusbar.
+ * Deprecated. For compatibility with KDE 3.1, remove if we stop supporting KDE 3.1
+ */
+ void slotViewStatusBar();
+
+ /**
+ * Autolayouts the current class diagram
+ */
+ void slotAutolayout();
+
+ /**
+ * Changes the statusbar contents for the standard label
+ * permanently, used to indicate current actions.
+ * @param text The text that is displayed in the statusbar
+ */
+ void slotStatusMsg(const QString &text);
+
+ /**
+ * Create this view.
+ */
+ void slotClassDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotSequenceDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotCollaborationDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotUseCaseDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotStateDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotActivityDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotComponentDiagram();
+
+ /**
+ * Create this view.
+ */
+ void slotDeploymentDiagram();
+ /**
+ * Create this view.
+ */
+ void slotEntityRelationshipDiagram();
+
+ /**
+ * Notification of changed clipboard data.
+ */
+ void slotClipDataChanged();
+
+ /**
+ *
+ */
+ void slotCopyChanged();
+
+ /**
+ * Shows the global preferences dialog.
+ */
+ void slotPrefs();
+
+ /**
+ * Commits the changes from the global preferences dialog.
+ */
+ void slotApplyPrefs();
+
+ /**
+ * Register new views (aka diagram) with the GUI so they show up
+ * in the menu.
+ */
+ void slotUpdateViews();
+
+ /**
+ * Generate code for all classes.
+ */
+ void generateAllCode();
+
+ /**
+ * Set the language for which code will be generated.
+ *
+ * @param menuID the ID of the langSelect menu item for
+ * the relevant language.
+ */
+ void setActiveLanguage(int menuID);
+
+ /**
+ * Set the language for which code will be generated.
+ *
+ * @param activeLanguage The name of the language to set
+ */
+ void setActiveLanguage( const QString &activeLanguage );
+
+ /**
+ * Get the language for import and code generation.
+ */
+ Uml::Programming_Language getActiveLanguage();
+
+ /**
+ * Return true if the active language is case sensitive.
+ */
+ bool activeLanguageIsCaseSensitive();
+
+ /**
+ * Return the target language depedent scope separator.
+ */
+ QString activeLanguageScopeSeparator();
+
+ /**
+ * Return the default code generation language as configured by KConfig.
+ * If the activeLanguage is not found in the KConfig then use Uml::pl_Cpp
+ * as the default.
+ */
+ Uml::Programming_Language getDefaultLanguage();
+
+ /**
+ * Menu selection for clear current view.
+ */
+ void slotCurrentViewClearDiagram();
+
+ /**
+ * Menu selection for current view snap to grid property.
+ */
+ void slotCurrentViewToggleSnapToGrid();
+
+ /**
+ * Menu selection for current view show grid property.
+ */
+ void slotCurrentViewToggleShowGrid();
+
+ /**
+ * Menu selection for exporting current view as an image.
+ */
+ void slotCurrentViewExportImage();
+
+ /**
+ * Menu selection for exporting all views as images.
+ */
+ void slotAllViewsExportImage();
+
+ /**
+ * Menu selection for current view properties.
+ */
+ void slotCurrentViewProperties();
+
+ /**
+ * Import classes menu selection.
+ */
+ void slotImportClasses();
+
+ /**
+ * Class wizard menu selection.
+ */
+ void slotClassWizard();
+
+ /**
+ * Calls the active code generator to add its default datatypes
+ */
+ void slotAddDefaultDatatypes();
+
+ /**
+ * The displayed diagram has changed.
+ */
+ void slotCurrentViewChanged();
+
+ /**
+ * The snap to grid value has been changed.
+ */
+ void slotSnapToGridToggled(bool gridOn);
+
+ /**
+ * The show grid value has been changed.
+ */
+ void slotShowGridToggled(bool gridOn);
+
+ /**
+ * Select all widgets on the current diagram.
+ */
+ void slotSelectAll();
+
+ /**
+ * Deletes the selected widget.
+ */
+ void slotDeleteSelectedWidget();
+
+ /**
+ * Deletes the current diagram.
+ */
+ void slotDeleteDiagram();
+
+ /**
+ * Set the zoom factor of the current diagram.
+ *
+ * @param zoom Zoom factor in percentage.
+ */
+ void setZoom(int zoom);
+
+ /**
+ * Connected to by the KPlayerSliderAction zoomAction, a value of between 300
+ * and 2200 is scaled to zoom to between 9% and 525%.
+ * The min and max values of the slider are hard coded in KPlayerSliderAction for now.
+ * @param value Zoom factor before scaleing
+ */
+ void slotZoomSliderMoved(int value);
+
+ /**
+ * Set zoom to 100%
+ */
+ void slotZoom100();
+
+ /**
+ * Prepares the zoom menu for display.
+ */
+ void setupZoomMenu();
+
+ /**
+ * Reverts the document back to the state it was prior to the
+ * last action performed by the user.
+ */
+ void slotEditUndo();
+
+ /**
+ * Reverts the document back to the state it was prior to the
+ * last undo.
+ */
+ void slotEditRedo();
+
+ /**
+ * Searches for a menu with the given name
+ *
+ * @param menu The QPopupMenu or QMenuBar to search through.
+ * @param name The name of the menu to search for (name, not text)
+ */
+ QPopupMenu* findMenu(QMenuData* menu, const QString &name);
+
+ /**
+ * called when the tab has changed
+ */
+ void slotTabChanged(QWidget* view);
+
+ /**
+ * make the tab on the left of the current one the active one
+ */
+ void slotChangeTabLeft();
+
+ /**
+ * make the tab on the right of the current one the active one
+ */
+ void slotChangeTabRight();
+
+ /**
+ * Move the current tab left, not implemented
+ */
+ void slotMoveTabLeft();
+
+ /**
+ * Move the current tab right, not implemented
+ */
+ void slotMoveTabRight();
+
+ KConfig *getConfig() { return m_config; }
+
+ /**
+ * This slot deletes the current XHTML documentation generator as soon as
+ * this one signals that it has finished.
+ */
+ void slotXhtmlDocGenerationFinished();
+
+private:
+ static UMLApp* s_instance;
+
+ /**
+ * For selecting the active language.
+ */
+ QPopupMenu *m_langSelect;
+
+ /**
+ * Popup menu for zoom selection.
+ */
+ QPopupMenu *m_zoomSelect;
+
+ /**
+ * Active language.
+ */
+ Uml::Programming_Language m_activeLanguage;
+
+ /**
+ * Active code generator.
+ */
+ CodeGenerator *m_codegen;
+
+ /**
+ * Active policy extension.
+ * Only used for new code generators ({Cpp,Java,Ruby}CodeGenerator)
+ */
+ CodeGenPolicyExt *m_policyext;
+
+ /**
+ * Returns whether we can decode the given mimesource
+ */
+ static bool canDecode(const QMimeSource* mimeSource);
+
+ /**
+ * Reads from the config file the options state.
+ * Not in @ref readOptions as it needs to be read earlier than some
+ * of the other options, before some items are created.
+ */
+ void readOptionState();
+
+ /**
+ * Initialize Qt's global clipboard support for the application.
+ */
+ void initClip();
+
+ /**
+ * Initialize code generators at startup.
+ * Why is this important? Because IF we don't do this, then changes
+ * to the UML may not be synced with the saved code generation params
+ * for those languages which arent currently active.
+ */
+ void initSavedCodeGenerators();
+
+ /**
+ * The configuration object of the application.
+ */
+ KConfig* m_config;
+
+ /**
+ * View is the main widget which represents your working area.
+ * The View class should handle all events of the view widget.
+ * It is kept empty so you can create your view according to your
+ * application's needs by changing the view class.
+ */
+ UMLView* m_view;
+
+ /**
+ * doc represents your actual document and is created only once.
+ * It keeps information such as filename and does the loading and
+ * saving of your files.
+ */
+ UMLDoc* m_doc;
+
+ /**
+ * Listview shows the current open file.
+ */
+ UMLListView* m_listView;
+
+ /**
+ * The widget which shows the diagrams.
+ */
+ KDockWidget* m_mainDock;
+
+ /**
+ * Contains the UMLListView tree view.
+ */
+ KDockWidget* m_listDock;
+
+ /**
+ * Contains the documentation DocWindow widget.
+ */
+ KDockWidget* m_documentationDock;
+
+ /**
+ * Documentation window.
+ */
+ DocWindow* m_pDocWindow;
+
+ /** Refactoring assistant. */
+ RefactoringAssistant* m_refactoringAssist;
+
+ //KAction pointers to enable/disable actions
+ KAction* fileNew;
+ KAction* fileOpen;
+ KRecentFilesAction* fileOpenRecent;
+ KAction* fileSave;
+ KAction* fileSaveAs;
+ KAction* fileClose;
+ KAction* filePrint;
+ KAction* fileQuit;
+ KAction* fileExportDocbook;
+ KAction* fileExportXhtml;
+
+ KAction* editCut;
+ KAction* editCopy;
+ KAction* editPaste;
+ KAction* editUndo;
+ KAction* editRedo;
+ KAction* selectAll;
+ KAction* preferences;
+
+ KActionMenu* newDiagram;
+ KAction* classDiagram;
+ KAction* sequenceDiagram;
+ KAction* collaborationDiagram;
+ KAction* useCaseDiagram;
+ KAction* stateDiagram;
+ KAction* activityDiagram;
+ KAction* componentDiagram;
+ KAction* deploymentDiagram;
+ KAction* entityRelationshipDiagram;
+ KAction* viewClearDiagram;
+
+ KToggleAction* viewSnapToGrid;
+ KToggleAction* viewShowGrid;
+ KAction* viewExportImage;
+ KAction* viewExportImageAll;
+ KAction* viewProperties;
+
+ KAction* zoom100Action;
+ KPlayerPopupSliderAction* zoomAction;
+
+ KAction* genAll;
+ KAction* genWizard;
+ KAction* importClasses;
+ KAction* classWizard;
+ KAction* deleteSelectedWidget;
+ KAction* deleteDiagram;
+#ifdef HAVE_DOT
+ KAction* autolayout;
+#endif
+
+ KAction* changeTabLeft;
+ KAction* changeTabRight;
+ KAction* moveTabLeft;
+ KAction* moveTabRight;
+ KToolBarButton* m_newSessionButton;
+ KPopupMenu* m_diagramMenu;
+ QToolButton* m_closeDiagramButton;
+ KToggleAction* viewToolBar;
+ KToggleAction* viewStatusBar;
+ WorkToolBar* toolsbar;
+ QTimer* m_clipTimer;
+ QTimer* m_copyTimer;
+ AlignToolBar* m_alignToolBar;
+
+ KStatusBarLabel* m_statusLabel;
+
+ /**
+ * True if the application is opening an existing document
+ */
+ bool m_loading;
+
+ /**
+ * Shows, and is parent of, all the UMLViews (diagrams)
+ * if tabbed diagrams are not enabled.
+ */
+ QWidgetStack* m_viewStack;
+
+ /**
+ * Shows, and is parent of, all the UMLViews (diagrams)
+ * if tabbed diagrams are enabled.
+ */
+ KTabWidget* m_tabWidget;
+
+ /**
+ * Default mime type to use for image export.
+ */
+ QString m_imageMimeType;
+
+ /**
+ * the global UML settings dialog
+ */
+ SettingsDlg* m_dlg;
+
+ /**
+ * The UMLViewImageExporterAll used to export all the views.
+ */
+ UMLViewImageExporterAll* m_imageExporterAll;
+
+ /**
+ * The running XHTML documentation generator. null when no generation is
+ * running
+ */
+ XhtmlGenerator* m_xhtmlGenerator;
+
+signals:
+
+ /**
+ * Emitted when a cut operation is successful.
+ */
+ void sigCutSuccessful();
+};
+
+#endif // UML_H
diff --git a/umbrello/umbrello/umlassociationlist.h b/umbrello/umbrello/umlassociationlist.h
new file mode 100644
index 00000000..55810c7d
--- /dev/null
+++ b/umbrello/umbrello/umlassociationlist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLASSOCIATIONLIST_H
+#define UMLASSOCIATIONLIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLAssociation;
+
+typedef QPtrList<UMLAssociation> UMLAssociationList;
+typedef QPtrListIterator<UMLAssociation> UMLAssociationListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlattributelist.cpp b/umbrello/umbrello/umlattributelist.cpp
new file mode 100644
index 00000000..f335b7e7
--- /dev/null
+++ b/umbrello/umbrello/umlattributelist.cpp
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlattributelist.h"
+#include "attribute.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+void UMLAttributeList::copyInto(UMLAttributeList *rhs) const {
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLAttributeList *tmp = new UMLAttributeList(*this);
+
+ UMLAttribute *item;
+ for (item = tmp->first(); item; item = tmp->next() )
+ {
+ rhs->append((UMLAttribute*)item->clone());
+ }
+ delete tmp;
+}
+
+
+UMLAttributeList* UMLAttributeList::clone() const {
+ UMLAttributeList *clone = new UMLAttributeList();
+ copyInto(clone);
+ return clone;
+}
diff --git a/umbrello/umbrello/umlattributelist.h b/umbrello/umbrello/umlattributelist.h
new file mode 100644
index 00000000..6dd25db2
--- /dev/null
+++ b/umbrello/umbrello/umlattributelist.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLATTRIBUTELIST_H
+#define UMLATTRIBUTELIST_H
+
+#include <qptrlist.h>
+
+#include "attribute.h"
+
+//typedef QPtrList<UMLAttribute> UMLAttributeList;
+typedef QPtrListIterator<UMLAttribute> UMLAttributeListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLAttribute>
+ * base class.
+ */
+class UMLAttributeList : public QPtrList<UMLAttribute>
+{
+public:
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto (UMLAttributeList *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLAttributeList* clone() const;
+};
+
+
+#endif
diff --git a/umbrello/umbrello/umlcanvasobject.cpp b/umbrello/umbrello/umlcanvasobject.cpp
new file mode 100644
index 00000000..4b002228
--- /dev/null
+++ b/umbrello/umbrello/umlcanvasobject.cpp
@@ -0,0 +1,322 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlcanvasobject.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <klocale.h>
+
+// local includes
+#include "uml.h"
+#include "umldoc.h"
+#include "classifier.h"
+#include "association.h"
+#include "attribute.h"
+#include "operation.h"
+#include "template.h"
+#include "stereotype.h"
+#include "clipboard/idchangelog.h"
+
+UMLCanvasObject::UMLCanvasObject(const QString & name, Uml::IDType id)
+ : UMLObject(name, id)
+{
+ init();
+}
+
+UMLCanvasObject::~UMLCanvasObject() {
+ //removeAllAssociations();
+ /* No! This is way too late to do that.
+ It should have been called explicitly before destructing the
+ UMLCanvasObject.
+ Here is an example crash that happens if we rely on
+ removeAllAssociations() at this point:
+#4 0x415aac7f in __dynamic_cast () from /usr/lib/libstdc++.so.5
+#5 0x081acdbd in UMLCanvasObject::removeAllAssociations() (this=0x89e5b08)
+ at umlcanvasobject.cpp:83
+#6 0x081ac9fa in ~UMLCanvasObject (this=0x89e5b08) at umlcanvasobject.cpp:29
+#7 0x08193ffc in ~UMLPackage (this=0x89e5b08) at package.cpp:35
+#8 0x0813cbf6 in ~UMLClassifier (this=0x89e5b08) at classifier.cpp:40
+#9 0x081af3a6 in UMLDoc::closeDocument() (this=0x8468b10) at umldoc.cpp:284
+ */
+ if (associations())
+ kDebug() << "UMLCanvasObject destructor: FIXME: there are still associations()" << endl;
+}
+
+UMLAssociationList UMLCanvasObject::getSpecificAssocs(Uml::Association_Type assocType) {
+ UMLAssociationList list;
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() != Uml::ot_Association)
+ continue;
+ UMLAssociation *a = static_cast<UMLAssociation*>(o);
+ if (a->getAssocType() == assocType)
+ list.append(a);
+ }
+ return list;
+}
+
+bool UMLCanvasObject::addAssociationEnd(UMLAssociation* assoc) {
+ // add association only if not already present in list
+ if(!hasAssociation(assoc))
+ {
+ m_List.append( assoc );
+
+ // Don't emit signals during load from XMI
+ UMLObject::emitModified();
+ emit sigAssociationEndAdded(assoc);
+ return true;
+ }
+ return false;
+}
+
+bool UMLCanvasObject::hasAssociation(UMLAssociation* assoc) {
+ if(m_List.containsRef(assoc) > 0)
+ return true;
+ return false;
+}
+
+int UMLCanvasObject::removeAssociationEnd(UMLAssociation * assoc) {
+ if(!hasAssociation(assoc) || !m_List.remove(assoc)) {
+ kWarning() << "UMLCanvasObject::removeAssociation: "
+ << "can't find given assoc in list" << endl;
+ return -1;
+ }
+ UMLObject::emitModified();
+ emit sigAssociationEndRemoved(assoc);
+ return m_List.count();
+}
+
+void UMLCanvasObject::removeAllAssociationEnds() {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ) {
+ if (o->getBaseType() != Uml::ot_Association) {
+ ++oit;
+ continue;
+ }
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ //umldoc->slotRemoveUMLObject(assoc);
+ UMLObject* objA = assoc->getObject(Uml::A);
+ UMLObject* objB = assoc->getObject(Uml::B);
+ UMLCanvasObject *roleAObj = dynamic_cast<UMLCanvasObject*>(objA);
+ if (roleAObj) {
+ roleAObj->removeAssociationEnd(assoc);
+ } else if (objA)
+ kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
+ << "): objA " << objA->getName() << " is not a UMLCanvasObject"
+ << endl;
+ else
+ kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
+ << "): objA is NULL" << endl;
+ UMLCanvasObject *roleBObj = dynamic_cast<UMLCanvasObject*>(objB);
+ if (roleBObj) {
+ roleBObj->removeAssociationEnd(assoc);
+ } else if (objB)
+ kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
+ << "): objB " << objB->getName() << " is not a UMLCanvasObject"
+ << endl;
+ else
+ kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
+ << "): objB is NULL" << endl;
+ m_List.remove(assoc);
+ }
+}
+
+void UMLCanvasObject::removeAllChildObjects() {
+ removeAllAssociationEnds();
+ m_List.setAutoDelete(true);
+ m_List.clear();
+ m_List.setAutoDelete(false);
+}
+
+QString UMLCanvasObject::uniqChildName( const Uml::Object_Type type,
+ const QString &prefix /* = QString() */ ) {
+ QString currentName = prefix;
+ if (currentName.isEmpty()) {
+ switch (type) {
+ case Uml::ot_Association:
+ currentName = i18n("new_association");
+ break;
+ case Uml::ot_Attribute:
+ currentName = i18n("new_attribute");
+ break;
+ case Uml::ot_Template:
+ currentName = i18n("new_template");
+ break;
+ case Uml::ot_Operation:
+ currentName = i18n("new_operation");
+ break;
+ case Uml::ot_EnumLiteral:
+ currentName = i18n("new_literal");
+ break;
+ case Uml::ot_EntityAttribute:
+ currentName = i18n("new_field");
+ break;
+ default:
+ kWarning() << "uniqChildName() called for unknown child type " << type << endl;
+ return "ERROR_in_UMLCanvasObject_uniqChildName";
+ }
+ }
+
+ QString name = currentName;
+ for (int number = 1; findChildObject(name); ++number) {
+ name = currentName + '_' + QString::number(number);
+ }
+ return name;
+}
+
+UMLObject * UMLCanvasObject::findChildObject(const QString &n, Uml::Object_Type t) {
+ const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
+ UMLObject *obj;
+ for (UMLObjectListIt oit(m_List); (obj = oit.current()) != NULL; ++oit) {
+ if (t != Uml::ot_UMLObject && obj->getBaseType() != t)
+ continue;
+ if (caseSensitive) {
+ if (obj->getName() == n)
+ return obj;
+ } else if (obj->getName().lower() == n.lower()) {
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+UMLObject* UMLCanvasObject::findChildObjectById(Uml::IDType id, bool /* considerAncestors */) {
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
+ if (o->getID() == id)
+ return o;
+ }
+ return 0;
+}
+
+void UMLCanvasObject::init() {
+ m_List.setAutoDelete(false);
+}
+
+bool UMLCanvasObject::operator==(UMLCanvasObject& rhs) {
+ if (this == &rhs) {
+ return true;
+ }
+ if ( !UMLObject::operator==(rhs) ) {
+ return false;
+ }
+ if ( m_List.count() != rhs.m_List.count() ) {
+ return false;
+ }
+ if ( &m_List != &(rhs.m_List) ) {
+ return false;
+ }
+ return true;
+}
+
+void UMLCanvasObject::copyInto(UMLCanvasObject *rhs) const
+{
+ UMLObject::copyInto(rhs);
+
+ // TODO Associations are not copied at the moment. This because
+ // the duplicate function (on umlwidgets) do not copy the associations.
+ //
+ //rhs->m_List = m_List;
+}
+
+int UMLCanvasObject::associations() {
+ int count = 0;
+ UMLObject *obj;
+ for (UMLObjectListIt oit(m_List); (obj = oit.current()) != NULL; ++oit) {
+ if (obj->getBaseType() == Uml::ot_Association)
+ count++;
+ }
+ return count;
+}
+
+UMLAssociationList UMLCanvasObject::getAssociations() {
+ UMLAssociationList assocs;
+ UMLObject *o;
+ for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
+ if (o->getBaseType() != Uml::ot_Association)
+ continue;
+ UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
+ assocs.append(assoc);
+ }
+ return assocs;
+}
+
+UMLClassifierList UMLCanvasObject::getSuperClasses() {
+ UMLClassifierList list;
+ UMLAssociationList assocs = getAssociations();
+ for (UMLAssociation* a = assocs.first(); a; a = assocs.next()) {
+ if ((a->getAssocType() != Uml::at_Generalization &&
+ a->getAssocType() != Uml::at_Realization) ||
+ a->getObjectId(Uml::A) != getID() )
+ continue;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B));
+ if (c)
+ list.append(c);
+ else
+ kDebug() << "UMLCanvasObject::getSuperClasses(" << m_Name
+ << "): generalization's other end is not a "
+ << "UMLClassifier (id= " << ID2STR(a->getObjectId(Uml::B)) << ")"
+ << endl;
+ }
+ return list;
+}
+
+UMLClassifierList UMLCanvasObject::getSubClasses() {
+ UMLClassifierList list;
+ UMLAssociationList assocs = getAssociations();
+ for (UMLAssociation* a = assocs.first(); a; a = assocs.next()) {
+ if ((a->getAssocType() != Uml::at_Generalization &&
+ a->getAssocType() != Uml::at_Realization) ||
+ a->getObjectId(Uml::B) != getID() )
+ continue;
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ if (c)
+ list.append(c);
+ else
+ kDebug() << "UMLCanvasObject::getSubClasses: specialization's"
+ << " other end is not a UMLClassifier"
+ << " (id=" << ID2STR(a->getObjectId(Uml::A)) << ")" << endl;
+ }
+ return list;
+}
+
+UMLAssociationList UMLCanvasObject::getRealizations() {
+ return getSpecificAssocs(Uml::at_Realization);
+}
+
+UMLAssociationList UMLCanvasObject::getAggregations() {
+ return getSpecificAssocs(Uml::at_Aggregation);
+}
+
+UMLAssociationList UMLCanvasObject::getCompositions() {
+ return getSpecificAssocs(Uml::at_Composition);
+}
+
+UMLAssociationList UMLCanvasObject::getRelationships() {
+ return getSpecificAssocs(Uml::at_Relationship);
+}
+
+bool UMLCanvasObject::resolveRef() {
+ bool overallSuccess = UMLObject::resolveRef();
+ for (UMLObjectListIt ait(m_List); ait.current(); ++ait) {
+ UMLObject *obj = ait.current();
+ if (! obj->resolveRef()) {
+ m_List.remove(obj);
+ overallSuccess = false;
+ }
+ }
+ return overallSuccess;
+}
+
+#include "umlcanvasobject.moc"
+
diff --git a/umbrello/umbrello/umlcanvasobject.h b/umbrello/umbrello/umlcanvasobject.h
new file mode 100644
index 00000000..626b9fe9
--- /dev/null
+++ b/umbrello/umbrello/umlcanvasobject.h
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CANVASOBJECT_H
+#define CANVASOBJECT_H
+
+#include "umlobject.h"
+#include "umlobjectlist.h"
+#include "umlclassifierlist.h"
+#include "umlassociationlist.h"
+
+
+/**
+ * This class contains the non-graphical information required for UMLObjects
+ * which appear as moveable widgets on the canvas.
+ *
+ * This class inherits from @ref UMLObject which contains most of the
+ * information.
+ * It is not instantiated itself, it's just used as a super class for
+ * actual model objects.
+ *
+ * @short Non-graphical information for a UMLCanvasObject.
+ * @author Jonathan Riddell
+ * @see UMLObject
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLCanvasObject : public UMLObject {
+ Q_OBJECT
+public:
+ /**
+ * Sets up a UMLCanvasObject.
+ *
+ * @param name The name of the Concept.
+ * @param id The unique id of the Concept.
+ */
+ explicit UMLCanvasObject(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLCanvasObject();
+
+ /**
+ * Overloaded '==' operator
+ */
+ virtual bool operator==(UMLCanvasObject& rhs);
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLCanvasObject *rhs) const;
+
+ // The abstract method UMLObject::clone() is implemented
+ // in the classes inheriting from UMLCanvasObject.
+
+ /**
+ * Adds an association end to m_List.
+ *
+ * @param assoc The association to add.
+ * @todo change param type to UMLRole
+ */
+ bool addAssociationEnd(UMLAssociation* assoc);
+
+ /**
+ * Determine if this canvasobject has the given association.
+ *
+ * @param assoc The association to check.
+ */
+ bool hasAssociation(UMLAssociation* assoc);
+
+ /**
+ * Remove an association end from the CanvasObject.
+ *
+ * @param assoc The association to remove.
+ * @todo change param type to UMLRole
+ */
+ int removeAssociationEnd(UMLAssociation *assoc);
+
+ /**
+ * Remove all association ends from the CanvasObject.
+ */
+ void removeAllAssociationEnds();
+
+ /**
+ * Returns the number of associations for the CanvasObject.
+ * This is the sum of the aggregations and compositions.
+ *
+ * @return The number of associations for the Concept.
+ */
+ int associations();
+
+ /**
+ * Return the list of associations for the CanvasObject.
+ *
+ * @return The list of associations for the CanvasObject.
+ */
+ UMLAssociationList getAssociations();
+
+ /**
+ * Return the subset of m_List that matches the given type.
+ *
+ * @param assocType The Association_Type to match.
+ * @return The list of associations that match assocType.
+ */
+ UMLAssociationList getSpecificAssocs(Uml::Association_Type assocType);
+
+ /**
+ * Return a list of the superclasses of this concept.
+ * TODO: This overlaps with UMLClassifier::findSuperClassConcepts(),
+ * see if we can merge the two.
+ *
+ * @return The list of superclasses for the concept.
+ */
+ UMLClassifierList getSuperClasses();
+
+ /**
+ * Return a list of the classes that inherit from this concept.
+ * TODO: This overlaps with UMLClassifier::findSubClassConcepts(),
+ * see if we can merge the two.
+ *
+ * @return The list of classes inheriting from the concept.
+ */
+ UMLClassifierList getSubClasses();
+
+ /**
+ * Shorthand for getSpecificAssocs(Uml::at_Realization)
+ *
+ * @return The list of realizations for the Concept.
+ */
+ virtual UMLAssociationList getRealizations();
+
+ /**
+ * Shorthand for getSpecificAssocs(Uml::at_Aggregation)
+ *
+ * @return The list of aggregations for the Concept.
+ */
+ UMLAssociationList getAggregations();
+
+ /**
+ * Shorthand for getSpecificAssocs(Uml::at_Composition)
+ *
+ * @return The list of compositions for the Concept.
+ */
+ UMLAssociationList getCompositions();
+
+ /**
+ * Shorthand for getSpecificAssocs(Uml::at_Relationship)
+ *
+ * @return The list of relationships for the entity.
+ */
+ UMLAssociationList getRelationships();
+
+ /**
+ * Find a child object with the given name.
+ *
+ * @param n The name of the object to find.
+ * @param t The type to find (optional.) If not given then
+ * any object type will match.
+ * @return Pointer to the object found; NULL if none found.
+ */
+ virtual UMLObject *findChildObject(const QString &n, Uml::Object_Type t = Uml::ot_UMLObject);
+
+ /**
+ * Find an association.
+ *
+ * @param id The id of the object to find.
+ * @param considerAncestors boolean switch to consider ancestors while searching
+ * @return Pointer to the object found (NULL if not found.)
+ */
+ virtual UMLObject *findChildObjectById(Uml::IDType id, bool considerAncestors = false);
+
+ /**
+ * Returns a name for the new association, operation, template
+ * or attribute appended with a number if the default name is
+ * taken e.g. new_association, new_association_1 etc.
+ *
+ * @param type The object type for which to make a name.
+ * @param prefix Optional prefix to use for the name.
+ * If not given then uniqChildName() will choose the prefix
+ * internally based on the object type.
+ * @return Unique name string for the Object_Type given.
+ */
+ virtual QString uniqChildName(const Uml::Object_Type type,
+ const QString &prefix = QString());
+
+ virtual void removeAllChildObjects();
+
+ /**
+ * Return the list of subordinate items.
+ */
+ UMLObjectList subordinates() const {
+ return m_List;
+ }
+
+ /**
+ * Reimplementation of UMLObject method.
+ */
+ virtual bool resolveRef();
+
+ // The abstract method UMLObject::saveToXMI() is implemented
+ // in the classes inheriting from UMLCanvasObject.
+
+protected:
+
+ /**
+ * List of all the associations in this object.
+ * Inheriting classes add more types of objects that are possible in this list;
+ * for example, UMLClassifier adds operations, attributes, and templates.
+ *
+ * @todo Only a pointer to the appropriate assocation end object
+ * (UMLRole) should be saved here, not the entire UMLAssociation.
+ *
+ */
+ UMLObjectList m_List;
+
+private:
+
+ /**
+ * Initialises key variables of the class.
+ */
+ void init();
+
+signals:
+
+ /**
+ * Emit when new association is added.
+ * @param assoc Pointer to the association which has been added.
+ */
+ void sigAssociationEndAdded(UMLAssociation * assoc);
+
+ /**
+ * Emit when new association is removed.
+ * @param assoc Pointer to the association which has been removed.
+ */
+ void sigAssociationEndRemoved(UMLAssociation * assoc);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umlclassifierlist.h b/umbrello/umbrello/umlclassifierlist.h
new file mode 100644
index 00000000..45bd2b62
--- /dev/null
+++ b/umbrello/umbrello/umlclassifierlist.h
@@ -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) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLCLASSIFIERLIST_H
+#define UMLCLASSIFIERLIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLClassifier;
+
+typedef QPtrList<UMLClassifier> UMLClassifierList;
+typedef QPtrListIterator<UMLClassifier> UMLClassifierListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlclassifierlistitemlist.cpp b/umbrello/umbrello/umlclassifierlistitemlist.cpp
new file mode 100644
index 00000000..1672c0cb
--- /dev/null
+++ b/umbrello/umbrello/umlclassifierlistitemlist.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlclassifierlistitemlist.h"
+#include "classifierlistitem.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+void UMLClassifierListItemList::copyInto(UMLClassifierListItemList *rhs) const {
+ // Prevent copying to yourself. (Can cause serious injuries)
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLClassifierListItemList *tmp = new UMLClassifierListItemList(*this);
+
+ UMLClassifierListItem *item;
+ for (item = tmp->first(); item; item = tmp->next() )
+ {
+ rhs->append((UMLClassifierListItem*)item->clone());
+ }
+ delete tmp;
+}
+
+
+UMLClassifierListItemList* UMLClassifierListItemList::clone() const {
+ UMLClassifierListItemList *clone = new UMLClassifierListItemList();
+ copyInto(clone);
+ return clone;
+}
+
+
+
diff --git a/umbrello/umbrello/umlclassifierlistitemlist.h b/umbrello/umbrello/umlclassifierlistitemlist.h
new file mode 100644
index 00000000..675e8d5c
--- /dev/null
+++ b/umbrello/umbrello/umlclassifierlistitemlist.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLCLASSIFIERLISTITEMLIST_H
+#define UMLCLASSIFIERLISTITEMLIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLClassifierListItem;
+
+//typedef QPtrList<UMLClassifierListItem> UMLClassifierListItemList;
+typedef QPtrListIterator<UMLClassifierListItem> UMLClassifierListItemListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLClassifierListItem>
+ * base class.
+ */
+class UMLClassifierListItemList : public QPtrList<UMLClassifierListItem>
+{
+
+public:
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto (UMLClassifierListItemList *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLClassifierListItemList* clone() const;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umldoc.cpp b/umbrello/umbrello/umldoc.cpp
new file mode 100644
index 00000000..9783cfbd
--- /dev/null
+++ b/umbrello/umbrello/umldoc.cpp
@@ -0,0 +1,2356 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umldoc.h"
+
+// qt includes
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include <qbuffer.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <qlabel.h>
+
+// kde includes
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <kdebug.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kprinter.h>
+#include <ktar.h>
+#include <ktempdir.h>
+#include <ktempfile.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+#include <ktabwidget.h>
+
+// app includes
+#include "uniqueid.h"
+#include "associationwidget.h"
+#include "association.h"
+#include "package.h"
+#include "folder.h"
+#include "codegenerator.h"
+#include "classifier.h"
+#include "enum.h"
+#include "entity.h"
+#include "docwindow.h"
+#include "operation.h"
+#include "attribute.h"
+#include "template.h"
+#include "enumliteral.h"
+#include "entityattribute.h"
+#include "stereotype.h"
+#include "classifierlistitem.h"
+#include "object_factory.h"
+#include "import_rose.h"
+#include "model_utils.h"
+#include "widget_utils.h"
+#include "uml.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+#include "umlview.h"
+#include "clipboard/idchangelog.h"
+#include "dialogs/classpropdlg.h"
+#include "codegenerators/codegenfactory.h"
+#include "listpopupmenu.h"
+#include "version.h"
+
+#define XMI_FILE_VERSION UMBRELLO_VERSION
+// For the moment, the XMI_FILE_VERSION changes with each UMBRELLO_VERSION.
+// But someday that may stabilize ;)
+
+using namespace Uml;
+
+static const uint undoMax = 30;
+
+UMLDoc::UMLDoc() {
+ m_Name = i18n("UML Model");
+ m_modelID = "m1";
+ m_count = 0;
+ m_pChangeLog = 0;
+ m_Doc = "";
+ m_modified = false;
+ m_bLoading = false;
+ m_bTypesAreResolved = false;
+ m_pAutoSaveTimer = 0;
+ m_nViewID = Uml::id_None;
+ m_pTabPopupMenu = 0;
+ m_pCurrentRoot = NULL;
+}
+
+void UMLDoc::init() {
+ // Initialize predefined folders.
+ const QString nativeRootName[Uml::N_MODELTYPES] = {
+ "Logical View",
+ "Use Case View",
+ "Component View",
+ "Deployment View",
+ "Entity Relationship Model"
+ };
+ const QString localizedRootName[Uml::N_MODELTYPES] = {
+ i18n("Logical View"),
+ i18n("Use Case View"),
+ i18n("Component View"),
+ i18n("Deployment View"),
+ i18n("Entity Relationship Model")
+ };
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ m_root[i] = new UMLFolder(nativeRootName[i], STR2ID(nativeRootName[i]));
+ m_root[i]->setLocalName(localizedRootName[i]);
+ }
+ m_datatypeRoot = new UMLFolder("Datatypes", "Datatypes");
+ m_datatypeRoot->setLocalName(i18n("Datatypes"));
+ m_datatypeRoot->setUMLPackage(m_root[Uml::mt_Logical]);
+ m_root[Uml::mt_Logical]->addObject(m_datatypeRoot);
+
+ // Connect signals.
+ UMLApp * pApp = UMLApp::app();
+ connect(this, SIGNAL(sigDiagramCreated(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
+ connect(this, SIGNAL(sigDiagramRemoved(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
+ connect(this, SIGNAL(sigDiagramRenamed(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
+ connect(this, SIGNAL( sigCurrentViewChanged() ), pApp, SLOT( slotCurrentViewChanged() ) );
+}
+
+UMLDoc::~UMLDoc() {
+ delete m_pChangeLog;
+ m_pChangeLog = 0;
+}
+
+void UMLDoc::addView(UMLView *view) {
+ if (view == NULL) {
+ kError() << "UMLDoc::addView: argument is NULL" << endl;
+ return;
+ }
+ UMLFolder *f = view->getFolder();
+ if (f == NULL) {
+ kError() << "UMLDoc::addView: view folder is not set" << endl;
+ return;
+ }
+ f->addView(view);
+
+ UMLApp * pApp = UMLApp::app();
+ if ( pApp->getListView() )
+ connect(this, SIGNAL(sigObjectRemoved(UMLObject *)), view, SLOT(slotObjectRemoved(UMLObject *)));
+
+ pApp->setCurrentView(view);
+ if ( ! m_bLoading ) {
+ view -> show();
+ emit sigDiagramChanged(view ->getType());
+ }
+
+ Settings::OptionState optionState = Settings::getOptionState();
+ KTabWidget* tabWidget = NULL;
+ if (optionState.generalState.tabdiagrams) {
+ tabWidget = UMLApp::app()->tabWidget();
+ tabWidget->addTab(view, view->getName());
+ tabWidget->setTabIconSet(view, Widget_Utils::iconSet(view->getType()));
+ }
+ pApp->setDiagramMenuItemsState(true);
+ pApp->slotUpdateViews();
+ pApp->setCurrentView(view);
+ if (tabWidget) {
+ tabWidget->showPage(view);
+ tabWidget->setCurrentPage(tabWidget->currentPageIndex());
+ }
+}
+
+void UMLDoc::removeView(UMLView *view , bool enforceCurrentView ) {
+ if(!view)
+ {
+ kError()<<"UMLDoc::removeView(UMLView *view) called with view = 0"<<endl;
+ return;
+ }
+ if ( UMLApp::app()->getListView() ) {
+ disconnect(this,SIGNAL(sigObjectRemoved(UMLObject *)), view,SLOT(slotObjectRemoved(UMLObject *)));
+ }
+ view->hide();
+ //remove all widgets before deleting view
+ view->removeAllWidgets();
+ UMLFolder *f = view->getFolder();
+ if (f == NULL) {
+ kError() << "UMLDoc::removeView(" << view->getName()
+ << "): view->getFolder() returns NULL" << endl;
+ return;
+ }
+ f->removeView(view);
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView == view)
+ {
+ UMLApp::app()->setCurrentView(NULL);
+ UMLViewList viewList;
+ m_root[mt_Logical]->appendViews(viewList);
+ UMLView* firstView = viewList.first();
+ if (!firstView && enforceCurrentView) //create a diagram
+ {
+ createDiagram(m_root[mt_Logical], dt_Class, false);
+ kapp->processEvents();
+ m_root[mt_Logical]->appendViews(viewList);
+ firstView = viewList.first();
+ }
+
+ if ( firstView )
+ {
+ changeCurrentView( firstView->getID() );
+ UMLApp::app()->setDiagramMenuItemsState(true);
+ }
+ }
+}
+
+void UMLDoc::setURL(const KURL &url) {
+ m_doc_url = url;
+ return;
+}
+
+const KURL& UMLDoc::URL() const {
+ return m_doc_url;
+}
+
+bool UMLDoc::saveModified() {
+ bool completed(true);
+ if (!m_modified)
+ return completed;
+
+ UMLApp *win = UMLApp::app();
+ int want_save = KMessageBox::warningYesNoCancel(win, i18n("The current file has been modified.\nDo you want to save it?"), i18n("Warning"),KStdGuiItem::save(),KStdGuiItem::discard());
+ switch(want_save) {
+ case KMessageBox::Yes:
+ if (m_doc_url.fileName() == i18n("Untitled")) {
+ if (win->slotFileSaveAs()) {
+ closeDocument();
+ completed=true;
+ } else {
+ completed=false;
+ }
+ } else {
+ saveDocument(URL());
+ closeDocument();
+ completed=true;
+ }
+ break;
+
+ case KMessageBox::No:
+ setModified(false);
+ closeDocument();
+ completed=true;
+ break;
+
+ case KMessageBox::Cancel:
+ completed=false;
+ break;
+
+ default:
+ completed=false;
+ break;
+ }
+ return completed;
+}
+
+void UMLDoc::closeDocument() {
+ UMLApp::app()->setGenerator(Uml::pl_Reserved); // delete the codegen
+ m_Doc = "";
+ DocWindow* dw = UMLApp::app()->getDocWindow();
+ if (dw) {
+ dw->newDocumentation();
+ }
+
+ UMLListView *listView = UMLApp::app()->getListView();
+ if (listView) {
+ listView->init();
+ // store old setting - for restore of last setting
+ bool m_bLoading_old = m_bLoading;
+ m_bLoading = true; // This is to prevent document becoming modified.
+ // For reference, here is an example of a call sequence that would
+ // otherwise result in futile addToUndoStack() calls:
+ // removeAllViews() =>
+ // UMLView::removeAllAssociations() =>
+ // UMLView::removeAssoc() =>
+ // UMLDoc::setModified(true, true) =>
+ // addToUndoStack().
+ removeAllViews();
+ m_bLoading = m_bLoading_old;
+ // Remove all objects from the predefined folders.
+ // @fixme With advanced code generation enabled, this crashes.
+ UMLObject *obj;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_root[i]->removeAllObjects();
+ // Restore the datatype folder, it has been deleted above.
+ m_datatypeRoot = new UMLFolder("Datatypes", "Datatypes");
+ m_datatypeRoot->setLocalName(i18n("Datatypes"));
+ m_datatypeRoot->setUMLPackage(m_root[Uml::mt_Logical]);
+ m_root[Uml::mt_Logical]->addObject(m_datatypeRoot);
+ listView->theDatatypeFolder()->setUMLObject(m_datatypeRoot);
+ /* Remove any stereotypes.
+ if (m_stereoList.count() > 0) {
+ UMLStereotype *s;
+ for (UMLStereotypeListIt sit(m_stereoList); (s = sit.current()) != 0; ++sit)
+ delete s;
+ m_stereoList.clear();
+ }
+ */
+ }
+ m_bTypesAreResolved = false;
+}
+
+bool UMLDoc::newDocument() {
+ closeDocument();
+ UMLApp::app()->setCurrentView(NULL);
+ m_doc_url.setFileName(i18n("Untitled"));
+ //see if we need to start with a new diagram
+ Settings::OptionState optionState = Settings::getOptionState();
+ Uml::Diagram_Type dt = optionState.generalState.diagram;
+ Uml::Model_Type mt = Model_Utils::convert_DT_MT(dt);
+ if (mt == Uml::N_MODELTYPES) { // don't allow no diagram
+ dt = Uml::dt_Class;
+ mt = Uml::mt_Logical;
+ }
+ createDiagram(m_root[mt], dt, false);
+
+ UMLApp::app()->initGenerator();
+ addDefaultDatatypes();
+ addDefaultStereotypes();
+
+ setModified(false);
+ initSaveTimer();
+
+ UMLApp::app()->enableUndo(false);
+ clearUndoStack();
+ addToUndoStack();
+
+ return true;
+}
+
+bool UMLDoc::openDocument(const KURL& url, const char* /*format =0*/) {
+ if(url.fileName().length() == 0) {
+ newDocument();
+ return false;
+ }
+
+ m_doc_url = url;
+ QDir d = url.path(1);
+ closeDocument();
+ // IMPORTANT: set m_bLoading to true
+ // _AFTER_ the call of UMLDoc::closeDocument()
+ // as it sets m_bLoading to false afer it was temporarily
+ // changed to true to block recording of changes in redo-buffer
+ m_bLoading = true;
+ QString tmpfile;
+ KIO::NetAccess::download( url, tmpfile, UMLApp::app() );
+ QFile file( tmpfile );
+ if ( !file.exists() ) {
+ KMessageBox::error(0, i18n("The file %1 does not exist.").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+
+ // status of XMI loading
+ bool status = false;
+
+ // check if the xmi file is a compressed archive like tar.bzip2 or tar.gz
+ QString filetype = m_doc_url.fileName(true);
+ QString mimetype = "";
+ if (filetype.find(QRegExp("\\.tgz$")) != -1)
+ {
+ mimetype = "application/x-gzip";
+ } else if (filetype.find(QRegExp("\\.tar.bz2$")) != -1) {
+ mimetype = "application/x-bzip2";
+ }
+
+ if (mimetype.isEmpty() == false)
+ {
+ KTar archive(tmpfile, mimetype);
+ if (archive.open(IO_ReadOnly) == false)
+ {
+ KMessageBox::error(0, i18n("The file %1 seems to be corrupted.").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+
+ // get the root directory and all entries in
+ const KArchiveDirectory * rootDir = archive.directory();
+ QStringList entries = rootDir->entries();
+ QString entryMimeType;
+ bool foundXMI = false;
+ QStringList::Iterator it;
+ QStringList::Iterator end(entries.end());
+
+ // now go through all entries till we find an xmi file
+ for (it = entries.begin(); it != end; ++it)
+ {
+ // only check files, we do not go in subdirectories
+ if (rootDir->entry(*it)->isFile() == true)
+ {
+ // we found a file, check the mimetype
+ entryMimeType = KMimeType::findByPath(*it, 0, true)->name();
+ if (entryMimeType == "application/x-uml")
+ {
+ foundXMI = true;
+ break;
+ }
+ }
+ }
+
+ // if we found an XMI file, we have to extract it to a temporary file
+ if (foundXMI == true)
+ {
+ KTempDir tmp_dir;
+ KArchiveEntry * entry;
+ KArchiveFile * fileEntry;
+
+ // try to cast the file entry in the archive to an archive entry
+ entry = const_cast<KArchiveEntry*>(rootDir->entry(*it));
+ if (entry == 0)
+ {
+ KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+
+ // now try to cast the archive entry to a file entry, so that we can
+ // extract the file
+ fileEntry = dynamic_cast<KArchiveFile*>(entry);
+ if (fileEntry == 0)
+ {
+ KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+
+ // now we can extract the file to the temporary directory
+ fileEntry->copyTo(tmp_dir.name());
+
+ // now open the extracted file for reading
+ QFile xmi_file(tmp_dir.name() + *it);
+ if( !xmi_file.open( IO_ReadOnly ) )
+ {
+ KMessageBox::error(0, i18n("There was a problem loading the extracted file: %1").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+ status = loadFromXMI( xmi_file, ENC_UNKNOWN );
+
+ // close the extracted file and the temporary directory
+ xmi_file.close();
+ tmp_dir.unlink();
+
+ } else {
+ KMessageBox::error(0, i18n("There was no XMI file found in the compressed file %1.").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+
+ archive.close();
+ } else {
+ // no, it seems to be an ordinary file
+ if( !file.open( IO_ReadOnly ) ) {
+ KMessageBox::error(0, i18n("There was a problem loading file: %1").arg(d.path()), i18n("Load Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+ if (filetype.endsWith(".mdl"))
+ status = Import_Rose::loadFromMDL(file);
+ else
+ status = loadFromXMI( file, ENC_UNKNOWN );
+ }
+
+ file.close();
+ KIO::NetAccess::removeTempFile( tmpfile );
+ if( !status )
+ {
+ KMessageBox::error(0, i18n("There was a problem loading file: %1").arg(d.path()), i18n("Load Error"));
+ m_bLoading = false;
+ newDocument();
+ return false;
+ }
+ setModified(false);
+ m_bLoading = false;
+ initSaveTimer();
+
+ UMLApp::app()->enableUndo(false);
+ clearUndoStack();
+ addToUndoStack();
+ // for compatibility
+ addDefaultStereotypes();
+
+ return true;
+}
+
+bool UMLDoc::saveDocument(const KURL& url, const char * /* format */) {
+ m_doc_url = url;
+ QDir d = m_doc_url.path(1);
+ QFile file;
+ bool uploaded = true;
+
+ // first, we have to find out which format to use
+ QString strFileName = url.path(-1);
+ QFileInfo fileInfo(strFileName);
+ QString fileExt = fileInfo.extension();
+ QString fileFormat = "xmi";
+ if (fileExt == "xmi" || fileExt == "bak.xmi")
+ {
+ fileFormat = "xmi";
+ } else if (fileExt == "xmi.tgz" || fileExt == "bak.xmi.tgz") {
+ fileFormat = "tgz";
+ } else if (fileExt == "xmi.tar.bz2" || fileExt == "bak.xmi.tar.bz2") {
+ fileFormat = "bz2";
+ } else {
+ fileFormat = "xmi";
+ }
+
+ initSaveTimer();
+
+ if (fileFormat == "tgz" || fileFormat == "bz2")
+ {
+ KTar * archive;
+ KTempFile tmp_tgz_file;
+
+ // first we have to check if we are saving to a local or remote file
+ if (url.isLocalFile())
+ {
+ if (fileFormat == "tgz") // check tgz or bzip2
+ {
+ archive = new KTar(d.path(), "application/x-gzip");
+ } else {
+ archive = new KTar(d.path(), "application/x-bzip2");
+ }
+ } else {
+ if (fileFormat == "tgz") // check tgz or bzip2
+ {
+ archive = new KTar(tmp_tgz_file.name(), "application/x-gzip");
+ } else {
+ archive = new KTar(tmp_tgz_file.name(), "application/x-bzip2");
+ }
+ }
+
+ // now check if we can write to the file
+ if (archive->open(IO_WriteOnly) == false)
+ {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
+ return false;
+ }
+
+ // we have to create a temporary xmi file
+ // we will add this file later to the archive
+ KTempFile tmp_xmi_file;
+ file.setName(tmp_xmi_file.name());
+ if( !file.open( IO_WriteOnly ) ) {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
+ return false;
+ }
+ saveToXMI(file); // save XMI to this file...
+ file.close(); // ...and close it
+
+ // now add this file to the archive, but without the extension
+ QString tmpQString = url.fileName();
+ if (fileFormat == "tgz")
+ {
+ tmpQString.replace(QRegExp("\\.tgz$"), "");
+ } else {
+ tmpQString.replace(QRegExp("\\.tar\\.bz2$"), "");
+ }
+ archive->addLocalFile(tmp_xmi_file.name(), tmpQString);
+ archive->close();
+
+#if KDE_IS_VERSION(3,4,89)
+ if (!archive->closeSucceeded())
+ {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
+ return false;
+ }
+#endif
+ // now the xmi file was added to the archive, so we can delete it
+ tmp_xmi_file.close();
+ tmp_xmi_file.unlink();
+
+ // now we have to check, if we have to upload the file
+ if ( !url.isLocalFile() ) {
+ uploaded = KIO::NetAccess::upload( tmp_tgz_file.name(), m_doc_url,
+ UMLApp::app() );
+ }
+
+ // now the archive was written to disk (or remote) so we can delete the
+ // objects
+ tmp_tgz_file.close();
+ tmp_tgz_file.unlink();
+ delete archive;
+
+ } else {
+ // save as normal uncompressed XMI
+
+ KTempFile tmpfile; // we need this tmp file if we are writing to a remote file
+
+ // save in _any_ case to a temp file
+ // -> if something goes wrong during saveToXmi, the
+ // original content is preserved
+ // ( e.g. if umbrello dies in the middle of the document model parsing
+ // for saveToXMI due to some problems )
+ /// @TODO insert some checks in saveToXMI to detect a failed save attempt
+ file.setName( tmpfile.name() );
+
+ // lets open the file for writing
+ if( !file.open( IO_WriteOnly ) ) {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
+ return false;
+ }
+ saveToXMI(file); // save the xmi stuff to it
+ file.close();
+ tmpfile.close();
+
+ // if it is a remote file, we have to upload the tmp file
+ if ( !url.isLocalFile() ) {
+ uploaded = KIO::NetAccess::upload( tmpfile.name(), m_doc_url, UMLApp::app() );
+ } else {
+ // now remove the original file
+ if ( KIO::NetAccess::file_move( tmpfile.name(), d.path(), -1, true ) == false ) {
+ KMessageBox::error(0, i18n("There was a problem saving file: %1").arg(d.path()), i18n("Save Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ return false;
+ }
+ }
+ }
+ if( !uploaded )
+ {
+ KMessageBox::error(0, i18n("There was a problem uploading file: %1").arg(d.path()), i18n("Save Error"));
+ m_doc_url.setFileName(i18n("Untitled"));
+ }
+ setModified(false);
+ return uploaded;
+}
+
+void UMLDoc::setupSignals() {
+ WorkToolBar *tb = UMLApp::app() -> getWorkToolBar();
+
+
+ connect(this, SIGNAL(sigDiagramChanged(Uml::Diagram_Type)), tb, SLOT(slotCheckToolBar(Uml::Diagram_Type)));
+ //new signals below
+
+ return;
+}
+
+UMLView * UMLDoc::findView(Uml::IDType id) {
+ UMLView *v = NULL;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ v = m_root[i]->findView(id);
+ if (v)
+ break;
+ }
+ return v;
+}
+
+UMLView * UMLDoc::findView(Uml::Diagram_Type type, const QString &name,
+ bool searchAllScopes /* =false */) {
+ Uml::Model_Type mt = Model_Utils::convert_DT_MT(type);
+ return m_root[mt]->findView(type, name, searchAllScopes);
+}
+
+UMLObject* UMLDoc::findObjectById(Uml::IDType id) {
+ UMLObject *o = NULL;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ if (id == m_root[i]->getID())
+ return m_root[i];
+ o = m_root[i]->findObjectById(id);
+ if (o)
+ return o;
+ }
+ o = findStereotypeById(id);
+ return o;
+}
+
+UMLStereotype * UMLDoc::findStereotypeById(Uml::IDType id) {
+ for (UMLStereotype *s = m_stereoList.first(); s; s = m_stereoList.next() ) {
+ if (s->getID() == id)
+ return s;
+ }
+ return NULL;
+}
+
+UMLObject* UMLDoc::findUMLObject(const QString &name,
+ Uml::Object_Type type /* = ot_UMLObject */,
+ UMLObject *currentObj /* = NULL */) {
+ UMLObject *o = m_datatypeRoot->findObject(name);
+ if (o)
+ return o;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ UMLObjectList list = m_root[i]->containedObjects();
+ o = Model_Utils::findUMLObject(list, name, type, currentObj);
+ if (o)
+ return o;
+ if ((type == ot_UMLObject || type == ot_Folder) &&
+ name == m_root[i]->getName())
+ return m_root[i];
+ }
+ return NULL;
+}
+
+UMLClassifier* UMLDoc::findUMLClassifier(const QString &name) {
+ //this is used only by code generator so we don't need to look at Datatypes
+ UMLObject * obj = findUMLObject(name);
+ return dynamic_cast<UMLClassifier*>(obj);
+}
+
+/**
+ * Adds a UMLObject thats already created but doesn't change
+ * any ids or signal. Used by the list view. Use
+ * AddUMLObjectPaste if pasting.
+ */
+bool UMLDoc::addUMLObject(UMLObject* object) {
+ Object_Type ot = object->getBaseType();
+ if (ot == ot_Attribute || ot == ot_Operation || ot == ot_EnumLiteral
+ || ot == ot_EntityAttribute || ot == ot_Template || ot == ot_Stereotype) {
+ kDebug() << "UMLDoc::addUMLObject(" << object->getName()
+ << "): not adding type " << ot << endl;
+ return false;
+ }
+ UMLPackage *pkg = object->getUMLPackage();
+ if (pkg == NULL) {
+ pkg = currentRoot();
+ kDebug() << "UMLDoc::addUMLObject(" << object->getName()
+ << "): no parent package set, assuming " << pkg->getName() << endl;
+ object->setUMLPackage( pkg );
+ }
+ return pkg->addObject(object);
+}
+
+void UMLDoc::addStereotype(const UMLStereotype *s) {
+ if (! m_stereoList.contains(s))
+ m_stereoList.append(s);
+}
+
+void UMLDoc::removeStereotype(const UMLStereotype *s) {
+ if (m_stereoList.contains(s))
+ m_stereoList.remove(s);
+}
+
+void UMLDoc::writeToStatusBar(const QString &text) {
+ emit sigWriteToStatusBar(text);
+}
+
+// simple removal of an object
+void UMLDoc::slotRemoveUMLObject(UMLObject* object) {
+ //m_objectList.remove(object);
+ UMLPackage *pkg = object->getUMLPackage();
+ if (pkg == NULL) {
+ kError() << "UMLDoc::slotRemoveUMLObject(" << object->getName()
+ << "): parent package is not set !" << endl;
+ return;
+ }
+ pkg->removeObject(object);
+}
+
+bool UMLDoc::isUnique(const QString &name)
+{
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *currentItem = (UMLListViewItem*)listView->currentItem();
+ UMLListViewItem *parentItem = 0;
+
+ // check for current item, if its a package, then we do a check on that
+ // otherwise, if current item exists, find its parent and check if thats
+ // a package..
+ if(currentItem)
+ {
+ // its possible that the current item *is* a package, then just
+ // do check now
+ if (Model_Utils::typeIsContainer(currentItem->getType()))
+ return isUnique (name, (UMLPackage*) currentItem->getUMLObject());
+ parentItem = (UMLListViewItem*)currentItem->parent();
+ }
+
+ // item is in a package so do check only in that
+ if (parentItem != NULL && Model_Utils::typeIsContainer(parentItem->getType())) {
+ UMLPackage *parentPkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
+ return isUnique(name, parentPkg);
+ }
+
+ kError() << "UMLDoc::isUnique(" << name << "): Not currently in a package"
+ << endl;
+ /* Check against all objects that _don't_ have a parent package.
+ for (UMLObjectListIt oit(m_objectList); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (obj->getUMLPackage() == NULL && obj->getName() == name)
+ return false;
+ }
+ */
+ return true;
+}
+
+bool UMLDoc::isUnique(const QString &name, UMLPackage *package)
+{
+ // if a package, then only do check in that
+ if (package)
+ return (package->findObject(name) == NULL);
+
+ // Not currently in a package: ERROR
+ kError() << "UMLDoc::isUnique(2)(" << name << "): Not currently in a package"
+ << endl;
+ /* Check against all objects that _don't_ have a parent package.
+ for (UMLObjectListIt oit(m_objectList); oit.current(); ++oit) {
+ UMLObject *obj = oit.current();
+ if (obj->getUMLPackage() == NULL && obj->getName() == name)
+ return false;
+ }
+ */
+ return true;
+}
+
+UMLStereotype* UMLDoc::findStereotype(const QString &name) {
+ UMLStereotype *s;
+ for (UMLStereotypeListIt it(m_stereoList); (s = it.current()) != NULL; ++it) {
+ if (s->getName() == name)
+ return s;
+ }
+ return NULL;
+}
+
+UMLStereotype* UMLDoc::findOrCreateStereotype(const QString &name) {
+ UMLStereotype *s = findStereotype(name);
+ if (s != NULL) {
+ return s;
+ }
+ s = new UMLStereotype(name, STR2ID(name));
+ addStereotype(s);
+ //emit modified();
+ return s;
+}
+
+void UMLDoc::removeAssociation (UMLAssociation * assoc, bool doSetModified /*=true*/) {
+ if(!assoc)
+ return;
+
+ // Remove the UMLAssociation from m_objectList.
+ UMLPackage *pkg = assoc->getUMLPackage();
+ if (pkg == NULL) {
+ kError() << "UMLDoc::removeAssociation(" << assoc->getName()
+ << "): parent package is not set !" << endl;
+ return;
+ }
+ pkg->removeObject(assoc);
+
+ if (doSetModified) // so we will save our document
+ setModified(true, false);
+}
+
+UMLAssociation * UMLDoc::findAssociation(Uml::Association_Type assocType,
+ const UMLObject *roleAObj,
+ const UMLObject *roleBObj,
+ bool *swap)
+{
+ UMLAssociationList assocs = getAssociations();
+ UMLAssociation *a, *ret = NULL;
+ for (a = assocs.first(); a; a = assocs.next()) {
+ if (a->getAssocType() != assocType)
+ continue;
+ if (a->getObject(Uml::A) == roleAObj && a->getObject(Uml::B) == roleBObj)
+ return a;
+ if (a->getObject(Uml::A) == roleBObj && a->getObject(Uml::B) == roleAObj) {
+ ret = a;
+ }
+ }
+ if (swap)
+ *swap = (ret != NULL);
+ return ret;
+}
+
+// create AND add an association. Used by refactoring assistant.
+UMLAssociation* UMLDoc::createUMLAssociation(UMLObject *a, UMLObject *b, Uml::Association_Type type)
+{
+ bool swap;
+ UMLAssociation *assoc = findAssociation(type, a, b, &swap);
+ if (assoc == NULL) {
+ assoc = new UMLAssociation(type, a, b );
+ addAssociation(assoc);
+ }
+ return assoc;
+}
+
+void UMLDoc::addAssociation(UMLAssociation *Assoc)
+{
+ if (Assoc == NULL)
+ return;
+
+ // First, check that this association has not already been added.
+ // This may happen when loading old XMI files where all the association
+ // information was taken from the <UML:AssocWidget> tag.
+ UMLAssociationList assocs = getAssociations();
+ for (UMLAssociationListIt ait(assocs); ait.current(); ++ait) {
+ UMLAssociation *a = ait.current();
+ // check if its already been added (shouldn't be the case right now
+ // as UMLAssociations only belong to one associationwidget at a time)
+ if (a == Assoc)
+ {
+ kDebug() << "UMLDoc::addAssociation: duplicate addition attempted"
+ << endl;
+ return;
+ }
+ }
+
+ // If we get here it's really a new association.
+
+ // Add the UMLAssociation at the owning UMLPackage.
+ UMLPackage *pkg = Assoc->getUMLPackage();
+ if (pkg == NULL) {
+ kError() << "UMLDoc::addAssociation(" << Assoc->getName()
+ << "): parent package is not set !" << endl;
+ return;
+ }
+ pkg->addObject(Assoc);
+
+ // I don't believe this appropriate, UMLAssociations ARENT UMLWidgets -b.t.
+ // emit sigObjectCreated(o);
+
+ setModified(true);
+}
+
+QString UMLDoc::uniqViewName(const Uml::Diagram_Type type) {
+ QString dname;
+ if(type == dt_UseCase)
+ dname = i18n("use case diagram");
+ else if(type == dt_Class)
+ dname = i18n("class diagram");
+ else if(type == dt_Sequence)
+ dname = i18n("sequence diagram");
+ else if(type == dt_Collaboration)
+ dname = i18n("collaboration diagram");
+ else if( type == dt_State )
+ dname = i18n( "state diagram" );
+ else if( type == dt_Activity )
+ dname = i18n( "activity diagram" );
+ else if( type == dt_Component )
+ dname = i18n( "component diagram" );
+ else if( type == dt_Deployment )
+ dname = i18n( "deployment diagram" );
+ else if( type == dt_EntityRelationship )
+ dname = i18n( "entity relationship diagram" );
+ else {
+ kWarning() << "uniqViewName() called with unknown diagram type" << endl;
+ }
+ QString name = dname;
+ for (int number = 0; findView(type, name, true); ++number,
+ name = dname + '_' + QString::number(number))
+ ;
+ return name;
+}
+
+bool UMLDoc::loading() const {
+ return m_bLoading;
+}
+
+void UMLDoc::setLoading(bool state /* = true */) {
+ m_bLoading = state;
+}
+
+UMLView* UMLDoc::createDiagram(UMLFolder *folder, Uml::Diagram_Type type, bool askForName /*= true */) {
+ bool ok = true;
+ QString name,
+ dname = uniqViewName(type);
+
+ while(true) {
+ if (askForName) {
+ name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), dname, &ok, (QWidget*)UMLApp::app());
+ } else {
+ name = dname;
+ }
+ if (!ok) {
+ break;
+ }
+ if (name.length() == 0) {
+ KMessageBox::error(0, i18n("That is an invalid name for a diagram."), i18n("Invalid Name"));
+ } else if(!findView(type, name)) {
+ UMLView* temp = new UMLView(folder);
+ temp -> setOptionState( Settings::getOptionState() );
+ temp->setName( name );
+ temp->setType( type );
+ temp->setID( UniqueID::gen() );
+ addView(temp);
+ emit sigDiagramCreated( temp->getID() );
+ setModified(true, false);
+ UMLApp::app()->enablePrint(true);
+ changeCurrentView( temp->getID() );
+ return temp;
+ } else {
+ KMessageBox::error(0, i18n("A diagram is already using that name."), i18n("Not a Unique Name"));
+ }
+ }//end while
+ return 0;
+}
+
+void UMLDoc::renameDiagram(Uml::IDType id) {
+ bool ok = false;
+
+ UMLView *temp = findView(id);
+ Diagram_Type type = temp->getType();
+
+ QString oldName= temp->getName();
+ while(true) {
+ QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
+
+ if(!ok)
+ break;
+ if(name.length() == 0)
+ KMessageBox::error(0, i18n("That is an invalid name for a diagram."), i18n("Invalid Name"));
+ else if(!findView(type, name)) {
+ temp->setName(name);
+
+ emit sigDiagramRenamed(id);
+ setModified(true);
+ break;
+ } else
+ KMessageBox::error(0, i18n("A diagram is already using that name."), i18n("Not a Unique Name"));
+ }
+}
+
+void UMLDoc::renameUMLObject(UMLObject *o) {
+ bool ok = false;
+ QString oldName= o->getName();
+ while(true) {
+ QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
+ if(!ok)
+ break;
+ if(name.length() == 0)
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ else if (isUnique(name)) {
+ o->setName(name);
+ setModified(true);
+ break;
+ } else {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ }
+ }
+ return;
+}
+
+void UMLDoc::renameChildUMLObject(UMLObject *o) {
+ bool ok = false;
+ UMLClassifier* p = dynamic_cast<UMLClassifier *>(o->parent());
+ if(!p) {
+ kDebug() << "Can't create object, no parent found" << endl;
+ return;
+ }
+
+ QString oldName= o->getName();
+ while(true) {
+ QString name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), oldName, &ok, (QWidget*)UMLApp::app());
+ if(!ok)
+ break;
+ if(name.length() == 0)
+ KMessageBox::error(0, i18n("That is an invalid name."), i18n("Invalid Name"));
+ else {
+ if (p->findChildObject(name) == NULL
+ || ((o->getBaseType() == Uml::ot_Operation) && KMessageBox::warningYesNo( kapp -> mainWidget() ,
+ i18n( "The name you entered was not unique.\nIs this what you wanted?" ),
+ i18n( "Name Not Unique"),i18n("Use Name"),i18n("Enter New Name")) == KMessageBox::Yes) ) {
+ o->setName(name);
+ setModified(true);
+ break;
+ } else {
+ KMessageBox::error(0, i18n("That name is already being used."), i18n("Not a Unique Name"));
+ }
+ }
+ }
+}
+
+void UMLDoc::changeCurrentView(Uml::IDType id) {
+ UMLApp* pApp = UMLApp::app();
+ UMLView* w = findView(id);
+ if (w) {
+ pApp->setCurrentView(w);
+ emit sigDiagramChanged(w->getType());
+ pApp->setDiagramMenuItemsState( true );
+ setModified(true);
+ }
+ emit sigCurrentViewChanged();
+}
+
+void UMLDoc::removeDiagram(Uml::IDType id) {
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+ UMLView* umlview = findView(id);
+ if(!umlview)
+ {
+ kError()<<"Request to remove diagram " << ID2STR(id) << ": Diagram not found!"<<endl;
+ return;
+ }
+ if (KMessageBox::warningContinueCancel(0, i18n("Are you sure you want to delete diagram %1?").arg(umlview->getName()), i18n("Delete Diagram"),KGuiItem( i18n("&Delete"), "editdelete")) == KMessageBox::Continue) {
+ removeView(umlview);
+ emit sigDiagramRemoved(id);
+ setModified(true);
+ /* if (infoWidget->isVisible()) {
+ emit sigDiagramChanged(dt_Undefined);
+ UMLApp::app()->enablePrint(false);
+ }
+ */ //FIXME sort out all the KActions for when there's no diagram
+ //also remove the buttons from the WorkToolBar, then get rid of infowidget
+ }
+}
+
+UMLFolder *UMLDoc::currentRoot() {
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView == NULL) {
+ if (m_pCurrentRoot)
+ return m_pCurrentRoot;
+ kError() << "UMLDoc::currentRoot: m_pCurrentRoot is NULL" << endl;
+ return NULL;
+ }
+ UMLFolder *f = currentView->getFolder();
+ while (f->getUMLPackage()) {
+ f = static_cast<UMLFolder*>(f->getUMLPackage());
+ }
+ return f;
+}
+
+void UMLDoc::setCurrentRoot(Uml::Model_Type rootType) {
+ m_pCurrentRoot = m_root[rootType];
+}
+
+void UMLDoc::removeUMLObject(UMLObject* umlobject) {
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+ Object_Type type = umlobject->getBaseType();
+
+ umlobject->setUMLStereotype(NULL); // triggers possible cleanup of UMLStereotype
+ if (dynamic_cast<UMLClassifierListItem*>(umlobject)) {
+ UMLClassifier* parent = dynamic_cast<UMLClassifier*>(umlobject->parent());
+ if (parent == NULL) {
+ kError() << "UMLDoc::removeUMLObject: parent of umlobject is NULL"
+ << endl;
+ return;
+ }
+ if (type == ot_Operation) {
+ parent->removeOperation(static_cast<UMLOperation*>(umlobject));
+ } else if (type == ot_EnumLiteral) {
+ UMLEnum *e = static_cast<UMLEnum*>(parent);
+ e->removeEnumLiteral(static_cast<UMLEnumLiteral*>(umlobject));
+ } else if (type == ot_EntityAttribute) {
+ UMLEntity *ent = static_cast<UMLEntity*>(parent);
+ ent->removeEntityAttribute(static_cast<UMLClassifierListItem*>(umlobject));
+ } else {
+ UMLClassifier* pClass = dynamic_cast<UMLClassifier*>(parent);
+ if (pClass == NULL) {
+ kError() << "UMLDoc::removeUMLObject: parent of umlobject has "
+ << "unexpected type " << parent->getBaseType() << endl;
+ return;
+ }
+ if (type == ot_Attribute) {
+ pClass->removeAttribute(static_cast<UMLAttribute*>(umlobject));
+ } else if (type == ot_Template) {
+ pClass->removeTemplate(static_cast<UMLTemplate*>(umlobject));
+ } else {
+ kError() << "UMLDoc::removeUMLObject: umlobject has "
+ << "unexpected type " << type << endl;
+ }
+ }
+ } else {
+ if (type == ot_Association) {
+ UMLAssociation *a = (UMLAssociation *)umlobject;
+ removeAssociation(a, false); // don't call setModified here, it's done below
+ } else {
+ UMLPackage* pkg = umlobject->getUMLPackage();
+ if (pkg) {
+ pkg->removeObject(umlobject);
+ } else {
+ kError() << "UMLDoc::removeUMLObject(" << umlobject->getName()
+ << "): parent package is not set !" << endl;
+ }
+ }
+ emit sigObjectRemoved(umlobject);
+ }
+ setModified(true);
+}
+
+void UMLDoc::signalUMLObjectCreated(UMLObject * o) {
+ emit sigObjectCreated(o);
+ /* This is the wrong place to do:
+ setModified(true);
+ Instead, that should be done by the callers when object creation and all
+ its side effects (e.g. new widget in view, new list view item, etc.) is
+ finalized.
+ */
+}
+
+void UMLDoc::setName(const QString& name) {
+ m_Name = name;
+}
+
+QString UMLDoc::getName() const {
+ return m_Name;
+}
+
+Uml::IDType UMLDoc::getModelID() const {
+ return m_modelID;
+}
+
+void UMLDoc::saveToXMI(QIODevice& file) {
+ QDomDocument doc;
+
+ QDomProcessingInstruction xmlHeading =
+ doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
+ doc.appendChild(xmlHeading);
+
+ QDomElement root = doc.createElement( "XMI" );
+ root.setAttribute( "xmi.version", "1.2" );
+ QDateTime now = QDateTime::currentDateTime();
+ root.setAttribute( "timestamp", now.toString(Qt::ISODate));
+ root.setAttribute( "verified", "false");
+ root.setAttribute( "xmlns:UML", "http://schema.omg.org/spec/UML/1.3");
+ doc.appendChild( root );
+
+ QDomElement header = doc.createElement( "XMI.header" );
+ QDomElement meta = doc.createElement( "XMI.metamodel" );
+ meta.setAttribute( "xmi.name", "UML" );
+ meta.setAttribute( "xmi.version", "1.3" );
+ meta.setAttribute( "href", "UML.xml" );
+ header.appendChild( meta );
+
+ /**
+ * bugs.kde.org/56184 comment by M. Alanen 2004-12-19:
+ * " XMI.model requires xmi.version. (or leave the whole XMI.model out,
+ * it's not required) "
+ QDomElement model = doc.createElement( "XMI.model" );
+ QFile* qfile = dynamic_cast<QFile*>(&file);
+ if (qfile) {
+ QString modelName = qfile->name();
+ modelName = modelName.section('/', -1 );
+ modelName = modelName.section('.', 0, 0);
+ model.setAttribute( "xmi.name", modelName );
+ model.setAttribute( "href", qfile->name() );
+ }
+ */
+
+ QDomElement documentation = doc.createElement( "XMI.documentation" );
+
+ // If we consider it useful we might add user and contact details
+ // QDomElement owner = doc.createElement( "XMI.owner" );
+ // owner.appendChild( doc.createTextNode( "Jens Kruger" ) ); // Add a User
+ // documentation.appendChild( owner );
+
+ // QDomElement contact = doc.createElement( "XMI.contact" );
+ // contact.appendChild( doc.createTextNode( "je.krueger@web.de" ) ); // add a contact
+ // documentation.appendChild( contact );
+
+ QDomElement exporter = doc.createElement( "XMI.exporter" );
+ exporter.appendChild( doc.createTextNode( "umbrello uml modeller http://uml.sf.net" ) );
+ documentation.appendChild( exporter );
+
+ QDomElement exporterVersion = doc.createElement( "XMI.exporterVersion" );
+ exporterVersion.appendChild( doc.createTextNode( XMI_FILE_VERSION ) );
+ documentation.appendChild( exporterVersion );
+
+ // all files are now saved with correct Unicode encoding, we add this
+ // information to the header, so that the file will be loaded correctly
+ QDomElement exporterEncoding = doc.createElement( "XMI.exporterEncoding" );
+ exporterEncoding.appendChild( doc.createTextNode( "UnicodeUTF8" ) );
+ documentation.appendChild( exporterEncoding );
+
+ header.appendChild( documentation );
+
+ /**
+ * See comment on <XMI.model> above
+ header.appendChild( model );
+ */
+ header.appendChild( meta );
+ root.appendChild( header );
+
+ QDomElement content = doc.createElement( "XMI.content" );
+
+ QDomElement contentNS = doc.createElement( "UML:Namespace.contents" );
+
+ QDomElement objectsElement = doc.createElement( "UML:Model" );
+ objectsElement.setAttribute( "xmi.id", ID2STR(m_modelID) );
+ objectsElement.setAttribute( "name", m_Name );
+ objectsElement.setAttribute( "isSpecification", "false" );
+ objectsElement.setAttribute( "isAbstract", "false" );
+ objectsElement.setAttribute( "isRoot", "false" );
+ objectsElement.setAttribute( "isLeaf", "false" );
+
+ QDomElement ownedNS = doc.createElement( "UML:Namespace.ownedElement" );
+
+ // Save stereotypes and toplevel datatypes first so that upon loading
+ // they are known first.
+ // There is a bug causing duplication of the same stereotype in m_stereoList.
+ // As a workaround, we use a string list to memorize which stereotype has been saved.
+ QStringList stereoNames;
+ QValueList<Uml::IDType> stereoIDs;
+ for (UMLStereotype *s = m_stereoList.first(); s; s = m_stereoList.next() ) {
+ QString stName = s->getName();
+ Uml::IDType stID = s->getID();
+ if (!stereoNames.contains(stName) && !stereoIDs.contains(stID)) {
+ s->saveToXMI(doc, ownedNS);
+ stereoNames.append(stName);
+ stereoIDs.append(stID);
+ } else {
+ kDebug() << "UMLDoc::saveToXMI: encountered duplicated stereotype "
+ << stName << " (id " << ID2STR(stID) << "), see bug 144924" << endl;
+ }
+ }
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ m_root[i]->saveToXMI(doc, ownedNS);
+ }
+
+ objectsElement.appendChild( ownedNS );
+
+ content.appendChild( objectsElement );
+
+ root.appendChild( content );
+
+ // Save the XMI extensions: docsettings, diagrams, listview, and codegeneration.
+ QDomElement extensions = doc.createElement( "XMI.extensions" );
+ extensions.setAttribute( "xmi.extender", "umbrello" );
+
+ QDomElement docElement = doc.createElement( "docsettings" );
+ Uml::IDType viewID = Uml::id_None;
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView)
+ viewID = currentView->getID();
+ docElement.setAttribute( "viewid", ID2STR(viewID) );
+ docElement.setAttribute( "documentation", m_Doc );
+ docElement.setAttribute( "uniqueid", ID2STR(UniqueID::get()) );
+ extensions.appendChild( docElement );
+
+ // save listview
+ UMLApp::app()->getListView()->saveToXMI(doc, extensions);
+
+ // save code generator
+ CodeGenerator *codegen = UMLApp::app()->getGenerator();
+ if (codegen) {
+ QDomElement codeGenElement = doc.createElement( "codegeneration" );
+ codegen->saveToXMI( doc, codeGenElement );
+ extensions.appendChild( codeGenElement );
+ }
+
+ root.appendChild( extensions );
+
+ QTextStream stream( &file );
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ stream << doc.toString();
+}
+
+short UMLDoc::getEncoding(QIODevice & file)
+{
+ QTextStream stream( &file );
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ QString data = stream.read();
+ QString error;
+ int line;
+ QDomDocument doc;
+ if( !doc.setContent( data, false, &error, &line ) )
+ {
+ kWarning()<<"Can't set content: "<<error<<" Line: "<<line<<endl;
+ return ENC_UNKNOWN;
+ }
+
+ // we start at the beginning and go to the point in the header where we can
+ // find out if the file was saved using Unicode
+ QDomNode node = doc.firstChild();
+ while (node.isComment() || node.isProcessingInstruction())
+ {
+ node = node.nextSibling();
+ }
+ QDomElement root = node.toElement();
+ if( root.isNull() )
+ {
+ return ENC_UNKNOWN;
+ }
+ // make sure it is an XMI file
+ if( root.tagName() != "XMI" )
+ {
+ return ENC_UNKNOWN;
+ }
+ node = node.firstChild();
+
+ if ( node.isNull() )
+ return ENC_UNKNOWN;
+
+ QDomElement element = node.toElement();
+ // check header
+ if( element.isNull() || element.tagName() != "XMI.header" )
+ return ENC_UNKNOWN;
+
+ QDomNode headerNode = node.firstChild();
+ while ( !headerNode.isNull() )
+ {
+ QDomElement headerElement = headerNode.toElement();
+ // the information if Unicode was used is now stored in the
+ // XMI.documentation section of the header
+ if (headerElement.isNull() ||
+ headerElement.tagName() != "XMI.documentation") {
+ headerNode = headerNode.nextSibling();
+ continue;
+ }
+ QDomNode docuNode = headerNode.firstChild();
+ while ( !docuNode.isNull() )
+ {
+ QDomElement docuElement = docuNode.toElement();
+ // a tag XMI.exporterEncoding was added since version 1.2 to
+ // mark a file as saved with Unicode
+ if (! docuElement.isNull() &&
+ docuElement.tagName() == "XMI.exporterEncoding")
+ {
+ // at the moment this if isn't really necessary, but maybe
+ // later we will have other encoding standards
+ if (docuElement.text() == QString("UnicodeUTF8"))
+ {
+ return ENC_UNICODE; // stop here
+ }
+ }
+ docuNode = docuNode.nextSibling();
+ }
+ break;
+ }
+ return ENC_OLD_ENC;
+}
+
+bool UMLDoc::loadFromXMI( QIODevice & file, short encode )
+{
+ // old Umbrello versions (version < 1.2) didn't save the XMI in Unicode
+ // this wasn't correct, because non Latin1 chars where lost
+ // to ensure backward compatibility we have to ensure to load the old files
+ // with non Unicode encoding
+ if (encode == ENC_UNKNOWN)
+ {
+ if ((encode = getEncoding(file)) == ENC_UNKNOWN)
+ return false;
+ file.reset();
+ }
+ QTextStream stream( &file );
+ if (encode == ENC_UNICODE)
+ {
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ }
+
+ QString data = stream.read();
+ kapp->processEvents(); // give UI events a chance
+ QString error;
+ int line;
+ QDomDocument doc;
+ if( !doc.setContent( data, false, &error, &line ) ) {
+ kWarning()<<"Can't set content:"<<error<<" Line:"<<line<<endl;
+ return false;
+ }
+ kapp->processEvents(); // give UI events a chance
+ QDomNode node = doc.firstChild();
+ //Before Umbrello 1.1-rc1 we didn't add a <?xml heading
+ //so we allow the option of this being missing
+ while (node.isComment() || node.isProcessingInstruction()) {
+ node = node.nextSibling();
+ }
+
+ QDomElement root = node.toElement();
+ if( root.isNull() ) {
+ return false;
+ }
+ // make sure it is an XMI file
+ if( root.tagName() != "XMI" ) {
+ return false;
+ }
+
+ m_nViewID = Uml::id_None;
+ for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement element = node.toElement();
+ if (element.isNull()) {
+ kDebug() << "loadFromXMI: skip empty elem" << endl;
+ continue;
+ }
+ bool recognized = false;
+ QString outerTag = element.tagName();
+ //check header
+ if (outerTag == "XMI.header") {
+ QDomNode headerNode = node.firstChild();
+ if ( !validateXMIHeader(headerNode) ) {
+ return false;
+ }
+ recognized = true;
+ } else if (outerTag == "XMI.extensions") {
+ QDomNode extensionsNode = node.firstChild();
+ while (! extensionsNode.isNull()) {
+ loadExtensionsFromXMI(extensionsNode);
+ extensionsNode = extensionsNode.nextSibling();
+ }
+ recognized = true;
+ }
+ if (outerTag != "XMI.content" ) {
+ if (!recognized)
+ kDebug() << "UMLDoc::loadFromXMI: skipping <"
+ << outerTag << ">" << endl;
+ continue;
+ }
+ bool seen_UMLObjects = false;
+ //process content
+ for (QDomNode child = node.firstChild(); !child.isNull();
+ child = child.nextSibling()) {
+ if (child.isComment())
+ continue;
+ element = child.toElement();
+ QString tag = element.tagName();
+ if (tag == "umlobjects" // for bkwd compat.
+ || tagEq(tag, "Subsystem")
+ || tagEq(tag, "Model") ) {
+ if( !loadUMLObjectsFromXMI( element ) ) {
+ kWarning() << "failed load on objects" << endl;
+ return false;
+ }
+ m_Name = element.attribute( "name", i18n("UML Model") );
+ UMLListView *lv = UMLApp::app()->getListView();
+ lv->setColumnText(0, m_Name);
+ seen_UMLObjects = true;
+ } else if (tagEq(tag, "Package") ||
+ tagEq(tag, "Class") ||
+ tagEq(tag, "Interface")) {
+ // These tests are only for foreign XMI files that
+ // are missing the <Model> tag (e.g. NSUML)
+ QDomElement parentElem = node.toElement();
+ if( !loadUMLObjectsFromXMI( parentElem ) ) {
+ kWarning() << "failed load on model objects" << endl;
+ return false;
+ }
+ seen_UMLObjects = true;
+ } else if (tagEq(tag, "TaggedValue")) {
+ // This tag is produced here, i.e. outside of <UML:Model>,
+ // by the Unisys.JCR.1 Rose-to-XMI tool.
+ if (! seen_UMLObjects) {
+ kDebug() << "skipping TaggedValue because not seen_UMLObjects"
+ << endl;
+ continue;
+ }
+ tag = element.attribute("tag", "");
+ if (tag != "documentation") {
+ continue;
+ }
+ QString modelElement = element.attribute("modelElement", "");
+ if (modelElement.isEmpty()) {
+ kDebug() << "skipping TaggedValue(documentation) because "
+ << "modelElement.isEmpty()" << endl;
+ continue;
+ }
+ UMLObject *o = findObjectById(STR2ID(modelElement));
+ if (o == NULL) {
+ kDebug() << "TaggedValue(documentation): cannot find object"
+ << " for modelElement " << modelElement << endl;
+ continue;
+ }
+ QString value = element.attribute("value", "");
+ if (! value.isEmpty())
+ o->setDoc(value);
+ } else {
+ // for backward compatibility
+ loadExtensionsFromXMI(child);
+ }
+ }
+ }
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLDoc::m_objectList.count() is " << m_objectList.count() << endl;
+#endif
+ resolveTypes();
+ // set a default code generator if no <XMI.extensions><codegeneration> tag seen
+ if (UMLApp::app()->getGenerator() == NULL)
+ UMLApp::app()->setGenerator(UMLApp::app()->getDefaultLanguage());
+ emit sigWriteToStatusBar( i18n("Setting up the document...") );
+ kapp->processEvents(); // give UI events a chance
+ activateAllViews();
+
+ UMLView *viewToBeSet = NULL;
+ if (m_nViewID != Uml::id_None)
+ viewToBeSet = findView( m_nViewID );
+ if (viewToBeSet) {
+ changeCurrentView( m_nViewID );
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (optionState.generalState.tabdiagrams) {
+ UMLApp::app()->tabWidget()->showPage(viewToBeSet);
+ }
+ } else {
+ createDiagram(m_root[mt_Logical], Uml::dt_Class, false);
+ m_pCurrentRoot = m_root[mt_Logical];
+ }
+ emit sigResetStatusbarProgress();
+ return true;
+}
+
+void UMLDoc::resolveTypes() {
+ // Resolve the types.
+ // This is done in a separate pass because of possible forward references.
+ if (m_bTypesAreResolved)
+ return;
+ m_bTypesAreResolved = true;
+ writeToStatusBar( i18n("Resolving object references...") );
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ UMLFolder *obj = m_root[i];
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLDoc: invoking resolveRef() for " << obj->getName()
+ << " (id=" << ID2STR(obj->getID()) << ")" << endl;
+#endif
+ obj->resolveRef();
+ }
+ kapp->processEvents(); // give UI events a chance
+}
+
+bool UMLDoc::validateXMIHeader(QDomNode& headerNode) {
+ QDomElement headerElement = headerNode.toElement();
+ while ( !headerNode.isNull() ) {
+ /* //Seems older Umbrello files used a different metamodel, so don't validate it for now
+ if( !headerElement.isNull() && headerElement.tagName() == "XMI.metamodel" ) {
+ String metamodel = headerElement.attribute("xmi.name", "");
+ if (metamodel != "UML") {
+ return false;
+ }
+ }
+ */
+ headerNode = headerNode.nextSibling();
+ headerElement = headerNode.toElement();
+ }
+ return true;
+}
+
+bool UMLDoc::loadUMLObjectsFromXMI(QDomElement& element) {
+ /* FIXME need a way to make status bar actually reflect
+ how much of the file has been loaded rather than just
+ counting to 10 (an arbitrary number)
+ emit sigResetStatusbarProgress();
+ emit sigSetStatusbarProgress( 0 );
+ emit sigSetStatusbarProgressSteps( 10 );
+ m_count = 0;
+ */
+ emit sigWriteToStatusBar( i18n("Loading UML elements...") );
+
+ for (QDomNode node = element.firstChild(); !node.isNull();
+ node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString type = tempElement.tagName();
+ if (tagEq(type, "Model")) {
+ bool foundUmbrelloRootFolder = false;
+ QString name = tempElement.attribute("name");
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ if (name == m_root[i]->getName()) {
+ m_pCurrentRoot = m_root[i];
+ m_root[i]->loadFromXMI(tempElement);
+ foundUmbrelloRootFolder = true;
+ break;
+ }
+ }
+ if (foundUmbrelloRootFolder)
+ continue;
+ }
+ // From here on, it's support for stereotypes, pre 1.5.5 versions, and foreign files
+ if (tagEq(type, "Namespace.ownedElement") ||
+ tagEq(type, "Namespace.contents") ||
+ tagEq(type, "Model")) {
+ //CHECK: Umbrello currently assumes that nested elements
+ // are ownedElements anyway.
+ // Therefore the <UML:Namespace.ownedElement> tag is of no
+ // significance.
+ if( !loadUMLObjectsFromXMI( tempElement ) ) {
+ kWarning() << "failed load on " << type << endl;
+ return false;
+ }
+ continue;
+ }
+ if (Model_Utils::isCommonXMIAttribute(type))
+ continue;
+ if (! tempElement.hasAttribute("xmi.id")) {
+ QString idref = tempElement.attribute("xmi.idref", "");
+ if (! idref.isEmpty()) {
+ kDebug() << "resolution of xmi.idref " << idref
+ << " is not yet implemented" << endl;
+ } else {
+ kError() << "Cannot load " << type
+ << " because xmi.id is missing" << endl;
+ }
+ continue;
+ }
+ QString stID = tempElement.attribute("stereotype", "");
+ UMLObject *pObject = Object_Factory::makeObjectFromXMI(type, stID);
+ if( !pObject ) {
+ kWarning() << "Unknown type of umlobject to create: " << type << endl;
+ // We want a best effort, therefore this is handled as a
+ // soft error.
+ continue;
+ }
+ Uml::Object_Type ot = pObject->getBaseType();
+ // Set the parent root folder.
+ UMLPackage *pkg = NULL;
+ if (ot == Uml::ot_Datatype) {
+ pkg = m_datatypeRoot;
+ } else {
+ Uml::Model_Type guess = Model_Utils::guessContainer(pObject);
+ if (guess != Uml::N_MODELTYPES)
+ pkg = m_root[guess];
+ }
+ pObject->setUMLPackage(pkg);
+
+ bool status = pObject -> loadFromXMI( tempElement );
+ if ( !status ) {
+ //delete pObject;
+ // Unfortunately we cannot do this because the pObject
+ // may be still referenced by other model objects.
+ kError() << "loadFromXMI failed for " << pObject->getName() << " xmi.id="
+ << ID2STR(pObject->getID()) << endl;
+ continue;
+ }
+ pkg = pObject->getUMLPackage();
+ if (ot == ot_Stereotype) {
+ UMLStereotype *s = static_cast<UMLStereotype*>(pObject);
+ UMLStereotype *exist = findStereotype(pObject->getName());
+ if (exist) {
+ if (exist->getID() == pObject->getID()) {
+ delete pObject;
+ } else {
+ kDebug() << "Stereotype " << pObject->getName()
+ << "(id=" << ID2STR(pObject->getID())
+ << ") already exists with id="
+ << ID2STR(exist->getID()) << endl;
+ addStereotype(s);
+ }
+ } else {
+ addStereotype(s);
+ }
+ continue;
+ }
+ if (pkg == NULL)
+ kError() << "UMLDoc::loadUMLObjectsFromXMI: pkg is NULL for "
+ << pObject->getName() << " xmi.id="
+ << ID2STR(pObject->getID()) << endl;
+ else
+ pkg->addObject(pObject);
+
+ /* FIXME see comment at loadUMLObjectsFromXMI
+ emit sigSetStatusbarProgress( ++m_count );
+ */
+ }
+ return true;
+}
+
+void UMLDoc::setMainViewID(Uml::IDType viewID) {
+ m_nViewID = viewID;
+}
+
+void UMLDoc::loadExtensionsFromXMI(QDomNode& node) {
+ QDomElement element = node.toElement();
+ QString tag = element.tagName();
+
+ if (tag == "docsettings") {
+ QString viewID = element.attribute( "viewid", "-1" );
+ m_Doc = element.attribute( "documentation", "" );
+ QString uniqueid = element.attribute( "uniqueid", "0" );
+
+ m_nViewID = STR2ID(viewID);
+ UniqueID::set(STR2ID(uniqueid));
+ UMLApp::app()->getDocWindow() -> newDocumentation();
+
+ } else if (tag == "diagrams" || tag == "UISModelElement") {
+ // For backward compatibility only:
+ // Since version 1.5.5 diagrams are saved as part of the UMLFolder.
+ QDomNode diagramNode = node.firstChild();
+ if (tag == "UISModelElement") { // Unisys.IntegratePlus.2
+ element = diagramNode.toElement();
+ tag = element.tagName();
+ if (tag != "uisOwnedDiagram") {
+ kError() << "unknown child node " << tag << endl;
+ return;
+ }
+ diagramNode = diagramNode.firstChild();
+ }
+ if( !loadDiagramsFromXMI( diagramNode ) ) {
+ kWarning() << "failed load on diagrams" << endl;
+ }
+
+ } else if (tag == "listview") {
+ //FIXME: Need to resolveTypes() before loading listview,
+ // else listview items are duplicated.
+ resolveTypes();
+ if( !UMLApp::app()->getListView() -> loadFromXMI( element ) ) {
+ kWarning() << "failed load on listview" << endl;
+ }
+
+ } else if (tag == "codegeneration") {
+ QDomNode cgnode = node.firstChild();
+ QDomElement cgelement = cgnode.toElement();
+ while( !cgelement.isNull() ) {
+ QString nodeName = cgelement.tagName();
+ QString lang = cgelement.attribute("language","UNKNOWN");
+ Uml::Programming_Language pl = Model_Utils::stringToProgLang(lang);
+ CodeGenerator *g = UMLApp::app()->setGenerator(pl);
+ g->loadFromXMI(cgelement);
+ cgnode = cgnode.nextSibling();
+ cgelement = cgnode.toElement();
+ }
+ if (UMLApp::app()->getGenerator() == NULL)
+ UMLApp::app()->setGenerator(UMLApp::app()->getDefaultLanguage());
+ }
+}
+
+// For backward compatibility only:
+// Since version 1.5.5 diagrams are saved as part of the UMLFolder.
+bool UMLDoc::loadDiagramsFromXMI( QDomNode & node ) {
+ emit sigWriteToStatusBar( i18n("Loading diagrams...") );
+ emit sigResetStatusbarProgress();
+ emit sigSetStatusbarProgress( 0 );
+ emit sigSetStatusbarProgressSteps( 10 ); //FIX ME
+ QDomElement element = node.toElement();
+ if( element.isNull() )
+ return true;//return ok as it means there is no umlobjects
+ const Settings::OptionState state = Settings::getOptionState();
+ UMLView * pView = 0;
+ int count = 0;
+ while( !element.isNull() ) {
+ QString tag = element.tagName();
+ if (tag == "diagram" || tag == "UISDiagram") {
+ pView = new UMLView(NULL);
+ // IMPORTANT: Set OptionState of new UMLView _BEFORE_
+ // reading the corresponding diagram:
+ // + allow using per-diagram color and line-width settings
+ // + avoid crashes due to uninitialized values for lineWidth
+ pView -> setOptionState( state );
+ bool success = false;
+ if (tag == "UISDiagram") {
+ success = pView->loadUISDiagram(element);
+ } else {
+ success = pView->loadFromXMI(element);
+ }
+ if (!success) {
+ kWarning() << "failed load on viewdata loadfromXMI" << endl;
+ delete pView;
+ return false;
+ }
+ // Put diagram in default predefined folder.
+ // @todo pass in the parent folder - it might be a user defined one.
+ Uml::Model_Type mt = Model_Utils::convert_DT_MT(pView->getType());
+ pView->setFolder(m_root[mt]);
+ pView -> hide();
+ addView( pView );
+ emit sigSetStatusbarProgress( ++count );
+ kapp->processEvents(); // give UI events a chance
+ }
+ node = node.nextSibling();
+ element = node.toElement();
+ }
+ return true;
+}
+
+void UMLDoc::removeAllViews() {
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_root[i]->removeAllViews();
+ UMLApp::app()->setCurrentView(NULL);
+ emit sigDiagramChanged(dt_Undefined);
+ UMLApp::app()->setDiagramMenuItemsState(false);
+}
+
+UMLClassifierList UMLDoc::getConcepts(bool includeNested /* =true */) {
+ UMLClassifierList conceptList;
+ m_root[mt_Logical]->appendClassifiers(conceptList, includeNested);
+ return conceptList;
+}
+
+UMLClassifierList UMLDoc::getClasses(bool includeNested /* =true */) {
+ UMLClassifierList conceptList;
+ m_root[mt_Logical]->appendClasses(conceptList, includeNested);
+ return conceptList;
+}
+
+UMLClassifierList UMLDoc::getClassesAndInterfaces(bool includeNested /* =true */) {
+ UMLClassifierList conceptList;
+ m_root[mt_Logical]->appendClassesAndInterfaces(conceptList, includeNested);
+ return conceptList;
+}
+
+UMLClassifierList UMLDoc::getInterfaces(bool includeNested /* =true */) {
+ UMLClassifierList interfaceList;
+ m_root[mt_Logical]->appendInterfaces(interfaceList, includeNested);
+ return interfaceList;
+}
+
+UMLClassifierList UMLDoc::getDatatypes() {
+ UMLObjectList objects = m_datatypeRoot->containedObjects();
+ UMLClassifierList datatypeList;
+ UMLObject *obj;
+ for (UMLObjectListIt oit(objects); (obj = oit.current()) != NULL; ++oit) {
+ if (obj->getBaseType() == ot_Datatype) {
+ datatypeList.append(static_cast<UMLClassifier*>(obj));
+ }
+ }
+ return datatypeList;
+}
+
+UMLAssociationList UMLDoc::getAssociations() {
+ UMLAssociationList associationList;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ UMLAssociationList assocs = m_root[i]->getAssociations();
+ UMLAssociation *a;
+ for (UMLAssociationListIt ait(assocs); (a = ait.current()) != NULL; ++ait)
+ associationList.append(a);
+ }
+ return associationList;
+}
+
+void UMLDoc::print(KPrinter * pPrinter) {
+ UMLView * printView = 0;
+ int count = QString(pPrinter -> option("kde-uml-count")).toInt();
+ QPainter painter(pPrinter);
+ for(int i = 0;i < count;i++) {
+ if(i>0)
+ pPrinter -> newPage();
+ QString diagram = i18n("kde-uml-Diagram") + QString("%1").arg(i);
+ QString sID = pPrinter -> option(diagram);
+ Uml::IDType id = STR2ID(sID);
+ printView = findView(id);
+
+ if(printView)
+ printView ->print(pPrinter, painter);
+ printView = 0;
+ }
+ painter.end();
+}
+
+UMLViewList UMLDoc::getViewIterator() {
+ UMLViewList accumulator;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_root[i]->appendViews(accumulator, true);
+ return accumulator;
+}
+
+void UMLDoc::setModified(bool modified /*=true*/, bool addToUndo /*=true*/) {
+ if(!m_bLoading) {
+ m_modified = modified;
+ UMLApp::app()->setModified(modified);
+
+ if (modified && addToUndo) {
+ addToUndoStack();
+ clearRedoStack();
+ }
+ }
+}
+
+bool UMLDoc::assignNewIDs(UMLObject* Obj) {
+ if(!Obj || !m_pChangeLog) {
+ kDebug() << "no Obj || Changelog" << endl;
+ return false;
+ }
+ Uml::IDType result = assignNewID(Obj->getID());
+ Obj->setID(result);
+
+ //If it is a CONCEPT then change the ids of all its operations and attributes
+ if(Obj->getBaseType() == ot_Class ) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(Obj);
+ UMLClassifierListItemList attributes = c->getFilteredList(ot_Attribute);
+ for(UMLObject* listItem = attributes.first(); listItem; listItem = attributes.next()) {
+ result = assignNewID(listItem->getID());
+ listItem->setID(result);
+ }
+
+ UMLClassifierListItemList templates = c->getFilteredList(ot_Template);
+ for(UMLObject* listItem = templates.first(); listItem; listItem = templates.next()) {
+ result = assignNewID(listItem->getID());
+ listItem->setID(result);
+ }
+ }
+
+ if(Obj->getBaseType() == ot_Interface || Obj->getBaseType() == ot_Class ) {
+ UMLOperationList operations(((UMLClassifier*)Obj)->getOpList());
+ for(UMLObject* listItem = operations.first(); listItem; listItem = operations.next()) {
+ result = assignNewID(listItem->getID());
+ listItem->setID(result);
+ }
+ }
+
+ setModified(true);
+
+ return true;
+}
+
+UMLFolder *UMLDoc::getRootFolder(Uml::Model_Type mt) {
+ if (mt < Uml::mt_Logical || mt >= Uml::N_MODELTYPES) {
+ kError() << "UMLDoc::getRootFolder: illegal input value " << mt << endl;
+ return NULL;
+ }
+ return m_root[mt];
+}
+
+Uml::Model_Type UMLDoc::rootFolderType(UMLObject *obj) {
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ const Uml::Model_Type m = (Uml::Model_Type)i;
+ if (obj == m_root[m])
+ return m;
+ }
+ return Uml::N_MODELTYPES;
+}
+
+/** Read property of IDChangeLog* m_pChangeLog. */
+IDChangeLog* UMLDoc::getChangeLog() {
+ return m_pChangeLog;
+}
+
+/** Opens a Paste session,
+Deletes the Old ChangeLog and Creates an empty one */
+
+void UMLDoc::beginPaste() {
+ if(m_pChangeLog) {
+ delete m_pChangeLog;
+ m_pChangeLog = 0;
+ }
+ m_pChangeLog = new IDChangeLog;
+}
+
+/** Closes a Paste session,
+Deletes the ChangeLog */
+void UMLDoc::endPaste() {
+ if(m_pChangeLog) {
+ delete m_pChangeLog;
+ m_pChangeLog = 0;
+ }
+}
+
+/** Assigns a New ID to an Object, and also logs the assignment to its internal
+ChangeLog */
+Uml::IDType UMLDoc::assignNewID(Uml::IDType OldID) {
+ Uml::IDType result = UniqueID::gen();
+ if (m_pChangeLog) {
+ m_pChangeLog->addIDChange(OldID, result);
+ }
+ return result;
+}
+
+/** Adds an already created UMLView to the document, it gets assigned a new ID.
+ If its name is already in use then the function appends a number to it to
+ differentiate it from the others; this number is incremental so if
+ number 1 is in use then it tries 2 and then 3 and so on */
+bool UMLDoc::addUMLView(UMLView * pView ) {
+ if(!pView || !m_pChangeLog)
+ return false;
+
+ int i = 0;
+ QString viewName = (QString)pView->getName();
+ QString name = viewName;
+ while( findView(pView->getType(), name) != NULL) {
+ name = viewName + '_' + QString::number(++i);
+ }
+ if(i) //If name was modified
+ pView->setName(name);
+ Uml::IDType result = assignNewID(pView->getID());
+ pView->setID(result);
+
+ pView->activateAfterLoad( true );
+ pView->endPartialWidgetPaste();
+ pView->setOptionState( Settings::getOptionState() );
+ addView(pView);
+ setModified(true);
+ return true;
+}
+
+void UMLDoc::activateAllViews() {
+ // store old setting - for restore of last setting
+ bool m_bLoading_old = m_bLoading;
+ m_bLoading = true; //this is to prevent document becoming modified when activating a view
+
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_root[i]->activateViews();
+ m_bLoading = m_bLoading_old;
+}
+
+void UMLDoc::settingsChanged(Settings::OptionState optionState) {
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_root[i]->setViewOptions(optionState);
+ initSaveTimer();
+}
+
+void UMLDoc::initSaveTimer() {
+ if( m_pAutoSaveTimer ) {
+ m_pAutoSaveTimer -> stop();
+ disconnect( m_pAutoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
+ delete m_pAutoSaveTimer;
+ m_pAutoSaveTimer = 0;
+ }
+ Settings::OptionState optionState = Settings::getOptionState();
+ if( optionState.generalState.autosave ) {
+ m_pAutoSaveTimer = new QTimer(this, "_AUTOSAVETIMER_" );
+ connect( m_pAutoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
+ m_pAutoSaveTimer->start( optionState.generalState.autosavetime * 60000, false );
+ }
+ return;
+}
+
+void UMLDoc::slotAutoSave() {
+ //Only save if modified.
+ if( !m_modified ) {
+ return;
+ }
+ KURL tempURL = m_doc_url;
+ if( tempURL.fileName() == i18n("Untitled") ) {
+ tempURL.setPath( QDir::homeDirPath() + i18n("/autosave%1").arg(".xmi") );
+ saveDocument( tempURL );
+ m_doc_url.setFileName( i18n("Untitled") );
+ m_modified = true;
+ UMLApp::app()->setModified( m_modified );
+ } else {
+ // 2004-05-17 Achim Spangler
+ KURL orgDocUrl = m_doc_url;
+ QString orgFileName = m_doc_url.fileName();
+ // don't overwrite manually saved file with autosave content
+ QString fileName = tempURL.fileName();
+ Settings::OptionState optionState = Settings::getOptionState();
+ fileName.replace( ".xmi", optionState.generalState.autosavesuffix );
+ tempURL.setFileName( fileName );
+ // End Achim Spangler
+
+ saveDocument( tempURL );
+ // 2004-05-17 Achim Spangler
+ // re-activate m_modified if autosave is writing to other file
+ // than the main project file -> autosave-suffix != ".xmi"
+ if ( ".xmi" != optionState.generalState.autosavesuffix ) {
+ m_modified = true;
+ UMLApp::app()->setModified( m_modified );
+ }
+ // restore original file name -
+ // UMLDoc::saveDocument() sets doc_url to filename which is given as autosave-filename
+ setURL( orgDocUrl );
+ UMLApp * pApp = UMLApp::app();
+ pApp->setCaption(orgFileName, isModified() );
+ // End Achim Spangler
+ }
+}
+
+void UMLDoc::signalDiagramRenamed(UMLView* pView ) {
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (optionState.generalState.tabdiagrams)
+ UMLApp::app()->tabWidget()->setTabLabel( pView, pView->getName() );
+ emit sigDiagramRenamed( pView -> getID() );
+}
+
+void UMLDoc::addToUndoStack() {
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (!m_bLoading && optionState.generalState.undo) {
+ QBuffer* buffer = new QBuffer();
+ buffer->open(IO_WriteOnly);
+ QDataStream* undoData = new QDataStream();
+ undoData->setDevice(buffer);
+ saveToXMI(*buffer);
+ buffer->close();
+ undoStack.prepend(undoData);
+
+ if (undoStack.count() > 1) {
+ UMLApp::app()->enableUndo(true);
+ }
+ }
+}
+
+void UMLDoc::clearUndoStack() {
+ undoStack.setAutoDelete(true);
+ undoStack.clear();
+ UMLApp::app()->enableRedo(false);
+ undoStack.setAutoDelete(false);
+ clearRedoStack();
+}
+
+void UMLDoc::clearRedoStack() {
+ redoStack.setAutoDelete(true);
+ redoStack.clear();
+ UMLApp::app()->enableRedo(false);
+ redoStack.setAutoDelete(false);
+}
+
+void UMLDoc::loadUndoData() {
+ if (undoStack.count() < 1) {
+ kWarning() << "no data in undostack" << endl;
+ return;
+ }
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView == NULL) {
+ kWarning() << "UMLDoc::loadUndoData: currentView is NULL" << endl;
+ undoStack.setAutoDelete(true);
+ undoStack.clear();
+ undoStack.setAutoDelete(false);
+ UMLApp::app()->enableUndo(false);
+ return;
+ }
+ Uml::IDType currentViewID = currentView->getID();
+ // store old setting - for restore of last setting
+ bool m_bLoading_old = m_bLoading;
+ m_bLoading = true;
+ closeDocument();
+ redoStack.prepend( undoStack.take(0) );
+ QDataStream* undoData = undoStack.getFirst();
+ QBuffer* buffer = static_cast<QBuffer*>( undoData->device() );
+ buffer->open(IO_ReadOnly);
+ loadFromXMI(*buffer);
+ buffer->close();
+
+ setModified(true, false);
+ m_bLoading = m_bLoading_old;
+
+ undoStack.setAutoDelete(true);
+ if (undoStack.count() <= 1) {
+ UMLApp::app()->enableUndo(false);
+ }
+ if (redoStack.count() >= 1) {
+ UMLApp::app()->enableRedo(true);
+ }
+ while (undoStack.count() > undoMax) {
+ undoStack.removeLast();
+ }
+ undoStack.setAutoDelete(false);
+
+ currentView = UMLApp::app()->getCurrentView();
+ if (currentView) {
+ if (currentView->getID() != currentViewID)
+ changeCurrentView( currentView->getID() );
+ currentView->resizeCanvasToItems();
+ }
+}
+
+void UMLDoc::loadRedoData() {
+ if (redoStack.count() >= 1) {
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ Uml::IDType currentViewID = currentView->getID();
+ // store old setting - for restore of last setting
+ bool m_bLoading_old = m_bLoading;
+ m_bLoading = true;
+ closeDocument();
+ undoStack.prepend( redoStack.getFirst() );
+ QDataStream* redoData = redoStack.getFirst();
+ redoStack.removeFirst();
+ QBuffer* buffer = static_cast<QBuffer*>( redoData->device() );
+ buffer->open(IO_ReadOnly);
+ loadFromXMI(*buffer);
+ buffer->close();
+
+ setModified(true, false);
+ currentView = UMLApp::app()->getCurrentView();
+ currentView->resizeCanvasToItems();
+ m_bLoading = m_bLoading_old;
+
+ redoStack.setAutoDelete(true);
+ if (redoStack.count() < 1) {
+ UMLApp::app()->enableRedo(false);
+ }
+ if (undoStack.count() > 1) {
+ UMLApp::app()->enableUndo(true);
+ }
+ if (currentView->getID() != currentViewID) {
+ changeCurrentView(currentViewID);
+ }
+ redoStack.setAutoDelete(false);
+ } else {
+ kWarning() << "no data in redostack" << endl;
+ }
+}
+
+void UMLDoc::addDefaultDatatypes() {
+ CodeGenerator *cg = UMLApp::app()->getGenerator();
+ if (cg == NULL) {
+ kDebug() << "UMLDoc::addDefaultDatatypes: CodeGenerator is still NULL"
+ << endl;
+ return;
+ }
+ QStringList entries = cg->defaultDatatypes();
+ QStringList::Iterator end(entries.end());
+ for (QStringList::Iterator it = entries.begin(); it != end; ++it)
+ createDatatype(*it);
+}
+
+void UMLDoc::createDatatype(const QString &name) {
+ UMLObjectList datatypes = m_datatypeRoot->containedObjects();
+ UMLObject* umlobject = Model_Utils::findUMLObject(datatypes, name,
+ ot_Datatype, m_datatypeRoot);
+ if (!umlobject) {
+ Object_Factory::createUMLObject(ot_Datatype, name, m_datatypeRoot);
+ }
+ UMLApp::app()->getListView()->closeDatatypesFolder();
+}
+
+void UMLDoc::slotDiagramPopupMenu(QWidget* umlview, const QPoint& point) {
+ UMLView* view = (UMLView*) umlview;
+ if(m_pTabPopupMenu != 0) {
+ m_pTabPopupMenu->hide();
+ delete m_pTabPopupMenu;
+ m_pTabPopupMenu = 0;
+ }
+ Settings::OptionState optionState = Settings::getOptionState();
+ if (! optionState.generalState.tabdiagrams)
+ return;
+
+ Uml::ListView_Type type = lvt_Unknown;
+ switch( view->getType() ) {
+ case dt_Class:
+ type = lvt_Class_Diagram;
+ break;
+
+ case dt_UseCase:
+ type = lvt_UseCase_Diagram;
+ break;
+
+ case dt_Sequence:
+ type = lvt_Sequence_Diagram;
+ break;
+
+ case dt_Collaboration:
+ type = lvt_Collaboration_Diagram;
+ break;
+
+ case dt_State:
+ type = lvt_State_Diagram;
+ break;
+
+ case dt_Activity:
+ type = lvt_Activity_Diagram;
+ break;
+
+ case dt_Component:
+ type = lvt_Component_Diagram;
+ break;
+
+ case dt_Deployment:
+ type = lvt_Deployment_Diagram;
+ break;
+
+ case dt_EntityRelationship:
+ type = lvt_EntityRelationship_Diagram;
+ break;
+
+ default:
+ kWarning() << "unknown diagram type in slotDiagramPopupMenu()" << endl;
+ break;
+ }//end switch
+
+ m_pTabPopupMenu = new ListPopupMenu(UMLApp::app()->getMainViewWidget(), type);
+ m_pTabPopupMenu->popup(point);
+ connect(m_pTabPopupMenu, SIGNAL(activated(int)), view, SLOT(slotMenuSelection(int)));
+}
+
+void UMLDoc::addDefaultStereotypes() {
+ CodeGenerator *gen = UMLApp::app()->getGenerator();
+ if (gen)
+ gen->createDefaultStereotypes();
+}
+
+const UMLStereotypeList& UMLDoc::getStereotypes() {
+ return m_stereoList;
+}
+
+
+#include "umldoc.moc"
+
diff --git a/umbrello/umbrello/umldoc.h b/umbrello/umbrello/umldoc.h
new file mode 100644
index 00000000..2e936a3f
--- /dev/null
+++ b/umbrello/umbrello/umldoc.h
@@ -0,0 +1,920 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLDOC_H
+#define UMLDOC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// system includes
+#include <typeinfo>
+
+// qt includes
+#include <qdatastream.h>
+#include <qmap.h>
+#include <qdict.h>
+#include <qptrstack.h>
+
+// kde includes
+#include <kurl.h>
+#include <kdockwidget.h>
+#include <kpopupmenu.h>
+
+// app includes
+#include "umlnamespace.h"
+#include "optionstate.h"
+#include "umlobjectlist.h"
+#include "umlassociationlist.h"
+#include "umlclassifierlist.h"
+#include "umlviewlist.h"
+#include "umlstereotypelist.h"
+
+#define ENC_UNKNOWN 0
+#define ENC_UNICODE 1
+#define ENC_OLD_ENC 2
+
+
+// forward declarations
+class QDomNode;
+class QFile;
+class QSplitter;
+
+class KPrinter;
+
+class DocWindow;
+class IDChangeLog;
+class ObjectWidget;
+class UMLWidget;
+class UMLPackage;
+class UMLFolder;
+
+/**
+ * UMLDoc provides a document object for a document-view model.
+ *
+ * The UMLDoc class provides a document object that can be used
+ * in conjunction with the classes UMLApp and UMLView to create
+ * a document-view model for standard KDE applications based on
+ * KApplication and KMainWindow. Thereby, the document object
+ * is created by the UMLApp instance and contains the document
+ * structure with the according methods for manipulation of the
+ * document data by UMLView objects. Also, UMLDoc contains the
+ * methods for serialization of the document data from and to
+ * files.
+ *
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLDoc : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Constructor for the fileclass of the application
+ */
+ UMLDoc();
+
+ /**
+ * Destructor for the fileclass of the application
+ */
+ ~UMLDoc();
+
+ /**
+ * Initialize the UMLDoc.
+ * To be called after the constructor, before anything else.
+ */
+ void init();
+
+ /**
+ * Adds a view to the document which represents the document
+ * contents. Usually this is your main view.
+ *
+ * @param view Pointer to the UMLView to add.
+ */
+ void addView(UMLView *view);
+
+ /**
+ * Removes a view from the list of currently connected views.
+ *
+ * @param view Pointer to the UMLView to remove.
+ * @param enforceOneView switch to determine if we have a current view or not.
+ * most of the time, we DO want this, except when exiting the program.
+ */
+ void removeView(UMLView *view , bool enforceOneView = true );
+
+ /**
+ * Sets m_nViewID.
+ */
+ void setMainViewID(Uml::IDType viewID);
+
+ /**
+ * Sets the modified flag for the document after a modifying
+ * action on the view connected to the document.
+ *
+ * @param _m The value to set the modified flag to.
+ * @param addToUndo Whether this is an action which should be
+ * added to the undo stack.
+ */
+ void setModified(bool _m=true, bool addToUndo=true);
+
+ /**
+ * Returns if the document is modified or not. Use this to
+ * determine if your document needs saving by the user on
+ * closing.
+ *
+ * @return True if this UMLDoc is modified.
+ */
+ bool isModified() {
+ return m_modified;
+ }
+
+ /**
+ * "save modified" - Asks the user for saving if the document
+ * is modified.
+ *
+ * @return True if document can be closed.
+ */
+ bool saveModified();
+
+ /**
+ * Initializes the document generally.
+ *
+ * @return True if operation successful.
+ */
+ bool newDocument();
+
+ /**
+ * Closes the current document.
+ */
+ void closeDocument();
+
+ /**
+ * Loads the document by filename and format and emits the
+ * updateViews() signal.
+ *
+ * @param url The filename in KURL format.
+ * @param format The format (optional.)
+ * @return True if operation successful.
+ */
+ bool openDocument(const KURL& url, const char *format=0);
+
+ /**
+ * Saves the document using the given filename and format.
+ *
+ * @param url The filename in KURL format.
+ * @param format The format (optional.)
+ * @return True if operation successful.
+ */
+ bool saveDocument(const KURL& url, const char *format=0);
+
+ /**
+ * Returns the KURL of the document.
+ *
+ * @return The KURL of this UMLDoc.
+ */
+ const KURL& URL() const;
+
+ /**
+ * Sets the URL of the document.
+ *
+ * @param url The KURL to set.
+ */
+ void setURL(const KURL& url);
+
+ /**
+ * Sets up the signals needed by the program for it to work.
+ */
+ void setupSignals();
+
+ /**
+ * Returns true if the given name is unique within its scope.
+ *
+ * @param name The name to check.
+ * @return True if name is unique.
+ */
+ bool isUnique(const QString &name);
+
+ /**
+ * Returns true if the given name is unique within its scope of given package.
+ *
+ * @param name The name to check.
+ * @package The UMLPackage in which we have to determine the unique-ness
+ * @return True if name is unique.
+ */
+ bool isUnique(const QString &name, UMLPackage *package);
+
+ /**
+ * Finds or creates a stereotype for the parent object.
+ */
+ UMLStereotype* findOrCreateStereotype(const QString &name);
+
+ /**
+ * Creates an association between two UMLObjects.
+ * NOTE: this method does not check if the association is valid / legal
+ *
+ * @param a The UMLObject "A" for the association (source)
+ * @param b The UMLObject "B" for the association (destination)
+ * @param type The association's type
+ * @return The Association created
+ */
+ UMLAssociation* createUMLAssociation(UMLObject *a, UMLObject *b, Uml::Association_Type type);
+
+ /**
+ * Adds an association.
+ *
+ * @param pAssoc Pointer to the UMLAssociation to add.
+ */
+ void addAssociation(UMLAssociation *pAssoc);
+
+ /**
+ * Removes an association.
+ *
+ * @param pAssoc Pointer to the UMLAssociation to remove.
+ * @param doSetModified Whether to mark the document as modified (default: true.)
+ */
+ void removeAssociation(UMLAssociation *pAssoc, bool doSetModified = true);
+
+ /**
+ * Finds an association.
+ *
+ * @param assocType Type of the UMLAssociation to seek.
+ * @param roleAObj Pointer to the role A UMLCanvasObject.
+ * @param roleBObj Pointer to the role B UMLCanvasObject.
+ * @param swap Optional pointer to boolean.
+ * The bool is set to true if the assocation
+ * matched with swapped roles, else it is set
+ * to false.
+ * @return Pointer to the UMLAssociation found or NULL if not found.
+ */
+ UMLAssociation * findAssociation(Uml::Association_Type assocType,
+ const UMLObject *roleAObj,
+ const UMLObject *roleBObj,
+ bool *swap = NULL);
+
+ /**
+ * Creates a diagram of the given type.
+ *
+ * @param folder The folder in which tp create the diagram.
+ * @param type The type of diagram to create.
+ * @param askForName If true shows a dialog box asking for name,
+ * else uses a default name.
+ * @return Pointer to the UMLView of the new diagram.
+ */
+ UMLView* createDiagram(UMLFolder *folder, Uml::Diagram_Type type, bool askForName = true);
+
+ /**
+ * Removes an @ref UMLObject from the current file. If this object
+ * is being represented on a diagram it will also delete all those
+ * representations.
+ *
+ * @param o Pointer to the UMLObject to delete.
+ */
+ void removeUMLObject(UMLObject*o);
+
+ /**
+ * Used to rename a document. This method takes care of everything.
+ * You just need to give the ID of the diagram to the method.
+ *
+ * @param id The ID of the diagram to rename.
+ */
+ void renameDiagram(Uml::IDType id);
+
+ /**
+ * Used to rename a @ref UMLObject. The @ref UMLObject is to be an
+ * actor, use case or concept.
+ *
+ * @param o The object to rename.
+ */
+ void renameUMLObject(UMLObject *o);
+
+ /**
+ * Used to rename an operation or attribute of a concept.
+ *
+ * @param o The attribute or operation to rename.
+ */
+ void renameChildUMLObject(UMLObject *o);
+
+
+ /**
+ * Changes the current view (diagram) to the view with the given ID.
+ *
+ * @param id The ID of the view to change to.
+ */
+ void changeCurrentView(Uml::IDType id);
+
+ /**
+ * Deletes a diagram from the current file.
+ *
+ * @param id The ID of the diagram to delete.
+ */
+ void removeDiagram(Uml::IDType id);
+
+ /**
+ * Used to find a reference to a @ref UMLObject by its ID.
+ *
+ * @param id The @ref UMLObject to find.
+ * @return Pointer to the UMLObject found, or NULL if not found.
+ */
+ UMLObject* findObjectById(Uml::IDType id);
+
+ /**
+ * Used to find a @ref UMLObject by its type and name.
+ *
+ * @param name The name of the @ref UMLObject to find.
+ * @param type Object_Type of the object to find (optional.)
+ * When the given type is ot_UMLObject the type is
+ * disregarded, i.e. the given name is the only
+ * search criterion.
+ * @param currentObj Object relative to which to search (optional.)
+ * If given then the enclosing scope(s) of this
+ * object are searched before the global scope.
+ * @return Pointer to the UMLObject found, or NULL if not found.
+ */
+ UMLObject* findUMLObject(const QString &name,
+ Uml::Object_Type type = Uml::ot_UMLObject,
+ UMLObject *currentObj = NULL);
+
+ /**
+ * Used to find a reference to a @ref UMLObject given its non-numeric
+ * ID string.
+ * Only used for intermediate processing while loading files
+ * containing objects with non-numeric xmi.id's.
+ *
+ * @param idStr The AuxId for the @ref UMLObject to find.
+ * @return Pointer to the UMLObject found, or NULL if not found.
+ */
+ UMLObject* findObjectByAuxId(const QString &idStr);
+
+ /**
+ * Used to find a @ref UMLClassifier by its name.
+ *
+ * @param name The name of the @ref UMLObject to find.
+ */
+ UMLClassifier * findUMLClassifier (const QString &name);
+
+ /**
+ * Finds a UMLStereotype by its name.
+ *
+ * @param name The name of the UMLStereotype to find.
+ * @return Pointer to the UMLStereotype found, or NULL if not found.
+ */
+ UMLStereotype * findStereotype(const QString &name);
+
+ /**
+ * Finds a view (diagram) by the ID given to method.
+ *
+ * @param id The ID of the view to search for.
+ * @return Pointer to the view found, or NULL if not found.
+ */
+ UMLView * findView(Uml::IDType id);
+
+ /**
+ * Finds a view (diagram) by the type and name given.
+ *
+ * @param type The type of view to find.
+ * @param name The name of the view to find.
+ * @param searchAllScopes Search in all subfolders (default: false.)
+ * @return Pointer to the view found, or NULL if not found.
+ */
+ UMLView * findView(Uml::Diagram_Type type, const QString &name,
+ bool searchAllScopes = false);
+
+ /**
+ * Set the name of this model.
+ */
+ void setName(const QString& name);
+
+ /**
+ * Return the name of this model.
+ */
+ QString getName() const;
+
+ /**
+ * Return the m_modelID (currently this a fixed value:
+ * Umbrello supports only a single document.)
+ */
+ Uml::IDType getModelID() const;
+
+ /**
+ * This method is called for saving the given model as a XMI file.
+ * It is virtual and calls the corresponding saveToXMI() functions
+ * of the derived classes.
+ *
+ * @param file The file to be saved to.
+ */
+ virtual void saveToXMI(QIODevice& file);
+
+ /**
+ * Checks the given XMI file if it was saved with correct Unicode
+ * encoding set or not.
+ *
+ * @param file The file to be checked.
+ */
+ short getEncoding(QIODevice & file);
+
+ /**
+ * Load a given XMI model from a file. If the encoding of the file
+ * is already known it can be passed to the function. If this info
+ * isn't given, loadFromXMI will check which encoding was used.
+ *
+ * @param file The file to be loaded.
+ * @param encode The encoding used.
+ */
+ virtual bool loadFromXMI(QIODevice& file, short encode = ENC_UNKNOWN);
+
+ /**
+ * Ensures the XMI file is a valid UML file.
+ * Currently only checks for metamodel=UML.
+ *
+ * @param headerNode The <XMI.header> node
+ */
+ bool validateXMIHeader(QDomNode& headerNode);
+
+ /**
+ * Loads all UML objects from XMI into the current UMLDoc.
+ *
+ * @return True if operation successful.
+ */
+ bool loadUMLObjectsFromXMI( QDomElement & element );
+
+ /**
+ * Loads umbrello specific extensions from XMI to the UMLDoc.
+ * The extension tags are: "docsettings", "diagrams", "listview",
+ * and "codegeneration".
+ */
+ void loadExtensionsFromXMI(QDomNode & node);
+
+ /**
+ * Loads all diagrams from XMI into the current UMLDoc.
+ *
+ * @return True if operation successful.
+ */
+ bool loadDiagramsFromXMI( QDomNode & node );
+
+ /**
+ * Signal a view/diagram has been renamed.
+ */
+ void signalDiagramRenamed(UMLView * pView );
+
+ /**
+ * Call to remove all the views (diagrams) in the current file.
+ */
+ void removeAllViews();
+
+ /**
+ * Signal that a UMLObject has been created.
+ *
+ * @param o The object that has been created.
+ */
+ void signalUMLObjectCreated(UMLObject * o);
+
+ /**
+ * Returns the datatype folder.
+ *
+ * @return Pointer to the predefined folder for datatypes.
+ */
+ UMLFolder * getDatatypeFolder() {
+ return m_datatypeRoot;
+ }
+
+ /**
+ * Returns a list of the concepts in this UMLDoc.
+ *
+ * @param includeNested Whether to include the concepts from
+ * nested packages (default: true.)
+ * @return List of UML concepts.
+ */
+ UMLClassifierList getConcepts(bool includeNested = true);
+
+ /**
+ * Returns a list of the classes in this UMLDoc.
+ *
+ * @param includeNested Whether to include the concepts from
+ * nested packages (default: true.)
+ * @return List of UML classes.
+ */
+ UMLClassifierList getClasses(bool includeNested = true);
+
+ /**
+ * Returns a list of the classes and interfaces in this UMLDoc.
+ *
+ * @param includeNested Whether to include the concepts from
+ * nested packages (default: true.)
+ * @return List of UML concepts.
+ */
+ UMLClassifierList getClassesAndInterfaces(bool includeNested = true);
+
+ /**
+ * Returns a list of the interfaces in this UMLDoc.
+ *
+ * @param includeNested Whether to include the concepts from
+ * nested packages (default: true.)
+ * @return List of UML interfaces.
+ */
+ UMLClassifierList getInterfaces(bool includeNested = true);
+
+ /**
+ * Returns a list of the datatypes in this UMLDoc.
+ *
+ * @return List of datatypes.
+ */
+ UMLClassifierList getDatatypes();
+
+ /**
+ * Returns a list of the associations in this UMLDoc.
+ *
+ * @return List of UML associations.
+ */
+ UMLAssociationList getAssociations();
+
+ /**
+ * Controls the printing of the program.
+ *
+ * @param pPrinter The printer (object) to use.
+ */
+ void print(KPrinter * pPrinter);
+
+ /**
+ * Return the list of views for this document.
+ *
+ * @return List of UML views.
+ */
+ UMLViewList getViewIterator();
+
+ /**
+ * Assigns an already created UMLObject a new ID.
+ * If the object is a classifier then the operations/attributes
+ * are also assigned new IDs.
+ *
+ * @param Obj Pointer to the UMLObject to add.
+ * @return True if operation successful.
+ */
+ bool assignNewIDs(UMLObject* Obj);
+
+ /**
+ * Adds a UMLObject thats already created but doesn't change
+ * any ids or signal. Use AddUMLObjectPaste if pasting.
+ *
+ * @param object The object to add.
+ * @return True if the object was actually added.
+ */
+ bool addUMLObject(UMLObject * object);
+
+ /**
+ * Adds an already created UMLView to the document, it gets
+ * assigned a new ID, if its name is already in use then the
+ * function appends a number to it to differentiate it from
+ * the others; this number is incremental so if number 1 is in
+ * use then it tries 2 and then 3 and so on
+ *
+ * @param pView Pointer to the UMLView to add.
+ * @return True if operation successful.
+ */
+ bool addUMLView(UMLView * pView );
+
+ /**
+ * Return the predefined root folder of the given type.
+ */
+ UMLFolder *getRootFolder(Uml::Model_Type mt);
+
+ /**
+ * Return the corresponding Model_Type if the given object
+ * is one of the root folders.
+ * When the given object is not one of the root folders then
+ * return Uml::N_MODELTYPES.
+ */
+ Uml::Model_Type rootFolderType(UMLObject *obj);
+
+ /**
+ * Return the currently selected root folder.
+ * This will be an element from the m_root[] array.
+ */
+ UMLFolder *currentRoot();
+
+ /**
+ * Set the current root folder.
+ *
+ * @param rootType The type of the root folder to set.
+ * The element from m_root[] which is indexed
+ * by this type is selected.
+ */
+ void setCurrentRoot(Uml::Model_Type rootType);
+
+ /**
+ * Read property of IDChangeLog* m_pChangeLog.
+ *
+ * @return Pointer to the IDChangeLog object.
+ */
+ virtual IDChangeLog* getChangeLog();
+
+ /**
+ * Closes a paste session, deletes the ChangeLog.
+ */
+ void endPaste();
+
+ /**
+ * Opens a Paste session, deletes the old ChangeLog and
+ * creates an empty one.
+ */
+ void beginPaste();
+
+ /**
+ * Assigns a New ID to an Object, and also logs the assignment
+ * to its internal ChangeLog.
+ *
+ * @param OldID The present ID of the object.
+ * @return The new ID assigned to the object.
+ */
+ Uml::IDType assignNewID(Uml::IDType OldID);
+
+ /**
+ * Returns the documentation for the project.
+ *
+ * @return The documentation text of this UMLDoc.
+ */
+ QString getDocumentation() const {
+ return m_Doc;
+ }
+
+ /**
+ * Sets the documentation for the project.
+ *
+ * @param doc The documentation to set for this UMLDoc.
+ */
+ void setDocumentation(const QString &doc) {
+ m_Doc = doc;
+ }
+
+ /**
+ * Activate all the diagrams/views after loading so all their
+ * widgets keep their IDs.
+ */
+ void activateAllViews();
+
+ /**
+ * Sets the default settings to the given settings.
+ */
+ void settingsChanged(Settings::OptionState optionState);
+
+
+ /**
+ * Returns the version of the old UML files.
+ */
+ int getFileVersion(void) {return version;}
+
+ /**
+ * Performs the undo function, loading the document back to the
+ * state is was before the last addToUndoStack()
+ */
+ void loadUndoData();
+
+ /**
+ * Performs the redo function, loading the document back to the
+ * state is was before the last undo()
+ */
+ void loadRedoData();
+
+ /**
+ * Takes an image of the document and adds it to the UndoStack.
+ * Implemented using the saveToXMI functions.
+ */
+ void addToUndoStack();
+
+ /**
+ * Removes all entries from the UndoStack and RedoStack and disables the
+ * undo and redo actions.
+ */
+ void clearUndoStack();
+
+ /**
+ * Removes all entries from the RedoStack and disables the
+ * redo action.
+ */
+ void clearRedoStack();
+
+ /**
+ * Returns a name for the new object, appended with a number
+ * if the default name is taken e.g. class diagram, class
+ * diagram_1 etc
+ */
+ QString uniqViewName(const Uml::Diagram_Type type);
+
+ /**
+ * Returns true when loading a document file.
+ */
+ bool loading() const;
+
+ /**
+ * Sets loading boolean flag to the value given.
+ */
+ void setLoading(bool state = true);
+
+ /**
+ * Calls the active code generator to create its default datatypes
+ */
+ void addDefaultDatatypes();
+
+ /**
+ * Add a datatype if it doesn't already exist.
+ * Used by code generators and attribute dialog.
+ */
+ void createDatatype(const QString &name);
+
+ /**
+ * Find a UMLStereotype by its unique ID.
+ */
+ UMLStereotype * findStereotypeById(Uml::IDType id);
+
+ /**
+ * Add a UMLStereotype to the application.
+ */
+ void addStereotype(const UMLStereotype *s);
+
+ /**
+ * Remove a UMLStereotype from the application.
+ */
+ void removeStereotype(const UMLStereotype *s);
+
+ /**
+ * Add a stereotype if it doesn't already exist.
+ * Used by code generators, operations and attribute dialog.
+ */
+ void addDefaultStereotypes();
+
+ /**
+ * Returns a list of the stereotypes in this UMLDoc.
+ *
+ * @return List of UML stereotypes.
+ */
+ const UMLStereotypeList& getStereotypes();
+
+ /**
+ * Write text to the status bar.
+ */
+ void writeToStatusBar(const QString &text);
+
+ /**
+ * Type resolution pass.
+ */
+ void resolveTypes();
+
+private:
+ /**
+ * Sets up the autosave timer.
+ */
+ void initSaveTimer();
+
+ /**
+ * Array of predefined root folders.
+ */
+ UMLFolder *m_root[Uml::N_MODELTYPES];
+ /**
+ * Predefined root folder for datatypes, contained in
+ * m_root[Uml::mt_Logical]
+ */
+ UMLFolder *m_datatypeRoot;
+
+ /**
+ * The UMLDoc is the sole owner of all stereotypes.
+ * UMLStereotype instances are reference counted.
+ * When an UMLStereotype is no longer referenced anywhere,
+ * its refcount drops to zero. It is then removed from the
+ * m_stereoList and it is physically deleted.
+ */
+ UMLStereotypeList m_stereoList;
+
+ QString m_Name; ///< name of this model as stored in the <UML:Model> tag
+ Uml::IDType m_modelID; ///< xmi.id of this model in the <UML:Model>
+ int m_count; ///< auxiliary counter for the progress bar
+ bool m_modified;
+ KURL m_doc_url;
+
+ /**
+ * Contains all the UMLObject id changes of paste session.
+ */
+ IDChangeLog* m_pChangeLog;
+
+ /**
+ * true if the we're loading a new document
+ */
+ bool m_bLoading;
+
+ /**
+ * Documentation for the project.
+ */
+ QString m_Doc;
+
+ /**
+ * Used for autosave
+ */
+ QTimer * m_pAutoSaveTimer;
+
+ /**
+ * Stores the version of old UML files.
+ */
+ int version;
+
+ /**
+ * The stack of images of the document added to each time
+ * something is changed. A QPtrList is used rather than a
+ * QPtrStack to be able to remove the ones off the bottom once
+ * the stack gets too big.
+ */
+ QPtrList<QDataStream> undoStack;
+
+ /**
+ * The stack of images of the document added to each time
+ * undo is called.
+ */
+ QPtrList<QDataStream> redoStack;
+
+ /**
+ * Auxiliary to <docsettings> processing
+ */
+ Uml::IDType m_nViewID;
+
+ /**
+ * True when type resolution pass has been executed.
+ */
+ bool m_bTypesAreResolved;
+
+ /**
+ * the context menu on the tabs,
+ * plugs into umlview::slotMenuSelection()
+ */
+ KPopupMenu* m_pTabPopupMenu;
+
+ /**
+ * Auxiliary variable for currentRoot():
+ * m_pCurrentRoot is only used if UMLApp::app()->getCurrentView()
+ * returns NULL.
+ */
+ UMLFolder * m_pCurrentRoot;
+
+public slots:
+
+ void slotRemoveUMLObject(UMLObject*o);
+
+ /**
+ * Called after a specified time to autosave the document.
+ */
+ void slotAutoSave();
+
+ /**
+ * Make a popup menu for the tabs
+ * signalled from tabWidget's contextMenu()
+ */
+ void slotDiagramPopupMenu(QWidget* umlview, const QPoint& point);
+
+signals:
+ void sigDiagramCreated(Uml::IDType id);
+ void sigDiagramRemoved(Uml::IDType id);
+ void sigDiagramRenamed(Uml::IDType t);
+ void sigDiagramChanged(Uml::Diagram_Type);
+
+ void sigObjectCreated(UMLObject *);
+ void sigObjectRemoved(UMLObject *);
+
+ /**
+ * Reset the status bar.
+ */
+ void sigResetStatusbarProgress();
+
+ /**
+ * Set the total range of the progressbar.
+ *
+ * @param totalSteps Total range of the progressbar (0..totalSteps)
+ */
+ void sigSetStatusbarProgressSteps(int totalSteps);
+
+
+ /**
+ * Set the progress position of the progressbar.
+ *
+ * @param stepPosition The step position to set.
+ */
+ void sigSetStatusbarProgress(int stepPosition);
+
+ /**
+ * Write text to the status bar.
+ */
+ void sigWriteToStatusBar(const QString &text);
+
+ /**
+ * The diagram being displayed has changed.
+ * UMLApp uses this to keep its menu items state up to date.
+ */
+ void sigCurrentViewChanged();
+
+
+};
+
+#endif // UMLDOC_H
diff --git a/umbrello/umbrello/umlentityattributelist.cpp b/umbrello/umbrello/umlentityattributelist.cpp
new file mode 100644
index 00000000..5855859a
--- /dev/null
+++ b/umbrello/umbrello/umlentityattributelist.cpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlentityattributelist.h"
+#include "entityattribute.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+void UMLEntityAttributeList::copyInto(UMLEntityAttributeList* rhs) const {
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLEntityAttributeList* tmp = new UMLEntityAttributeList(*this);
+
+ UMLEntityAttribute* item;
+ for (item = tmp->first(); item; item = tmp->next() ) {
+ rhs->append((UMLEntityAttribute*)item->clone());
+ }
+ delete tmp;
+}
+
+
+UMLEntityAttributeList* UMLEntityAttributeList::clone() const {
+ UMLEntityAttributeList *clone = new UMLEntityAttributeList();
+ copyInto(clone);
+ return clone;
+}
diff --git a/umbrello/umbrello/umlentityattributelist.h b/umbrello/umbrello/umlentityattributelist.h
new file mode 100644
index 00000000..35c0a150
--- /dev/null
+++ b/umbrello/umbrello/umlentityattributelist.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLENTITYATTRIBUTELIST_H
+#define UMLENTITYATTRIBUTELIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLEntityAttribute;
+
+//typedef QPtrList<UMLEntityAttribute> UMLEntityAttributeList;
+typedef QPtrListIterator<UMLEntityAttribute> UMLEntityAttributeListIt;
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLEntityAttribute>
+ * base class.
+ */
+class UMLEntityAttributeList : public QPtrList<UMLEntityAttribute>
+{
+public:
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto (UMLEntityAttributeList* rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLEntityAttributeList* clone() const;
+};
+
+
+#endif
diff --git a/umbrello/umbrello/umlenumliterallist.h b/umbrello/umbrello/umlenumliterallist.h
new file mode 100644
index 00000000..60e03199
--- /dev/null
+++ b/umbrello/umbrello/umlenumliterallist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLENUMLITERALLIST_H
+#define UMLENUMLITERALLIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLEnumLiteral;
+
+typedef QPtrList<UMLEnumLiteral> UMLEnumLiteralList;
+typedef QPtrListIterator<UMLEnumLiteral> UMLEnumLiteralListIt;
+
+#endif
diff --git a/umbrello/umbrello/umllistview.cpp b/umbrello/umbrello/umllistview.cpp
new file mode 100644
index 00000000..d12fed58
--- /dev/null
+++ b/umbrello/umbrello/umllistview.cpp
@@ -0,0 +1,2703 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umllistview.h"
+
+// qt/kde includes
+#include <qregexp.h>
+#include <qpoint.h>
+#include <qrect.h>
+#include <qevent.h>
+#include <qheader.h>
+#include <qtooltip.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kinputdialog.h>
+
+// app includes
+#include "actor.h"
+#include "classifier.h"
+#include "package.h"
+#include "folder.h"
+#include "component.h"
+#include "node.h"
+#include "artifact.h"
+#include "enum.h"
+#include "enumliteral.h"
+#include "entity.h"
+#include "docwindow.h"
+#include "listpopupmenu.h"
+#include "template.h"
+#include "operation.h"
+#include "attribute.h"
+#include "entityattribute.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistviewitemlist.h"
+#include "umllistviewitem.h"
+#include "umlview.h"
+#include "umlviewimageexporter.h"
+#include "usecase.h"
+#include "model_utils.h"
+#include "uniqueid.h"
+#include "clipboard/idchangelog.h"
+#include "clipboard/umldrag.h"
+#include "dialogs/classpropdlg.h"
+#include "dialogs/umlattributedialog.h"
+#include "dialogs/umlentityattributedialog.h"
+#include "dialogs/umloperationdialog.h"
+#include "dialogs/umltemplatedialog.h"
+
+#ifdef WANT_LVTOOLTIP
+class LVToolTip : public QToolTip
+{
+public:
+ LVToolTip (QWidget* parent) : QToolTip (parent) {}
+ virtual ~LVToolTip () {}
+protected:
+ /**
+ * Reimplemented from QToolTip for internal reasons.
+ * At classifiers, only the method names are shown in the list view -
+ * we use a tooltip for the full signature display.
+ * Once KListView's tooltip overriding mechanism works, we can kick
+ * this class out.
+ */
+ virtual void maybeTip (const QPoint& pos) {
+ UMLListView *lv = UMLApp::app()->getListView();
+ UMLListViewItem * item = (UMLListViewItem*)lv->itemAt(pos);
+ if (item == NULL)
+ return;
+ UMLObject *obj = item->getUMLObject();
+ if (obj == NULL || obj->getBaseType() != Uml::ot_Operation)
+ return;
+ UMLOperation *op = static_cast<UMLOperation*>(obj);
+ QString text = op->toString(Uml::st_ShowSig);
+ QRect rect = lv->itemRect(item);
+ tip(rect, text);
+ }
+};
+#endif
+
+
+UMLListView::UMLListView(QWidget *parent, const char *name)
+ : KListView(parent,name), m_pMenu(0), m_doc(UMLApp::app()->getDocument())
+{
+ loadPixmaps();
+
+ //setup list view
+ setBackgroundColor(Qt::white);
+ setAcceptDrops(true);
+ setDropVisualizer(false);
+ setItemsMovable(true);
+ setItemsRenameable( true );
+ setSelectionModeExt(FileManager);
+ setFocusPolicy(QWidget::StrongFocus);
+ setDragEnabled(true);
+ setColumnWidthMode( 0, Manual );
+ setDefaultRenameAction( Accept );
+ setResizeMode( LastColumn );
+ header()->setClickEnabled(true);
+ //add columns and initial items
+ addColumn(m_doc->getName());
+
+#ifdef WANT_LVTOOLTIP
+ /* In KDE-3.3, we cannot use KListView's builtin mechanism for
+ overriding the tooltips. Instead, see the above class LVToolTip.
+ setShowToolTips( true );
+ setTooltipColumn( 0 );
+ */
+ (void) new LVToolTip(viewport());
+#endif
+ m_pMenu = NULL;
+ m_bStartedCut = m_bStartedCopy = false;
+ m_bIgnoreCancelRename = true;
+ m_bCreatingChildObject = false;
+ m_rv = NULL;
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_lv[i] = NULL;
+ m_datatypeFolder = NULL;
+ //setup slots/signals
+ connect(this, SIGNAL(dropped(QDropEvent *, QListViewItem *, QListViewItem *)),
+ this, SLOT(slotDropped(QDropEvent *, QListViewItem *, QListViewItem *)));
+ connect( this, SIGNAL( collapsed( QListViewItem * ) ),
+ this, SLOT( slotCollapsed( QListViewItem * ) ) );
+ connect( this, SIGNAL( expanded( QListViewItem * ) ), this, SLOT( slotExpanded( QListViewItem * ) ) );
+ connect( UMLApp::app(), SIGNAL( sigCutSuccessful() ), this, SLOT( slotCutSuccessful() ) );
+}
+
+UMLListView::~UMLListView() {}
+
+bool UMLListView::eventFilter(QObject *o, QEvent *e) {
+ if (e->type() != QEvent::MouseButtonPress || !o->isA("QHeader"))
+ return QListView::eventFilter(o, e);
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::RightButton) {
+ if (m_pMenu) {
+ m_pMenu->hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
+ delete m_pMenu;
+ }
+ m_pMenu = new ListPopupMenu(this, Uml::lvt_Model);
+ m_pMenu->popup(me->globalPos());
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
+ return true;
+ }
+ return QListView::eventFilter(o, e);
+}
+
+void UMLListView::contentsMousePressEvent(QMouseEvent *me) {
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView)
+ currentView->clearSelected();
+ if( me -> state() != Qt::ShiftButton )
+ clearSelection();
+ QPoint pt = this->QScrollView::contentsToViewport( me->pos() );
+ UMLListViewItem * item = (UMLListViewItem*)itemAt(pt);
+ const Qt::ButtonState button = me->button();
+
+ if (!item || (button != Qt::RightButton && button != Qt::LeftButton)) {
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+ return;
+ }
+
+ if (button == Qt::LeftButton) {
+ UMLObject *o = item->getUMLObject();
+ if (o)
+ UMLApp::app()->getDocWindow()->showDocumentation(o, false);
+ else
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+ }
+ if (button == Qt::RightButton) {
+ if(m_pMenu != 0) {
+ m_pMenu->hide();
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+ const Uml::ListView_Type type = item->getType();
+ m_pMenu = new ListPopupMenu(this, type);
+ m_pMenu->popup(me->globalPos());
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(popupMenuSel(int)));
+ }//end if right button
+
+ this->KListView::contentsMousePressEvent(me);
+}
+
+void UMLListView::contentsMouseReleaseEvent(QMouseEvent *me) {
+ if (me->button() != Qt::LeftButton) {
+ this->KListView::contentsMouseReleaseEvent(me);
+ return;
+ }
+ const QPoint pt = this->QScrollView::contentsToViewport( me->pos() );
+ UMLListViewItem *item = dynamic_cast<UMLListViewItem*>(itemAt(pt));
+ if (item == NULL || !Model_Utils::typeIsDiagram(item->getType())) {
+ this->KListView::contentsMouseReleaseEvent(me);
+ return;
+ }
+ // Switch to diagram on mouse release - not on mouse press
+ // because the user might intend a drag-to-note.
+ m_doc->changeCurrentView( item->getID() );
+ UMLApp::app()->getDocWindow()->showDocumentation(m_doc->findView(item->getID()), false);
+ this->KListView::contentsMouseReleaseEvent(me);
+}
+
+void UMLListView::keyPressEvent(QKeyEvent *ke) {
+ UMLView *view = UMLApp::app()->getCurrentView();
+ if (view && view->getSelectCount()) {
+ // Widgets have been selected in the diagram area,
+ // assume they handle the keypress.
+ ke->accept(); // munge and do nothing
+ } else {
+ const int k = ke->key();
+ if (k == Qt::Key_Delete || k == Qt::Key_Backspace) {
+ // delete every selected item
+ UMLListViewItemList selecteditems;
+ getSelectedItemsRoot(selecteditems);
+ UMLListViewItemListIt it(selecteditems);
+ for (UMLListViewItem *item = 0; (item = it.current()); ++it) {
+ deleteItem(dynamic_cast<UMLListViewItem*>(item));
+ }
+ } else {
+ QListView::keyPressEvent(ke); // let parent handle it
+ }
+ }
+}
+
+void UMLListView::popupMenuSel(int sel) {
+ UMLListViewItem * temp = (UMLListViewItem*)currentItem();
+ if ( !temp ) {
+ kDebug() << "popupMenuSel invoked without currently selectedItem" << endl;
+ return;
+ }
+ UMLObject * object = temp -> getUMLObject();
+ Uml::ListView_Type lvt = temp -> getType();
+ Uml::Object_Type umlType = Uml::ot_UMLObject;
+ ListPopupMenu::Menu_Type menuType = (ListPopupMenu::Menu_Type)sel;
+ QString name;
+
+ switch (menuType) {
+ case ListPopupMenu::mt_Class:
+ addNewItem( temp, Uml::lvt_Class );
+ break;
+
+ case ListPopupMenu::mt_Package:
+ addNewItem(temp, Uml::lvt_Package);
+ break;
+
+ case ListPopupMenu::mt_Subsystem:
+ addNewItem(temp, Uml::lvt_Subsystem);
+ break;
+
+ case ListPopupMenu::mt_Component:
+ addNewItem(temp, Uml::lvt_Component);
+ break;
+
+ case ListPopupMenu::mt_Node:
+ addNewItem(temp, Uml::lvt_Node);
+ break;
+
+ case ListPopupMenu::mt_Artifact:
+ addNewItem(temp, Uml::lvt_Artifact);
+ break;
+
+ case ListPopupMenu::mt_Interface:
+ addNewItem(temp, Uml::lvt_Interface);
+ break;
+
+ case ListPopupMenu::mt_Enum:
+ addNewItem(temp, Uml::lvt_Enum);
+ break;
+
+ case ListPopupMenu::mt_EnumLiteral:
+ addNewItem(temp, Uml::lvt_EnumLiteral);
+ break;
+
+ case ListPopupMenu::mt_Template:
+ addNewItem(temp, Uml::lvt_Template);
+ break;
+
+ case ListPopupMenu::mt_Entity:
+ addNewItem(temp, Uml::lvt_Entity);
+ break;
+
+ case ListPopupMenu::mt_Datatype:
+ addNewItem(temp, Uml::lvt_Datatype);
+ break;
+
+ case ListPopupMenu::mt_Actor:
+ addNewItem( temp, Uml::lvt_Actor );
+ break;
+
+ case ListPopupMenu::mt_UseCase:
+ addNewItem( temp, Uml::lvt_UseCase );
+ break;
+
+ case ListPopupMenu::mt_Attribute:
+ addNewItem( temp, Uml::lvt_Attribute );
+ break;
+
+ case ListPopupMenu::mt_EntityAttribute:
+ addNewItem( temp, Uml::lvt_EntityAttribute );
+ break;
+
+ case ListPopupMenu::mt_Operation:
+ addNewItem( temp, Uml::lvt_Operation );
+ break;
+
+ case ListPopupMenu::mt_Import_Classes:
+ UMLApp::app()->slotImportClasses();
+ break;
+
+ case ListPopupMenu::mt_Expand_All:
+ expandAll(temp);
+ break;
+
+ case ListPopupMenu::mt_Collapse_All:
+ collapseAll(temp);
+ break;
+
+ case ListPopupMenu::mt_Export_Image:
+ m_doc->findView(temp->getID())->getImageExporter()->exportView();
+ break;
+
+ case ListPopupMenu::mt_Externalize_Folder:
+ {
+ UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
+ UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
+ if (modelFolder == NULL) {
+ kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
+ return;
+ }
+ // configure & show the file dialog
+ const QString rootDir(m_doc->URL().directory());
+ KFileDialog fileDialog(rootDir, "*.xml", this, ":externalize-folder", true);
+ fileDialog.setCaption(i18n("Externalize Folder"));
+ fileDialog.setOperationMode(KFileDialog::Other);
+ // set a sensible default filename
+ QString defaultFilename = current->getText().lower();
+ defaultFilename.replace(QRegExp("\\W+"), "_");
+ defaultFilename.append(".xml"); // default extension
+ fileDialog.setSelection(defaultFilename);
+ fileDialog.exec();
+ KURL selURL = fileDialog.selectedURL();
+ if (selURL.isEmpty())
+ return;
+ QString path = selURL.path();
+ QString fileName = path;
+ if (fileName.startsWith(rootDir)) {
+ fileName.remove(rootDir);
+ } else {
+ // This should be done using a KMessageBox but we currently
+ // cannot add new i18n strings.
+ kError() << "Folder " << path
+ << " must be relative to the main model directory, "
+ << rootDir << endl;
+ return;
+ }
+ QFile file(path);
+ // Warn if file exists.
+ if (file.exists()) {
+ // This should be done using a KMessageBox but we currently
+ // cannot add new i18n strings.
+ kWarning() << "file " << fileName << " already exists!" << endl;
+ kWarning() << "The existing file will be overwritten." << endl;
+ }
+ // Test if file is writable.
+ if (file.open(IO_WriteOnly)) {
+ file.close();
+ } else {
+ KMessageBox::error(0,
+ i18n("There was a problem saving file: %1").arg(fileName),
+ i18n("Save Error"));
+ return;
+ }
+ modelFolder->setFolderFile(fileName);
+ // Recompute text of the folder
+ QString folderText = current->getText();
+ folderText.remove( QRegExp("\\s*\\(.*$") );
+ folderText.append( " (" + fileName + ')' );
+ current->setText(folderText);
+ break;
+ }
+
+ case ListPopupMenu::mt_Internalize_Folder:
+ {
+ UMLListViewItem *current = static_cast<UMLListViewItem*>(currentItem());
+ UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(current->getUMLObject());
+ if (modelFolder == NULL) {
+ kError() << "UMLListView::popupMenuSel: modelFolder is NULL" << endl;
+ return;
+ }
+ modelFolder->setFolderFile(QString::null);
+ // Recompute text of the folder
+ QString folderText = current->getText();
+ folderText.remove( QRegExp("\\s*\\(.*$") );
+ current->setText(folderText);
+ break;
+ }
+
+ case ListPopupMenu::mt_Model:
+ {
+ bool ok = false;
+ QString name = KInputDialog::getText( i18n("Enter Model Name"),
+ i18n("Enter the new name of the model:"),
+ m_doc->getName(), &ok, UMLApp::app() );
+ if (ok) {
+ setColumnText(0, name);
+ m_doc->setName(name);
+ }
+ break;
+ }
+
+ case ListPopupMenu::mt_Rename:
+ temp-> startRename(0);
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ deleteItem(temp);
+
+ return;
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ /* first check if we are on a diagram */
+ if( Model_Utils::typeIsDiagram(lvt) ) {
+ UMLView * pView = m_doc->findView( temp->getID() );
+ if( !pView ) {
+ return;
+ }
+ UMLApp::app()->getDocWindow()->updateDocumentation(false);
+ pView->showPropDialog();
+ UMLApp::app()->getDocWindow()->showDocumentation(pView, true);
+ temp->cancelRename(0);
+ return;
+ }
+
+ /* ok, we are on another object, so find out on which one */
+ umlType = object->getBaseType();
+
+ if ( Model_Utils::typeIsCanvasWidget(lvt) ) {
+ object->showProperties(ClassPropDlg::page_gen);
+ } else if(umlType == Uml::ot_Attribute) {
+ // show the attribute dialog
+ UMLAttribute* selectedAttribute = static_cast<UMLAttribute*>(object);
+ UMLAttributeDialog dialog( this, selectedAttribute );
+ dialog.exec();
+ } else if(umlType == Uml::ot_EntityAttribute) {
+ // show the attribute dialog
+ UMLEntityAttribute* selectedAttribute = static_cast<UMLEntityAttribute*>(object);
+ UMLEntityAttributeDialog dialog( this, selectedAttribute );
+ dialog.exec();
+ } else if(umlType == Uml::ot_Operation) {
+ // show the operation dialog
+ UMLOperation* selectedOperation = static_cast<UMLOperation*>(object);
+ UMLOperationDialog dialog( this, selectedOperation );
+ dialog.exec();
+ } else if(umlType == Uml::ot_Template) {
+ // show the template dialog
+ UMLTemplate* selectedTemplate = static_cast<UMLTemplate*>(object);
+ UMLTemplateDialog dialog( this, selectedTemplate );
+ dialog.exec();
+ } else {
+ kWarning() << "calling properties on unknown type" << endl;
+ }
+ temp -> cancelRename( 0 );
+ break;
+
+ case ListPopupMenu::mt_Logical_Folder:
+ addNewItem( temp, Uml::lvt_Logical_Folder );
+ break;
+
+ case ListPopupMenu::mt_UseCase_Folder:
+ addNewItem( temp, Uml::lvt_UseCase_Folder );
+ break;
+
+ case ListPopupMenu::mt_Component_Folder:
+ addNewItem(temp, Uml::lvt_Component_Folder);
+ break;
+
+ case ListPopupMenu::mt_Deployment_Folder:
+ addNewItem(temp, Uml::lvt_Deployment_Folder);
+ break;
+
+ case ListPopupMenu::mt_EntityRelationship_Folder:
+ addNewItem(temp, Uml::lvt_EntityRelationship_Folder);
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ m_bStartedCut = true;
+ m_bStartedCopy = false;
+ UMLApp::app() -> slotEditCut();
+ break;
+
+ case ListPopupMenu::mt_Copy:
+ m_bStartedCut = false;
+ m_bStartedCopy = true;
+ UMLApp::app() -> slotEditCopy();
+ break;
+
+ case ListPopupMenu::mt_Paste:
+ UMLApp::app() -> slotEditPaste();
+ break;
+
+ default:
+ {
+ Uml::Diagram_Type dt = ListPopupMenu::convert_MT_DT(menuType);
+ if (dt == Uml::dt_Undefined) {
+ kWarning() << "UMLListView::popupMenuSel: unknown type"
+ << sel << endl;
+ } else {
+ UMLFolder *f = dynamic_cast<UMLFolder*>(object);
+ if (f == NULL)
+ kError() << "UMLListView::popupMenuSel(" << menuType
+ << "): current item's UMLObject is not a UMLFolder" << endl;
+ else
+ m_doc->createDiagram(f, dt);
+ }
+ }
+ break;
+ }//end switch
+}
+
+UMLListViewItem *UMLListView::findFolderForDiagram(Uml::Diagram_Type dt) {
+ UMLListViewItem *p = static_cast<UMLListViewItem*>(currentItem());
+ if (p && Model_Utils::typeIsFolder(p->getType())
+ && !Model_Utils::typeIsRootView(p->getType())) {
+ return p;
+ }
+ switch (dt) {
+ case Uml::dt_UseCase:
+ p = m_lv[Uml::mt_UseCase];
+ break;
+ case Uml::dt_Component:
+ p = m_lv[Uml::mt_Component];
+ break;
+ case Uml::dt_Deployment:
+ p = m_lv[Uml::mt_Deployment];
+ break;
+ case Uml::dt_EntityRelationship:
+ p = m_lv[Uml::mt_EntityRelationship];
+ break;
+ default:
+ p = m_lv[Uml::mt_Logical];
+ break;
+ }
+ return p;
+}
+
+void UMLListView::slotDiagramCreated( Uml::IDType id ) {
+ if( m_doc->loading() )
+ return;
+ UMLView *v = m_doc -> findView( id );
+ if (!v)
+ return;
+ const Uml::Diagram_Type dt = v->getType();
+ UMLListViewItem * temp = 0, *p = findFolderForDiagram(dt);
+ temp = new UMLListViewItem(p, v->getName(), Model_Utils::convert_DT_LVT(dt), id);
+ setSelected( temp, true );
+ UMLApp::app() -> getDocWindow() -> showDocumentation( v , false );
+}
+
+UMLListViewItem* UMLListView::determineParentItem(UMLObject* object) const {
+ UMLListViewItem* parentItem = NULL;
+ UMLListViewItem* current = (UMLListViewItem*) currentItem();
+ Uml::ListView_Type lvt = Uml::lvt_Unknown;
+ if (current)
+ lvt = current->getType();
+ Uml::Object_Type t = object->getBaseType();
+
+ switch (t) {
+ case Uml::ot_Attribute:
+ case Uml::ot_Operation:
+ case Uml::ot_Template:
+ case Uml::ot_EnumLiteral:
+ case Uml::ot_EntityAttribute:
+ //this will be handled by childObjectAdded
+ return NULL;
+ break;
+ case Uml::ot_Association:
+ case Uml::ot_Role:
+ case Uml::ot_Stereotype:
+ return NULL; // currently no representation in list view
+ break;
+ default:
+ {
+ UMLPackage *pkg = object->getUMLPackage();
+ if (pkg) {
+ UMLListViewItem* pkgItem = findUMLObject(pkg);
+ if (pkgItem == NULL)
+ kError() << "UMLListView::determineParentItem: could not find "
+ << "parent package " << pkg->getName() << endl;
+ else
+ parentItem = pkgItem;
+ } else if ((lvt == Uml::lvt_UseCase_Folder &&
+ (t == Uml::ot_Actor || t == Uml::ot_UseCase))
+ || (lvt == Uml::lvt_Component_Folder && t == Uml::ot_Component)
+ || (lvt == Uml::lvt_Deployment_Folder && t == Uml::ot_Node)
+ || (lvt == Uml::lvt_EntityRelationship_Folder && t == Uml::ot_Entity)) {
+ parentItem = current;
+ } else if (t == Uml::ot_Datatype) {
+ parentItem = m_datatypeFolder;
+ } else {
+ Uml::Model_Type guess = Model_Utils::guessContainer(object);
+ parentItem = m_lv[guess];
+ }
+ }
+ break;
+ }
+ return parentItem;
+}
+
+bool UMLListView::mayHaveChildItems(Uml::Object_Type type) {
+ bool retval = false;
+ switch (type) {
+ case Uml::ot_Class:
+ case Uml::ot_Interface:
+ case Uml::ot_Enum:
+ case Uml::ot_Entity: // CHECK: more?
+ retval = true;
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+void UMLListView::slotObjectCreated(UMLObject* object) {
+ if (m_bCreatingChildObject) {
+ // @todo eliminate futile signal traffic
+ // e.g. we get here thru various indirections from
+ // ClassifierListPage::slot{Up,Down}Clicked()
+ return;
+ }
+ UMLListViewItem* newItem = findUMLObject(object);
+ if (newItem) {
+ kDebug() << "UMLListView::slotObjectCreated(" << object->getName()
+ << ", id= " << ID2STR(object->getID())
+ << "): item already exists." << endl;
+ Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(newItem->getType());
+ newItem->setIcon(icon);
+ return;
+ }
+ UMLListViewItem* parentItem = determineParentItem(object);
+ if (parentItem == NULL)
+ return;
+ Uml::Object_Type type = object->getBaseType();
+
+ connectNewObjectsSlots(object);
+ const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(object);
+ QString name = object->getName();
+ if (type == Uml::ot_Folder) {
+ UMLFolder *f = static_cast<UMLFolder*>(object);
+ QString folderFile = f->getFolderFile();
+ if (!folderFile.isEmpty())
+ name.append(" (" + folderFile + ')');
+ }
+ newItem = new UMLListViewItem(parentItem, name, lvt, object);
+ if (mayHaveChildItems(type)) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(object);
+ UMLClassifierListItemList cListItems = c->getFilteredList(Uml::ot_UMLObject);
+ UMLClassifierListItem *cli;
+ for (UMLClassifierListItemListIt it(cListItems); (cli = it.current()) != NULL; ++it)
+ childObjectAdded(cli, c);
+ }
+ if (m_doc->loading())
+ return;
+ ensureItemVisible(newItem);
+ newItem->setOpen(true);
+ clearSelection();
+ setSelected(newItem, true);
+ UMLApp::app()->getDocWindow()->showDocumentation(object, false);
+}
+
+void UMLListView::connectNewObjectsSlots(UMLObject* object) {
+ Uml::Object_Type type = object->getBaseType();
+ switch( type )
+ {
+ case Uml::ot_Class:
+ case Uml::ot_Interface:
+ {
+ UMLClassifier *c = static_cast<UMLClassifier*>(object);
+ connect(c, SIGNAL(attributeAdded(UMLClassifierListItem*)),
+ this, SLOT(childObjectAdded(UMLClassifierListItem*)));
+ connect(c, SIGNAL(attributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
+ connect(c, SIGNAL(operationAdded(UMLClassifierListItem*)),
+ this, SLOT(childObjectAdded(UMLClassifierListItem*)));
+ connect(c, SIGNAL(operationRemoved(UMLClassifierListItem*)),
+ this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
+ connect(c, SIGNAL(templateAdded(UMLClassifierListItem*)),
+ this, SLOT(childObjectAdded(UMLClassifierListItem*)));
+ connect(c, SIGNAL(templateRemoved(UMLClassifierListItem*)),
+ this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
+ connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
+ }
+ break;
+ case Uml::ot_Enum:
+ {
+ UMLEnum *e = static_cast<UMLEnum*>(object);
+ connect(e, SIGNAL(enumLiteralAdded(UMLClassifierListItem*)),
+ this, SLOT(childObjectAdded(UMLClassifierListItem*)));
+ connect(e, SIGNAL(enumLiteralRemoved(UMLClassifierListItem*)),
+ this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
+ }
+ connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
+ break;
+ case Uml::ot_Entity:
+ {
+ UMLEntity *ent = static_cast<UMLEntity*>(object);
+ connect(ent, SIGNAL(entityAttributeAdded(UMLClassifierListItem*)),
+ this, SLOT(childObjectAdded(UMLClassifierListItem*)));
+ connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)),
+ this, SLOT(childObjectRemoved(UMLClassifierListItem*)));
+ }
+ connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
+ break;
+ case Uml::ot_Datatype:
+ case Uml::ot_Attribute:
+ case Uml::ot_Operation:
+ case Uml::ot_Template:
+ case Uml::ot_EnumLiteral:
+ case Uml::ot_EntityAttribute:
+ case Uml::ot_Package:
+ case Uml::ot_Actor:
+ case Uml::ot_UseCase:
+ case Uml::ot_Component:
+ case Uml::ot_Artifact:
+ case Uml::ot_Node:
+ case Uml::ot_Folder:
+ connect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
+ break;
+ case Uml::ot_UMLObject:
+ case Uml::ot_Association:
+ case Uml::ot_Stereotype:
+ break;
+ default:
+ kWarning() << "unknown type in connectNewObjectsSlots" << endl;
+ break;
+ }
+}
+
+void UMLListView::slotObjectChanged() {
+ if (m_doc->loading()) { //needed for class wizard
+ return;
+ }
+ UMLObject* obj = const_cast<UMLObject*>( dynamic_cast<const UMLObject*>(sender()) );
+ UMLListViewItem* item = findUMLObject(obj);
+ if(item) {
+ item->updateObject();
+ }
+}
+
+void UMLListView::childObjectAdded(UMLClassifierListItem* obj) {
+ UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
+ childObjectAdded(obj, parent);
+}
+
+void UMLListView::childObjectAdded(UMLClassifierListItem* child, UMLClassifier* parent) {
+ if (m_bCreatingChildObject)
+ return;
+ const QString text = child->toString(Uml::st_SigNoVis);
+ UMLListViewItem *childItem = NULL;
+ UMLListViewItem *parentItem = findUMLObject(parent);
+ if (parentItem == NULL) {
+ kDebug() << "UMLListView::childObjectAdded(" << child->getName()
+ << "): parent " << parent->getName()
+ << " does not yet exist, creating it now." << endl;
+ const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(parent);
+ parentItem = new UMLListViewItem(m_lv[Uml::mt_Logical], parent->getName(), lvt, parent);
+ } else {
+ childItem = parentItem->findChildObject(child);
+ }
+ if (childItem) {
+ childItem->setText(text);
+ } else {
+ const Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(child);
+ childItem = new UMLListViewItem(parentItem, text, lvt, child);
+ if (! m_doc->loading()) {
+ ensureItemVisible(childItem);
+ clearSelection();
+ setSelected(childItem, true);
+ }
+ connectNewObjectsSlots(child);
+ }
+}
+
+void UMLListView::childObjectRemoved(UMLClassifierListItem* obj) {
+ UMLClassifier *parent = const_cast<UMLClassifier*>(dynamic_cast<const UMLClassifier*>(sender()));
+ UMLListViewItem *parentItem = findUMLObject(parent);
+ if (parentItem == NULL) {
+ kError() << "UMLListView::childObjectRemoved(" << obj->getName()
+ << "): cannot find parent UMLListViewItem" << endl;
+ return;
+ }
+ parentItem->deleteChildItem(obj);
+}
+
+void UMLListView::slotDiagramRenamed(Uml::IDType id) {
+ UMLListViewItem* temp;
+ UMLView* v = m_doc->findView(id);
+ if ((temp = findView(v)) == NULL) {
+ kError() << "UMLListView::slotDiagramRenamed: UMLDoc::findView("
+ << ID2STR(id) << ") returns NULL" << endl;
+ return;
+ }
+ temp->setText( v->getName() );
+}
+
+void UMLListView::setDocument(UMLDoc *d) {
+ if( m_doc && m_doc != d)
+ {
+ //disconnect signals from old doc and reset view
+ }
+ m_doc = d;
+
+ connect(m_doc, SIGNAL(sigDiagramCreated(Uml::IDType)), this, SLOT(slotDiagramCreated(Uml::IDType)));
+ connect(m_doc, SIGNAL(sigDiagramRemoved(Uml::IDType)), this, SLOT(slotDiagramRemoved(Uml::IDType)));
+ connect(m_doc, SIGNAL(sigDiagramRenamed(Uml::IDType)), this, SLOT(slotDiagramRenamed(Uml::IDType)));
+ connect(m_doc, SIGNAL(sigObjectCreated(UMLObject *)), this, SLOT(slotObjectCreated(UMLObject *)));
+ connect(m_doc, SIGNAL(sigObjectRemoved(UMLObject *)), this, SLOT(slotObjectRemoved(UMLObject *)));
+}
+
+void UMLListView::slotObjectRemoved(UMLObject* object) {
+ if (m_doc->loading()) { //needed for class wizard
+ return;
+ }
+ disconnect(object,SIGNAL(modified()),this,SLOT(slotObjectChanged()));
+ UMLListViewItem* item = findItem(object->getID());
+ delete item;
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+}
+
+void UMLListView::slotDiagramRemoved(Uml::IDType id) {
+ UMLListViewItem* item = findItem(id);
+ delete item;
+ UMLApp::app()->getDocWindow()->updateDocumentation(true);
+}
+
+QDragObject* UMLListView::dragObject() {
+ UMLListViewItemList selecteditems;
+ getSelectedItems(selecteditems);
+ selecteditems.setAutoDelete( false );
+ UMLListViewItemListIt it(selecteditems);
+ UMLListViewItem * item = 0;
+ UMLListViewItemList list;
+ list.setAutoDelete( false );
+ while((item=it.current()) != 0) {
+ ++it;
+ Uml::ListView_Type type = item->getType();
+ if (!Model_Utils::typeIsCanvasWidget(type) && !Model_Utils::typeIsDiagram(type)
+ && !Model_Utils::typeIsClassifierList(type)) {
+ return 0;
+ }
+ list.append(item);
+ }
+ UMLDrag *t = new UMLDrag(list, this);
+
+ return t;
+}
+
+void UMLListView::startDrag() {
+ QDragObject *o = dragObject();
+ if (o)
+ o->dragCopy();
+}
+
+UMLListViewItem * UMLListView::findUMLObjectInFolder(UMLListViewItem* folder, UMLObject* obj) {
+ UMLListViewItem *item = static_cast<UMLListViewItem *>(folder->firstChild());
+ while(item)
+ {
+ switch(item->getType())
+ {
+ case Uml::lvt_Actor :
+ case Uml::lvt_UseCase :
+ case Uml::lvt_Class :
+ case Uml::lvt_Package :
+ case Uml::lvt_Subsystem :
+ case Uml::lvt_Component :
+ case Uml::lvt_Node :
+ case Uml::lvt_Artifact :
+ case Uml::lvt_Interface :
+ case Uml::lvt_Datatype :
+ case Uml::lvt_Enum :
+ case Uml::lvt_Entity :
+ if(item->getUMLObject() == obj)
+ return item;
+ break;
+ case Uml::lvt_Logical_Folder :
+ case Uml::lvt_UseCase_Folder :
+ case Uml::lvt_Component_Folder :
+ case Uml::lvt_Deployment_Folder :
+ case Uml::lvt_EntityRelationship_Folder :
+ case Uml::lvt_Datatype_Folder :
+ {
+ UMLListViewItem *temp = findUMLObjectInFolder(item, obj);
+ if (temp)
+ return temp;
+ }
+ default:
+ break;
+ }
+ item = static_cast<UMLListViewItem *>(item->nextSibling());
+ }
+ return 0;
+}
+
+UMLListViewItem * UMLListView::findUMLObject(const UMLObject *p) const {
+ UMLListViewItem *item = static_cast<UMLListViewItem*>(firstChild());
+ while (item) {
+ UMLListViewItem *testItem = item->findUMLObject(p);
+ if (testItem)
+ return testItem;
+ item = static_cast<UMLListViewItem*>(item->nextSibling());
+ }
+ return item;
+}
+
+void UMLListView::changeIconOf(UMLObject *o, Uml::Icon_Type to) {
+ UMLListViewItem *item = findUMLObject(o);
+ if (item == NULL)
+ return;
+ item->setIcon(to);
+}
+
+UMLListViewItem* UMLListView::findView(UMLView* v) {
+ if (!v) {
+ kWarning() << "returning 0 from UMLListView::findView()" << endl;
+ return 0;
+ }
+ UMLListViewItem* item;
+ Uml::Diagram_Type dType = v->getType();
+ Uml::ListView_Type type = Model_Utils::convert_DT_LVT( dType );
+ Uml::IDType id = v->getID();
+ if (dType == Uml::dt_UseCase) {
+ item = m_lv[Uml::mt_UseCase];
+ } else if (dType == Uml::dt_Component) {
+ item = m_lv[Uml::mt_Component];
+ } else if (dType == Uml::dt_Deployment) {
+ item = m_lv[Uml::mt_Deployment];
+ } else if (dType == Uml::dt_EntityRelationship) {
+ item = m_lv[Uml::mt_EntityRelationship];
+ } else {
+ item = m_lv[Uml::mt_Logical];
+ }
+
+ UMLListViewItem* searchStartItem = (UMLListViewItem *)item->firstChild();
+
+ UMLListViewItem* foundItem = recursiveSearchForView(searchStartItem, type, id);
+
+ if (!foundItem) {
+ kWarning() << "returning 0 at UMLListView::findView" << endl;
+ }
+ return foundItem;
+}
+
+UMLListViewItem* UMLListView::recursiveSearchForView(UMLListViewItem* listViewItem,
+ Uml::ListView_Type type, Uml::IDType id) {
+ while (listViewItem) {
+ if ( Model_Utils::typeIsFolder(listViewItem->getType()) ) {
+ UMLListViewItem* child = (UMLListViewItem *)listViewItem->firstChild();
+ UMLListViewItem* resultListViewItem = recursiveSearchForView(child, type, id);
+ if (resultListViewItem) {
+ return resultListViewItem;
+ }
+ } else {
+ if(listViewItem->getType() == type && listViewItem->getID() == id) {
+ return listViewItem;
+ }
+ }
+ listViewItem = (UMLListViewItem*)listViewItem->nextSibling();
+ }
+ return 0;
+}
+
+UMLListViewItem* UMLListView::findItem(Uml::IDType id) {
+ UMLListViewItem *temp;
+ QListViewItemIterator it(this);
+ for( ; (temp = (UMLListViewItem*)it.current()); ++it ) {
+ UMLListViewItem * item = temp->findItem(id);
+ if (item)
+ return item;
+ }
+ return 0;
+}
+
+
+//
+// This method is called more than once during an instance's lifetime (by UMLDoc)!
+// So we must not allocate any memory before freeing the previously allocated one
+// or do connect()s.
+//
+void UMLListView::init() {
+ if (m_rv == NULL) {
+ m_rv = new UMLListViewItem(this, i18n("Views"), Uml::lvt_View);
+ for (int i = 0; i < Uml::N_MODELTYPES; i++) {
+ Uml::Model_Type mt = (Uml::Model_Type)i;
+ UMLFolder *sysFolder = m_doc->getRootFolder(mt);
+ Uml::ListView_Type lvt = Model_Utils::convert_MT_LVT(mt);
+ m_lv[i] = new UMLListViewItem(m_rv, sysFolder->getLocalName(), lvt, sysFolder);
+ }
+ } else {
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ deleteChildrenOf(m_lv[i]);
+ }
+ UMLFolder *datatypeFolder = m_doc->getDatatypeFolder();
+ m_datatypeFolder = new UMLListViewItem(m_lv[Uml::mt_Logical], datatypeFolder->getLocalName(),
+ Uml::lvt_Datatype_Folder, datatypeFolder);
+ m_rv->setOpen(true);
+ for (int i = 0; i < Uml::N_MODELTYPES; i++)
+ m_lv[i]->setOpen(true);
+ m_datatypeFolder->setOpen(false);
+
+ //setup misc.
+ delete m_pMenu;
+ m_pMenu = 0;
+ m_bStartedCut = m_bStartedCopy = false;
+ m_bIgnoreCancelRename = true;
+ m_bCreatingChildObject = false;
+}
+
+void UMLListView::setView(UMLView * v) {
+ if(!v)
+ return;
+ UMLListViewItem * temp = findView(v);
+ if(temp)
+ setSelected(temp, true);
+}
+
+void UMLListView::contentsMouseDoubleClickEvent(QMouseEvent * me) {
+ UMLListViewItem * item = static_cast<UMLListViewItem *>( currentItem() );
+ if( !item || me -> button() != Qt::LeftButton )
+ return;
+ //see if on view
+ Uml::ListView_Type lvType = item -> getType();
+ if( Model_Utils::typeIsDiagram(lvType) ) {
+ UMLView * pView = m_doc -> findView( item -> getID() );
+ if( !pView )
+ return;
+ UMLApp::app() -> getDocWindow() -> updateDocumentation( false );
+ pView -> showPropDialog();
+ UMLApp::app() -> getDocWindow() -> showDocumentation( pView, true );
+ item -> cancelRename( 0 );
+ return;
+ }
+ //else see if an object
+ UMLObject * object = item -> getUMLObject();
+ //continue only if we are on a UMLObject
+ if(!object)
+ return;
+
+
+ Uml::Object_Type type = object -> getBaseType();
+ int page = ClassPropDlg::page_gen;
+ if(type == Uml::ot_Attribute || type == Uml::ot_Operation)
+ object = (UMLObject *)object -> parent();
+ //set what page to show
+ if(type == Uml::ot_Attribute)
+ page = ClassPropDlg::page_att;
+ else if(type == Uml::ot_Operation)
+ page = ClassPropDlg::page_op;
+ //FIXME for entityattributes
+
+ if(object)
+ object->showProperties(page);
+ item -> cancelRename( 0 );//double click can cause it to go into rename mode.
+}
+
+
+bool UMLListView::acceptDrag(QDropEvent* event) const {
+ QPoint mousePoint = ((UMLListView*)this)->contentsToViewport( event->pos() );
+
+ UMLListViewItem* item = (UMLListViewItem*)itemAt(mousePoint);
+ if(!item) {
+ kDebug() << "UMLListView::acceptDrag: itemAt(mousePoint) returns NULL"
+ << endl;
+ return false;
+ }
+ ((QListView*)this)->setCurrentItem( (QListViewItem*)item );
+
+ UMLDrag::LvTypeAndID_List list;
+ if (! UMLDrag::getClip3TypeAndID(event, list)) {
+ kDebug() << "UMLListView::acceptDrag: UMLDrag::getClip3TypeAndID returns false"
+ << endl;
+ return false;
+ }
+
+ UMLDrag::LvTypeAndID_It it(list);
+ UMLDrag::LvTypeAndID * data = 0;
+ Uml::ListView_Type dstType = item->getType();
+ bool accept = true;
+ while(accept && ((data = it.current()) != 0)) {
+ ++it;
+ Uml::ListView_Type srcType = data->type;
+ switch (srcType) {
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Enum:
+ if (dstType == Uml::lvt_Logical_View ||
+ dstType == Uml::lvt_Class ||
+ dstType == Uml::lvt_Package) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_Logical_Folder);
+ }
+ break;
+ case Uml::lvt_Attribute:
+ if (dstType == Uml::lvt_Class) {
+ accept = !item->isOwnParent(data->id);
+ }
+ break;
+ case Uml::lvt_EntityAttribute:
+ if (dstType == Uml::lvt_Entity) {
+ accept = !item->isOwnParent(data->id);
+ }
+ break;
+ case Uml::lvt_Operation:
+ if (dstType == Uml::lvt_Class ||
+ dstType == Uml::lvt_Interface) {
+ accept = !item->isOwnParent(data->id);
+ }
+ break;
+ case Uml::lvt_Datatype:
+ accept = (dstType == Uml::lvt_Logical_Folder ||
+ dstType == Uml::lvt_Datatype_Folder ||
+ dstType == Uml::lvt_Class ||
+ dstType == Uml::lvt_Interface ||
+ dstType == Uml::lvt_Package);
+ break;
+ case Uml::lvt_Class_Diagram:
+ case Uml::lvt_Collaboration_Diagram:
+ case Uml::lvt_State_Diagram:
+ case Uml::lvt_Activity_Diagram:
+ case Uml::lvt_Sequence_Diagram:
+ accept = (dstType == Uml::lvt_Logical_Folder ||
+ dstType == Uml::lvt_Logical_View);
+ break;
+ case Uml::lvt_Logical_Folder:
+ if (dstType == Uml::lvt_Logical_Folder) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_Logical_View);
+ }
+ break;
+ case Uml::lvt_UseCase_Folder:
+ if (dstType == Uml::lvt_UseCase_Folder) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_UseCase_View);
+ }
+ break;
+ case Uml::lvt_Component_Folder:
+ if (dstType == Uml::lvt_Component_Folder) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_Component_View);
+ }
+ break;
+ case Uml::lvt_Deployment_Folder:
+ if (dstType == Uml::lvt_Deployment_Folder) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_Deployment_View);
+ }
+ break;
+ case Uml::lvt_EntityRelationship_Folder:
+ if (dstType == Uml::lvt_EntityRelationship_Folder) {
+ accept = !item->isOwnParent(data->id);
+ } else {
+ accept = (dstType == Uml::lvt_EntityRelationship_Model);
+ }
+ break;
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_UseCase_Diagram:
+ accept = (dstType == Uml::lvt_UseCase_Folder ||
+ dstType == Uml::lvt_UseCase_View);
+ break;
+ case Uml::lvt_Subsystem:
+ accept = (dstType == Uml::lvt_Component_Folder ||
+ dstType == Uml::lvt_Subsystem);
+ break;
+ case Uml::lvt_Component:
+ accept = (dstType == Uml::lvt_Component_Folder ||
+ dstType == Uml::lvt_Component ||
+ dstType == Uml::lvt_Subsystem);
+ break;
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Component_Diagram:
+ accept = (dstType == Uml::lvt_Component_Folder ||
+ dstType == Uml::lvt_Component_View);
+ break;
+ case Uml::lvt_Node:
+ case Uml::lvt_Deployment_Diagram:
+ accept = (dstType == Uml::lvt_Deployment_Folder);
+ break;
+ case Uml::lvt_Entity:
+ case Uml::lvt_EntityRelationship_Diagram:
+ accept = (dstType == Uml::lvt_EntityRelationship_Folder);
+ break;
+ default:
+ accept = false;
+ break;
+ }
+ }
+
+ //kDebug() << "UMLListView::acceptDrag: dstType = " << dstType
+ // << ", accept=" << accept << endl;
+ return accept;
+}
+
+void UMLListView::addAtContainer(UMLListViewItem *item, UMLListViewItem *parent) {
+ UMLCanvasObject *o = static_cast<UMLCanvasObject*>(item->getUMLObject());
+ if (o == NULL) {
+ kDebug() << "UMLListView::addAtContainer(" << item->getText()
+ << "): item's UMLObject is NULL" << endl;
+ } else if (Model_Utils::typeIsContainer(parent->getType())) {
+ /**** TBC: Do this here?
+ If yes then remove that logic at the callers
+ and rename this method to moveAtContainer()
+ UMLPackage *oldPkg = o->getUMLPackage();
+ if (oldPkg)
+ oldPkg->removeObject(o);
+ *********/
+ UMLPackage *pkg = static_cast<UMLPackage*>(parent->getUMLObject());
+ o->setUMLPackage(pkg);
+ pkg->addObject(o);
+ } else {
+ kError() << "UMLListView::addAtContainer(" << item->getText()
+ << "): parent type is " << parent->getType() << endl;
+ }
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView)
+ currentView->updateContainment(o);
+}
+
+UMLListViewItem * UMLListView::moveObject(Uml::IDType srcId, Uml::ListView_Type srcType,
+ UMLListViewItem *newParent) {
+ if (newParent == NULL)
+ return NULL;
+ UMLListViewItem * move = findItem( srcId );
+ if (move == NULL)
+ return NULL;
+
+ UMLObject *newParentObj = NULL;
+ // Remove the source object at the old parent package.
+ UMLObject *srcObj = m_doc->findObjectById(srcId);
+ if (srcObj) {
+ newParentObj = newParent->getUMLObject();
+ if (srcObj == newParentObj) {
+ kError() << "UMLListView::moveObject(" << srcObj->getName()
+ << "): Cannot move onto self" << endl;
+ return NULL;
+ }
+ UMLPackage *srcPkg = srcObj->getUMLPackage();
+ if (srcPkg) {
+ if (srcPkg == newParentObj) {
+ kError() << "UMLListView::moveObject(" << srcObj->getName()
+ << "): Object is already in target package" << endl;
+ return NULL;
+ }
+ srcPkg->removeObject(srcObj);
+ }
+ }
+
+ Uml::ListView_Type newParentType = newParent->getType();
+ kDebug() << "UMLListView::moveObject: newParentType is " << newParentType << endl;
+ UMLListViewItem *newItem = NULL;
+
+ //make sure trying to place in correct location
+ switch (srcType) {
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_UseCase_Diagram:
+ if (newParentType == Uml::lvt_UseCase_Folder ||
+ newParentType == Uml::lvt_UseCase_View) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Component_Diagram:
+ if (newParentType == Uml::lvt_Component_Folder ||
+ newParentType == Uml::lvt_Component_View) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Subsystem:
+ if (newParentType == Uml::lvt_Component_Folder ||
+ newParentType == Uml::lvt_Component_View ||
+ newParentType == Uml::lvt_Subsystem) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Component:
+ if (newParentType == Uml::lvt_Component_Folder ||
+ newParentType == Uml::lvt_Component_View ||
+ newParentType == Uml::lvt_Component ||
+ newParentType == Uml::lvt_Subsystem) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_Node:
+ case Uml::lvt_Deployment_Diagram:
+ if (newParentType == Uml::lvt_Deployment_Folder ||
+ newParentType == Uml::lvt_Deployment_View) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_EntityRelationship_Folder:
+ case Uml::lvt_Entity:
+ case Uml::lvt_EntityRelationship_Diagram:
+ if (newParentType == Uml::lvt_EntityRelationship_Folder ||
+ newParentType == Uml::lvt_EntityRelationship_Model) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Collaboration_Diagram:
+ case Uml::lvt_Class_Diagram:
+ case Uml::lvt_State_Diagram:
+ case Uml::lvt_Activity_Diagram:
+ case Uml::lvt_Sequence_Diagram:
+ case Uml::lvt_Logical_Folder:
+ if (newParentType == Uml::lvt_Logical_Folder ||
+ newParentType == Uml::lvt_Logical_View) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ addAtContainer(newItem, newParent);
+ }
+ break;
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Datatype:
+ if (newParentType == Uml::lvt_Logical_Folder ||
+ newParentType == Uml::lvt_Datatype_Folder ||
+ newParentType == Uml::lvt_Logical_View ||
+ newParentType == Uml::lvt_Class ||
+ newParentType == Uml::lvt_Interface ||
+ newParentType == Uml::lvt_Package) {
+ newItem = move->deepCopy(newParent);
+ if (m_doc->loading()) // deletion is not safe while loading
+ move->setVisible(false); // (the <listview> XMI may be corrupted)
+ else
+ delete move;
+ UMLCanvasObject *o = static_cast<UMLCanvasObject*>(newItem->getUMLObject());
+ if (o == NULL) {
+ kDebug() << "moveObject: newItem's UMLObject is NULL" << endl;
+ } else if (newParentObj == NULL) {
+ kError() << "UMLListView::moveObject(" << o->getName()
+ << "): newParentObj is NULL" << endl;
+ } else {
+ UMLPackage *pkg = static_cast<UMLPackage*>(newParentObj);
+ o->setUMLPackage( pkg );
+ pkg->addObject( o );
+ }
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ if (currentView)
+ currentView->updateContainment(o);
+ }
+ break;
+ case Uml::lvt_Attribute:
+ case Uml::lvt_Operation:
+ if (newParentType == Uml::lvt_Class ||
+ newParentType == Uml::lvt_Interface) {
+ // update list view
+
+ newItem = move->deepCopy(newParent);
+ // we don't delete move right away, it will be deleted in slots,
+ // called by subsequent steps
+ //delete move;
+
+ // update model objects
+ m_bCreatingChildObject = true;
+
+ UMLClassifier *oldParentClassifier = dynamic_cast<UMLClassifier*>(srcObj->parent());
+ UMLClassifier *newParentClassifier = dynamic_cast<UMLClassifier*>(newParentObj);
+ if (srcType == Uml::lvt_Attribute) {
+ UMLAttribute *att = dynamic_cast<UMLAttribute*>(srcObj);
+ // We can't use the existing 'att' directly
+ // because its parent is fixed to the old classifier
+ // and we have no way of changing that:
+ // QObject does not permit changing the parent().
+ if (att == NULL) {
+ kError() << "moveObject internal error: srcObj "
+ << srcObj->getName() << " is not a UMLAttribute" << endl;
+ } else if (oldParentClassifier->takeItem(att) == -1) {
+ kError() << "moveObject: oldParentClassifier->takeItem(att "
+ << att->getName() << ") returns NULL" << endl;
+ } else {
+ const QString& nm = att->getName();
+ UMLAttribute *newAtt = newParentClassifier->createAttribute(nm,
+ att->getType(),
+ att->getVisibility(),
+ att->getInitialValue());
+ newItem->setUMLObject(newAtt);
+ newParent->addClassifierListItem( newAtt, newItem );
+
+ connectNewObjectsSlots( newAtt );
+ // Let's not forget to update the DocWindow::m_pObject
+ // because the old one is about to be physically deleted !
+ UMLApp::app()->getDocWindow()->showDocumentation(newAtt, true);
+ delete att;
+ }
+ } else {
+ UMLOperation *op = dynamic_cast<UMLOperation*>(srcObj);
+ // We can't use the existing 'op' directly
+ // because its parent is fixed to the old classifier
+ // and we have no way of changing that:
+ // QObject does not permit changing the parent().
+ if (op && oldParentClassifier->takeItem(op) != -1) {
+ bool isExistingOp;
+ Model_Utils::NameAndType_List ntDummyList;
+ // We need to provide a dummy NameAndType_List
+ // else UMLClassifier::createOperation will
+ // bring up an operation dialog.
+ UMLOperation *newOp = newParentClassifier->createOperation(
+ op->getName(), &isExistingOp, &ntDummyList);
+ newOp->setType(op->getType());
+ newOp->setVisibility(op->getVisibility());
+ UMLAttributeList parmList = op->getParmList();
+ for (UMLAttributeListIt plit(parmList); plit.current(); ++plit) {
+ UMLAttribute *parm = plit.current();
+ UMLAttribute *newParm = new UMLAttribute(newParentClassifier,
+ parm->getName(),
+ Uml::id_None,
+ parm->getVisibility(),
+ parm->getType(),
+ parm->getInitialValue());
+ newParm->setParmKind(parm->getParmKind());
+ newOp->addParm(newParm);
+ }
+ newItem->setUMLObject(newOp);
+ newParent->addClassifierListItem( newOp, newItem );
+
+ connectNewObjectsSlots( newOp );
+
+ // Let's not forget to update the DocWindow::m_pObject
+ // because the old one is about to be physically deleted !
+ UMLApp::app()->getDocWindow()->showDocumentation(newOp, true);
+ delete op;
+ } else {
+ kError() << "moveObject: oldParentClassifier->takeItem(op) returns NULL"
+ << endl;
+ }
+ }
+ m_bCreatingChildObject = false;
+ }
+ break;
+ default:
+ break;
+ }
+ return newItem;
+}
+
+void UMLListView::slotDropped(QDropEvent* de, QListViewItem* /* parent */, QListViewItem* item) {
+ item = (UMLListViewItem *)currentItem();
+ if(!item) {
+ kDebug() << "UMLListView::slotDropped: item is NULL - doing nothing" << endl;
+ return;
+ }
+ UMLDrag::LvTypeAndID_List srcList;
+ if (! UMLDrag::getClip3TypeAndID(de, srcList)) {
+ return;
+ }
+ UMLListViewItem *newParent = (UMLListViewItem*)item;
+ kDebug() << "slotDropped: newParent->getText() is " << newParent->getText() << endl;
+ UMLDrag::LvTypeAndID_It it(srcList);
+ UMLDrag::LvTypeAndID * src = 0;
+ while((src = it.current()) != 0) {
+ ++it;
+ moveObject(src->id, src->type, newParent);
+ }
+}
+
+int UMLListView::getSelectedItems(UMLListViewItemList &ItemList) {
+ ItemList.setAutoDelete( false );
+ QListViewItemIterator it(this);
+ // iterate through all items of the list view
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isSelected() ) {
+ UMLListViewItem *item = (UMLListViewItem*)it.current();
+ ItemList.append(item);
+ }
+ }
+ kDebug() << "UMLListView::getSelectedItems: selItems = " << ItemList.count() << endl;
+
+ return (int)ItemList.count();
+}
+
+int UMLListView::getSelectedItemsRoot(UMLListViewItemList &ItemList) {
+ ItemList.setAutoDelete( false );
+ QListViewItemIterator it(this);
+
+ // iterate through all items of the list view
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isSelected() ) {
+ UMLListViewItem *item = (UMLListViewItem*)it.current();
+ // this is the trick, we select only the item with a parent unselected
+ // since we can't select a child and its grandfather without its parent
+ // we would be able to delete each item individually, without an invalid iterator
+ if (item && item->parent() && item->parent()->isSelected()==false) {
+ ItemList.append(item);
+ }
+ }
+ }
+ kDebug() << "UMLListView::getSelectedItemsRoot: selItems = " << ItemList.count() << endl;
+
+ return (int)ItemList.count();
+}
+
+UMLListViewItem* UMLListView::createDiagramItem(UMLView *v) {
+ Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
+ UMLListViewItem *parent = NULL;
+ UMLFolder *f = v->getFolder();
+ if (f) {
+ parent = findUMLObject(f);
+ if (parent == NULL)
+ kError() << "UMLListView::createDiagramItem(" << v->getName()
+ << "): findUMLObject(" << f->getName() << ") returns NULL"
+ << endl;
+ } else {
+ kDebug() << "UMLListView::createDiagramItem(" << v->getName()
+ << "): no parent folder set, using predefined folder" << endl;
+ }
+ if (parent == NULL) {
+ parent = determineParentItem(lvt);
+ lvt = Model_Utils::convert_DT_LVT(v->getType());
+ }
+ UMLListViewItem *item = new UMLListViewItem(parent, v->getName(), lvt, v->getID());
+ return item;
+}
+
+/** Creates a new UMLListViewItem from a UMLListViewItem,
+ if parent is null the ListView Decides who is going to be
+ the parent */
+UMLListViewItem* UMLListView::createItem(UMLListViewItem& Data, IDChangeLog& IDChanges,
+ UMLListViewItem* parent /*= 0*/) {
+ UMLObject* pObject = 0;
+ UMLListViewItem* item = 0;
+ Uml::ListView_Type lvt = Data.getType();
+ if(!parent) {
+ parent = determineParentItem(lvt);
+ if (!parent)
+ return 0;
+ }
+
+ switch(lvt) {
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Component:
+ case Uml::lvt_Node:
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Entity:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ /***
+ int newID = IDChanges.findNewID(Data.getID());
+ //if there is no ListViewItem associated with the new ID,
+ //it could exist an Item already asocciated if the user chose to reuse an uml object
+ if(!(item = findItem(newID))) {
+ pObject = m_doc->findObjectById( IDChanges.findNewID(Data.getID()) );
+ item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
+ } ***/
+ pObject = m_doc->findObjectById( Data.getID() );
+ item = new UMLListViewItem(parent, Data.getText(), lvt, pObject);
+ break;
+ case Uml::lvt_Datatype_Folder:
+ item = new UMLListViewItem(parent, Data.getText(), lvt);
+ break;
+ case Uml::lvt_Attribute:
+ case Uml::lvt_EntityAttribute:
+ case Uml::lvt_Operation:
+ case Uml::lvt_Template:
+ case Uml::lvt_EnumLiteral:
+ {
+ UMLClassifier *pClass = static_cast<UMLClassifier*>(parent->getUMLObject());
+ Uml::IDType newID = IDChanges.findNewID( Data.getID() );
+ pObject = pClass->findChildObjectById(newID);
+ if (pObject) {
+ item = new UMLListViewItem( parent, Data.getText(), lvt, pObject );
+ } else {
+ item = 0;
+ }
+ break;
+ }
+ case Uml::lvt_UseCase_Diagram:
+ case Uml::lvt_Sequence_Diagram:
+ case Uml::lvt_Collaboration_Diagram:
+ case Uml::lvt_Class_Diagram:
+ case Uml::lvt_State_Diagram:
+ case Uml::lvt_Activity_Diagram:
+ case Uml::lvt_Component_Diagram:
+ case Uml::lvt_Deployment_Diagram:
+ case Uml::lvt_EntityRelationship_Diagram:
+ {
+ Uml::IDType newID = IDChanges.findNewID(Data.getID());
+ UMLView* v = m_doc->findView(newID);
+ if (v == NULL) {
+ return NULL;
+ }
+ const Uml::ListView_Type lvt = Model_Utils::convert_DT_LVT(v->getType());
+ item = new UMLListViewItem(parent, v->getName(), lvt, newID);
+ }
+ break;
+ default:
+ kWarning() << "createItem() called on unknown type" << endl;
+ break;
+ }
+ return item;
+}
+
+UMLListViewItem* UMLListView::determineParentItem(Uml::ListView_Type lvt) const {
+ UMLListViewItem* parent = 0;
+ switch (lvt) {
+ case Uml::lvt_Datatype:
+ parent = m_datatypeFolder;
+ break;
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_UseCase_Diagram:
+ parent = m_lv[Uml::mt_UseCase];
+ break;
+ case Uml::lvt_Component_Diagram:
+ case Uml::lvt_Component:
+ case Uml::lvt_Artifact:
+ parent = m_lv[Uml::mt_Component];
+ break;
+ case Uml::lvt_Deployment_Diagram:
+ case Uml::lvt_Node:
+ parent = m_lv[Uml::mt_Deployment];
+ break;
+ case Uml::lvt_EntityRelationship_Diagram:
+ case Uml::lvt_Entity:
+ parent = m_lv[Uml::mt_EntityRelationship];
+ break;
+ default:
+ if (Model_Utils::typeIsDiagram(lvt) || !Model_Utils::typeIsClassifierList(lvt))
+ parent = m_lv[Uml::mt_Logical];
+ break;
+ }
+ return parent;
+}
+
+int UMLListView::getSelectedCount() {
+ QListViewItemIterator it(this);
+ int count = 0;
+ // iterate through all items of the list view
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isSelected() ) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+void UMLListView::focusOutEvent ( QFocusEvent * fe) {
+ QFocusEvent::Reason reason = fe->reason();
+ if (reason != QFocusEvent::Popup) {
+ clearSelection();
+ triggerUpdate();
+ }
+ //repaint();
+
+ QListView::focusOutEvent(fe);
+}
+
+Uml::ListView_Type UMLListView::rootViewType(UMLListViewItem *item) {
+ if (item == m_rv)
+ return Uml::lvt_View;
+ if (item == m_lv[Uml::mt_Logical])
+ return Uml::lvt_Logical_View;
+ if (item == m_lv[Uml::mt_UseCase])
+ return Uml::lvt_UseCase_View;
+ if (item == m_lv[Uml::mt_Component])
+ return Uml::lvt_Component_View;
+ if (item == m_lv[Uml::mt_Deployment])
+ return Uml::lvt_Deployment_View;
+ if (item == m_lv[Uml::mt_EntityRelationship])
+ return Uml::lvt_EntityRelationship_Model;
+ UMLListViewItem *parent = dynamic_cast<UMLListViewItem*>(item->parent());
+ if (parent)
+ return rootViewType(parent);
+ return Uml::lvt_Unknown;
+}
+
+QPixmap & UMLListView::getPixmap(Uml::Icon_Type type) {
+ if (type < Uml::it_Home || type >= Uml::N_ICONTYPES) {
+ kWarning() << "getPixmap() called on unknown icon " << type << endl;
+ // you'll know you have a problem if this shows up in the list
+ type = Uml::it_Home;
+ }
+ return m_Pixmaps[type];
+}
+
+void UMLListView::loadPixmaps() {
+ KStandardDirs * dirs = KGlobal::dirs();
+ QString dataDir = dirs -> findResourceDir("data", "umbrello/pics/object.png");
+ dataDir += "/umbrello/pics/";
+
+#define makeBarIcon(iconType, barIcon) m_Pixmaps[iconType] = BarIcon(barIcon)
+ makeBarIcon(Uml::it_Home, "folder_home");
+ makeBarIcon(Uml::it_Folder_Cyan, "folder");
+ makeBarIcon(Uml::it_Folder_Cyan_Open, "folder_open");
+ makeBarIcon(Uml::it_Folder_Green, "folder_green");
+ makeBarIcon(Uml::it_Folder_Green_Open, "folder_green_open");
+ makeBarIcon(Uml::it_Folder_Orange, "folder_orange");
+ makeBarIcon(Uml::it_Folder_Orange_Open, "folder_orange_open");
+ makeBarIcon(Uml::it_Folder_Grey, "folder_grey");
+ makeBarIcon(Uml::it_Folder_Grey_Open, "folder_grey_open");
+ makeBarIcon(Uml::it_Folder_Red, "folder_red");
+ makeBarIcon(Uml::it_Folder_Red_Open, "folder_red_open");
+ makeBarIcon(Uml::it_Folder_Violet, "folder_violet");
+ makeBarIcon(Uml::it_Folder_Violet_Open, "folder_violet_open");
+
+ makeBarIcon(Uml::it_Diagram_Activity, "umbrello_diagram_activity");
+ makeBarIcon(Uml::it_Diagram_Class, "umbrello_diagram_class");
+ makeBarIcon(Uml::it_Diagram_Component, "umbrello_diagram_component");
+ makeBarIcon(Uml::it_Diagram_State, "umbrello_diagram_state");
+ makeBarIcon(Uml::it_Diagram_Sequence, "umbrello_diagram_sequence");
+ makeBarIcon(Uml::it_Diagram_Deployment, "umbrello_diagram_deployment");
+ makeBarIcon(Uml::it_Diagram_EntityRelationship, "umbrello_diagram_deployment");
+ makeBarIcon(Uml::it_Diagram_Usecase, "umbrello_diagram_usecase");
+ makeBarIcon(Uml::it_Diagram_Collaboration, "umbrello_diagram_collaboration");
+#undef makeBarIcon
+
+#define loadPixmap(iconType, pngName) m_Pixmaps[iconType].load(dataDir + pngName)
+ loadPixmap(Uml::it_Diagram, "CVnamespace.png");
+ loadPixmap(Uml::it_Class, "class.png");
+ loadPixmap(Uml::it_Template, "template.png");
+ loadPixmap(Uml::it_Package, "package.png");
+ loadPixmap(Uml::it_Subsystem, "subsystem.png");
+ loadPixmap(Uml::it_Component, "component.png");
+ loadPixmap(Uml::it_Node, "node.png");
+ loadPixmap(Uml::it_Artifact, "artifact.png");
+ loadPixmap(Uml::it_Interface, "interface.png");
+ loadPixmap(Uml::it_Datatype, "datatype.png");
+ loadPixmap(Uml::it_Enum, "enum.png");
+ loadPixmap(Uml::it_Entity, "entity.png");
+ loadPixmap(Uml::it_Actor, "actor.png");
+ loadPixmap(Uml::it_UseCase, "usecase.png");
+ loadPixmap(Uml::it_Public_Method, "CVpublic_meth.png");
+ loadPixmap(Uml::it_Private_Method, "CVprivate_meth.png");
+ loadPixmap(Uml::it_Protected_Method, "CVprotected_meth.png");
+ loadPixmap(Uml::it_Public_Attribute, "CVpublic_var.png");
+ loadPixmap(Uml::it_Private_Attribute, "CVprivate_var.png");
+ loadPixmap(Uml::it_Protected_Attribute, "CVprotected_var.png");
+#undef loadPixmap
+}
+
+bool UMLListView::isExpandable(Uml::ListView_Type lvt) {
+ if (Model_Utils::typeIsRootView(lvt) || Model_Utils::typeIsFolder(lvt))
+ return true;
+ switch (lvt) {
+ case Uml::lvt_Package:
+ case Uml::lvt_Component:
+ case Uml::lvt_Subsystem:
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void UMLListView::slotExpanded( QListViewItem * item ) {
+ UMLListViewItem * myItem= static_cast<UMLListViewItem*>(item);
+ if (isExpandable(myItem->getType()))
+ myItem->updateFolder();
+}
+
+void UMLListView::slotCollapsed( QListViewItem * item ) {
+ UMLListViewItem * myItem = static_cast<UMLListViewItem*>(item);
+ if (isExpandable(myItem->getType()))
+ myItem->updateFolder();
+}
+
+void UMLListView::slotCutSuccessful() {
+ if( m_bStartedCut ) {
+ popupMenuSel( ListPopupMenu::mt_Delete );
+ //deletion code here
+ m_bStartedCut = false;
+ }
+}
+
+void UMLListView::addNewItem(UMLListViewItem *parentItem, Uml::ListView_Type type) {
+ if (type == Uml::lvt_Datatype) {
+ parentItem = m_datatypeFolder;
+ }
+
+ UMLListViewItem * newItem = NULL;
+ parentItem->setOpen( true );
+
+ Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(type);
+
+ QString name;
+ if (Model_Utils::typeIsDiagram(type)) {
+ Uml::Diagram_Type dt = Model_Utils::convert_LVT_DT(type);
+ name = getUniqueDiagramName(dt);
+ newItem = new UMLListViewItem(parentItem, name, type, Uml::id_None);
+ } else {
+ Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
+ if (ot == Uml::ot_UMLObject) {
+ kDebug() << "UMLListView::addNewItem: no UMLObject for listview type "
+ << type << endl;
+ return;
+ }
+ UMLPackage *parentPkg =
+ dynamic_cast<UMLPackage*>(parentItem->getUMLObject());
+ if (parentPkg == NULL) {
+ kError() << "UMLListView::addNewItem(type " << type
+ << "): parentPkg is NULL" << endl;
+ return;
+ }
+ if (Model_Utils::typeIsClassifierList(type)) {
+ UMLClassifier *parent = static_cast<UMLClassifier*>(parentPkg);
+ name = parent->uniqChildName(ot);
+ } else {
+ name = Model_Utils::uniqObjectName(ot, parentPkg);
+ }
+ newItem = new UMLListViewItem(parentItem, name, type, (UMLObject*)0);
+ }
+ m_bIgnoreCancelRename = false;
+ newItem->setIcon( icon );
+ newItem->setOpen( true );
+ newItem->setCreating( true );
+ newItem->startRename( 0 ); // calls QListView::ensureItemVisible()
+ // When the user accepts the rename operation, UMLListViewItem::okRename()
+ // is called (automatically by QListViewItem.)
+}
+
+bool UMLListView::itemRenamed( QListViewItem * item , int /*col*/ ) {
+ //if true the item was cancel before this message
+ if( m_bIgnoreCancelRename ) {
+ return true;
+ }
+ m_bIgnoreCancelRename = true;
+ UMLListViewItem * renamedItem = static_cast< UMLListViewItem *>( item ) ;
+ Uml::ListView_Type type = renamedItem -> getType();
+ QString newText = renamedItem -> text( 0 );
+ renamedItem -> setCreating( false );
+
+ // If the type is empty then delete it.
+ if (newText.isEmpty() || newText.contains(QRegExp("^\\s+$"))) {
+ KMessageBox::error(
+ kapp -> mainWidget(),
+ i18n( "The name you entered was invalid.\nCreation process has been canceled." ),
+ i18n( "Name Not Valid" ) );
+ return false;
+ }
+
+ if( !isUnique( renamedItem, newText ) ) {
+ //if operation ask if ok not to be unique i.e overloading
+ if( type == Uml::lvt_Operation ) {
+ if( KMessageBox::warningYesNo(
+ kapp -> mainWidget(),
+ i18n( "The name you entered was not unique.\nIs this what you wanted?" ),
+ i18n( "Name Not Unique" ), i18n("Use Name"), i18n("Enter New Name") ) == KMessageBox::No ) {
+ return false;
+ }
+ } else {
+ KMessageBox::error(
+ kapp -> mainWidget(),
+ i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
+ i18n( "Name Not Unique" ) );
+ return false;
+ }
+ }
+
+ switch( type ) {
+ case Uml::lvt_Actor:
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Component:
+ case Uml::lvt_Node:
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Entity:
+ case Uml::lvt_UseCase:
+ {
+ Uml::Object_Type ot = Model_Utils::convert_LVT_OT(type);
+ if (! ot) {
+ kError() << "UMLListView::itemRenamed() internal" << endl;
+ return false;
+ }
+ UMLObject *o = createUMLObject( renamedItem, ot );
+ if (type == Uml::lvt_Subsystem)
+ o->setStereotype("subsystem");
+ else if (Model_Utils::typeIsFolder(type))
+ o->setStereotype("folder");
+ }
+ break;
+
+ case Uml::lvt_Attribute:
+ case Uml::lvt_EntityAttribute:
+ case Uml::lvt_Operation:
+ case Uml::lvt_Template:
+ case Uml::lvt_EnumLiteral:
+ return createChildUMLObject( renamedItem, Model_Utils::convert_LVT_OT(type) );
+ break;
+
+ case Uml::lvt_Class_Diagram:
+ createDiagram( renamedItem, Uml::dt_Class );
+ break;
+
+ case Uml::lvt_UseCase_Diagram:
+ createDiagram( renamedItem, Uml::dt_UseCase );
+ break;
+
+ case Uml::lvt_Sequence_Diagram:
+ createDiagram( renamedItem, Uml::dt_Sequence );
+ break;
+
+ case Uml::lvt_Collaboration_Diagram:
+ createDiagram( renamedItem, Uml::dt_Collaboration );
+ break;
+
+ case Uml::lvt_State_Diagram:
+ createDiagram( renamedItem, Uml::dt_State );
+ break;
+
+ case Uml::lvt_Activity_Diagram:
+ createDiagram( renamedItem, Uml::dt_Activity );
+ break;
+
+ case Uml::lvt_Component_Diagram:
+ createDiagram( renamedItem, Uml::dt_Component );
+ break;
+
+ case Uml::lvt_Deployment_Diagram:
+ createDiagram( renamedItem, Uml::dt_Deployment );
+ break;
+
+ case Uml::lvt_EntityRelationship_Diagram:
+ createDiagram( renamedItem, Uml::dt_EntityRelationship );
+ break;
+
+ default:
+ break;
+ }
+ return true;
+}
+
+UMLObject *UMLListView::createUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
+ QString name = item -> text( 0 );
+ UMLObject * object = NULL;
+ switch( type ) {
+ case Uml::ot_UseCase:
+ object = new UMLUseCase( name );
+ break;
+
+ case Uml::ot_Actor:
+ object = new UMLActor( name );
+ break;
+
+ case Uml::ot_Class:
+ object = new UMLClassifier( name );
+ break;
+
+ case Uml::ot_Package:
+ object = new UMLPackage( name );
+ break;
+
+ case Uml::ot_Folder:
+ object = new UMLFolder( name );
+ break;
+
+ case Uml::ot_Component:
+ object = new UMLComponent( name );
+ break;
+
+ case Uml::ot_Node:
+ object = new UMLNode( name );
+ break;
+
+ case Uml::ot_Artifact:
+ object = new UMLArtifact( name );
+ break;
+
+ case Uml::ot_Interface:
+ {
+ UMLClassifier *c = new UMLClassifier(name);
+ c->setBaseType(Uml::ot_Interface);
+ object = c;
+ }
+ break;
+
+ case Uml::ot_Datatype:
+ {
+ UMLClassifier *c = new UMLClassifier(name);
+ c->setBaseType(Uml::ot_Datatype);
+ object = c;
+ }
+ break;
+
+ case Uml::ot_Enum:
+ object = new UMLEnum( name );
+ break;
+
+ case Uml::ot_Entity:
+ object = new UMLEntity( name );
+ break;
+
+ default:
+ kWarning() << "creating UML Object of unknown type" << endl;
+ return NULL;
+ }
+
+ UMLListViewItem * parentItem = static_cast<UMLListViewItem *>(item->parent());
+ const Uml::ListView_Type lvt = parentItem->getType();
+ if (! Model_Utils::typeIsContainer(lvt)) {
+ kError() << "UMLListView::createUMLObject(" << object->getName()
+ << "): parentItem (" << lvt << " is not a container" << endl;
+ delete object;
+ return NULL;
+ }
+ UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
+ object->setUMLPackage(pkg);
+ pkg->addObject(object);
+ connectNewObjectsSlots(object);
+ item -> setUMLObject( object );
+ item -> setText( name );
+ return object;
+}
+
+bool UMLListView::createChildUMLObject( UMLListViewItem * item, Uml::Object_Type type ) {
+ m_bCreatingChildObject = true;
+ QString text = item->text( 0 );
+ UMLObject* parent = static_cast<UMLListViewItem *>( item->parent() )->getUMLObject();
+ if( !parent ) {
+ kError() << "UMLListView::createChildUMLObject: parent UMLObject is NULL" << endl;
+ m_bCreatingChildObject = false;
+ return false;
+ }
+
+ //kDebug() << "UMLListView::createChildUMLObject (" << text << ")" << endl;
+ UMLObject* newObject = NULL;
+ if ( type == Uml::ot_EnumLiteral ) {
+ UMLEnum *owningEnum = static_cast<UMLEnum*>(parent);
+ newObject = owningEnum->createEnumLiteral(text);
+
+ UMLEnumLiteral* enumLiteral = static_cast<UMLEnumLiteral*>(newObject);
+ text = enumLiteral->toString(Uml::st_SigNoVis);
+ } else if ( type == Uml::ot_Template ) {
+ UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
+ Model_Utils::NameAndType nt;
+ Model_Utils::Parse_Status st = Model_Utils::parseTemplate(text, nt, owningClassifier);
+ if (st) {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Creation canceled") );
+ m_bCreatingChildObject = false;
+ return false;
+ }
+ newObject = owningClassifier->createTemplate(nt.m_name);
+ UMLTemplate *tmplParm = static_cast<UMLTemplate*>(newObject);
+ tmplParm->setType(nt.m_type);
+ text = tmplParm->toString(Uml::st_SigNoVis);
+ } else if (type == Uml::ot_Attribute || type == Uml::ot_EntityAttribute) {
+ UMLClassifier *owningClass = static_cast<UMLClassifier*>(parent);
+ Model_Utils::NameAndType nt;
+ Uml::Visibility vis;
+ Model_Utils::Parse_Status st;
+ st = Model_Utils::parseAttribute(text, nt, owningClass, &vis);
+ if (st) {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Creation canceled") );
+ m_bCreatingChildObject = false;
+ return false;
+ }
+ newObject = owningClass->createAttribute(nt.m_name, nt.m_type, vis, nt.m_initialValue);
+ UMLAttribute *att = static_cast<UMLAttribute*>(newObject);
+ att->setParmKind(nt.m_direction);
+ text = att->toString(Uml::st_SigNoVis);
+ } else if ( type == Uml::ot_Operation ) {
+ UMLClassifier *owningClassifier = static_cast<UMLClassifier*>(parent);
+ Model_Utils::OpDescriptor od;
+ Model_Utils::Parse_Status st = Model_Utils::parseOperation(text, od, owningClassifier);
+ if (st) {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Creation canceled") );
+ m_bCreatingChildObject = false;
+ return false;
+ }
+ bool isExistingOp = false;
+ newObject = owningClassifier->createOperation(od.m_name, &isExistingOp, &od.m_args);
+ if (newObject == NULL || isExistingOp) {
+ if (isExistingOp)
+ KMessageBox::error(
+ kapp -> mainWidget(),
+ i18n( "The name you entered was not unique!\nCreation process has been canceled." ),
+ i18n( "Name Not Unique" ) );
+ m_bCreatingChildObject = false;
+ return false;
+ }
+ UMLOperation *op = static_cast<UMLOperation*>(newObject);
+ if (od.m_pReturnType) {
+ op->setType(od.m_pReturnType);
+ }
+ text = op->toString(Uml::st_SigNoVis);
+ } else {
+ kError() << "UMLListView::createChildUMLObject called for type "
+ << type << " (ignored)" << endl;
+ m_bCreatingChildObject = false;
+ return false;
+ }
+
+ // make changes to the object visible to this umllistviewitem
+ connectNewObjectsSlots( newObject );
+ item->setUMLObject( newObject );
+ item->setText( text );
+ ensureItemVisible(item);
+
+ // as it's a ClassifierListItem add it to the childObjectMap of the parent
+ UMLClassifierListItem* classifierListItem = static_cast<UMLClassifierListItem*>( newObject );
+ static_cast<UMLListViewItem*>( item->parent() )->addClassifierListItem(classifierListItem, item );
+
+ m_bCreatingChildObject = false;
+
+ if (! m_doc->loading())
+ m_doc->setModified();
+ return true;
+}
+
+void UMLListView::createDiagram( UMLListViewItem * item, Uml::Diagram_Type type ) {
+ QString name = item -> text( 0 );
+ UMLView * view = m_doc -> findView( type, name );
+ if( view ) {
+ delete item;
+ return;
+ }
+ UMLListViewItem *parentItem = static_cast<UMLListViewItem*>(item->parent());
+ UMLFolder *parentFolder = dynamic_cast<UMLFolder*>(parentItem->getUMLObject());
+ if (parentFolder == NULL) {
+ kError() << "UMLListView::createDiagram(" << name
+ << "): parent UMLObject is not a UMLFolder" << endl;
+ delete item;
+ return;
+ }
+ view = new UMLView(parentFolder);
+ view->setName( name );
+ view->setType( type );
+ view->setID( UniqueID::gen() );
+ m_doc -> addView( view );
+ view -> setOptionState( Settings::getOptionState() );
+ item -> setID( view -> getID() );
+ item -> setText( name );
+ view->activate();
+ m_doc -> changeCurrentView( view -> getID() );
+}
+
+QString UMLListView::getUniqueDiagramName(Uml::Diagram_Type type) {
+ return m_doc->uniqViewName(type);
+}
+
+bool UMLListView::isUnique( UMLListViewItem * item, const QString &name ) {
+ UMLListViewItem * parentItem = static_cast<UMLListViewItem *>( item -> parent() );
+ Uml::ListView_Type type = item -> getType();
+ switch( type ) {
+ case Uml::lvt_Class_Diagram:
+ return !m_doc -> findView( Uml::dt_Class, name );
+ break;
+
+ case Uml::lvt_Sequence_Diagram:
+ return !m_doc -> findView( Uml::dt_Sequence, name );
+ break;
+
+ case Uml::lvt_UseCase_Diagram:
+ return !m_doc -> findView( Uml::dt_UseCase, name );
+ break;
+
+ case Uml::lvt_Collaboration_Diagram:
+ return !m_doc -> findView( Uml::dt_Collaboration, name );
+ break;
+
+ case Uml::lvt_State_Diagram:
+ return !m_doc -> findView( Uml::dt_State, name );
+ break;
+
+ case Uml::lvt_Activity_Diagram:
+ return !m_doc -> findView( Uml::dt_Activity, name );
+ break;
+
+ case Uml::lvt_Component_Diagram:
+ return !m_doc->findView(Uml::dt_Component, name);
+ break;
+
+ case Uml::lvt_Deployment_Diagram:
+ return !m_doc->findView(Uml::dt_Deployment, name);
+ break;
+
+ case Uml::lvt_EntityRelationship_Diagram:
+ return !m_doc->findView(Uml::dt_EntityRelationship, name);
+ break;
+
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_Node:
+ case Uml::lvt_Artifact:
+ return !m_doc->findUMLObject( name, Model_Utils::convert_LVT_OT(type) );
+ break;
+
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Entity:
+ case Uml::lvt_Component:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ {
+ Uml::ListView_Type lvt = parentItem->getType();
+ if (!Model_Utils::typeIsContainer(lvt))
+ return (m_doc->findUMLObject(name) == NULL);
+ UMLPackage *pkg = static_cast<UMLPackage*>(parentItem->getUMLObject());
+ if (pkg == NULL) {
+ kError() << "UMLListView::isUnique: internal error - "
+ << "parent listviewitem is package but has no UMLObject" << endl;
+ return true;
+ }
+ return (pkg->findObject(name) == NULL);
+ break;
+ }
+
+ case Uml::lvt_Template:
+ case Uml::lvt_Attribute:
+ case Uml::lvt_EntityAttribute:
+ case Uml::lvt_Operation:
+ case Uml::lvt_EnumLiteral:
+ {
+ UMLClassifier *parent = static_cast<UMLClassifier*>(parentItem->getUMLObject());
+ return (parent->findChildObject(name) == NULL);
+ break;
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+void UMLListView::cancelRename( QListViewItem * item ) {
+ if( !m_bIgnoreCancelRename ) {
+ delete item;
+ m_bIgnoreCancelRename = true;
+ }
+}
+
+void UMLListView::saveToXMI( QDomDocument & qDoc, QDomElement & qElement) {
+ QDomElement listElement = qDoc.createElement( "listview" );
+ m_rv->saveToXMI(qDoc, listElement);
+ qElement.appendChild( listElement );
+}
+
+bool UMLListView::loadFromXMI( QDomElement & element ) {
+ /*
+ deleteChildrenOf( m_ucv );
+ deleteChildrenOf( m_lv );
+ deleteChildrenOf( m_cmpv );
+ deleteChildrenOf( m_dplv );
+ */
+ QDomNode node = element.firstChild();
+ QDomElement domElement = node.toElement();
+ m_doc->writeToStatusBar( i18n("Loading listview...") );
+ while( !domElement.isNull() ) {
+ if( domElement.tagName() == "listitem" ) {
+ QString type = domElement.attribute( "type", "-1" );
+ if( type == "-1" )
+ return false;
+ Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
+ if( lvType == Uml::lvt_View ) {
+ if( !loadChildrenFromXMI( m_rv, domElement ) )
+ return false;
+ } else
+ return false;
+ }
+ node = node.nextSibling();
+ domElement = node.toElement();
+
+ }//end while
+ return true;
+}
+
+bool UMLListView::loadChildrenFromXMI( UMLListViewItem * parent, QDomElement & element ) {
+ QDomNode node = element.firstChild();
+ QDomElement domElement = node.toElement();
+ const QString pfx("UMLListView::loadChildrenFromXMI: ");
+ while( !domElement.isNull() ) {
+ node = domElement.nextSibling();
+ if( domElement.tagName() != "listitem" ) {
+ domElement = node.toElement();
+ continue;
+ }
+ QString id = domElement.attribute( "id", "-1" );
+ QString type = domElement.attribute( "type", "-1" );
+ QString label = domElement.attribute( "label", "" );
+ QString open = domElement.attribute( "open", "1" );
+ if( type == "-1" )
+ return false;
+ Uml::ListView_Type lvType = (Uml::ListView_Type)type.toInt();
+ bool bOpen = (bool)open.toInt();
+ Uml::IDType nID = STR2ID(id);
+ UMLObject * pObject = 0;
+ UMLListViewItem * item = 0;
+ if (nID != Uml::id_None) {
+ // The following is an ad hoc hack for the copy/paste code.
+ // The clip still contains the old children although new
+ // UMLCLassifierListItems have already been created.
+ // If the IDChangeLog finds new IDs this means we are in
+ // copy/paste and need to adjust the child listitems to the
+ // new UMLCLassifierListItems.
+ IDChangeLog *idchanges = m_doc->getChangeLog();
+ if (idchanges != NULL) {
+ Uml::IDType newID = idchanges->findNewID(nID);
+ if (newID != Uml::id_None) {
+ kDebug() << pfx << " using id " << ID2STR(newID)
+ << " instead of " << ID2STR(nID) << endl;
+ nID = newID;
+ }
+ }
+ /************ End of hack for copy/paste code ************/
+
+ pObject = m_doc->findObjectById(nID);
+ if (pObject) {
+ if (label.isEmpty())
+ label = pObject->getName();
+ } else if (Model_Utils::typeIsFolder(lvType)) {
+ // Synthesize the UMLFolder here
+ UMLObject *umlParent = parent->getUMLObject();
+ UMLPackage *parentPkg = dynamic_cast<UMLPackage*>(umlParent);
+ if (parentPkg == NULL) {
+ kError() << pfx << "umlParent(" << umlParent << ") is not a UMLPackage"
+ << endl;
+ domElement = node.toElement();
+ continue;
+ }
+ UMLFolder *f = new UMLFolder(label, nID);
+ f->setUMLPackage(parentPkg);
+ parentPkg->addObject(f);
+ pObject = f;
+ item = new UMLListViewItem(parent, label, lvType, pObject);
+ // Moving all relevant UMLObjects to the new UMLFolder is done below,
+ // in the switch(lvType)
+ }
+ } else if (Model_Utils::typeIsRootView(lvType)) {
+ // Predefined folders did not have their ID set.
+ const Uml::Model_Type mt = Model_Utils::convert_LVT_MT(lvType);
+ nID = m_doc->getRootFolder(mt)->getID();
+ } else if (Model_Utils::typeIsFolder(lvType)) {
+ // Pre-1.2 format: Folders did not have their ID set.
+ // Pull a new ID now.
+ nID = UniqueID::get();
+ } else {
+ kError() << pfx << "item of type " << type << " has no ID, skipping." << endl;
+ domElement = node.toElement();
+ continue;
+ }
+
+ switch( lvType ) {
+ case Uml::lvt_Actor:
+ case Uml::lvt_UseCase:
+ case Uml::lvt_Class:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_Entity:
+ case Uml::lvt_Package:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Component:
+ case Uml::lvt_Node:
+ case Uml::lvt_Artifact:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ item = findItem(nID);
+ if (item == NULL) {
+ kError() << pfx << "INTERNAL ERROR: "
+ << "findItem(id " << ID2STR(nID) << ") returns NULL" << endl;
+ /*
+ if (pObject && pObject->getUMLPackage() &&
+ parent->getType() != Uml::lvt_Package) {
+ // Pre-1.2 file format:
+ // Objects were not nested in their packages.
+ // Synthesize the nesting here.
+ UMLPackage *umlpkg = pObject->getUMLPackage();
+ UMLListViewItem *pkgItem = findUMLObject(umlpkg);
+ if (pkgItem == NULL) {
+ kDebug() << pfx << "synthesizing ListViewItem for package "
+ << ID2STR(umlpkg->getID()) << endl;
+ pkgItem = new UMLListViewItem(parent, umlpkg->getName(),
+ Uml::lvt_Package, umlpkg);
+ pkgItem->setOpen(true);
+ }
+ item = new UMLListViewItem(pkgItem, label, lvType, pObject);
+ } else {
+ item = new UMLListViewItem(parent, label, lvType, pObject);
+ }
+ */
+ }
+ else if (parent != item->parent()) {
+ // The existing item was created by the slot event triggered
+ // by the loading of the corresponding model object from the
+ // XMI file.
+ // This early creation is done in order to support the loading
+ // of foreign XMI files that do not have the umbrello specific
+ // <listview> tag.
+ // However, now that we encountered the real <listview> info,
+ // we need to delete the existing item: Its parent is always
+ // one of the default predefined folders, but the actual
+ // listview item might be located in a user created folder.
+ // Thanks to Achim Spangler for spotting the problem.
+ UMLListViewItem *itmParent = dynamic_cast<UMLListViewItem*>(item->parent());
+ kDebug() << pfx << item->getText() << " parent "
+ << parent->getText() << " (" << parent << ") != "
+ << itmParent->getText() << " (" << itmParent << ")" << endl;
+ if (item == m_datatypeFolder && itmParent == m_lv[Uml::mt_Logical]) {
+ kDebug() << pfx << "Reparenting the Datatypes folder is prohibited" << endl;
+ } else {
+ UMLListViewItem *newItem = moveObject(nID, lvType, parent);
+ item = newItem;
+ if (item) {
+ kDebug() << pfx << "Attempted reparenting of " << item->getText()
+ << "(current parent: " << (itmParent ? itmParent->getText() : "NULL")
+ << ", new parent: " << parent->getText() << ")" << endl;
+ }
+ }
+ }
+ break;
+ case Uml::lvt_Attribute:
+ case Uml::lvt_EntityAttribute:
+ case Uml::lvt_Template:
+ case Uml::lvt_Operation:
+ case Uml::lvt_EnumLiteral:
+ item = findItem(nID);
+ if (item == NULL) {
+ kDebug() << pfx << "item " << ID2STR(nID) << " (of type "
+ << lvType << ") does not yet exist..." << endl;
+ UMLObject* umlObject = parent->getUMLObject();
+ if (!umlObject) {
+ kDebug() << "And also the parent->getUMLObject() does not exist" << endl;
+ return false;
+ }
+ if (nID == Uml::id_None) {
+ kWarning() << pfx << "lvtype " << lvType << " has id -1" << endl;
+ } else {
+ UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(umlObject);
+ if (classifier) {
+ umlObject = classifier->findChildObjectById(nID);
+ if (umlObject) {
+ connectNewObjectsSlots(umlObject);
+ label = umlObject->getName();
+ item = new UMLListViewItem( parent, label, lvType, umlObject);
+ } else {
+ kDebug() << pfx << "lvtype " << lvType << " child object "
+ << ID2STR(nID) << " not found" << endl;
+ }
+ } else {
+ kDebug() << pfx << "cast to classifier object failed" << endl;
+ }
+ }
+ }
+ break;
+ case Uml::lvt_Logical_View:
+ item = m_lv[Uml::mt_Logical];
+ break;
+ case Uml::lvt_Datatype_Folder:
+ item = m_datatypeFolder;
+ break;
+ case Uml::lvt_UseCase_View:
+ item = m_lv[Uml::mt_UseCase];
+ break;
+ case Uml::lvt_Component_View:
+ item = m_lv[Uml::mt_Component];
+ break;
+ case Uml::lvt_Deployment_View:
+ item = m_lv[Uml::mt_Deployment];
+ break;
+ case Uml::lvt_EntityRelationship_Model:
+ item = m_lv[Uml::mt_EntityRelationship];
+ break;
+ default:
+ if (Model_Utils::typeIsDiagram(lvType)) {
+ item = new UMLListViewItem( parent, label, lvType, nID );
+ } else {
+ kError() << pfx << "INTERNAL ERROR: unexpected listview type "
+ << lvType << " (ID " << ID2STR(nID) << ")" << endl;
+ }
+ break;
+ }//end switch
+
+ if (item) {
+ item->setOpen( (bool)bOpen );
+ if ( !loadChildrenFromXMI(item, domElement) ) {
+ return false;
+ }
+ } else {
+ kWarning() << "unused list view item " << ID2STR(nID)
+ << " of lvtype " << lvType << endl;
+ }
+ domElement = node.toElement();
+ }//end while
+ return true;
+}
+
+/** Open all items in the list view*/
+void UMLListView::expandAll(QListViewItem *item) {
+ if(!item) item = firstChild();
+ for (item = item->firstChild(); item; item = item->nextSibling()) {
+ item->setOpen(true);
+ }
+}
+/** Close all items in the list view*/
+void UMLListView::collapseAll(QListViewItem *item) {
+ if(!item) item = firstChild();
+ for( item = item->firstChild(); item; item = item->nextSibling())
+ item->setOpen(false);
+}
+
+void UMLListView::setStartedCut(bool startedCut) {
+ m_bStartedCut = startedCut;
+}
+
+void UMLListView::setStartedCopy(bool startedCopy) {
+ m_bStartedCopy = startedCopy;
+}
+
+bool UMLListView::startedCopy() const {
+ return m_bStartedCopy;
+}
+
+UMLListViewItem *UMLListView::rootView(Uml::ListView_Type type) {
+ UMLListViewItem *theView = NULL;
+ switch (type) {
+ case Uml::lvt_View:
+ theView = m_rv;
+ break;
+ case Uml::lvt_Logical_View:
+ theView = m_lv[Uml::mt_Logical];
+ break;
+ case Uml::lvt_UseCase_View:
+ theView = m_lv[Uml::mt_UseCase];
+ break;
+ case Uml::lvt_Component_View:
+ theView = m_lv[Uml::mt_Component];
+ break;
+ case Uml::lvt_Deployment_View:
+ theView = m_lv[Uml::mt_Deployment];
+ break;
+ case Uml::lvt_EntityRelationship_Model:
+ theView = m_lv[Uml::mt_EntityRelationship];
+ break;
+ case Uml::lvt_Datatype_Folder: // @todo fix asymmetric naming
+ theView = m_datatypeFolder;
+ break;
+ default:
+ break;
+ }
+ return theView;
+}
+
+void UMLListView::deleteChildrenOf(QListViewItem* parent) {
+ if ( !parent ) {
+ return;
+ }
+ if (parent == m_lv[Uml::mt_Logical])
+ m_datatypeFolder = NULL;
+ while ( parent->firstChild() ) {
+ delete parent->firstChild();
+ }
+}
+
+void UMLListView::closeDatatypesFolder() {
+ m_datatypeFolder->setOpen(false);
+}
+
+
+bool UMLListView::deleteItem(UMLListViewItem *temp) {
+ if (!temp)
+ return false;
+ UMLObject *object = temp->getUMLObject();
+ Uml::ListView_Type lvt = temp->getType();
+ if ( Model_Utils::typeIsDiagram(lvt) ) {
+ m_doc->removeDiagram( temp->getID() );
+ } else if (temp == m_datatypeFolder) {
+ // we can't delete the datatypeFolder because umbrello will crash without a special handling
+ return false;
+ } else if (Model_Utils::typeIsCanvasWidget(lvt) || Model_Utils::typeIsClassifierList(lvt)) {
+ UMLPackage *nmSpc = dynamic_cast<UMLPackage*>(object);
+ if (nmSpc) {
+ UMLObjectList contained = nmSpc->containedObjects();
+ if (contained.count()) {
+ KMessageBox::error(
+ kapp->mainWidget(),
+ i18n("The folder must be emptied before it can be deleted."),
+ i18n("Folder Not Empty"));
+ return false;
+ }
+ }
+ UMLCanvasObject *canvasObj = dynamic_cast<UMLCanvasObject*>(object);
+ if (canvasObj) {
+ /**
+ * We cannot just delete canvasObj here: What if the object
+ * is still being used by others (for example, as a parameter
+ * or return type of an operation) ?
+ * Deletion should not have been permitted in the first place
+ * if the object still has users - but Umbrello is lacking
+ * that logic.
+ */
+ canvasObj->removeAllChildObjects();
+ }
+ if (object) {
+ m_doc->removeUMLObject(object);
+ // Physical deletion of `temp' will be done by Qt signal, see
+ // UMLDoc::removeUMLObject()
+ } else {
+ delete temp;
+ }
+ } else {
+ kWarning() << "umllistview::listpopupmenu::mt_Delete called with unknown type"
+ << endl;
+ }
+ return true;
+}
+
+
+#include "umllistview.moc"
diff --git a/umbrello/umbrello/umllistview.h b/umbrello/umbrello/umllistview.h
new file mode 100644
index 00000000..5656a537
--- /dev/null
+++ b/umbrello/umbrello/umllistview.h
@@ -0,0 +1,473 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLLISTVIEW_H
+#define UMLLISTVIEW_H
+
+#include <qdom.h>
+#include <qpixmap.h>
+#include <klistview.h>
+#include "umlnamespace.h"
+#include "umllistviewitemlist.h"
+
+/**
+ * This is one of the main classes used in this program.
+ * Information is displayed here in a tree view. No objects are created
+ * here. A call to @ref UMLDoc make any additions/deletion or updates to
+ * objects. This class will then wait for a signal before updating the tree view.
+ *
+ * @short Displays the list view for the program.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class QMouseEvent;
+class QContextMenuEvent;
+class QKeyEvent;
+class IDChangeLog;
+class ListPopupMenu;
+class UMLClassifier;
+class UMLDoc;
+class UMLListViewItem;
+class UMLView;
+class UMLObject;
+class UMLClassifierListItem;
+
+class UMLListView : public KListView {
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs the tree view.
+ *
+ * @param parent The parent to this.
+ * @param name The internal name for this class.
+ */
+ UMLListView(QWidget *parent,const char *name);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~UMLListView();
+
+ /**
+ * Sets the document his is associated with. This is important as
+ * this is required as to setup the callbacks.
+ *
+ * @param d The document to associate with this class.
+ */
+ void setDocument(UMLDoc * d);
+
+ /**
+ * Carries out initalisation of attributes in class.
+ */
+ void init();
+
+ /**
+ * Set the current view to the given view.
+ *
+ * @param v The current view.
+ */
+ void setView(UMLView* v);
+
+ /**
+ * Get selected items.
+ *
+ * @param ItemList List of UMLListViewItems returned.
+ * @return The number of selected items.
+ */
+ int getSelectedItems(UMLListViewItemList &ItemList);
+
+ /**
+ * Get selected items, but only root elements selected (without children).
+ *
+ * @param ItemList List of UMLListViewItems returned.
+ * @return The number of selected items.
+ */
+ int getSelectedItemsRoot(UMLListViewItemList &ItemList);
+
+ /**
+ * Create a listview item for an existing diagram.
+ *
+ * @param v The existing diagram.
+ */
+ UMLListViewItem* createDiagramItem(UMLView *v);
+
+ /**
+ * CHECK - This is perhaps redundant since the
+ * UMLListViewItemData => UMLListViewItem merge.
+ * Creates a new UMLListViewItem from a UMLListViewItem, if
+ * parent is null the ListView Decides who is going to be the
+ * parent
+ */
+ UMLListViewItem* createItem(UMLListViewItem& Data, IDChangeLog& IDChanges,
+ UMLListViewItem* parent = 0);
+
+ /**
+ * Find the parent folder for a diagram.
+ * If the currently selected item in the list view is a folder
+ * then that folder is returned as the parent.
+ *
+ * @param dt The Diagram_Type of the diagram.
+ * The type will only be used if there is no currently
+ * selected item, or if the current item is not a folder.
+ * In that case the root folder which is suitable for the
+ * Diagram_Type is returned.
+ * @return Pointer to the parent UMLListViewItem for the diagram.
+ */
+ UMLListViewItem *findFolderForDiagram(Uml::Diagram_Type dt);
+
+ /**
+ * Determine the parent ListViewItem given an UMLObject.
+ *
+ * @param object Pointer to the UMLObject for which to look up the parent.
+ * @return Pointer to the parent UMLListViewItem chosen.
+ * Returns NULL on error (no parent could be determined.)
+ */
+ UMLListViewItem* determineParentItem(UMLObject* object) const;
+
+ /**
+ * Determine the parent ListViewItem given a ListView_Type.
+ * This parent is used for creating new UMLListViewItems.
+ *
+ * @param lvt The ListView_Type for which to lookup the parent.
+ * @return Pointer to the parent UMLListViewItem chosen.
+ */
+ UMLListViewItem* determineParentItem(Uml::ListView_Type lvt) const;
+
+ /**
+ * Return true if the given Object_Type permits child items.
+ * A "child item" is anything that qualifies as a UMLClassifierListItem,
+ * e.g. operations and attributes of classifiers.
+ */
+ static bool mayHaveChildItems(Uml::Object_Type type);
+
+ /**
+ * Return the amount of items selected.
+ */
+ int getSelectedCount();
+
+ /**
+ * Returns the correct pixmap for the given type.
+ */
+ QPixmap & getPixmap( Uml::Icon_Type type );
+
+ /**
+ * Returns the document pointer. Called by the UMLListViewItem class.
+ */
+ UMLDoc * getDocument() {
+ return m_doc;
+ }
+
+ /**
+ * Adds a new item to the tree of the given type under the given parent.
+ * Method will take care of signalling anyone needed on creation of new item.
+ * e.g. UMLDoc if an UMLObject is created.
+ */
+ void addNewItem(UMLListViewItem * parent, Uml::ListView_Type type);
+
+ /**
+ * Find an UMLObject in the listview.
+ *
+ * @param p Pointer to the object to find in the list view.
+ * @return Pointer to the UMLObject found or NULL if not found.
+ */
+ UMLListViewItem * findUMLObject(const UMLObject *p) const;
+
+ /**
+ * Searches through the tree for the item which represents the diagram given
+ * @param v the diagram to search for
+ * @return the item which represents the diagram
+ */
+ UMLListViewItem * findView(UMLView *v);
+
+ /**
+ * Searches through the tree for the item with the given ID.
+ *
+ * @param id The ID to search for.
+ * @return The item with the given ID or NULL if not found.
+ */
+ UMLListViewItem * findItem(Uml::IDType id);
+
+ /**
+ * Returns the corresponding view if the listview type is one of the root views,
+ * Root/Logical/UseCase/Component/Deployment/EntityRelation View.
+ */
+ UMLListViewItem *rootView(Uml::ListView_Type type);
+
+ /**
+ * Changes the icon for the given UMLObject to the given icon.
+ */
+ void changeIconOf(UMLObject *o, Uml::Icon_Type to);
+
+ /**
+ * Creates a UMLObject out of the given list view item.
+ */
+ UMLObject *createUMLObject( UMLListViewItem * item, Uml::Object_Type type );
+
+ /**
+ * Creates a child UMLObject out of the given list view item.
+ */
+ bool createChildUMLObject( UMLListViewItem * item, Uml::Object_Type type );
+
+ /**
+ * Creates a diagram out of the given list view item.
+ */
+ void createDiagram( UMLListViewItem * item, Uml::Diagram_Type type );
+
+ /**
+ * Returns a unique name for a diagram.
+ */
+ QString getUniqueDiagramName( Uml::Diagram_Type type );
+
+ /**
+ * Returns if the given name is unique for the given items type.
+ */
+ bool isUnique( UMLListViewItem * item, const QString &name );
+
+ /**
+ * Cancel rename event has occurred for the given item.
+ */
+ void cancelRename( QListViewItem * item );
+
+ /**
+ * Set the variable m_bStartedCut
+ * to indicate that selection should be deleted
+ * in slotCutSuccessful()
+ */
+ void setStartedCut(bool startedCut);
+
+ /**
+ * Set the variable m_bStartedCopy.
+ * NB: While m_bStartedCut is reset as soon as the Cut operation is done,
+ * the variable m_bStartedCopy is reset much later - upon pasting.
+ */
+ void setStartedCopy(bool startedCopy);
+
+ /**
+ * Return the variable m_bStartedCopy.
+ */
+ bool startedCopy() const;
+
+ /**
+ * Moves an object given is unique ID and listview type to an
+ * other listview parent item.
+ * Also takes care of the corresponding move in the model.
+ */
+ UMLListViewItem * moveObject(Uml::IDType srcId, Uml::ListView_Type srcType,
+ UMLListViewItem *newParent);
+
+ /**
+ * Called for informing the list view that an item was renamed.
+ */
+ bool itemRenamed(QListViewItem* item , int col);
+
+ void closeDatatypesFolder();
+
+ UMLListViewItem *theRootView() { return m_rv; }
+ UMLListViewItem *theLogicalView() { return m_lv[Uml::mt_Logical]; }
+ UMLListViewItem *theUseCaseView() { return m_lv[Uml::mt_UseCase]; }
+ UMLListViewItem *theComponentView() { return m_lv[Uml::mt_Component]; }
+ UMLListViewItem *theDeploymentView() { return m_lv[Uml::mt_Deployment]; }
+ UMLListViewItem *theDatatypeFolder() { return m_datatypeFolder; }
+
+ /**
+ * Determines the root listview type of the given UMLListViewItem.
+ * Starts at the given item, compares it against each of the
+ * predefined root views (Root, Logical, UseCase, Component,
+ * Deployment, EntityRelationship.) Returns the ListView_Type
+ * of the matching root view; if no match then continues the
+ * search using the item's parent, then grandparent, and so forth.
+ * Returns Uml::lvt_Unknown if no match at all is found.
+ */
+ Uml::ListView_Type rootViewType(UMLListViewItem *item);
+
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement);
+
+ bool loadFromXMI( QDomElement & element );
+
+ bool loadChildrenFromXMI( UMLListViewItem * parent, QDomElement & element );
+
+protected:
+ UMLListViewItem* m_rv; // root view (home)
+ UMLListViewItem* m_lv[Uml::N_MODELTYPES]; // predefined list view roots
+ UMLListViewItem* m_datatypeFolder;
+ ListPopupMenu * m_pMenu;
+ QString oldText, message;
+ UMLDoc *m_doc;
+ bool m_bStartedCut, m_bStartedCopy, m_bIgnoreCancelRename;
+
+ /**
+ * Used when creating an attribute or an operation to stop it adding a second listViewItem
+ */
+ bool m_bCreatingChildObject;
+
+ QPixmap m_Pixmaps[Uml::N_ICONTYPES];
+
+ bool eventFilter(QObject *o, QEvent *e);
+ void contentsMouseReleaseEvent(QMouseEvent * me);
+ void contentsMousePressEvent(QMouseEvent *me);
+ void contentsMouseDoubleClickEvent(QMouseEvent * me);
+ void focusOutEvent ( QFocusEvent * fe);
+ QDragObject* dragObject();
+ void startDrag();
+ bool acceptDrag (QDropEvent* event) const;
+ void keyPressEvent(QKeyEvent *);
+
+ /**
+ * This methods looks for a object in a folder an its subfolders recursive.
+ * @param item The folder entry of the list view.
+ * @param o The object to be found in the folder.
+ *
+ * @return The object if found else a NULL pointer.
+ */
+ UMLListViewItem * findUMLObjectInFolder(UMLListViewItem *item, UMLObject *o);
+
+ /**
+ * Return true if the given list view type can be expanded/collapsed.
+ */
+ static bool isExpandable(Uml::ListView_Type lvt);
+
+ /**
+ * Loads the pixmaps to use in the list items.
+ */
+ void loadPixmaps();
+
+ /**
+ * Deletes all child-items of @p parent.
+ */
+ void deleteChildrenOf( QListViewItem *parent );
+
+ /**
+ * Delete a listview item.
+ * @param temp a non-null UMLListViewItem, for example:
+ (UMLListViewItem*)currentItem()
+ * @return true if correctly deleted
+ */
+ bool deleteItem( UMLListViewItem *temp );
+
+ /**
+ * Adds a new operation, attribute or template item to a classifier, identical to
+ * childObjectAdded(obj) but with an explicit parent.
+ * @param child the child object
+ * @param parent the parent object
+ */
+ void childObjectAdded(UMLClassifierListItem* child, UMLClassifier* parent);
+
+ /**
+ * Auxiliary method for moveObject(): Adds the model object at the proper
+ * new container (package if nested, UMLDoc if at global level), and
+ * updates the containment relationships in the model.
+ */
+ void addAtContainer(UMLListViewItem *item, UMLListViewItem *parent);
+
+public slots:
+
+ /**
+ * Creates a new item to represent a new diagram
+ * @param id the id of the new diagram
+ */
+ void slotDiagramCreated(Uml::IDType id);
+
+ /**
+ * renames a diagram in the list view
+ * @param id the id of the renamed diagram
+ */
+ void slotDiagramRenamed(Uml::IDType id);
+
+ /**
+ * Creates a new list view item and connects the appropriate signals/slots
+ * @param object the newly created object
+ */
+ void slotObjectCreated(UMLObject* object);
+
+ /**
+ * connect some signals into slots in the list view for newly created UMLObjects
+ */
+ void connectNewObjectsSlots(UMLObject* object);
+
+ /**
+ * Adds a new operation, attribute or template item to a classifier
+ * @param obj the child object
+ */
+ void childObjectAdded(UMLClassifierListItem* obj);
+
+ /**
+ * disconnects signals and removes the list view item
+ * @param object the object about to be removed
+ */
+ void slotObjectRemoved(UMLObject* object);
+
+ /**
+ * deletes the list view item
+ * @param obj the object to remove
+ */
+ void childObjectRemoved(UMLClassifierListItem* obj);
+
+ /**
+ * calls updateObject() on the item representing the sending object
+ * no parameters, uses sender() to work out which object called the slot
+ */
+ void slotObjectChanged();
+
+ /**
+ * removes the item representing a diagram
+ * @param id the id of the diagram
+ */
+ void slotDiagramRemoved(Uml::IDType id);
+
+ /**
+ * Called when a right mouse button menu has an item selected
+ */
+ void popupMenuSel(int sel);
+
+ /**
+ * Something has been dragged and dropped onto the list view
+ */
+ void slotDropped(QDropEvent* de, QListViewItem* parent, QListViewItem* item);
+
+ /**
+ * calls updateFolder() on the item to update the icon to open
+ */
+ void slotExpanded(QListViewItem* item);
+
+ /**
+ * calls updateFolder() on the item to update the icon to closed
+ */
+ void slotCollapsed(QListViewItem* item);
+
+ /**
+ * Open all items in the list view
+ */
+ void expandAll(QListViewItem *item);
+
+ /**
+ * Close all items in the list view
+ */
+ void collapseAll(QListViewItem *item);
+
+ /**
+ * Connects to the signal that @ref UMLApp emits when a
+ * cut operation is successful.
+ */
+ void slotCutSuccessful();
+
+private:
+ /**
+ * Searches the tree for a diagram (view).
+ * Used by findView().
+ */
+ UMLListViewItem* recursiveSearchForView(UMLListViewItem* folder,
+ Uml::ListView_Type type, Uml::IDType id);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umllistviewitem.cpp b/umbrello/umbrello/umllistviewitem.cpp
new file mode 100644
index 00000000..c24ac853
--- /dev/null
+++ b/umbrello/umbrello/umllistviewitem.cpp
@@ -0,0 +1,696 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umllistviewitem.h"
+
+// system includes
+#include <cstdlib>
+
+// qt/kde includes
+#include <qfile.h>
+#include <qregexp.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// app includes
+#include "folder.h"
+#include "classifier.h"
+#include "template.h"
+#include "attribute.h"
+#include "operation.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umlobjectlist.h"
+#include "umlview.h"
+#include "model_utils.h"
+#include "uniqueid.h"
+#include "uml.h"
+
+UMLListView* UMLListViewItem::s_pListView = 0;
+
+UMLListViewItem::UMLListViewItem( UMLListView * parent, const QString &name,
+ Uml::ListView_Type t, UMLObject* o)
+ : QListViewItem(parent, name) {
+ init(parent);
+ m_Type = t;
+ m_pObject = o;
+ if (o)
+ m_nId = o->getID();
+ setIcon(Uml::it_Home);
+ setText( name );
+ setRenameEnabled( 0, false );
+}
+
+UMLListViewItem::UMLListViewItem(UMLListView * parent)
+ : QListViewItem(parent) {
+ init(parent);
+ if (parent == NULL)
+ kDebug() << "UMLListViewItem constructor called with a NULL listview parent" << endl;
+}
+
+UMLListViewItem::UMLListViewItem(UMLListViewItem * parent)
+ : QListViewItem(parent) {
+ init();
+}
+
+UMLListViewItem::UMLListViewItem(UMLListViewItem * parent, const QString &name, Uml::ListView_Type t,UMLObject*o)
+ : QListViewItem(parent, name) {
+ init();
+ m_Type = t;
+ m_pObject = o;
+ if( !o ) {
+ m_nId = Uml::id_None;
+ updateFolder();
+ } else {
+ UMLClassifierListItem *umlchild = dynamic_cast<UMLClassifierListItem*>(o);
+ if (umlchild)
+ parent->addClassifierListItem(umlchild, this);
+ updateObject();
+ m_nId = o->getID();
+ }
+ setRenameEnabled( 0, !Model_Utils::typeIsRootView(t) );
+ setText( name );
+}
+
+UMLListViewItem::UMLListViewItem(UMLListViewItem * parent, const QString &name, Uml::ListView_Type t,Uml::IDType id)
+ : QListViewItem(parent, name) {
+ init();
+ m_Type = t;
+ m_nId = id;
+ switch (m_Type) {
+ case Uml::lvt_Collaboration_Diagram:
+ setIcon(Uml::it_Diagram_Collaboration);
+ break;
+ case Uml::lvt_Class_Diagram:
+ setIcon(Uml::it_Diagram_Class);
+ break;
+ case Uml::lvt_State_Diagram:
+ setIcon(Uml::it_Diagram_State);
+ break;
+ case Uml::lvt_Activity_Diagram:
+ setIcon(Uml::it_Diagram_Activity);
+ break;
+ case Uml::lvt_Sequence_Diagram:
+ setIcon(Uml::it_Diagram_Sequence);
+ break;
+ case Uml::lvt_Component_Diagram:
+ setIcon(Uml::it_Diagram_Component);
+ break;
+ case Uml::lvt_Deployment_Diagram:
+ setIcon(Uml::it_Diagram_Deployment);
+ break;
+ case Uml::lvt_UseCase_Diagram:
+ setIcon(Uml::it_Diagram_Usecase);
+ break;
+ default:
+ setIcon(Uml::it_Diagram);
+ }
+ /*
+ Constructor also used by folder so just make sure we don't need to
+ to set pixmap to folder. doesn't hurt diagrams.
+ */
+ updateFolder();
+ setText( name );
+ setRenameEnabled( 0, true );
+}
+
+UMLListViewItem::~UMLListViewItem() {}
+
+void UMLListViewItem::init(UMLListView * parent) {
+ m_Type = Uml::lvt_Unknown;
+ m_bCreating = false;
+ m_pObject = NULL;
+ m_nId = Uml::id_None;
+ m_nChildren = 0;
+ if (s_pListView == NULL && parent != NULL) {
+ kDebug() << "UMLListViewItem::init: s_pListView still NULL, setting it now "
+ << endl;
+ s_pListView = parent;
+ }
+}
+
+Uml::ListView_Type UMLListViewItem::getType() const {
+ return m_Type;
+}
+
+void UMLListViewItem::addClassifierListItem(UMLClassifierListItem *child, UMLListViewItem *childItem) {
+ m_comap[child] = childItem;
+}
+
+void UMLListViewItem::deleteChildItem(UMLClassifierListItem *child) {
+ UMLListViewItem *childItem = findChildObject(child);
+ if (childItem == NULL) {
+ kError() << "UMLListViewItem::deleteChildItem(" << child->getName()
+ << "): child listview item not found" << endl;
+ return;
+ }
+ m_comap.remove(child);
+ delete childItem;
+}
+
+Uml::IDType UMLListViewItem::getID() const {
+ if (m_pObject)
+ return m_pObject->getID();
+ return m_nId;
+}
+
+void UMLListViewItem::setID(Uml::IDType id) {
+ if (m_pObject) {
+ Uml::IDType oid = m_pObject->getID();
+ if (id != Uml::id_None && oid != id)
+ kDebug() << "UMLListViewItem::setID: new id " << ID2STR(id)
+ << " does not agree with object id " << ID2STR(oid) << endl;
+ }
+ m_nId = id;
+}
+
+bool UMLListViewItem::isOwnParent(Uml::IDType listViewItemID) {
+ QListViewItem *lvi = (QListViewItem*)s_pListView->findItem(listViewItemID);
+ if (lvi == NULL) {
+ kError() << "UMLListViewItem::isOwnParent: ListView->findItem("
+ << ID2STR(listViewItemID) << ") returns NULL" << endl;
+ return true;
+ }
+ for (QListViewItem *self = (QListViewItem*)this; self; self = self->parent()) {
+ if (lvi == self)
+ return true;
+ }
+ return false;
+}
+
+void UMLListViewItem::updateObject() {
+ if( m_pObject == NULL )
+ return;
+
+ Uml::Visibility scope = m_pObject->getVisibility();
+ Uml::Object_Type ot = m_pObject->getBaseType();
+ QString modelObjText = m_pObject->getName();
+ if (Model_Utils::isClassifierListitem(ot)) {
+ UMLClassifierListItem *pNarrowed = static_cast<UMLClassifierListItem*>(m_pObject);
+ modelObjText = pNarrowed->toString(Uml::st_SigNoVis);
+ }
+ setText(modelObjText);
+
+ Uml::Icon_Type icon = Uml::it_Home;
+ switch (ot) {
+ case Uml::ot_Package:
+ if (m_pObject->getStereotype() == "subsystem")
+ icon = Uml::it_Subsystem;
+ else
+ icon = Uml::it_Package;
+ break;
+/*
+ case Uml::ot_Folder:
+ {
+ Uml::ListView_Type lvt = Model_Utils::convert_OT_LVT(m_pObject);
+ icon = Model_Utils::convert_LVT_IT(lvt);
+ }
+ break;
+ */
+ case Uml::ot_Operation:
+ if (scope == Uml::Visibility::Public)
+ icon = Uml::it_Public_Method;
+ else if (scope == Uml::Visibility::Private)
+ icon = Uml::it_Private_Method;
+ else if (scope == Uml::Visibility::Implementation)
+ icon = Uml::it_Private_Method;
+ else
+ icon = Uml::it_Protected_Method;
+ break;
+
+ case Uml::ot_Attribute:
+ case Uml::ot_EntityAttribute:
+ if (scope == Uml::Visibility::Public)
+ icon = Uml::it_Public_Attribute;
+ else if (scope == Uml::Visibility::Private)
+ icon = Uml::it_Private_Attribute;
+ else if (scope == Uml::Visibility::Implementation)
+ icon = Uml::it_Private_Attribute;
+ else
+ icon = Uml::it_Protected_Attribute;
+ break;
+ default:
+ icon = Model_Utils::convert_LVT_IT(m_Type);
+ break;
+ }//end switch
+ if (icon)
+ setIcon(icon);
+}
+
+void UMLListViewItem::updateFolder() {
+ Uml::Icon_Type icon = Model_Utils::convert_LVT_IT(m_Type);
+ if (icon) {
+ if (Model_Utils::typeIsFolder(m_Type))
+ icon = (Uml::Icon_Type)((int)icon + (int)isOpen());
+ setIcon(icon);
+ }
+}
+
+void UMLListViewItem::setOpen( bool open ) {
+ QListViewItem::setOpen( open );
+ updateFolder();
+}
+
+void UMLListViewItem::setText(const QString &newText) {
+ m_Label = newText;
+ QListViewItem::setText(0, newText);
+}
+
+QString UMLListViewItem::getText() const {
+ return m_Label;
+}
+
+void UMLListViewItem::setIcon(Uml::Icon_Type iconType) {
+ setPixmap(0, s_pListView->getPixmap(iconType));
+}
+
+void UMLListViewItem::okRename( int col ) {
+ QListViewItem::okRename( col );
+ UMLDoc* doc = s_pListView->getDocument();
+ if (m_bCreating) {
+ m_bCreating = false;
+ QString savedLabel = m_Label;
+ m_Label = text(col);
+ if ( s_pListView->itemRenamed( this, col ) ) {
+ s_pListView->ensureItemVisible(this);
+ doc->setModified(true);
+ } else {
+ delete this;
+ }
+ return;
+ }
+ QString newText = text( col );
+ if ( newText == m_Label ) {
+ return;
+ }
+ if( newText.isEmpty() ) {
+ cancelRenameWithMsg();
+ return;
+ }
+ switch( m_Type ) {
+ case Uml::lvt_UseCase:
+ case Uml::lvt_Actor:
+ case Uml::lvt_Class:
+ case Uml::lvt_Package:
+ case Uml::lvt_UseCase_Folder:
+ case Uml::lvt_Logical_Folder:
+ case Uml::lvt_Component_Folder:
+ case Uml::lvt_Deployment_Folder:
+ case Uml::lvt_EntityRelationship_Folder:
+ case Uml::lvt_Interface:
+ case Uml::lvt_Datatype:
+ case Uml::lvt_Enum:
+ case Uml::lvt_EnumLiteral:
+ case Uml::lvt_Subsystem:
+ case Uml::lvt_Component:
+ case Uml::lvt_Node:
+ if (m_pObject == NULL || !doc->isUnique(newText)) {
+ cancelRenameWithMsg();
+ return;
+ }
+ m_pObject -> setName( newText );
+ doc->setModified(true);
+ m_Label = newText;
+ break;
+
+ case Uml::lvt_Operation:
+ {
+ if (m_pObject == NULL) {
+ cancelRenameWithMsg();
+ return;
+ }
+ UMLOperation *op = static_cast<UMLOperation*>(m_pObject);
+ UMLClassifier *parent = static_cast<UMLClassifier *>( op -> parent() );
+ Model_Utils::OpDescriptor od;
+ Model_Utils::Parse_Status st = Model_Utils::parseOperation(newText, od, parent);
+ if (st == Model_Utils::PS_OK) {
+ // TODO: Check that no operation with the exact same profile exists.
+ op->setName( od.m_name );
+ op->setType( od.m_pReturnType );
+ UMLAttributeList parmList = op->getParmList();
+ const unsigned newParmListCount = parmList.count();
+ if (newParmListCount > od.m_args.count()) {
+ // Remove parameters at end of of list that no longer exist.
+ for (unsigned i = od.m_args.count(); i < newParmListCount; i++) {
+ UMLAttribute *a = parmList.at(i);
+ op->removeParm(a, false);
+ }
+ }
+ Model_Utils::NameAndType_ListIt lit = od.m_args.begin();
+ for (unsigned i = 0; lit != od.m_args.end(); ++lit, ++i) {
+ const Model_Utils::NameAndType& nm_tp = *lit;
+ UMLAttribute *a;
+ if (i < newParmListCount) {
+ a = parmList.at(i);
+ } else {
+ a = new UMLAttribute(op);
+ a->setID( UniqueID::gen() );
+ }
+ a->setName(nm_tp.m_name);
+ a->setType(nm_tp.m_type);
+ a->setParmKind(nm_tp.m_direction);
+ a->setInitialValue(nm_tp.m_initialValue);
+ if (i >= newParmListCount) {
+ op->addParm(a);
+ }
+ }
+ m_Label = op->toString(Uml::st_SigNoVis);
+ } else {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Rename canceled") );
+ }
+ QListViewItem::setText(0, m_Label);
+ break;
+ }
+
+ case Uml::lvt_Attribute:
+ case Uml::lvt_EntityAttribute:
+ {
+ if (m_pObject == NULL) {
+ cancelRenameWithMsg();
+ return;
+ }
+ UMLClassifier *parent = static_cast<UMLClassifier*>(m_pObject->parent());
+ Model_Utils::NameAndType nt;
+ Uml::Visibility vis;
+ Model_Utils::Parse_Status st;
+ st = Model_Utils::parseAttribute(newText, nt, parent, &vis);
+ if (st == Model_Utils::PS_OK) {
+ UMLObject *exists = parent->findChildObject(newText);
+ if (exists) {
+ cancelRenameWithMsg();
+ return;
+ }
+ m_pObject->setName(nt.m_name);
+ UMLAttribute *pAtt = static_cast<UMLAttribute*>(m_pObject);
+ pAtt->setType(nt.m_type);
+ pAtt->setVisibility(vis);
+ pAtt->setParmKind(nt.m_direction);
+ pAtt->setInitialValue(nt.m_initialValue);
+ m_Label = pAtt->toString(Uml::st_SigNoVis);
+ } else {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Rename canceled") );
+ }
+ QListViewItem::setText(0, m_Label);
+ break;
+ }
+
+ case Uml::lvt_Template:
+ {
+ if (m_pObject == NULL) {
+ cancelRenameWithMsg();
+ return;
+ }
+ UMLClassifier *parent = static_cast<UMLClassifier*>(m_pObject->parent());
+ Model_Utils::NameAndType nt;
+ Model_Utils::Parse_Status st = Model_Utils::parseTemplate(newText, nt, parent);
+ if (st == Model_Utils::PS_OK) {
+ UMLObject *exists = parent->findChildObject(newText);
+ if (exists) {
+ cancelRenameWithMsg();
+ return;
+ }
+ m_pObject->setName(nt.m_name);
+ UMLTemplate *tmpl = static_cast<UMLTemplate*>(m_pObject);
+ tmpl->setType(nt.m_type);
+ m_Label = tmpl->toString(Uml::st_SigNoVis);
+ } else {
+ KMessageBox::error( kapp->mainWidget(),
+ Model_Utils::psText(st),
+ i18n("Rename canceled") );
+ }
+ QListViewItem::setText(0, m_Label);
+ break;
+ }
+
+ case Uml::lvt_UseCase_Diagram:
+ case Uml::lvt_Class_Diagram:
+ case Uml::lvt_Sequence_Diagram:
+ case Uml::lvt_Collaboration_Diagram:
+ case Uml::lvt_State_Diagram:
+ case Uml::lvt_Activity_Diagram:
+ case Uml::lvt_Component_Diagram:
+ case Uml::lvt_Deployment_Diagram:
+ {
+ UMLView *view = doc -> findView( getID() );
+ if (view == NULL) {
+ cancelRenameWithMsg();
+ return;
+ }
+ UMLView *anotherView = doc -> findView( view->getType(), newText );
+ if( anotherView && anotherView -> getID() == getID() )
+ anotherView = 0;
+ if (anotherView) {
+ cancelRenameWithMsg();
+ return;
+ }
+ view->setName( newText );
+ setText(newText);
+ doc->signalDiagramRenamed(view);
+ break;
+ }
+ default:
+ KMessageBox::error( kapp->mainWidget() ,
+ i18n("Renaming an item of listview type %1 is not yet implemented.").arg(m_Type),
+ i18n("Function Not Implemented") );
+ QListViewItem::setText(0, m_Label);
+ break;
+ }
+ doc->setModified(true);
+}
+
+void UMLListViewItem::cancelRenameWithMsg() {
+ KMessageBox::error( kapp->mainWidget() ,
+ i18n("The name you entered was invalid.\nRenaming process has been canceled."),
+ i18n("Name Not Valid") );
+ QListViewItem::setText(0, m_Label);
+}
+
+void UMLListViewItem::cancelRename(int col) {
+ QListViewItem::cancelRename(col);
+ if (m_bCreating) {
+ s_pListView->cancelRename(this);
+ }
+}
+
+// Sort the listview items by type and position within the corresponding list
+// of UMLObjects. If the item does not have an UMLObject then place it last.
+int UMLListViewItem::compare(QListViewItem *other, int col, bool ascending) const
+{
+ UMLListViewItem *ulvi = static_cast<UMLListViewItem*>(other);
+ Uml::ListView_Type ourType = getType();
+ Uml::ListView_Type otherType = ulvi->getType();
+
+ if ( ourType < otherType )
+ return -1;
+ if ( ourType > otherType )
+ return 1;
+ // ourType == otherType
+ const bool subItem = Model_Utils::typeIsClassifierList(ourType);
+ const int alphaOrder = key(col, ascending).compare(other->key(col, ascending));
+ int retval = 0;
+ QString dbgPfx = "compare(type=" + QString::number((int)ourType)
+ + ", self=" + getText() + ", other=" + ulvi->getText()
+ + "): return ";
+ UMLObject *otherObj = ulvi->getUMLObject();
+ if (m_pObject == NULL) {
+ retval = (subItem ? 1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (m_pObject==NULL)" << endl;
+#endif
+ return retval;
+ }
+ if (otherObj == NULL) {
+ retval = (subItem ? -1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (otherObj==NULL)" << endl;
+#endif
+ return retval;
+ }
+ UMLClassifier *ourParent = dynamic_cast<UMLClassifier*>(m_pObject->parent());
+ UMLClassifier *otherParent = dynamic_cast<UMLClassifier*>(otherObj->parent());
+ if (ourParent == NULL) {
+ retval = (subItem ? 1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (ourParent==NULL)" << endl;
+#endif
+ return retval;
+ }
+ if (otherParent == NULL) {
+ retval = (subItem ? -1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (otherParent==NULL)" << endl;
+#endif
+ return retval;
+ }
+ if (ourParent != otherParent) {
+ retval = (subItem ? 0 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (ourParent != otherParent)" << endl;
+#endif
+ return retval;
+ }
+ UMLClassifierListItem *thisUmlItem = dynamic_cast<UMLClassifierListItem*>(m_pObject);
+ UMLClassifierListItem *otherUmlItem = dynamic_cast<UMLClassifierListItem*>(otherObj);
+ if (thisUmlItem == NULL) {
+ retval = (subItem ? 1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (thisUmlItem==NULL)" << endl;
+#endif
+ return retval;
+ }
+ if (otherUmlItem == NULL) {
+ retval = (subItem ? -1 : alphaOrder);
+#ifdef DEBUG_LVITEM_INSERTION_ORDER
+ kDebug() << dbgPfx << retval << " because (otherUmlItem==NULL)" << endl;
+#endif
+ return retval;
+ }
+ UMLClassifierListItemList items = ourParent->getFilteredList(thisUmlItem->getBaseType());
+ int myIndex = items.findRef(thisUmlItem);
+ int otherIndex = items.findRef(otherUmlItem);
+ if (myIndex < 0) {
+ retval = (subItem ? -1 : alphaOrder);
+ kError() << dbgPfx << retval << " because (myIndex < 0)" << endl;
+ return retval;
+ }
+ if (otherIndex < 0) {
+ retval = (subItem ? 1 : alphaOrder);
+ kError() << dbgPfx << retval << " because (otherIndex < 0)" << endl;
+ return retval;
+ }
+ return (myIndex < otherIndex ? -1 : myIndex > otherIndex ? 1 : 0);
+}
+
+UMLListViewItem* UMLListViewItem::deepCopy(UMLListViewItem *newParent) {
+ QString nm = getText();
+ Uml::ListView_Type t = getType();
+ UMLObject *o = getUMLObject();
+ UMLListViewItem* newItem;
+ if (o)
+ newItem = new UMLListViewItem(newParent, nm, t, o);
+ else
+ newItem = new UMLListViewItem(newParent, nm, t, m_nId);
+ UMLListViewItem *childItem = static_cast<UMLListViewItem*>(firstChild());
+ while (childItem) {
+ childItem->deepCopy(newItem);
+ childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
+ }
+ return newItem;
+}
+
+UMLListViewItem* UMLListViewItem::findUMLObject(const UMLObject *o) {
+ if (m_pObject == o)
+ return this;
+ UMLListViewItem *childItem = static_cast<UMLListViewItem*>(firstChild());
+ while (childItem) {
+ UMLListViewItem *inner = childItem->findUMLObject(o);
+ if (inner)
+ return inner;
+ childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
+ }
+ return NULL;
+}
+
+UMLListViewItem* UMLListViewItem::findChildObject(UMLClassifierListItem *cli) {
+ ChildObjectMap::iterator it = m_comap.find(cli);
+ if (it != m_comap.end()) {
+ return *it;
+ }
+ return NULL;
+}
+
+UMLListViewItem * UMLListViewItem::findItem(Uml::IDType id) {
+ if (getID() == id)
+ return this;
+ UMLListViewItem *childItem = static_cast<UMLListViewItem*>(firstChild());
+ while (childItem) {
+ UMLListViewItem *inner = childItem->findItem(id);
+ if (inner)
+ return inner;
+ childItem = static_cast<UMLListViewItem*>(childItem->nextSibling());
+ }
+ return NULL;
+}
+
+void UMLListViewItem::saveToXMI( QDomDocument & qDoc, QDomElement & qElement) {
+ QDomElement itemElement = qDoc.createElement( "listitem" );
+ Uml::IDType id = getID();
+ QString idStr = ID2STR(id);
+ //kDebug() << "UMLListViewItem::saveToXMI: id = " << idStr
+ // << ", type = " << m_Type << endl;
+ if (id != Uml::id_None)
+ itemElement.setAttribute( "id", idStr );
+ itemElement.setAttribute( "type", m_Type );
+ UMLFolder *extFolder = NULL;
+ if (m_pObject == NULL) {
+ if (! Model_Utils::typeIsDiagram(m_Type) && m_Type != Uml::lvt_View)
+ kError() << "UMLListViewItem::saveToXMI(" << m_Label
+ << "): m_pObject is NULL" << endl;
+ itemElement.setAttribute( "label", m_Label );
+ } else if (m_pObject->getID() == Uml::id_None) {
+ if (m_Label.isEmpty()) {
+ kDebug() << "UMLListViewItem::saveToXMI(): Skipping empty item"
+ << endl;
+ return;
+ }
+ kDebug() << "UMLListViewItem::saveToXMI(): saving local label "
+ << m_Label << " because umlobject ID is not set" << endl;
+ itemElement.setAttribute( "label", m_Label );
+ } else if (m_pObject->getBaseType() == Uml::ot_Folder) {
+ extFolder = static_cast<UMLFolder*>(m_pObject);
+ if (!extFolder->getFolderFile().isEmpty()) {
+ itemElement.setAttribute("open", "0");
+ qElement.appendChild(itemElement);
+ return;
+ }
+ }
+ itemElement.setAttribute("open", isOpen());
+ QDomElement folderRoot;
+ UMLListViewItem *childItem = static_cast<UMLListViewItem*>( firstChild() );
+ while (childItem) {
+ childItem->saveToXMI(qDoc, itemElement);
+ childItem = dynamic_cast<UMLListViewItem *> ( childItem->nextSibling() );
+ }
+ qElement.appendChild( itemElement );
+}
+
+bool UMLListViewItem::loadFromXMI(QDomElement& qElement) {
+ QString id = qElement.attribute( "id", "-1" );
+ QString type = qElement.attribute( "type", "-1" );
+ QString label = qElement.attribute( "label", "" );
+ QString open = qElement.attribute( "open", "1" );
+ if (!label.isEmpty())
+ setText( label );
+ else if (id == "-1") {
+ kError() << "UMLListViewItem::loadFromXMI: Item of type "
+ << type << " has neither ID nor label" << endl;
+ return false;
+ }
+
+ m_nChildren = qElement.childNodes().count();
+
+ m_nId = STR2ID(id);
+ if (m_nId != Uml::id_None)
+ m_pObject = s_pListView->getDocument()->findObjectById( m_nId );
+ m_Type = (Uml::ListView_Type)(type.toInt());
+ if (m_pObject)
+ updateObject();
+ setOpen( (bool)open.toInt() );
+ return true;
+}
+
diff --git a/umbrello/umbrello/umllistviewitem.h b/umbrello/umbrello/umllistviewitem.h
new file mode 100644
index 00000000..99cedf4e
--- /dev/null
+++ b/umbrello/umbrello/umllistviewitem.h
@@ -0,0 +1,285 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ * *
+ ***************************************************************************/
+
+#ifndef UMLLISTVIEWITEM_H
+#define UMLLISTVIEWITEM_H
+
+#include <qlistview.h>
+#include <qmap.h>
+#include <qdom.h>
+#include "umlnamespace.h"
+
+// forward declarations
+class UMLListView;
+class UMLObject;
+class UMLClassifierListItem;
+
+/**
+ * Items used by the class @ref UMLListView. This is needed as the type
+ * and object information is required to be stored.
+ *
+ * @short Items used by @ref UMLListView.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * @see UMLListView
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLListViewItem : public QListViewItem {
+public:
+ /**
+ * Sets up an instance.
+ *
+ * @param parent The parent to this instance.
+ * @param name The name of this instance.
+ * @param t The type of this instance.
+ * @param o The object it represents.
+ */
+ UMLListViewItem(UMLListView * parent, const QString &name, Uml::ListView_Type t, UMLObject*o=0);
+
+ /**
+ * Sets up an instance for subsequent loadFromXMI().
+ *
+ * @param parent The parent to this instance.
+ */
+ UMLListViewItem(UMLListView * parent);
+
+ /**
+ * Sets up an instance for subsequent loadFromXMI().
+ *
+ * @param parent The parent to this instance.
+ */
+ UMLListViewItem(UMLListViewItem * parent);
+
+ /**
+ * Sets up an instance.
+ *
+ * @param parent The parent to this instance.
+ * @param name The name of this instance.
+ * @param t The type of this instance.
+ * @param o The object it represents.
+ */
+ UMLListViewItem(UMLListViewItem * parent, const QString &name, Uml::ListView_Type t, UMLObject*o=0);
+
+ /**
+ * Sets up an instance.
+ *
+ * @param parent The parent to this instance.
+ * @param name The name of this instance.
+ * @param t The type of this instance.
+ * @param id The id of this instance.
+ */
+ UMLListViewItem(UMLListViewItem * parent, const QString &name, Uml::ListView_Type t, Uml::IDType id);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~UMLListViewItem();
+
+ /**
+ * Returns the type this instance represents.
+ *
+ * @return The type this instance represents.
+ */
+ Uml::ListView_Type getType() const;
+
+ /**
+ * Sets the id this class represents.
+ * This only sets the ID locally, not at the UMLObject that is perhaps
+ * associated to this UMLListViewItem.
+ *
+ * @return The id this class represents.
+ */
+ void setID(Uml::IDType id);
+
+ /**
+ * Returns the id this class represents.
+ *
+ * @return The id this class represents.
+ */
+ Uml::IDType getID() const;
+
+ /**
+ * Set the UMLObject associated with this instance.
+ *
+ * @param obj The object this class represents.
+ */
+ void setUMLObject(UMLObject * obj) {
+ m_pObject = obj;
+ }
+
+ /**
+ * Return the UMLObject associated with this instance.
+ *
+ * @return The object this class represents.
+ */
+ UMLObject * getUMLObject() {
+ return m_pObject;
+ }
+
+ /**
+ * Returns true if the UMLListViewItem of the given ID is a parent of
+ * this UMLListViewItem.
+ */
+ bool isOwnParent(Uml::IDType listViewItemID);
+
+ /**
+ * Updates the representation of the object.
+ */
+ void updateObject();
+
+ /**
+ * Updates the icon on a folder.
+ */
+ void updateFolder();
+
+ /**
+ * Overrides default method.
+ * Will call default method but also makes sure correct icon is shown.
+ */
+ void setOpen( bool open );
+
+ /**
+ * Changes the current text and updates the tooltip.
+ */
+ void setText( const QString &text );
+
+ /**
+ * Returns the current text.
+ */
+ QString getText() const;
+
+ /**
+ * Sets if the item is in the middle of being created.
+ */
+ void setCreating( bool creating ) {
+ m_bCreating = creating;
+ }
+
+ /**
+ * Set the pixmap corresponding to the given Icon_Type.
+ */
+ void setIcon(Uml::Icon_Type iconType);
+
+ /**
+ * Overrides default method to make public.
+ */
+ void cancelRename( int col );
+
+ /**
+ * Adds the child listview item representing the given UMLClassifierListItem.
+ */
+ void addClassifierListItem(UMLClassifierListItem *child, UMLListViewItem *childItem);
+
+ /**
+ * Deletes the child listview item representing the given UMLClassifierListItem.
+ */
+ void deleteChildItem(UMLClassifierListItem *child);
+
+ /**
+ * Overrides the default sorting to sort by item type.
+ */
+ virtual int compare(QListViewItem *other, int col, bool ascending) const;
+
+ /**
+ * Returns the number of children of the UMLListViewItem
+ * containing this object
+ */
+ int childCount() const {
+ return m_nChildren;
+ }
+
+ /**
+ * Create a deep copy of this UMLListViewItem, but using the
+ * given parent instead of the parent of this UMLListViewItem.
+ * Return the new UMLListViewItem created.
+ */
+ UMLListViewItem* deepCopy(UMLListViewItem *newParent);
+
+ /**
+ * Find the UMLListViewItem that is related to the given UMLObject
+ * in the tree rooted at the current UMLListViewItem.
+ * Return a pointer to the item or NULL if not found.
+ */
+ UMLListViewItem* findUMLObject(const UMLObject *o);
+
+ /**
+ * Find the UMLListViewItem that represents the given UMLClassifierListItem
+ * in the children of the current UMLListViewItem. (Only makes sense if
+ * the current UMLListViewItem represents a UMLClassifier.)
+ * Return a pointer to the item or NULL if not found.
+ */
+ UMLListViewItem* findChildObject(UMLClassifierListItem *cli);
+
+ /**
+ * Find the UMLListViewItem of the given ID in the tree rooted at
+ * the current UMLListViewItem.
+ * Return a pointer to the item or NULL if not found.
+ *
+ * @param id The ID to search for.
+ * @return The item with the given ID or NULL if not found.
+ */
+ UMLListViewItem * findItem(Uml::IDType id);
+
+ /**
+ * saves the listview item to a "listitem" tag
+ */
+ void saveToXMI( QDomDocument& qDoc, QDomElement& qElement);
+
+ /**
+ * Loads a "listitem" tag, this is only used by the clipboard currently
+ */
+ bool loadFromXMI(QDomElement& qElement);
+
+protected:
+ /**
+ * Initializes key variables of the class.
+ */
+ void init(UMLListView * parent = 0);
+
+ /**
+ * This function is called if the user presses Enter during in-place renaming
+ * of the item in column col, reimplemented from QlistViewItem
+ */
+ void okRename( int col );
+
+ /**
+ * Auxiliary method for okRename().
+ */
+ void cancelRenameWithMsg();
+
+ /**
+ * This list view all the instance of this class are displayed on.
+ */
+ static UMLListView * s_pListView;
+
+ /**
+ * Flag used to set the state of creating.
+ */
+ bool m_bCreating;
+
+ /**
+ * Auxiliary map of child UMLLisViewItems keyed by UMLClassifierListItem.
+ * Used by findChildObject() for efficiency instead of looping using
+ * firstChild()/nextSibling() because the latter incur enforceItemVisible()
+ * and thus expensive sorting.
+ */
+ typedef QMap<UMLClassifierListItem*, UMLListViewItem*> ChildObjectMap;
+
+ Uml::ListView_Type m_Type;
+ Uml::IDType m_nId;
+ int m_nChildren;
+ UMLObject * m_pObject;
+ QString m_Label;
+ ChildObjectMap m_comap;
+};
+
+#endif
diff --git a/umbrello/umbrello/umllistviewitemlist.h b/umbrello/umbrello/umllistviewitemlist.h
new file mode 100644
index 00000000..49663163
--- /dev/null
+++ b/umbrello/umbrello/umllistviewitemlist.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ umllistviewitemlist.h - description
+ -------------------
+ begin : Sat Dec 29 2001
+ copyright : (C) 2001 by Gustavo Madrigal
+ email : gmadrigal@nextphere.com
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMLLISTVIEWITEMLIST_H
+#define UMLLISTVIEWITEMLIST_H
+
+#include <qptrlist.h>
+
+class UMLListViewItem;
+
+typedef QPtrList<UMLListViewItem> UMLListViewItemList;
+typedef QPtrListIterator<UMLListViewItem> UMLListViewItemListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlnamespace.cpp b/umbrello/umbrello/umlnamespace.cpp
new file mode 100644
index 00000000..f2d81eeb
--- /dev/null
+++ b/umbrello/umbrello/umlnamespace.cpp
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlnamespace.h"
+#include "qregexp.h"
+
+namespace Uml {
+
+bool tagEq (const QString& inTag, const QString& inPattern) {
+ QString tag = inTag;
+ QString pattern = inPattern;
+ tag.remove( QRegExp("^\\w+:") ); // remove leading "UML:" or other
+ int patSections = pattern.contains( '.' ) + 1;
+ QString tagEnd = tag.section( '.', -patSections );
+ return (tagEnd.lower() == pattern.lower());
+}
+
+QString Visibility::toString(Value value, bool mnemonic) {
+ switch (value) {
+ case Protected:
+ return (mnemonic ? "#" : "protected");
+ break;
+ case Private:
+ return (mnemonic ? "-" : "private");
+ break;
+ case Implementation:
+ return (mnemonic ? "~" : "implementation");
+ break;
+ case Public:
+ default:
+ return (mnemonic ? "+" : "public");
+ break;
+ }
+}
+
+Visibility Visibility::fromString(const QString& vis) {
+ if (vis == "public" || vis == "+")
+ return Visibility(Public);
+ else if (vis == "protected" || vis == "#")
+ return Visibility(Protected);
+ else if (vis == "private" || vis == "-")
+ return Visibility(Private);
+ else if (vis == "~")
+ return Visibility(Implementation);
+ else if (vis == "signals")
+ return Visibility(Protected);
+ else if (vis == "class")
+ return Visibility(Private);
+ else
+ return Visibility(Public);
+}
+
+Visibility::Visibility(): _v(Public) {
+}
+
+Visibility::Visibility(Value v): _v(v) {
+}
+
+QString Visibility::toString(bool mnemonic) const {
+ return toString(_v, mnemonic);
+}
+
+Visibility::operator Visibility::Value() const {
+ return _v;
+}
+
+} // end namespace Uml
+
diff --git a/umbrello/umbrello/umlnamespace.h b/umbrello/umbrello/umlnamespace.h
new file mode 100644
index 00000000..0c0ea2fd
--- /dev/null
+++ b/umbrello/umbrello/umlnamespace.h
@@ -0,0 +1,353 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLNAMESPACE_H
+#define UMLNAMESPACE_H
+
+#include <string>
+#include <qstring.h>
+
+
+/**
+ *@author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Uml {
+
+enum Model_Type
+{
+ mt_Logical,
+ mt_UseCase,
+ mt_Component,
+ mt_Deployment,
+ mt_EntityRelationship,
+ N_MODELTYPES // must remain last
+};
+
+enum Object_Type
+{
+ ot_UMLObject = 100,
+ ot_Actor,
+ ot_UseCase,
+ ot_Package,
+ ot_Interface,
+ ot_Datatype,
+ ot_Enum,
+ ot_Class,
+ ot_Association,
+ ot_Attribute,
+ ot_Operation,
+ ot_EnumLiteral,
+ ot_Template,
+ ot_Component,
+ ot_Artifact,
+ ot_Node,
+ ot_Stereotype,
+ ot_Role,
+ ot_Entity,
+ ot_EntityAttribute,
+ ot_Folder
+};
+
+class Visibility {
+ public:
+ enum Value {
+ Public = 200,
+ Private,
+ Protected,
+ Implementation // objects marked with this are declared in the implementation file.
+ };
+ Visibility();
+ Visibility(Value v);
+ static QString toString(Value value, bool mnemonic);
+ static Visibility fromString(const QString& vis);
+ /**
+ * Convert Visibility value into QString representation.
+ *
+ * @param mnemonic If true then return a single character:
+ * "+" for public, "-" for private,
+ * "#" for protected or "~" for implementation
+ */
+ QString toString(bool mnemonic = false) const;
+ operator Value () const;
+ private:
+ Value _v;
+};
+
+enum Widget_Type
+{
+ wt_UMLWidget = 300, // 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
+};
+
+enum Diagram_Type
+{
+ //the values in this enum are saved out to the file
+ //for file compatibility, only add new values to the end
+ dt_Undefined = 0,
+ dt_Class,
+ dt_UseCase,
+ dt_Sequence,
+ dt_Collaboration,
+ dt_State,
+ dt_Activity,
+ dt_Component,
+ dt_Deployment,
+ dt_EntityRelationship
+};
+
+enum Association_Type
+{
+ at_Generalization = 500,
+ at_Aggregation,
+ at_Dependency,
+ at_Association,
+ at_Association_Self,
+ at_Coll_Message,
+ at_Seq_Message,
+ at_Coll_Message_Self,
+ at_Seq_Message_Self,
+ at_Containment,
+ at_Composition,
+ at_Realization,
+ at_UniAssociation,
+ at_Anchor,
+ at_State,
+ at_Activity,
+ at_Relationship,
+ at_Unknown = - 1
+};
+
+enum Signature_Type
+{
+ st_NoSig = 600,
+ st_ShowSig,
+ st_SigNoVis,
+ st_NoSigNoVis
+};
+
+enum Text_Role
+{
+ tr_Floating = 700, //text widget on diagrams
+ tr_MultiA, //Text for Multiple A
+ tr_MultiB, //Text for Multiple B
+ tr_Name, //middle text on most associations
+ tr_Seq_Message, //message on seq diagram between two objects
+ tr_Seq_Message_Self, //message to self on seq diagram - feature not implemented yet
+ tr_Coll_Message, //message between two objects on a collab diagram
+ tr_Coll_Message_Self, //message to object self on collab diagram
+ tr_State,
+ tr_RoleAName, //RoleA text on associations
+ tr_RoleBName, //RoleB text on associations
+ tr_ChangeA, //Changeability A text on associations
+ tr_ChangeB //Changeability B text on associations
+};
+
+enum ListView_Type
+{
+ //the values in this enum are saved out to the file
+ //for file compatibility, only add new values to the end
+ lvt_View = 800,
+ lvt_Logical_View,
+ lvt_UseCase_View,
+ lvt_Logical_Folder,
+ lvt_UseCase_Folder,
+ lvt_UseCase_Diagram,
+ lvt_Collaboration_Diagram,
+ lvt_Class_Diagram,
+ lvt_State_Diagram,
+ lvt_Activity_Diagram,
+ lvt_Sequence_Diagram,
+ lvt_Actor,
+ lvt_UseCase,
+ lvt_Class,
+ lvt_Attribute,
+ lvt_Operation,
+ lvt_Template,
+ lvt_Interface,
+ lvt_Package,
+ lvt_Component_Diagram,
+ lvt_Component_Folder,
+ lvt_Component_View,
+ lvt_Component,
+ lvt_Diagrams, // currently unused
+ lvt_Artifact,
+ lvt_Deployment_Diagram,
+ lvt_Deployment_Folder,
+ lvt_Deployment_View,
+ lvt_Node,
+ lvt_Datatype,
+ lvt_Datatype_Folder,
+ lvt_Enum,
+ lvt_Entity,
+ lvt_EntityAttribute,
+ lvt_EntityRelationship_Diagram,
+ lvt_EntityRelationship_Folder,
+ lvt_EntityRelationship_Model,
+ lvt_Subsystem,
+ lvt_Model,
+ lvt_EnumLiteral,
+ lvt_Unknown = -1
+};
+
+enum Icon_Type
+{
+ it_Home = 0,
+ it_Folder_Cyan,
+ it_Folder_Cyan_Open,
+ it_Folder_Green,
+ it_Folder_Green_Open,
+ it_Folder_Grey,
+ it_Folder_Grey_Open,
+ it_Folder_Red,
+ it_Folder_Red_Open,
+ it_Folder_Violet,
+ it_Folder_Violet_Open,
+ it_Folder_Orange,
+ it_Folder_Orange_Open,
+ it_Diagram, //change to have different one for each type of diagram
+ it_Class,
+ it_Template,
+ it_Package,
+ it_Subsystem,
+ it_Component,
+ it_Node,
+ it_Artifact,
+ it_Interface,
+ it_Datatype,
+ it_Enum,
+ it_Entity,
+ it_Actor,
+ it_UseCase,
+ it_Public_Method,
+ it_Private_Method,
+ it_Protected_Method,
+ it_Public_Attribute,
+ it_Private_Attribute,
+ it_Protected_Attribute,
+ it_Diagram_Activity,
+ it_Diagram_Class,
+ it_Diagram_Collaboration,
+ it_Diagram_Component,
+ it_Diagram_Deployment,
+ it_Diagram_EntityRelationship,
+ it_Diagram_Sequence,
+ it_Diagram_State,
+ it_Diagram_Usecase,
+ N_ICONTYPES // must remain last
+};
+
+enum Changeability_Type
+{
+ chg_Changeable = 900,
+ chg_Frozen,
+ chg_AddOnly
+};
+
+enum Sequence_Message_Type
+{
+ //This is saved out to the file so only add new entries at the end
+ sequence_message_synchronous = 1000,
+ sequence_message_asynchronous,
+ sequence_message_creation
+};
+
+enum DBIndex_Type
+{
+ None = 1100,
+ Primary,
+ Index,
+ Unique
+};
+
+/**
+ * Constants used for indexing the roles of associations.
+ */
+enum Role_Type { A, B };
+
+/**
+ * Direction of operation parameters:
+ * in = operation uses the parameter as an input value
+ * out = operation fills the parameter as a return value
+ * inout = operation both reads and writes the parameter
+ * The numeric values of this enum are not currently saved to file.
+ */
+enum Parameter_Direction { pd_In, pd_InOut, pd_Out };
+
+/**
+ * Supported programming languages
+ */
+enum Programming_Language {
+ pl_ActionScript,
+ pl_Ada,
+ pl_Cpp,
+ pl_CSharp,
+ pl_D,
+ pl_IDL,
+ pl_Java,
+ pl_JavaScript,
+ pl_Pascal,
+ pl_Perl,
+ pl_PHP,
+ pl_PHP5,
+ pl_Python,
+ pl_Ruby,
+ pl_SQL,
+ pl_Tcl,
+ pl_XMLSchema,
+ pl_Reserved
+};
+
+/**
+ * The data type used for unique IDs.
+ */
+typedef std::string IDType;
+/**
+ * Reserved value for uninitialized/illegal ID.
+ */
+const IDType id_None = "-1";
+const IDType id_Reserved = "0";
+
+# define STR2ID(id) id.ascii()
+# define ID2STR(id) QString(id.c_str())
+
+// KDE4 compatibility
+# define kDebug kdDebug
+# define kWarning kdWarning
+# define kError kdError
+
+/**
+ * Function for comparing tags in XMI files.
+ */
+bool tagEq (const QString& tag, const QString& pattern);
+
+} // end namespace Uml
+
+#endif
diff --git a/umbrello/umbrello/umlobject.cpp b/umbrello/umbrello/umlobject.cpp
new file mode 100644
index 00000000..e28ed7da
--- /dev/null
+++ b/umbrello/umbrello/umlobject.cpp
@@ -0,0 +1,753 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlobject.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+#include <kapplication.h>
+// app includes
+#include "uniqueid.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+#include "package.h"
+#include "folder.h"
+#include "stereotype.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "codeimport/import_utils.h"
+#include "docwindow.h"
+#include "dialogs/classpropdlg.h"
+
+UMLObject::UMLObject(const UMLObject * parent, const QString &name, Uml::IDType id)
+ : QObject(const_cast<UMLObject*>(parent), "UMLObject" ) {
+ init();
+ if (id == Uml::id_None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+ m_Name = name;
+}
+
+UMLObject::UMLObject(const QString &name, Uml::IDType id)
+ : QObject(UMLApp::app()->getDocument()) {
+ init();
+ if (id == Uml::id_None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+ m_Name = name;
+}
+
+UMLObject::UMLObject(const UMLObject * parent)
+ : QObject(const_cast<UMLObject*>(parent)) {
+ init();
+}
+
+UMLObject::~UMLObject() {
+}
+
+void UMLObject::init() {
+ m_BaseType = Uml::ot_UMLObject;
+ m_nId = Uml::id_None;
+ m_pUMLPackage = NULL;
+ m_Name = "";
+ m_Vis = Uml::Visibility::Public;
+ m_pStereotype = NULL;
+ m_Doc = "";
+ m_bAbstract = false;
+ m_bStatic = false;
+ m_bInPaste = false;
+ m_bCreationWasSignalled = false;
+ m_pSecondary = NULL;
+}
+
+bool UMLObject::showProperties(int page, bool assoc) {
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation(false);
+ ClassPropDlg* dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this, page, assoc);
+ bool modified = false;
+ if (dlg->exec()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->getDocument()->setModified(true);
+ modified = true;
+ }
+ dlg->close(true); //wipe from memory
+ return modified;
+}
+
+bool UMLObject::acceptAssociationType(Uml::Association_Type)
+{// A UMLObject accepts nothing. This should be reimplemented by the subclasses
+ return false;
+}
+
+void UMLObject::setID(Uml::IDType NewID) {
+ m_nId = NewID;
+ emitModified();
+}
+
+void UMLObject::setName(const QString &strName) {
+ m_Name = strName;
+ emitModified();
+}
+
+QString UMLObject::getName() const {
+ return m_Name;
+}
+
+QString UMLObject::getFullyQualifiedName(const QString& separator,
+ bool includeRoot /* = false */) const {
+ QString fqn;
+ if (m_pUMLPackage) {
+ bool skipPackage = false;
+ if (!includeRoot) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (umldoc->rootFolderType(m_pUMLPackage) != Uml::N_MODELTYPES ||
+ m_pUMLPackage == umldoc->getDatatypeFolder())
+ skipPackage = true;
+ }
+ if (!skipPackage) {
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ fqn = m_pUMLPackage->getFullyQualifiedName(tempSeparator, includeRoot);
+ fqn.append(tempSeparator);
+ }
+ }
+ fqn.append(m_Name);
+ return fqn;
+}
+
+bool UMLObject::operator==(UMLObject & rhs ) {
+ if( this == &rhs )
+ return true;
+
+ //don't compare IDs, these are program specific and
+ //don't mean the objects are the same
+ //***** CHECK: Who put in this comment? What was the reason?
+ //***** Currently some operator== in umbrello compare the IDs
+ //***** while others don't.
+
+ if( m_Name != rhs.m_Name )
+ return false;
+
+ // Packages create different namespaces, therefore they should be
+ // part of the equality test.
+ if( m_pUMLPackage != rhs.m_pUMLPackage )
+ return false;
+
+ // Making the type part of an object's identity has its problems:
+ // Not all programming languages support declarations of the same
+ // name but different type.
+ // In such cases, the code generator is responsible for generating
+ // the appropriate error message.
+ if( m_BaseType != rhs.m_BaseType )
+ return false;
+
+ // The documentation should not be part of the equality test.
+ // If two objects are the same but differ only in their documentation,
+ // what does that mean?
+ //if( m_Doc != rhs.m_Doc )
+ // return false;
+
+ // The scope should not be part of the equality test.
+ // What does it mean if two objects are the same but differ in their
+ // scope? - I'm not aware of any programming language that would
+ // support that.
+ //if( m_Vis != rhs.m_Vis )
+ // return false;
+
+ // See comments above
+ //if( m_pStereotype != rhs.m_pStereotype )
+ // return false;
+
+ // See comments above
+ //if( m_bAbstract != rhs.m_bAbstract )
+ // return false;
+
+ // See comments above
+ //if( m_bStatic != rhs.m_bStatic )
+ // return false;
+
+ return true;
+}
+
+void UMLObject::copyInto(UMLObject *rhs) const
+{
+ // Data members with copy constructor
+ rhs->m_Doc = m_Doc;
+ rhs->m_pStereotype = m_pStereotype;
+ rhs->m_bAbstract = m_bAbstract;
+ rhs->m_bStatic = m_bStatic;
+ rhs->m_BaseType = m_BaseType;
+ rhs->m_Vis = m_Vis;
+ rhs->m_pUMLPackage = m_pUMLPackage;
+
+ // We don't want the same name existing twice.
+ rhs->m_Name = Model_Utils::uniqObjectName(m_BaseType, m_pUMLPackage, m_Name);
+
+ // Create a new ID.
+ rhs->m_nId = UniqueID::gen();
+
+ // Hope that the parent from QObject is okay.
+ if (rhs->parent() != parent())
+ kDebug() << "copyInto has a wrong parent" << endl;
+}
+
+
+bool UMLObject::getAbstract() const{
+ return m_bAbstract;
+}
+
+void UMLObject::setAbstract(bool bAbstract) {
+ m_bAbstract = bAbstract;
+ emitModified();
+}
+
+void UMLObject::setInPaste(bool bInPaste /* =true */) {
+ m_bInPaste = bInPaste;
+}
+
+/** Returns true if this UMLObject has classifier scope, otherwise false (the default). */
+bool UMLObject::getStatic() const
+{
+ return m_bStatic;
+}
+/** Sets the value for m_bStatic. */
+void UMLObject::setStatic(bool bStatic)
+{
+ m_bStatic = bStatic;
+ emitModified();
+}
+
+void UMLObject::emitModified()
+{
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (! umldoc->loading())
+ emit modified();
+}
+
+void UMLObject::setDoc(const QString &d) {
+ m_Doc = d;
+ //emit modified(); No, this is done centrally at DocWindow::updateDocumentation()
+}
+
+Uml::Object_Type UMLObject::getBaseType() const {
+ return m_BaseType;
+}
+
+void UMLObject::setBaseType(Uml::Object_Type ot) {
+ m_BaseType = ot;
+}
+
+Uml::IDType UMLObject::getID() const {
+ return m_nId;
+}
+
+QString UMLObject::getDoc() const {
+ return m_Doc;
+}
+
+Uml::Visibility UMLObject::getVisibility() const {
+ return m_Vis;
+}
+
+void UMLObject::setVisibility(Uml::Visibility s) {
+ m_Vis = s;
+ emitModified();
+}
+
+void UMLObject::setUMLStereotype(UMLStereotype *stereo) {
+ if (stereo == m_pStereotype)
+ return;
+ if (stereo) {
+ stereo->incrRefCount();
+ }
+ if (m_pStereotype) {
+ m_pStereotype->decrRefCount();
+ if (m_pStereotype->refCount() == 0) {
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ pDoc->removeStereotype(m_pStereotype);
+ delete m_pStereotype;
+ }
+ }
+ m_pStereotype = stereo;
+ // TODO: don't emit modified() if predefined folder
+ emitModified();
+}
+
+void UMLObject::setStereotype(const QString &_name) {
+ if (_name.isEmpty()) {
+ setUMLStereotype(NULL);
+ return;
+ }
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLStereotype *s = pDoc->findOrCreateStereotype(_name);
+ setUMLStereotype(s);
+}
+
+void UMLObject::setPackage(const QString &_name) {
+ UMLObject *pkgObj = NULL;
+ if (!_name.isEmpty()) {
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ pkgObj = umldoc->findUMLObject(_name);
+ if (pkgObj == NULL) {
+ kDebug() << "UMLObject::setPackage: creating UMLPackage "
+ << _name << " for " << m_Name << endl;
+ pkgObj = Import_Utils::createUMLObject(Uml::ot_Package, _name);
+ } else {
+ const Uml::Object_Type ot = pkgObj->getBaseType();
+ if (ot != Uml::ot_Package && ot != Uml::ot_Folder && ot != Uml::ot_Component) {
+ kError() << "UMLObject::setPackage(" << m_Name << "): "
+ << "existing " << _name << " is not a container" << endl;
+ // This should not happen - if it does, there may be further problems.
+ // A container name should not overlap with another name in the same scope.
+ pkgObj = Import_Utils::createUMLObject(Uml::ot_Package, _name);
+ }
+ }
+ }
+ setUMLPackage( static_cast<UMLPackage *>(pkgObj) );
+}
+
+void UMLObject::setUMLPackage(UMLPackage* pPkg) {
+ m_pUMLPackage = pPkg;
+ emitModified();
+}
+
+const UMLStereotype * UMLObject::getUMLStereotype() {
+ return m_pStereotype;
+}
+
+QString UMLObject::getStereotype(bool includeAdornments /* = false */) const {
+ if (m_pStereotype == NULL)
+ return "";
+ QString name = m_pStereotype->getName();
+ if (includeAdornments)
+ name = QString::fromUtf8("«") + name + QString::fromUtf8("»");
+ return name;
+}
+
+QString UMLObject::getPackage(const QString& separator, bool includeRoot) {
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ QString fqn = getFullyQualifiedName(tempSeparator, includeRoot);
+ if (!fqn.contains(tempSeparator))
+ return "";
+ QString scope = fqn.left(fqn.length() - tempSeparator.length() - m_Name.length());
+ return scope;
+}
+
+UMLPackageList UMLObject::getPackages(bool includeRoot) const {
+ UMLPackageList pkgList;
+ UMLPackage* pkg = m_pUMLPackage;
+ while (pkg != NULL) {
+ pkgList.prepend(pkg);
+ pkg = pkg->getUMLPackage();
+ }
+ if (!includeRoot)
+ pkgList.removeFirst();
+ return pkgList;
+}
+
+UMLPackage* UMLObject::getUMLPackage() {
+ return m_pUMLPackage;
+}
+
+QString UMLObject::getSecondaryId() const {
+ return m_SecondaryId;
+}
+
+void UMLObject::setSecondaryId(const QString& id) {
+ m_SecondaryId = id;
+}
+
+QString UMLObject::getSecondaryFallback() const {
+ return m_SecondaryFallback;
+}
+
+void UMLObject::setSecondaryFallback(const QString& id) {
+ m_SecondaryFallback = id;
+}
+
+void UMLObject::maybeSignalObjectCreated() {
+ if (!m_bCreationWasSignalled &&
+ m_BaseType != Uml::ot_Stereotype &&
+ m_BaseType != Uml::ot_Association &&
+ m_BaseType != Uml::ot_Role) {
+ m_bCreationWasSignalled = true;
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(this);
+ }
+}
+
+bool UMLObject::resolveRef() {
+ if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) {
+ maybeSignalObjectCreated();
+ return true;
+ }
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLObject::resolveRef(" << m_Name << "): m_SecondaryId is "
+ << m_SecondaryId << endl;
+#endif
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ // In the new, XMI standard compliant save format,
+ // the type is the xmi.id of a UMLClassifier.
+ if (! m_SecondaryId.isEmpty()) {
+ m_pSecondary = pDoc->findObjectById(STR2ID(m_SecondaryId));
+ if (m_pSecondary != NULL) {
+ if (m_pSecondary->getBaseType() == Uml::ot_Stereotype) {
+ m_pStereotype = static_cast<UMLStereotype*>(m_pSecondary);
+ m_pStereotype->incrRefCount();
+ m_pSecondary = NULL;
+ }
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ return true;
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ kDebug() << "UMLObject::resolveRef: object with xmi.id=" << m_SecondaryId
+ << " not found, setting to undef" << endl;
+ UMLFolder *datatypes = pDoc->getDatatypeFolder();
+ m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Datatype, "undef", datatypes, false);
+ return true;
+ }
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ kError() << "UMLObject::resolveRef(" << m_Name
+ << "): cannot find type with id "
+ << m_SecondaryId << endl;
+ return false;
+ }
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLObject::resolveRef(" << m_Name
+ << "): could not resolve secondary ID " << m_SecondaryId
+ << ", using secondary fallback " << m_SecondaryFallback
+ << endl;
+#endif
+ m_SecondaryId = m_SecondaryFallback;
+ // Assume we're dealing with the older Umbrello format where
+ // the type name was saved in the "type" attribute rather
+ // than the xmi.id of the model object of the attribute type.
+ m_pSecondary = pDoc->findUMLObject( m_SecondaryId, Uml::ot_UMLObject, this );
+ if (m_pSecondary) {
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ return true;
+ }
+ // Work around Object_Factory::createUMLObject()'s incapability
+ // of on-the-fly scope creation:
+ if (m_SecondaryId.contains("::")) {
+ // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
+ m_pSecondary = Import_Utils::createUMLObject(Uml::ot_UMLObject, m_SecondaryId, m_pUMLPackage);
+ if (m_pSecondary) {
+ if (Import_Utils::newUMLObjectWasCreated()) {
+ maybeSignalObjectCreated();
+ kapp->processEvents();
+ kDebug() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "created a new type for " << m_SecondaryId << endl;
+ } else {
+ kDebug() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "returned an existing type for " << m_SecondaryId << endl;
+ }
+ m_SecondaryId = "";
+ return true;
+ }
+ kError() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "failed to create a new type for " << m_SecondaryId << endl;
+ return false;
+ }
+ kDebug() << "UMLObject::resolveRef: Creating new type for " << m_SecondaryId << endl;
+ // This is very C++ specific - we rely on some '*' or
+ // '&' to decide it's a ref type. Plus, we don't recognize
+ // typedefs of ref types.
+ bool isReferenceType = ( m_SecondaryId.contains('*') ||
+ m_SecondaryId.contains('&') );
+ Uml::Object_Type ot = Uml::ot_Class;
+ if (isReferenceType) {
+ ot = Uml::ot_Datatype;
+ } else {
+ if (Model_Utils::isCommonDataType(m_SecondaryId))
+ ot = Uml::ot_Datatype;
+ }
+ m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL);
+ if (m_pSecondary == NULL)
+ return false;
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ //kapp->processEvents();
+ return true;
+}
+
+QDomElement UMLObject::save( const QString &tag, QDomDocument & qDoc ) {
+ /*
+ Call as the first action of saveToXMI() in child class:
+ This creates the QDomElement with which to work.
+ */
+ QDomElement qElement = qDoc.createElement(tag);
+ qElement.setAttribute( "isSpecification", "false" );
+ if (m_BaseType != Uml::ot_Association &&
+ m_BaseType != Uml::ot_Role &&
+ m_BaseType != Uml::ot_Attribute) {
+ qElement.setAttribute( "isLeaf", "false" );
+ qElement.setAttribute( "isRoot", "false" );
+ if (m_bAbstract)
+ qElement.setAttribute( "isAbstract", "true" );
+ else
+ qElement.setAttribute( "isAbstract", "false" );
+ }
+ qElement.setAttribute( "xmi.id", ID2STR(m_nId) );
+ qElement.setAttribute( "name", m_Name );
+ if (m_BaseType != Uml::ot_Operation &&
+ m_BaseType != Uml::ot_Role &&
+ m_BaseType != Uml::ot_Attribute) {
+ Uml::IDType nmSpc;
+ if (m_pUMLPackage)
+ nmSpc = m_pUMLPackage->getID();
+ else
+ nmSpc = UMLApp::app()->getDocument()->getModelID();
+ qElement.setAttribute( "namespace", ID2STR(nmSpc) );
+ }
+ if (! m_Doc.isEmpty())
+ qElement.setAttribute( "comment", m_Doc ); //CHECK: uml13.dtd compliance
+#ifdef XMI_FLAT_PACKAGES
+ if (m_pUMLPackage) //FIXME: uml13.dtd compliance
+ qElement.setAttribute( "package", m_pUMLPackage->getID() );
+#endif
+ QString visibility = m_Vis.toString(false);
+ qElement.setAttribute( "visibility", visibility);
+ if (m_pStereotype != NULL)
+ qElement.setAttribute( "stereotype", ID2STR(m_pStereotype->getID()) );
+ if (m_bStatic)
+ qElement.setAttribute( "ownerScope", "classifier" );
+ /* else
+ qElement.setAttribute( "ownerScope", "instance" );
+ *** ownerScope defaults to instance if not set **********/
+ return qElement;
+}
+
+bool UMLObject::load( QDomElement& ) {
+ // This body is not usually executed because child classes
+ // overwrite the load method.
+ return true;
+}
+
+bool UMLObject::loadStereotype(QDomElement & element) {
+ QString tag = element.tagName();
+ if (!Uml::tagEq(tag, "stereotype"))
+ return false;
+ QString stereo = element.attribute("xmi.value", "");
+ if (stereo.isEmpty() && element.hasChildNodes()) {
+ /* like so:
+ <UML:ModelElement.stereotype>
+ <UML:Stereotype xmi.idref = '07CD'/>
+ </UML:ModelElement.stereotype>
+ */
+ QDomNode stereoNode = element.firstChild();
+ QDomElement stereoElem = stereoNode.toElement();
+ tag = stereoElem.tagName();
+ if (Uml::tagEq(tag, "Stereotype")) {
+ stereo = stereoElem.attribute("xmi.idref", "");
+ }
+ }
+ if (stereo.isEmpty())
+ return false;
+ Uml::IDType stereoID = STR2ID(stereo);
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ m_pStereotype = pDoc->findStereotypeById(stereoID);
+ if (m_pStereotype)
+ m_pStereotype->incrRefCount();
+ else
+ m_SecondaryId = stereo; // leave it to resolveRef()
+ return true;
+}
+
+bool UMLObject::loadFromXMI( QDomElement & element) {
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ if (umldoc == NULL) {
+ kError() << "UMLObject::loadFromXMI: umldoc is NULL" << endl;
+ return false;
+ }
+ // Read the name first so that if we encounter a problem, the error
+ // message can say the name.
+ m_Name = element.attribute( "name", "" );
+ QString id = element.attribute( "xmi.id", "" );
+ if (id.isEmpty() || id == "-1") {
+ if (m_BaseType == Uml::ot_Role) {
+ // Before version 1.4, Umbrello did not save the xmi.id
+ // of UMLRole objects.
+ m_nId = UniqueID::gen();
+ } else {
+ kError() << "UMLObject::loadFromXMI(" << m_Name
+ << "): nonexistent or illegal xmi.id" << endl;
+ return false;
+ }
+ } else {
+ m_nId = STR2ID(id);
+ if (m_BaseType == Uml::ot_Role) {
+ // Some older Umbrello versions had a problem with xmi.id's
+ // of other objects being reused for the UMLRole, see e.g.
+ // attachment 21179 at http://bugs.kde.org/147988 .
+ // If the xmi.id is already being used then we generate a new one.
+ UMLObject *o = umldoc->findObjectById(m_nId);
+ if (o) {
+ kDebug() << "loadFromXMI(UMLRole): id " << id
+ << " is already in use, generating a new one." << endl;
+ m_nId = UniqueID::gen();
+ }
+ }
+ }
+
+ if (element.hasAttribute("documentation")) // for bkwd compat.
+ m_Doc = element.attribute( "documentation", "" );
+ else
+ m_Doc = element.attribute( "comment", "" ); //CHECK: need a UML:Comment?
+
+ m_Vis = Uml::Visibility::Public;
+ if (element.hasAttribute("scope")) { // for bkwd compat.
+ QString scope = element.attribute( "scope", "" );
+ if (scope == "instance_level") // nsuml compat.
+ m_bStatic = false;
+ else if (scope == "classifier_level") // nsuml compat.
+ m_bStatic = true;
+ else {
+ int nScope = scope.toInt();
+ if (nScope >= Uml::Visibility::Public && nScope <= Uml::Visibility::Protected)
+ m_Vis = (Uml::Visibility::Value)nScope;
+ else
+ kError() << "UMLObject::loadFromXMI(" << m_Name
+ << "): illegal scope" << endl; // soft error
+ }
+ } else {
+ QString visibility = element.attribute( "visibility", "public" );
+ if (visibility == "private"
+ || visibility == "private_vis") // for compatibility with other programs
+ m_Vis = Uml::Visibility::Private;
+ else if (visibility == "protected"
+ || visibility == "protected_vis") // for compatibility with other programs
+ m_Vis = Uml::Visibility::Protected;
+ else if (visibility == "implementation")
+ m_Vis = Uml::Visibility::Implementation;
+ }
+
+ QString stereo = element.attribute( "stereotype", "" );
+ if (!stereo.isEmpty()) {
+ Uml::IDType stereoID = STR2ID(stereo);
+ m_pStereotype = umldoc->findStereotypeById(stereoID);
+ if (m_pStereotype) {
+ m_pStereotype->incrRefCount();
+ } else {
+ kDebug() << "UMLObject::loadFromXMI(" << m_Name << "): "
+ << "UMLStereotype " << ID2STR(stereoID)
+ << " not found, creating now." << endl;
+ setStereotype(stereo);
+ }
+ }
+
+ if( element.hasAttribute("abstract") ) { // for bkwd compat.
+ QString abstract = element.attribute( "abstract", "0" );
+ m_bAbstract = (bool)abstract.toInt();
+ } else {
+ QString isAbstract = element.attribute( "isAbstract", "false" );
+ m_bAbstract = (isAbstract == "true");
+ }
+
+ if( element.hasAttribute("static") ) { // for bkwd compat.
+ QString staticScope = element.attribute( "static", "0" );
+ m_bStatic = (bool)staticScope.toInt();
+ } else {
+ QString ownerScope = element.attribute( "ownerScope", "instance" );
+ m_bStatic = (ownerScope == "classifier");
+ }
+
+ // If the node has child nodes, check whether attributes can be
+ // extracted from them.
+ if (element.hasChildNodes()) {
+ QDomNode node = element.firstChild();
+ if (node.isComment())
+ node = node.nextSibling();
+ QDomElement elem = node.toElement();
+ while( !elem.isNull() ) {
+ QString tag = elem.tagName();
+ if (Uml::tagEq(tag, "name")) {
+ m_Name = elem.attribute("xmi.value", "");
+ if (m_Name.isEmpty())
+ m_Name = elem.text();
+ } else if (Uml::tagEq(tag, "visibility")) {
+ QString vis = elem.attribute("xmi.value", "");
+ if (vis.isEmpty())
+ vis = elem.text();
+ if (vis == "private" || vis == "private_vis")
+ m_Vis = Uml::Visibility::Private;
+ else if (vis == "protected" || vis == "protected_vis")
+ m_Vis = Uml::Visibility::Protected;
+ else if (vis == "implementation")
+ m_Vis = Uml::Visibility::Implementation;
+ } else if (Uml::tagEq(tag, "isAbstract")) {
+ QString isAbstract = elem.attribute("xmi.value", "");
+ if (isAbstract.isEmpty())
+ isAbstract = elem.text();
+ m_bAbstract = (isAbstract == "true");
+ } else if (Uml::tagEq(tag, "ownerScope")) {
+ QString ownerScope = elem.attribute("xmi.value", "");
+ if (ownerScope.isEmpty())
+ ownerScope = elem.text();
+ m_bStatic = (ownerScope == "classifier");
+ } else {
+ loadStereotype(elem);
+ }
+ node = node.nextSibling();
+ if (node.isComment())
+ node = node.nextSibling();
+ elem = node.toElement();
+ }
+ }
+
+ // Operations, attributes, enum literals, templates, stereotypes,
+ // and association role objects get added and signaled elsewhere.
+ if (m_BaseType != Uml::ot_Operation && m_BaseType != Uml::ot_Attribute &&
+ m_BaseType != Uml::ot_EnumLiteral && m_BaseType != Uml::ot_EntityAttribute &&
+ m_BaseType != Uml::ot_Template && m_BaseType != Uml::ot_Stereotype &&
+ m_BaseType != Uml::ot_Role) {
+ if (m_bInPaste) {
+ m_pUMLPackage = NULL; // forget any old parent
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *parentItem = (UMLListViewItem*)listView->currentItem();
+ if (parentItem) {
+ Uml::ListView_Type lvt = parentItem->getType();
+ if (Model_Utils::typeIsContainer(lvt) ||
+ lvt == Uml::lvt_Class ||
+ lvt == Uml::lvt_Interface) {
+ UMLObject *o = parentItem->getUMLObject();
+ m_pUMLPackage = static_cast<UMLPackage*>( o );
+ }
+ }
+ }
+ if (m_pUMLPackage) {
+ m_pUMLPackage->addObject(this);
+ } else if (umldoc->rootFolderType(this) == Uml::N_MODELTYPES) {
+ // m_pUMLPackage is not set on the root folders.
+ kDebug() << "UMLObject::loadFromXMI(" << m_Name << "): m_pUMLPackage is not set"
+ << endl;
+ }
+ }
+ return load(element);
+}
+
+kdbgstream& operator<< (kdbgstream& s, const UMLObject& a) {
+ s << a.getName();
+ return s;
+}
+
+#include "umlobject.moc"
diff --git a/umbrello/umbrello/umlobject.h b/umbrello/umbrello/umlobject.h
new file mode 100644
index 00000000..d912bafc
--- /dev/null
+++ b/umbrello/umbrello/umlobject.h
@@ -0,0 +1,495 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLOBJECT_H
+#define UMLOBJECT_H
+
+//qt includes
+#include <qobject.h>
+#include <qstring.h>
+#include <qdom.h>
+
+#include "umlnamespace.h"
+#include "umlpackagelist.h"
+
+class kdbgstream;
+class UMLStereotype;
+class UMLObject;
+
+/**
+ * This class is the non-graphical version of @ref UMLWidget. These are
+ * created and maintained in the class @ref UMLDoc. This class holds all
+ * the generic information needed for all UML objects.
+ *
+ * @short The base class for UML objects.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLObject : public QObject {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a UMLObject.
+ *
+ * @param parent The parent of the object.
+ * @param name The name of the object.
+ * @param id The ID of the object (optional.) If omitted
+ * then a new ID will be assigned internally.
+ */
+ UMLObject(const UMLObject * parent, const QString &name, Uml::IDType id = Uml::id_None);
+
+ /**
+ * Creates a UMLObject.
+ *
+ * @param parent The parent of the object.
+ */
+ UMLObject(const UMLObject * parent);
+
+ /**
+ * Creates a UMLObject with a given name and unique ID.
+ *
+ * @param name The name of the object.
+ * @param id The unique ID of the object.
+ */
+ explicit UMLObject(const QString &name = "" , Uml::IDType id = Uml::id_None);
+
+ /**
+ * Overloaded '==' operator
+ */
+ virtual bool operator==(UMLObject & rhs );
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLObject();
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto(UMLObject *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ * To be implemented by inheriting classes.
+ */
+ virtual UMLObject* clone() const = 0;
+
+ /**
+ * Returns the type of the object.
+ *
+ * @return Returns the type of the object.
+ */
+ Uml::Object_Type getBaseType() const;
+
+ /**
+ * Set the type of the object.
+ *
+ * @param ot The Uml::Object_Type to set.
+ */
+ virtual void setBaseType(Uml::Object_Type ot);
+
+ /**
+ * Returns the ID of the object.
+ *
+ * @return Returns the ID of the object.
+ */
+ virtual Uml::IDType getID() const;
+
+ /**
+ * Sets the documentation for the object.
+ *
+ * @param d The documentation for the object.
+ */
+ void setDoc(const QString &d);
+
+ /**
+ * Returns the documentation for the object.
+ *
+ * @return Returns the documentation for the object.
+ */
+ QString getDoc() const;
+
+ /**
+ * Returns the visibility of the object.
+ *
+ * @return Returns the visibility of the object.
+ */
+ Uml::Visibility getVisibility() const;
+
+ /**
+ * Sets the visibility of the object.
+ *
+ * @param s The visibility of the object.
+ */
+ virtual void setVisibility(Uml::Visibility s);
+
+ /**
+ * Sets the classes stereotype name.
+ * Internally uses setUMLStereotype().
+ *
+ * @param _name Sets the classes stereotype name.
+ */
+ void setStereotype(const QString &_name);
+
+ /**
+ * Sets the class' UMLStereotype. Adjusts the reference counts
+ * at the previously set stereotype and at the new stereotype.
+ * If the previously set UMLStereotype's reference count drops
+ * to zero then the UMLStereotype is removed at the UMLDoc and
+ * it is then physically deleted.
+ *
+ * @param s Sets the classes UMLStereotype.
+ */
+ void setUMLStereotype(UMLStereotype *s);
+
+ /**
+ * Sets the classes Package.
+ * DEPRECATED - use SetUMLPackage instead.
+ *
+ * @param _name The classes Package name.
+ */
+ void setPackage(const QString &_name);
+
+ /**
+ * Sets the UMLPackage in which this class is located.
+ *
+ * @param pPkg Pointer to the class' UMLPackage.
+ */
+ void setUMLPackage(UMLPackage* pPkg);
+
+ /**
+ * Returns the classes UMLStereotype object.
+ *
+ * @return Returns the classes UMLStereotype object.
+ */
+ const UMLStereotype * getUMLStereotype();
+
+ /**
+ * Returns the classes stereotype name.
+ * Returns an empty string if no stereotype object is set.
+ *
+ * @param includeAdornments Include surrounding angled brackets
+ * "«" and "»".
+ * @return Returns the classes stereotype name.
+ */
+ QString getStereotype(bool includeAdornments = false) const;
+
+ /**
+ * Return the package(s) in which this UMLObject is contained
+ * as a text.
+ *
+ * @param separator Separator string for joining together the
+ * individual package prefixes (optional.)
+ * If no separator is given then the separator
+ * of the currently selected language is used.
+ * @param includeRoot Whether to prefix the root folder name.
+ * Default: false.
+ * @return The UMLObject's enclosing package(s) as a text.
+ */
+ QString getPackage(const QString& separator = QString::null,
+ bool includeRoot = false);
+
+ /**
+ * Return a list of the packages in which this class is embedded.
+ * The outermost package is first in the list.
+ *
+ * @param includeRoot Whether to prefix the root folder name.
+ * Default: false.
+ * @return UMLPackageList of the containing packages.
+ */
+ UMLPackageList getPackages(bool includeRoot = false) const;
+
+ /**
+ * Returns the UMLPackage that this class is located in.
+ *
+ * @return Pointer to the UMLPackage of this class.
+ */
+ UMLPackage* getUMLPackage();
+
+ /**
+ * Assigns a new Id to the object
+ */
+ virtual void setID(Uml::IDType NewID);
+
+ /**
+ * Returns a copy of m_Name
+ */
+ QString getName() const;
+
+ /**
+ * Set the UMLObject's name
+ */
+ virtual void setName(const QString &strName);
+
+ /**
+ * Returns the fully qualified name, i.e. all package prefixes and then m_Name.
+ *
+ * @param separator The separator string to use (optional.)
+ * If not given then the separator is chosen according
+ * to the currently selected active programming language
+ * of import and code generation.
+ * @param includeRoot Whether to prefix the root folder name to the FQN.
+ * See UMLDoc::getRootFolder(). Default: false.
+ * @return The fully qualified name of this UMLObject.
+ */
+ virtual QString getFullyQualifiedName(const QString& separator = QString::null,
+ bool includeRoot = false) const;
+
+ /**
+ * Returns the abstract state of the object.
+ */
+ bool getAbstract() const;
+
+ /**
+ * Sets the abstract state of the object.
+ */
+ void setAbstract(bool bAbstract);
+
+ /**
+ * Sets the abstract state of the object.
+ */
+ void setInPaste(bool bInPaste = true);
+
+ /**
+ * This method is called if you wish to see the properties of a
+ * UMLObject. A dialog box will be displayed from which you
+ * can change the object's properties.
+ *
+ * @param page The page to show.
+ * @param assoc Whether to show association page.
+ * @return True if we modified the object.
+ */
+ bool showProperties(int page = 0, bool assoc = false);
+
+ /**
+ * Resolve referenced objects (if any.)
+ * Needs to be called after all UML objects are loaded from file.
+ * This needs to be done after all model objects are loaded because
+ * some of the xmi.id's might be forward references, i.e. they may
+ * identify model objects which were not yet loaded at the point of
+ * reference.
+ * The default implementation attempts resolution of the m_SecondaryId.
+ *
+ * @return True for success.
+ */
+ virtual bool resolveRef();
+
+ /**
+ * This method saves the XMI attributes of each specific model class.
+ * It needs to be implemented by each child class.
+ * For creating the QDomElement and saving the common XMI parts,
+ * it can use the save() method.
+ */
+ virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) = 0;
+
+ /**
+ * This method loads the generic parts of the XMI common to most model
+ * classes. It is not usually reimplemented by child classes.
+ * Instead, it invokes the load() method which implements the loading
+ * of the specifics of each child class.
+ *
+ * @param element The QDomElement from which to load.
+ */
+ virtual bool loadFromXMI( QDomElement & element );
+
+ /**
+ * Analyzes the given QDomElement for a reference to a stereotype.
+ *
+ * @param element QDomElement to analyze.
+ * @return True if a stereotype reference was found, else false.
+ */
+ bool loadStereotype(QDomElement & element);
+
+ /**
+ * Returns true if this UMLObject has classifier scope,
+ * otherwise false (the default).
+ */
+ bool getStatic() const;
+
+
+ /**
+ * Sets the value for m_bStatic.
+ */
+ void setStatic(bool bStatic);
+
+ /**
+ * This should be reimplemented by subclasses if they wish to
+ * accept certain types of associations. Note that this only
+ * tells if this UMLObject can accept the association
+ * type. When creating an association another check is made to
+ * see if the association is valid. For example a UMLClass
+ * (UMLClassifier) can accept generalizations and should
+ * return true. If while creating a generalization the
+ * superclass is already subclassed from this, the association
+ * is not valid and will not be created. The default accepts
+ * nothing (returns false)
+ */
+ virtual bool acceptAssociationType(Uml::Association_Type);
+
+ /**
+ * Return secondary ID. Required by resolveRef().
+ */
+ QString getSecondaryId() const;
+
+ /**
+ * Set the secondary ID.
+ * Currently only required by petalTree2Uml(); all other setting of the
+ * m_SecondaryID is internal to the UMLObject class hierarchy.
+ */
+ void setSecondaryId(const QString& id);
+
+ /**
+ * Return secondary ID fallback.
+ * Required by resolveRef() for imported model files.
+ */
+ QString getSecondaryFallback() const;
+
+ /**
+ * Set the secondary ID fallback.
+ * Currently only used by petalTree2Uml().
+ */
+ void setSecondaryFallback(const QString& id);
+
+ /**
+ * Auxiliary to saveToXMI.
+ * Create a QDomElement with the given tag, and save the XMI attributes
+ * that are common to all child classes to the newly created element.
+ * This method does not need to be overridden by child classes.
+ */
+ QDomElement save( const QString &tag, QDomDocument & qDoc );
+
+public slots:
+ /**
+ * Forces the emission of the modified signal. Useful when
+ * updating several attributes at a time: you can block the
+ * signals, update all atts, and then force the signal.
+ */
+ void emitModified();
+
+signals:
+ /** Emitted when the UMLObject has changed. Note that some objects emit
+ * this signal when one of its children changes, for example, a UMLClass
+ * emits a modified() signal when one of its operation changes while the Operation
+ * itself emits the corresponding signal as well.
+ */
+ void modified();
+
+protected:
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Calls UMLDoc::signalUMLObjectCreated() if m_BaseType affords
+ * doing so.
+ */
+ void maybeSignalObjectCreated();
+
+ /**
+ * Auxiliary to loadFromXMI.
+ * This method is usually overridden by child classes.
+ * It is responsible for loading the specific XMI structure
+ * of the child class.
+ */
+ virtual bool load( QDomElement& element );
+
+ /**
+ * The object's id.
+ */
+ Uml::IDType m_nId;
+
+ /**
+ * The object's documentation.
+ */
+ QString m_Doc;
+
+ /**
+ * The package the object belongs to if applicable.
+ */
+ UMLPackage* m_pUMLPackage;
+
+ /**
+ * The stereotype of the object if applicable.
+ */
+ UMLStereotype* m_pStereotype;
+
+ /**
+ * The objects name.
+ */
+ QString m_Name;
+
+ /**
+ * The objects type.
+ */
+ Uml::Object_Type m_BaseType;
+
+ /**
+ * The objects visibility.
+ */
+ Uml::Visibility m_Vis;
+
+ /**
+ * The state of whether the object is abstract or not.
+ */
+ bool m_bAbstract;
+
+ /**
+ * This attribute holds whether the UMLObject has instance scope
+ * (false - the default) or classifier scope (true).
+ */
+ bool m_bStatic;
+
+ /**
+ * Caller sets this true when in paste operation.
+ */
+ bool m_bInPaste;
+
+ /**
+ * Auxiliary to maybeSignalObjectCreated().
+ */
+ bool m_bCreationWasSignalled;
+
+ /**
+ * Pointer to an associated object.
+ * Only a few of the classes inheriting from UMLObject use this.
+ * However, it needs to be here because of inheritance graph
+ * disjunctness.
+ */
+ UMLObject* m_pSecondary;
+
+ /**
+ * xmi.id of the secondary object for intermediate use during
+ * loading. The secondary ID is resolved to the m_pSecondary
+ * in the course of resolveRef() at the end of loading.
+ */
+ QString m_SecondaryId;
+
+ /**
+ * Last-chance backup for when m_SecondaryId is not found.
+ * Used by Rose import: MDL files specify both a "quidu"
+ * (which corresponds to m_SecondaryId) and the human readable
+ * fully qualified target name of a reference.
+ * In case the quidu is not found, the human readable name is
+ * used which we store in m_SecondaryFallback.
+ */
+ QString m_SecondaryFallback;
+};
+
+/**
+ * Print UML Object to kdgstream, so it can be used like
+ * kdWarn() << "This object shouldn't be here:" << illegalObject << endl;
+ */
+kdbgstream& operator<< (kdbgstream& s, const UMLObject& a);
+
+#endif
diff --git a/umbrello/umbrello/umlobjectlist.cpp b/umbrello/umbrello/umlobjectlist.cpp
new file mode 100644
index 00000000..f2850ebd
--- /dev/null
+++ b/umbrello/umbrello/umlobjectlist.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "umlobjectlist.h"
+#include "umlobject.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+void UMLObjectList::copyInto(UMLObjectList *rhs) const {
+ // Don't copy yourself.
+ if (rhs == this) return;
+
+ rhs->clear();
+
+ // Suffering from const; we shall not modify our object.
+ UMLObjectList *tmp = new UMLObjectList(*this);
+
+ UMLObject *item;
+ for (item = tmp->first(); item; item = tmp->next() )
+ {
+ rhs->append(item->clone());
+ }
+ delete tmp;
+}
+
+
+UMLObjectList* UMLObjectList::clone() const {
+ UMLObjectList *clone = new UMLObjectList();
+ copyInto(clone);
+ return clone;
+}
+
+
+
diff --git a/umbrello/umbrello/umlobjectlist.h b/umbrello/umbrello/umlobjectlist.h
new file mode 100644
index 00000000..d9d11c83
--- /dev/null
+++ b/umbrello/umbrello/umlobjectlist.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ umlobjectlist.h - description
+ -------------------
+ begin : Sat Dec 29 2001
+ copyright : (C) 2001 by Gustavo Madrigal
+ email : gmadrigal@nextphere.com
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMLOBJECTLIST_H
+#define UMLOBJECTLIST_H
+
+#include <qptrlist.h>
+
+// forward declarations
+class UMLObject;
+
+//typedef QPtrList<UMLObject> UMLObjectList;
+typedef QPtrListIterator<UMLObject> UMLObjectListIt;
+
+
+/**
+ * This sub-class adds copyInto and clone to the QPtrList<UMLObject>
+ * base class.
+ */
+class UMLObjectList : public QPtrList<UMLObject>
+{
+
+public:
+
+ /**
+ * Copy the internal presentation of this object into the new
+ * object.
+ */
+ virtual void copyInto (UMLObjectList *rhs) const;
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObjectList* clone() const;
+};
+
+
+#endif
diff --git a/umbrello/umbrello/umloperationlist.h b/umbrello/umbrello/umloperationlist.h
new file mode 100644
index 00000000..dfb9007e
--- /dev/null
+++ b/umbrello/umbrello/umloperationlist.h
@@ -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) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLOPERATIONLIST_H
+#define UMLOPERATIONLIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLOperation;
+
+typedef QPtrList<UMLOperation> UMLOperationList;
+typedef QPtrListIterator<UMLOperation> UMLOperationListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlpackagelist.h b/umbrello/umbrello/umlpackagelist.h
new file mode 100644
index 00000000..d74e8c33
--- /dev/null
+++ b/umbrello/umbrello/umlpackagelist.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLPACKAGELIST_H
+#define UMLPACKAGELIST_H
+
+#include <qptrlist.h>
+
+class UMLPackage;
+
+typedef QPtrList<UMLPackage> UMLPackageList;
+typedef QPtrListIterator<UMLPackage> UMLPackageListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlrole.cpp b/umbrello/umbrello/umlrole.cpp
new file mode 100644
index 00000000..9b4449fc
--- /dev/null
+++ b/umbrello/umbrello/umlrole.cpp
@@ -0,0 +1,339 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlrole.h"
+
+// qt/kde includes
+#include <kdebug.h>
+#include <qregexp.h>
+
+// local includes
+#include "association.h"
+#include "umldoc.h"
+#include "uml.h"
+
+
+// constructor
+UMLRole::UMLRole(UMLAssociation * parent, UMLObject * parentObj, Uml::Role_Type role)
+ : UMLObject(const_cast<UMLAssociation*>(parent))
+{
+ init(parent, parentObj, role);
+}
+
+UMLRole::~UMLRole() { }
+
+bool UMLRole::operator==(UMLRole &rhs) {
+ if (this == &rhs) {
+ return true;
+ }
+ return ( UMLObject::operator==( rhs ) &&
+ m_Changeability == rhs.m_Changeability &&
+ m_Multi == rhs.m_Multi &&
+ m_Name == rhs.m_Name
+ );
+}
+
+UMLAssociation * UMLRole::getParentAssociation () {
+ return m_pAssoc;
+}
+
+UMLObject* UMLRole::getObject() {
+ return m_pSecondary;
+}
+
+Uml::Changeability_Type UMLRole::getChangeability() const {
+ return m_Changeability;
+}
+
+QString UMLRole::getMultiplicity() const {
+ return m_Multi;
+}
+
+void UMLRole::setObject (UMLObject *obj) {
+ // because we will get the id of this role from the parent
+ // object, we CANT allow UMLRoles to take other UMLRoles as
+ // parent objects. In fact, there is probably good reason
+ // to only take UMLClassifiers here, but I'll leave it more open
+ // for the time being. -b.t.
+ if (obj && dynamic_cast<UMLRole*>(obj)) {
+ kError() << "UMLRole(" << ID2STR(m_nId) << ") cannot setObject() to another UMLRole("
+ << ID2STR(obj->getID()) << ")" << endl;
+ return;
+ }
+
+ m_pSecondary = obj;
+ UMLObject::emitModified();
+}
+
+void UMLRole::setChangeability (Uml::Changeability_Type value) {
+ m_Changeability = value;
+ UMLObject::emitModified();
+}
+
+void UMLRole::setMultiplicity ( const QString &multi ) {
+ m_Multi = multi;
+ UMLObject::emitModified();
+}
+
+Uml::Role_Type UMLRole::getRole() {
+ return m_role;
+}
+
+void UMLRole::init(UMLAssociation * parent, UMLObject * parentObj, Uml::Role_Type r) {
+ m_BaseType = Uml::ot_Role;
+ m_role = r;
+ m_pAssoc = parent;
+ m_pSecondary = parentObj;
+ m_Multi = "";
+ m_Name = "";
+ m_Changeability = Uml::chg_Changeable;
+
+ // connect this up to parent
+ connect(this,SIGNAL(modified()),parent,SIGNAL(modified()));
+}
+
+void UMLRole::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement roleElement = UMLObject::save("UML:AssociationEnd", qDoc);
+ if (m_pSecondary)
+ roleElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) );
+ else
+ kError() << "UMLRole::saveToXMI(id " << ID2STR(m_nId)
+ << "): m_pSecondary is NULL" << endl;
+ if (!m_Multi.isEmpty())
+ roleElement.setAttribute("multiplicity", m_Multi);
+ if (m_role == Uml::A) { // role aggregation based on parent type
+ // role A
+ switch (m_pAssoc->getAssocType()) {
+ case Uml::at_Composition:
+ roleElement.setAttribute("aggregation", "composite");
+ break;
+ case Uml::at_Aggregation:
+ roleElement.setAttribute("aggregation", "aggregate");
+ break;
+ default:
+ roleElement.setAttribute("aggregation", "none");
+ break;
+ }
+ if (m_pAssoc->getAssocType() == Uml::at_UniAssociation) {
+ // Normally the isNavigable attribute is "true".
+ // We set it to false on role A to indicate that
+ // role B gets an explicit arrowhead.
+ roleElement.setAttribute("isNavigable", "false");
+ } else {
+ roleElement.setAttribute("isNavigable", "true");
+ }
+ } else {
+ roleElement.setAttribute("aggregation", "none");
+ roleElement.setAttribute("isNavigable", "true");
+ //FIXME obviously this isn't standard XMI
+ if (m_pAssoc->getAssocType() == Uml::at_Relationship) {
+ roleElement.setAttribute("relationship", "true");
+ }
+ }
+
+ roleElement.setAttribute("visibility", getVisibility().toString(false));
+
+ switch (m_Changeability) {
+ case Uml::chg_Frozen:
+ roleElement.setAttribute("changeability", "frozen");
+ break;
+ case Uml::chg_AddOnly:
+ roleElement.setAttribute("changeability", "addOnly");
+ break;
+ case Uml::chg_Changeable:
+ roleElement.setAttribute("changeability", "changeable");
+ break;
+ }
+ qElement.appendChild( roleElement );
+}
+
+bool UMLRole::load( QDomElement & element ) {
+ UMLDoc * doc = UMLApp::app()->getDocument();
+ QString type = element.attribute("type", "");
+ if (!type.isEmpty()) {
+ if (!m_SecondaryId.isEmpty())
+ kWarning() << "UMLRole::load: overwriting old m_SecondaryId \""
+ << m_SecondaryId << " with new value \""
+ << type << "\"" << endl;
+ m_SecondaryId = type;
+ }
+ // Inspect child nodes - for multiplicity (and type if not set above.)
+ for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement tempElement = node.toElement();
+ QString tag = tempElement.tagName();
+ if (Uml::tagEq(tag, "name")) {
+ m_Name = tempElement.text();
+ } else if (Uml::tagEq(tag, "AssociationEnd.multiplicity")) {
+ /**
+ * There are different ways in which the multiplicity might be given:
+ * - direct value in the <AssociationEnd.multiplicity> tag,
+ * - attributes "lower" and "upper" of a subordinate <MultiplicityRange>,
+ * - direct value in subordinate <MultiplicityRange.lower> and
+ * <MultiplicityRange.upper> tags
+ */
+ QDomNode n = tempElement.firstChild();
+ if (node.isNull() || tempElement.isNull() || n.isNull() ||
+ n.toElement().isNull()) {
+ m_Multi = tempElement.text().stripWhiteSpace();
+ continue;
+ }
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "Multiplicity")) {
+ m_Multi = tempElement.text().stripWhiteSpace();
+ continue;
+ }
+ n = tempElement.firstChild();
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "Multiplicity.range")) {
+ m_Multi = tempElement.text().stripWhiteSpace();
+ continue;
+ }
+ n = tempElement.firstChild();
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (!Uml::tagEq(tag, "MultiplicityRange")) {
+ m_Multi = tempElement.text().stripWhiteSpace();
+ continue;
+ }
+ QString multiUpper;
+ if (tempElement.hasAttribute("lower")) {
+ m_Multi = tempElement.attribute("lower", "");
+ multiUpper = tempElement.attribute("upper", "");
+ if (!multiUpper.isEmpty()) {
+ if (!m_Multi.isEmpty())
+ m_Multi.append("..");
+ m_Multi.append(multiUpper);
+ }
+ continue;
+ }
+ n = tempElement.firstChild();
+ while (!n.isNull()) {
+ tempElement = n.toElement();
+ tag = tempElement.tagName();
+ if (Uml::tagEq(tag, "MultiplicityRange.lower")) {
+ m_Multi = tempElement.text();
+ } else if (Uml::tagEq(tag, "MultiplicityRange.upper")) {
+ multiUpper = tempElement.text();
+ }
+ n = n.nextSibling();
+ }
+ if (!multiUpper.isEmpty()) {
+ if (!m_Multi.isEmpty())
+ m_Multi.append("..");
+ m_Multi.append(multiUpper);
+ }
+ } else if (m_SecondaryId.isEmpty() &&
+ (Uml::tagEq(tag, "type") ||
+ Uml::tagEq(tag, "participant"))) {
+ m_SecondaryId = tempElement.attribute("xmi.id", "");
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = tempElement.attribute("xmi.idref", "");
+ if (m_SecondaryId.isEmpty()) {
+ QDomNode inner = tempElement.firstChild();
+ QDomElement innerElem = inner.toElement();
+ m_SecondaryId = innerElem.attribute("xmi.id", "");
+ if (m_SecondaryId.isEmpty())
+ m_SecondaryId = innerElem.attribute("xmi.idref", "");
+ }
+ }
+ }
+ if (!m_Multi.isEmpty())
+ kDebug() << "UMLRole::load(" << m_Name << "): m_Multi is " << m_Multi << endl;
+ if (m_SecondaryId.isEmpty()) {
+ kError() << "UMLRole::load(" << m_Name << "): type not given or illegal" << endl;
+ return false;
+ }
+ UMLObject * obj;
+ obj = doc->findObjectById(STR2ID(m_SecondaryId));
+ if (obj) {
+ m_pSecondary = obj;
+ m_SecondaryId = "";
+ }
+
+ // block signals to prevent needless updating
+ blockSignals(true);
+ // Here comes the handling of the association type.
+ // This is open for discussion - I'm pretty sure there are better ways..
+
+ // Yeah, for one, setting the *parent* object parameters from here is sucky
+ // as hell. Why are we using roleA to store what is essentially a parent (association)
+ // parameter, eh? The UML13.dtd is pretty silly, but since that is what
+ // is driving us to that point, we have to go with it. Some analysis of
+ // the component roles/linked items needs to be done in order to get things
+ // right. *sigh* -b.t.
+
+ // Setting association type from the role (A)
+ // Determination of the "aggregation" attribute used to be done only
+ // when (m_role == Uml::A) but some XMI writers (e.g. StarUML) place
+ // the aggregation attribute at role B.
+ // The role end with the aggregation unequal to "none" wins.
+ QString aggregation = element.attribute("aggregation", "none");
+ if (aggregation == "composite")
+ m_pAssoc->setAssocType(Uml::at_Composition);
+ else if (aggregation == "shared" // UML1.3
+ || aggregation == "aggregate") // UML1.4
+ m_pAssoc->setAssocType(Uml::at_Aggregation);
+
+ if (!element.hasAttribute("isNavigable")) {
+ /* Backward compatibility mode: In Umbrello version 1.3.x the
+ logic for saving the isNavigable flag was wrong.
+ May happen on loading role A.
+ */
+ m_pAssoc->setOldLoadMode(true);
+ } else if (m_pAssoc->getOldLoadMode() == true) {
+ /* Here is the original logic:
+ " Role B:
+ If isNavigable is not given, we make no change to the
+ association type.
+ If isNavigable is given, and is "true", then we assume that
+ the association's other end (role A) is not navigable, and
+ therefore we change the association type to UniAssociation.
+ The case that isNavigable is given as "false" is ignored.
+ Combined with the association type logic for role A, this
+ allows us to support at_Association and at_UniAssociation. "
+ */
+ if (element.attribute("isNavigable") == "true")
+ m_pAssoc->setAssocType(Uml::at_UniAssociation);
+ } else if (element.attribute("isNavigable") == "false") {
+ m_pAssoc->setAssocType(Uml::at_UniAssociation);
+ }
+
+ //FIXME not standard XMI
+ if (element.hasAttribute("relationship")) {
+ if (element.attribute("relationship") == "true") {
+ m_pAssoc->setAssocType(Uml::at_Relationship);
+ }
+ }
+
+ if (m_Multi.isEmpty())
+ m_Multi = element.attribute("multiplicity", "");
+
+ // Changeability defaults to Changeable if it cant set it here..
+ m_Changeability = Uml::chg_Changeable;
+ QString changeability = element.attribute("changeability", "");
+ if (changeability.isEmpty())
+ element.attribute("changeable", ""); // for backward compatibility
+ if (changeability == "frozen")
+ m_Changeability = Uml::chg_Frozen;
+ else if (changeability == "addOnly")
+ m_Changeability = Uml::chg_AddOnly;
+
+ // finished config, now unblock
+ blockSignals(false);
+ return true;
+}
+
+#include "umlrole.moc"
diff --git a/umbrello/umbrello/umlrole.h b/umbrello/umbrello/umlrole.h
new file mode 100644
index 00000000..63fe42b2
--- /dev/null
+++ b/umbrello/umbrello/umlrole.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2003-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLROLE_H
+#define UMLROLE_H
+
+#include "umlobject.h"
+
+class UMLAssociation;
+
+/**
+ * This class contains the non-graphic representation of an association role.
+ *
+ * @author Brian Thomas <brian.thomas@gsfc.nasa.gov>
+ * @see UMLObject
+ */
+
+class UMLRole : public UMLObject {
+ Q_OBJECT
+public:
+ /**
+ * Sets up an association.
+ *
+ * @param parent The parent (association) of this UMLRole.
+ * @param parentUMLObject The Parent UML Object of this UMLRole
+ * @param role The Uml::Role_Type of this UMLRole
+ */
+ UMLRole (UMLAssociation * parent, UMLObject * parentUMLObject, Uml::Role_Type role);
+
+ /**
+ * Overloaded '==' operator
+ */
+ bool operator==(UMLRole & rhs);
+
+ /**
+ * Standard deconstructor.
+ */
+ virtual ~UMLRole();
+
+ /**
+ * Returns the UMLObject assigned to the role.
+ * @return Pointer to the UMLObject in role.
+ */
+ UMLObject* getObject();
+
+ /**
+ * Returns the Changeablity of the role.
+ *
+ * @return Changeability_Type of role.
+ */
+ Uml::Changeability_Type getChangeability() const;
+
+ /**
+ * Returns the multiplicity assigned to the role.
+ *
+ * @return The multiplicity assigned to the role.
+ */
+ QString getMultiplicity() const;
+
+ /**
+ * Sets the UMLObject playing the role in the association.
+ *
+ * @param obj Pointer to the UMLObject of role.
+ */
+ void setObject(UMLObject *obj);
+
+ /**
+ * Sets the changeability of the role.
+ *
+ * @param value Changeability_Type of role changeability.
+ */
+ void setChangeability (Uml::Changeability_Type value);
+
+ /**
+ * Sets the multiplicity of the role.
+ *
+ * @param multi The multiplicity of role.
+ */
+ void setMultiplicity ( const QString &multi );
+
+ UMLAssociation * getParentAssociation ();
+
+ /** get the 'id' of the role (NOT the parent object). This could be
+ * either Uml::A or Uml::B. Yes, it would be better if we
+ * could get along without this, but we need it to distinguish saved
+ * umlrole objects in the XMI for 'self' associations where both roles
+ * will point to the same underlying UMLObject.
+ */
+ Uml::Role_Type getRole();
+
+ /**
+ * Make a clone of this object.
+ * Not yet implemented.
+ */
+ UMLObject* clone() const { return NULL; }
+
+ /**
+ * Creates the <UML:AssociationEnd> XMI element.
+ */
+ void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
+
+protected:
+ /**
+ * Loads the <UML:AssociationEnd> XMI element.
+ * Auxiliary to UMLObject::loadFromXMI.
+ */
+ bool load(QDomElement& element);
+
+private:
+
+ /** do some initialization at construction time */
+ void init (UMLAssociation * parent, UMLObject * parentObj, Uml::Role_Type r);
+
+ UMLAssociation * m_pAssoc;
+ Uml::Role_Type m_role;
+ QString m_Multi;
+ Uml::Changeability_Type m_Changeability;
+};
+
+#endif
diff --git a/umbrello/umbrello/umlstereotypelist.h b/umbrello/umbrello/umlstereotypelist.h
new file mode 100644
index 00000000..acf2edd7
--- /dev/null
+++ b/umbrello/umbrello/umlstereotypelist.h
@@ -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) 2003-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLSTEREOTYPELIST_H
+#define UMLSTEREOTYPELIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLStereotype;
+
+typedef QPtrList<UMLStereotype> UMLStereotypeList;
+typedef QPtrListIterator<UMLStereotype> UMLStereotypeListIt;
+
+#endif
diff --git a/umbrello/umbrello/umltemplatelist.h b/umbrello/umbrello/umltemplatelist.h
new file mode 100644
index 00000000..aa7415a4
--- /dev/null
+++ b/umbrello/umbrello/umltemplatelist.h
@@ -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) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLTEMPLATELIST_H
+#define UMLTEMPLATELIST_H
+
+#include <qptrlist.h>
+
+// forward declaration
+class UMLTemplate;
+
+typedef QPtrList<UMLTemplate> UMLTemplateList;
+typedef QPtrListIterator<UMLTemplate> UMLTemplateListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlview.cpp b/umbrello/umbrello/umlview.cpp
new file mode 100644
index 00000000..0b6a7935
--- /dev/null
+++ b/umbrello/umbrello/umlview.cpp
@@ -0,0 +1,3352 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlview.h"
+
+// system includes
+#include <climits>
+#include <math.h>
+
+// include files for Qt
+#include <qpixmap.h>
+#include <qpicture.h>
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qobjectlist.h>
+#include <qobjectdict.h>
+#include <qdragobject.h>
+#include <qpaintdevicemetrics.h>
+#include <qfileinfo.h>
+#include <qptrlist.h>
+#include <qcolor.h>
+#include <qwmatrix.h>
+#include <qregexp.h>
+
+//kde include files
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <kprinter.h>
+#include <kcursor.h>
+#include <kfiledialog.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// application specific includes
+#include "umlviewimageexporter.h"
+#include "listpopupmenu.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlobject.h"
+#include "docwindow.h"
+#include "assocrules.h"
+#include "umlrole.h"
+#include "umlviewcanvas.h"
+#include "dialogs/classoptionspage.h"
+#include "dialogs/umlviewdialog.h"
+#include "clipboard/idchangelog.h"
+#include "clipboard/umldrag.h"
+#include "widget_factory.h"
+#include "floatingtextwidget.h"
+#include "classifierwidget.h"
+#include "classifier.h"
+#include "packagewidget.h"
+#include "package.h"
+#include "folder.h"
+#include "componentwidget.h"
+#include "nodewidget.h"
+#include "artifactwidget.h"
+#include "datatypewidget.h"
+#include "enumwidget.h"
+#include "entitywidget.h"
+#include "actorwidget.h"
+#include "usecasewidget.h"
+#include "notewidget.h"
+#include "boxwidget.h"
+#include "associationwidget.h"
+#include "objectwidget.h"
+#include "messagewidget.h"
+#include "statewidget.h"
+#include "forkjoinwidget.h"
+#include "activitywidget.h"
+#include "seqlinewidget.h"
+#include "uniqueid.h"
+#include "umllistviewitemlist.h"
+#include "umllistviewitem.h"
+#include "umllistview.h"
+#include "umlobjectlist.h"
+#include "association.h"
+#include "attribute.h"
+#include "model_utils.h"
+#include "object_factory.h"
+#include "umlwidget.h"
+#include "toolbarstatefactory.h"
+
+
+// control the manual DoubleBuffering of QCanvas
+// with a define, so that this memory X11 effect can
+// be tested more easily
+#define MANUAL_CONTROL_DOUBLE_BUFFERING
+
+// static members
+const int UMLView::defaultCanvasSize = 1300;
+
+using namespace Uml;
+
+
+// constructor
+UMLView::UMLView(UMLFolder *parentFolder) : QCanvasView(UMLApp::app()->getMainViewWidget()) {
+ init();
+ m_pDoc = UMLApp::app()->getDocument();
+ m_pFolder = parentFolder;
+}
+
+void UMLView::init() {
+ // Initialize loaded/saved data
+ m_nID = Uml::id_None;
+ m_pDoc = NULL;
+ m_Documentation = "";
+ m_Type = dt_Undefined;
+ m_bUseSnapToGrid = false;
+ m_bUseSnapComponentSizeToGrid = false;
+ m_bShowSnapGrid = false;
+ m_nSnapX = 10;
+ m_nSnapY = 10;
+ m_nZoom = 100;
+ m_nCanvasWidth = UMLView::defaultCanvasSize;
+ m_nCanvasHeight = UMLView::defaultCanvasSize;
+ m_nCollaborationId = 0;
+
+ // Initialize other data
+ m_AssociationList.setAutoDelete( true );
+
+ //Setup up booleans
+ m_bChildDisplayedDoc = false;
+ m_bPaste = false;
+ m_bActivated = false;
+ m_bCreateObject = false;
+ m_bDrawSelectedOnly = false;
+ m_bPopupShowing = false;
+ m_bStartedCut = false;
+ //clear pointers
+ m_PastePoint = QPoint(0, 0);
+ m_pIDChangesLog = 0;
+ m_pMenu = 0;
+
+ m_pImageExporter = new UMLViewImageExporter(this);
+
+ //setup graphical items
+ viewport() -> setBackgroundMode( Qt::NoBackground );
+ setCanvas( new UMLViewCanvas( this ) );
+ // don't set the quite frequent update rate for each
+ // diagram, as that causes also an update of invisible
+ // diagrams, which can cost high CPU load for many
+ // diagrams.
+ // Instead: set the updatePeriod to 20 on Show event,
+ // and switch update back off on Hide event
+ canvas() -> setUpdatePeriod( -1 );
+ resizeContents(defaultCanvasSize, defaultCanvasSize);
+ canvas() -> resize(defaultCanvasSize, defaultCanvasSize);
+ setAcceptDrops(true);
+ viewport() -> setAcceptDrops(true);
+ setDragAutoScroll(false);
+
+ viewport() -> setMouseTracking(false);
+
+ //setup signals
+ connect( this, SIGNAL(sigRemovePopupMenu()), this, SLOT(slotRemovePopupMenu() ) );
+ 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(this);
+ m_pToolBarState = m_pToolBarStateFactory->getState(WorkToolBar::tbb_Arrow);
+
+}
+
+UMLView::~UMLView() {
+ delete m_pImageExporter;
+
+ if(m_pIDChangesLog) {
+ 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 = NULL;
+
+ // Qt Doc for QCanvasView::~QCanvasView () states:
+ // "Destroys the canvas view. The associated canvas is not deleted."
+ // we should do it now
+ delete canvas();
+}
+
+QString UMLView::getName() const {
+ return m_Name;
+}
+
+void UMLView::setName(const QString &name) {
+ m_Name = name;
+}
+
+int UMLView::generateCollaborationId() {
+ return ++m_nCollaborationId;
+}
+
+void UMLView::print(KPrinter *pPrinter, QPainter & pPainter) {
+ int height, width;
+ //get the size of the page
+ pPrinter->setFullPage( true );
+ QPaintDeviceMetrics metrics(pPrinter);
+ QFontMetrics fm = pPainter.fontMetrics(); // use the painter font metrics, not the screen fm!
+ int fontHeight = fm.lineSpacing();
+ uint left, right, top, bottom;
+ // fetch printer margins individual for all four page sides, as at least top and bottom are not the same
+ pPrinter->margins ( &top, &left, &bottom, &right );
+ // give a little extra space at each side
+ left += 2;
+ right += 2;
+ top += 2;
+ bottom += 2;
+
+ if(pPrinter->orientation() == KPrinter::Landscape) {
+ // we are printing in LANDSCAPE --> swap marginX and marginY
+ uint right_old = right;
+ // the DiagramRight side is printed at PrintersTop
+ right = top;
+ // the DiagramTop side is printed at PrintersLeft
+ top = left;
+ // the DiagramLeft side is printed at PrintersBottom
+ left = bottom;
+ // the DiagramBottom side is printed at PrintersRight
+ bottom = right_old;
+ }
+
+ // The printer will probably use a different font with different font metrics,
+ // force the widgets to update accordingly on paint
+ forceUpdateWidgetFontMetrics(&pPainter);
+
+ width = metrics.width() - left - right;
+ height = metrics.height() - top - bottom;
+
+ //get the smallest rect holding the diagram
+ QRect rect = getDiagramRect();
+ //now draw to printer
+
+#if 0
+ int offsetX = 0, offsetY = 0, widthX = 0, heightY = 0;
+ // respect the margin
+ pPainter.translate(marginX, marginY);
+
+ // clip away everything outside of the margin
+ pPainter.setClipRect(marginX, marginY,
+ width, metrics.height() - marginY * 2);
+
+ //loop until all of the picture is printed
+ int numPagesX = (int)ceil((double)rect.width()/(double)width);
+ int numPagesY = (int)ceil((double)rect.height()/(double)height);
+ int page = 0;
+
+ // print the canvas to multiple pages
+ for (int pageY = 0; pageY < numPagesY; ++pageY) {
+ // tile vertically
+ offsetY = pageY * height + rect.y();
+ heightY = (pageY + 1) * height > rect.height()
+ ? rect.height() - pageY * height
+ : height;
+ for (int pageX = 0; pageX < numPagesX; ++pageX) {
+ // tile horizontally
+ offsetX = pageX * width + rect.x();
+ widthX = (pageX + 1) * width > rect.width()
+ ? rect.width() - pageX * width
+ : width;
+
+ // make sure the part of the diagram is painted at the correct
+ // place in the printout
+ pPainter.translate(-offsetX,-offsetY);
+ getDiagram(QRect(offsetX, offsetY,widthX, heightY),
+ pPainter);
+ // undo the translation so the coordinates for the painter
+ // correspond to the page again
+ pPainter.translate(offsetX,offsetY);
+
+ //draw foot note
+ QString string = i18n("Diagram: %2 Page %1").arg(page + 1).arg(getName());
+ QColor textColor(50, 50, 50);
+ pPainter.setPen(textColor);
+ pPainter.drawLine(0, height + 2, width, height + 2);
+ pPainter.drawText(0, height + 4, width, fontHeight, Qt::AlignLeft, string);
+
+ if(pageX+1 < numPagesX || pageY+1 < numPagesY) {
+ pPrinter -> newPage();
+ page++;
+ }
+ }
+ }
+#else
+ // be gentle - as described in Qt-Doc "The Coordinate System"
+ pPainter.save();
+
+ int diagramHeight = rect.height();
+ // + 4+fontHeight between diagram and footline as space-buffer
+ // + 2 between line and foot-text
+ // + 1 for foot-line
+ // + fontHeight for foot-text
+ // ==============
+ // (2*fontHeight) + 7
+ int footHeight = (2*fontHeight) + 7;
+ int footTop = rect.y() + diagramHeight + 4+fontHeight;
+ int drawHeight = diagramHeight + footHeight;
+
+ // set window of painter to dimensions of diagram
+ // set window to viewport relation so that x:y isn't changed
+ double dScaleX = (double)rect.width()/ (double)width;
+ double dScaleY = (double)drawHeight/ (double)height;
+ // select the scaling factor so that the larger dimension
+ // fits on the printer page -> use the larger scaling factor
+ // -> the virtual diagram window has some additional space at the
+ // shorter dimension
+ double dScaleUse = ( dScaleX > dScaleY )?dScaleX:dScaleY;
+
+ int windowWidth = (int)ceil(dScaleUse*width);
+ int windowHeight = (int)ceil(dScaleUse*height);
+#ifdef DEBUG_PRINTING
+ kDebug() << "drawHeight: " << drawHeight << ", width: " << rect.width()
+ << "\nPageHeight: " << height << ", PageWidht: " << width
+ << "\nScaleY: " << dScaleY << ", ScaleX: " << dScaleX
+ << "\ndScaleUse: " << dScaleUse
+ << "\nVirtualSize: Width: " << windowWidth << ", Height: " << windowHeight
+ << "\nFoot Top: " << footTop
+ << endl;
+#endif
+ // set virtual drawing area window - where diagram fits 100% in
+ pPainter.setWindow( rect.x(), rect.y(), windowWidth, windowHeight );
+
+ // set viewport - the physical mapping
+ // --> Qt's QPainter will map all drawed elements from diagram area ( window )
+ // to printer area ( viewport )
+ pPainter.setViewport( left, top, width, height );
+
+ // get Diagram
+ getDiagram(QRect(rect.x(), rect.y(), windowWidth, diagramHeight), pPainter);
+
+ //draw foot note
+ QString string = i18n("Diagram: %2 Page %1").arg( 1).arg(getName());
+ QColor textColor(50, 50, 50);
+ pPainter.setPen(textColor);
+ pPainter.drawLine(rect.x(), footTop , windowWidth, footTop);
+ pPainter.drawText(rect.x(), footTop + 3, windowWidth, fontHeight, Qt::AlignLeft, string);
+
+ // now restore scaling
+ pPainter.restore();
+
+#endif
+ // next painting will most probably be to a different device (i.e. the screen)
+ forceUpdateWidgetFontMetrics(0);
+}
+
+void UMLView::setupNewWidget(UMLWidget *w) {
+ w->setX( m_Pos.x() );
+ w->setY( m_Pos.y() );
+ w->setVisible( true );
+ w->setActivated();
+ w->setFont( getFont() );
+ w->slotColorChanged( getID() );
+ w->slotLineWidthChanged( getID() );
+ resizeCanvasToItems();
+ m_WidgetList.append( w );
+ m_pDoc->setModified();
+}
+
+void UMLView::contentsMouseReleaseEvent(QMouseEvent* ome) {
+ m_pToolBarState->mouseRelease(ome);
+}
+
+void UMLView::slotToolBarChanged(int c) {
+ m_pToolBarState->cleanBeforeChange();
+ m_pToolBarState = m_pToolBarStateFactory->getState((WorkToolBar::ToolBar_Buttons)c);
+ m_pToolBarState->init();
+
+ m_bPaste = false;
+}
+
+void UMLView::showEvent(QShowEvent* /*se*/) {
+
+# ifdef MANUAL_CONTROL_DOUBLE_BUFFERING
+ //kWarning() << "Show Event for " << getName() << endl;
+ canvas()->setDoubleBuffering( true );
+ // as the diagram gets now visible again,
+ // the update of the diagram elements shall be
+ // at the normal value of 20
+ canvas()-> setUpdatePeriod( 20 );
+# endif
+
+ UMLApp* theApp = UMLApp::app();
+ WorkToolBar* tb = theApp->getWorkToolBar();
+ connect(tb,SIGNAL(sigButtonChanged(int)), this, SLOT(slotToolBarChanged(int)));
+ connect(this,SIGNAL(sigResetToolBar()), tb, SLOT(slotResetToolBar()));
+ connect(m_pDoc, SIGNAL(sigObjectCreated(UMLObject *)),
+ this, SLOT(slotObjectCreated(UMLObject *)));
+ connect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
+ UMLApp::app()->getDocWindow(), SLOT(slotAssociationRemoved(AssociationWidget*)));
+ connect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)),
+ UMLApp::app()->getDocWindow(), SLOT(slotWidgetRemoved(UMLWidget*)));
+ resetToolbar();
+
+}
+
+void UMLView::hideEvent(QHideEvent* /*he*/) {
+ UMLApp* theApp = UMLApp::app();
+ WorkToolBar* tb = theApp->getWorkToolBar();
+ disconnect(tb,SIGNAL(sigButtonChanged(int)), this, SLOT(slotToolBarChanged(int)));
+ disconnect(this,SIGNAL(sigResetToolBar()), tb, SLOT(slotResetToolBar()));
+ disconnect(m_pDoc, SIGNAL(sigObjectCreated(UMLObject *)), this, SLOT(slotObjectCreated(UMLObject *)));
+ disconnect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
+ UMLApp::app()->getDocWindow(), SLOT(slotAssociationRemoved(AssociationWidget*)));
+ disconnect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)),
+ UMLApp::app()->getDocWindow(), SLOT(slotWidgetRemoved(UMLWidget*)));
+
+# ifdef MANUAL_CONTROL_DOUBLE_BUFFERING
+ //kWarning() << "Hide Event for " << getName() << endl;
+ canvas()->setDoubleBuffering( false );
+ // a periodic update of all - also invisible - diagrams
+ // can cause a very high CPU load if more than 100diagrams
+ // are inside a project - and this without any need
+ // => switch the update off for hidden diagrams
+ canvas()-> setUpdatePeriod( -1 );
+# endif
+}
+
+void UMLView::slotObjectCreated(UMLObject* o) {
+ 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 == NULL)
+ return;
+ newWidget->setVisible( true );
+ newWidget->setActivated();
+ newWidget->setFont( getFont() );
+ newWidget->slotColorChanged( getID() );
+ newWidget->slotLineWidthChanged( getID() );
+ newWidget->updateComponentSize();
+ if (m_Type == Uml::dt_Sequence) {
+ // Set proper position on the sequence line widget which is
+ // attached to the object widget.
+ ObjectWidget *ow = dynamic_cast<ObjectWidget*>(newWidget);
+ if (ow)
+ ow->moveEvent(NULL);
+ }
+ m_bCreateObject = false;
+ m_WidgetList.append(newWidget);
+ switch (o->getBaseType()) {
+ case ot_Actor:
+ case ot_UseCase:
+ case ot_Class:
+ case ot_Package:
+ case ot_Component:
+ case ot_Node:
+ case ot_Artifact:
+ case ot_Interface:
+ case ot_Enum:
+ case ot_Entity:
+ case ot_Datatype:
+ createAutoAssociations(newWidget);
+ // We need to invoke createAutoAttributeAssociations()
+ // on all other widgets again because the newly created
+ // widget might saturate some latent attribute assocs.
+ for (UMLWidgetListIt it(m_WidgetList); it.current(); ++it) {
+ UMLWidget *w = it.current();
+ if (w != newWidget)
+ createAutoAttributeAssociations(w);
+ }
+ break;
+ default:
+ break;
+ }
+ resizeCanvasToItems();
+}
+
+void UMLView::slotObjectRemoved(UMLObject * o) {
+ m_bPaste = false;
+ Uml::IDType id = o->getID();
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget *obj;
+
+ while ((obj = it.current()) != 0 ) {
+ ++it;
+ if(obj -> getID() != id)
+ continue;
+ removeWidget(obj);
+ }
+}
+
+void UMLView::contentsDragEnterEvent(QDragEnterEvent *e) {
+ UMLDrag::LvTypeAndID_List tidList;
+ if(!UMLDrag::getClip3TypeAndID(e, tidList)) {
+ return;
+ }
+ UMLDrag::LvTypeAndID_It tidIt(tidList);
+ UMLDrag::LvTypeAndID * tid = tidIt.current();
+ if (!tid) {
+ kDebug() << "UMLView::contentsDragEnterEvent: "
+ << "UMLDrag::getClip3TypeAndID returned empty list" << endl;
+ return;
+ }
+ ListView_Type lvtype = tid->type;
+ Uml::IDType id = tid->id;
+
+ Diagram_Type diagramType = getType();
+
+ UMLObject* temp = 0;
+ //if dragging diagram - might be a drag-to-note
+ if (Model_Utils::typeIsDiagram(lvtype)) {
+ e->accept(true);
+ return;
+ }
+ //can't drag anything onto state/activity diagrams
+ if( diagramType == dt_State || diagramType == dt_Activity) {
+ e->accept(false);
+ return;
+ }
+ //make sure can find UMLObject
+ if( !(temp = m_pDoc->findObjectById(id) ) ) {
+ kDebug() << "object " << ID2STR(id) << " not found" << endl;
+ e->accept(false);
+ return;
+ }
+ //make sure dragging item onto correct diagram
+ // concept - class,seq,coll diagram
+ // actor,usecase - usecase diagram
+ Object_Type ot = temp->getBaseType();
+ bool bAccept = true;
+ switch (diagramType) {
+ case dt_UseCase:
+ if ((widgetOnDiagram(id) && ot == ot_Actor) ||
+ (ot != ot_Actor && ot != ot_UseCase))
+ bAccept = false;
+ break;
+ case dt_Class:
+ if (widgetOnDiagram(id) ||
+ (ot != ot_Class &&
+ ot != ot_Package &&
+ ot != ot_Interface &&
+ ot != ot_Enum &&
+ ot != ot_Datatype)) {
+ bAccept = false;
+ }
+ break;
+ case dt_Sequence:
+ case dt_Collaboration:
+ if (ot != ot_Class &&
+ ot != ot_Interface &&
+ ot != ot_Actor)
+ bAccept = false;
+ break;
+ case dt_Deployment:
+ if (widgetOnDiagram(id))
+ bAccept = false;
+ else if (ot != ot_Interface &&
+ ot != ot_Package &&
+ ot != ot_Component &&
+ ot != ot_Class &&
+ ot != ot_Node)
+ bAccept = false;
+ else if (ot == ot_Package &&
+ temp->getStereotype() != "subsystem")
+ bAccept = false;
+ break;
+ case dt_Component:
+ if (widgetOnDiagram(id) ||
+ (ot != ot_Interface &&
+ ot != ot_Package &&
+ ot != ot_Component &&
+ ot != ot_Artifact &&
+ ot != ot_Class))
+ bAccept = false;
+ if (ot == ot_Class && !temp->getAbstract())
+ bAccept = false;
+ break;
+ case dt_EntityRelationship:
+ if (ot != ot_Entity)
+ bAccept = false;
+ break;
+ default:
+ break;
+ }
+ e->accept(bAccept);
+}
+
+void UMLView::contentsDropEvent(QDropEvent *e) {
+ UMLDrag::LvTypeAndID_List tidList;
+ if( !UMLDrag::getClip3TypeAndID(e, tidList) ) {
+ return;
+ }
+ UMLDrag::LvTypeAndID_It tidIt(tidList);
+ UMLDrag::LvTypeAndID * tid = tidIt.current();
+ if (!tid) {
+ kDebug() << "UMLView::contentsDropEvent: "
+ << "UMLDrag::getClip3TypeAndID returned empty list" << endl;
+ return;
+ }
+ ListView_Type lvtype = tid->type;
+ Uml::IDType id = tid->id;
+
+ if (Model_Utils::typeIsDiagram(lvtype)) {
+ UMLWidget *w = NULL;
+ for (w = m_WidgetList.first(); w; w = m_WidgetList.next()) {
+ if (w->getBaseType() == Uml::wt_Note && w->onWidget(e->pos()))
+ break;
+ }
+ if (w) {
+ NoteWidget *note = static_cast<NoteWidget*>(w);
+ note->setDiagramLink(id);
+ }
+ return;
+ }
+ UMLObject* o = m_pDoc->findObjectById(id);
+ if( !o ) {
+ kDebug() << "UMLView::contentsDropEvent: object id=" << ID2STR(id)
+ << " not found" << endl;
+ return;
+ }
+ m_bCreateObject = true;
+ m_Pos = (e->pos() * 100 ) / m_nZoom;
+
+ slotObjectCreated(o);
+
+ m_pDoc -> setModified(true);
+}
+
+ObjectWidget * UMLView::onWidgetLine( const QPoint &point ) {
+ UMLWidget *obj;
+ for (UMLWidgetListIt it(m_WidgetList); (obj = it.current()) != NULL; ++it) {
+ ObjectWidget *ow = dynamic_cast<ObjectWidget*>(obj);
+ if (ow == NULL)
+ continue;
+ SeqLineWidget *pLine = ow->getSeqLine();
+ if (pLine == NULL) {
+ kError() << "UMLView::onWidgetLine: SeqLineWidget of " << ow->getName()
+ << " (id=" << ID2STR(ow->getLocalID()) << ") is NULL" << endl;
+ continue;
+ }
+ if (pLine->onWidget(point))
+ return ow;
+ }
+ return 0;
+}
+
+UMLWidget *UMLView::getWidgetAt(const QPoint& p) {
+ int relativeSize = 10000; // start with an arbitrary large number
+ UMLWidget *obj, *retObj = NULL;
+ UMLWidgetListIt it(m_WidgetList);
+ for (UMLWidgetListIt it(m_WidgetList); (obj = it.current()) != NULL; ++it) {
+ const int s = obj->onWidget(p);
+ if (!s)
+ continue;
+ if (s < relativeSize) {
+ relativeSize = s;
+ retObj = obj;
+ }
+ }
+ return retObj;
+}
+
+void UMLView::checkMessages(ObjectWidget * w) {
+ if(getType() != dt_Sequence)
+ return;
+
+ MessageWidgetListIt it( m_MessageList );
+ MessageWidget *obj;
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ if(! obj -> contains(w))
+ continue;
+ //make sure message doesn't have any associations
+ removeAssociations(obj);
+ obj -> cleanup();
+ //make sure not in selected list
+ m_SelectedList.remove(obj);
+ m_MessageList.remove(obj);
+ delete obj;
+ }
+}
+
+bool UMLView::widgetOnDiagram(Uml::IDType id) {
+ UMLWidget *obj;
+
+ UMLWidgetListIt it( m_WidgetList );
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ if(id == obj -> getID())
+ return true;
+ }
+
+ MessageWidgetListIt mit( m_MessageList );
+ while ( (obj = (UMLWidget*)mit.current()) != 0 ) {
+ ++mit;
+ if(id == obj -> getID())
+ return true;
+ }
+
+ return false;
+}
+
+void UMLView::contentsMouseMoveEvent(QMouseEvent* ome) {
+ m_pToolBarState->mouseMove(ome);
+}
+
+// search both our UMLWidget AND MessageWidget lists
+UMLWidget * UMLView::findWidget( Uml::IDType id ) {
+
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget * obj = NULL;
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ // object widgets are special..the widget id is held by 'localId' attribute (crappy!)
+ if( obj -> getBaseType() == wt_Object ) {
+ if( static_cast<ObjectWidget *>( obj ) -> getLocalID() == id )
+ return obj;
+ } else if( obj -> getID() == id ) {
+ return obj;
+ }
+ }
+
+ MessageWidgetListIt mit( m_MessageList );
+ while ( (obj = (UMLWidget*)mit.current()) != 0 ) {
+ ++mit;
+ if( obj -> getID() == id )
+ return obj;
+ }
+
+ return 0;
+}
+
+
+
+AssociationWidget * UMLView::findAssocWidget( Uml::IDType id ) {
+ AssociationWidget *obj;
+ AssociationWidgetListIt it( m_AssociationList );
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ UMLAssociation* umlassoc = obj -> getAssociation();
+ if ( umlassoc && umlassoc->getID() == id ) {
+ return obj;
+ }
+ }
+ return 0;
+}
+
+AssociationWidget * UMLView::findAssocWidget(UMLWidget *pWidgetA,
+ UMLWidget *pWidgetB, const QString& roleNameB) {
+ AssociationWidget *assoc;
+ AssociationWidgetListIt it(m_AssociationList);
+ while ((assoc = it.current()) != 0) {
+ ++it;
+ const Association_Type testType = assoc->getAssocType();
+ if (testType != Uml::at_Association &&
+ testType != Uml::at_UniAssociation &&
+ testType != Uml::at_Composition &&
+ testType != Uml::at_Aggregation)
+ continue;
+ if (pWidgetA->getID() == assoc->getWidgetID(A) &&
+ pWidgetB->getID() == assoc->getWidgetID(B) &&
+ assoc->getRoleName(Uml::B) == roleNameB)
+ return assoc;
+ }
+ return 0;
+}
+
+
+AssociationWidget * UMLView::findAssocWidget(Uml::Association_Type at,
+ UMLWidget *pWidgetA, UMLWidget *pWidgetB) {
+ AssociationWidget *assoc;
+ AssociationWidgetListIt it(m_AssociationList);
+ while ((assoc = it.current()) != 0) {
+ ++it;
+ Association_Type testType = assoc->getAssocType();
+ if (testType != at)
+ continue;
+ if (pWidgetA->getID() == assoc->getWidgetID(A) &&
+ pWidgetB->getID() == assoc->getWidgetID(B))
+ return assoc;
+ }
+ return 0;
+}
+
+void UMLView::removeWidget(UMLWidget * o) {
+ if(!o)
+ return;
+
+ emit sigWidgetRemoved(o);
+
+ removeAssociations(o);
+
+ Widget_Type t = o->getBaseType();
+ if(getType() == dt_Sequence && t == wt_Object)
+ checkMessages( static_cast<ObjectWidget*>(o) );
+
+ o -> cleanup();
+ m_SelectedList.remove(o);
+ disconnect( this, SIGNAL( sigRemovePopupMenu() ), o, SLOT( slotRemovePopupMenu() ) );
+ disconnect( this, SIGNAL( sigClearAllSelected() ), o, SLOT( slotClearAllSelected() ) );
+ disconnect( this, SIGNAL(sigColorChanged(Uml::IDType)), o, SLOT(slotColorChanged(Uml::IDType)));
+ if (t == wt_Message)
+ m_MessageList.remove(static_cast<MessageWidget*>(o));
+ else
+ m_WidgetList.remove(o);
+ m_pDoc->setModified();
+ delete o;
+}
+
+bool UMLView::getUseFillColor() const {
+ return m_Options.uiState.useFillColor;
+}
+
+void UMLView::setUseFillColor(bool ufc) {
+ m_Options.uiState.useFillColor = ufc;
+}
+
+QColor UMLView::getFillColor() const {
+ return m_Options.uiState.fillColor;
+}
+
+void UMLView::setFillColor(const QColor &color) {
+ m_Options.uiState.fillColor = color;
+ emit sigColorChanged( getID() );
+ canvas()->setAllChanged();
+}
+
+QColor UMLView::getLineColor() const {
+ return m_Options.uiState.lineColor;
+}
+
+void UMLView::setLineColor(const QColor &color) {
+ m_Options.uiState.lineColor = color;
+ emit sigColorChanged( getID() );
+ canvas() -> setAllChanged();
+}
+
+uint UMLView::getLineWidth() const {
+ return m_Options.uiState.lineWidth;
+}
+
+void UMLView::setLineWidth(uint width) {
+ m_Options.uiState.lineWidth = width;
+ emit sigLineWidthChanged( getID() );
+ canvas() -> setAllChanged();
+}
+
+void UMLView::contentsMouseDoubleClickEvent(QMouseEvent* ome) {
+ m_pToolBarState->mouseDoubleClick(ome);
+}
+
+QRect UMLView::getDiagramRect() {
+ int startx, starty, endx, endy;
+ startx = starty = INT_MAX;
+ endx = endy = 0;
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget *obj;
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ if (! obj->isVisible())
+ continue;
+ int objEndX = obj -> getX() + obj -> getWidth();
+ int objEndY = obj -> getY() + obj -> getHeight();
+ int objStartX = obj -> getX();
+ int objStartY = obj -> getY();
+ if (startx >= objStartX)
+ startx = objStartX;
+ if (starty >= objStartY)
+ starty = objStartY;
+ if(endx <= objEndX)
+ endx = objEndX;
+ if(endy <= objEndY)
+ endy = objEndY;
+ }
+ //if seq. diagram, make sure print all of the lines
+ if (getType() == dt_Sequence ) {
+ for (UMLWidgetListIt it(m_WidgetList); (obj = it.current()) != NULL; ++it) {
+ ObjectWidget *ow = dynamic_cast<ObjectWidget*>(obj);
+ if (ow == NULL)
+ continue;
+ int y = ow->getEndLineY();
+ if (endy < y)
+ endy = y;
+ }
+ }
+
+ /* now we need another look at the associations, because they are no
+ * UMLWidgets */
+ AssociationWidgetListIt assoc_it (m_AssociationList);
+ AssociationWidget * assoc_obj;
+ QRect rect;
+
+ while ((assoc_obj = assoc_it.current()) != 0)
+ {
+ /* get the rectangle around all segments of the assoc */
+ rect = assoc_obj->getAssocLineRectangle();
+
+ if (startx >= rect.x())
+ startx = rect.x();
+ if (starty >= rect.y())
+ starty = rect.y();
+ if (endx <= rect.x() + rect.width())
+ endx = rect.x() + rect.width();
+ if (endy <= rect.y() + rect.height())
+ endy = rect.y() + rect.height();
+ ++assoc_it; // next assoc
+ }
+
+ /* Margin causes problems of black border around the edge
+ // Margin:
+ startx -= 24;
+ starty -= 20;
+ endx += 24;
+ endy += 20;
+ */
+
+ return QRect(startx, starty, endx - startx, endy - starty);
+}
+
+void UMLView::setSelected(UMLWidget * w, QMouseEvent * /*me*/) {
+ //only add if wasn't in list
+ if(!m_SelectedList.remove(w))
+ m_SelectedList.append(w);
+ int count = m_SelectedList.count();
+ //only call once - if we select more, no need to keep clearing window
+
+ // if count == 1, widget will update the doc window with their data when selected
+ if( count == 2 )
+ updateDocumentation( true );//clear doc window
+
+ /* selection changed, we have to make sure the copy and paste items
+ * are correctly enabled/disabled */
+ UMLApp::app()->slotCopyChanged();
+}
+
+void UMLView::clearSelected() {
+ m_SelectedList.clear();
+ emit sigClearAllSelected();
+ //m_pDoc -> enableCutCopy(false);
+}
+
+//TODO Only used in MLApp::handleCursorKeyReleaseEvent
+void UMLView::moveSelectedBy(int dX, int dY) {
+ for (UMLWidget *w = m_SelectedList.first(); w; w = m_SelectedList.next())
+ w->moveBy(dX, dY);
+}
+
+void UMLView::selectionUseFillColor(bool useFC) {
+ UMLWidget * temp = 0;
+ for(temp=(UMLWidget *)m_SelectedList.first();temp;temp=(UMLWidget *)m_SelectedList.next())
+ temp -> setUseFillColour(useFC);
+}
+
+void UMLView::selectionSetFont( const QFont &font )
+{
+ UMLWidget * temp = 0;
+ for(temp=(UMLWidget *)m_SelectedList.first();temp;temp=(UMLWidget *)m_SelectedList.next())
+ temp -> setFont( font );
+}
+
+void UMLView::selectionSetLineColor( const QColor &color )
+{
+ UMLWidget * temp = 0;
+ for (temp = m_SelectedList.first(); temp; temp = m_SelectedList.next()) {
+ temp->setLineColor(color);
+ temp->setUsesDiagramLineColour(false);
+ }
+ AssociationWidgetList assoclist = getSelectedAssocs();
+ for (AssociationWidget *aw = assoclist.first(); aw; aw = assoclist.next()) {
+ aw->setLineColor(color);
+ aw->setUsesDiagramLineColour(false);
+ }
+}
+
+void UMLView::selectionSetLineWidth( uint width )
+{
+ UMLWidget * temp = 0;
+ for (temp = m_SelectedList.first(); temp; temp = m_SelectedList.next()) {
+ temp->setLineWidth(width);
+ temp->setUsesDiagramLineWidth(false);
+ }
+ AssociationWidgetList assoclist = getSelectedAssocs();
+ for (AssociationWidget *aw = assoclist.first(); aw; aw = assoclist.next()) {
+ aw->setLineWidth(width);
+ aw->setUsesDiagramLineWidth(false);
+ }
+}
+
+void UMLView::selectionSetFillColor( const QColor &color )
+{
+ UMLWidget * temp = 0;
+ for(temp=(UMLWidget *) m_SelectedList.first();
+ temp;
+ temp=(UMLWidget *)m_SelectedList.next()) {
+ temp -> setFillColour( color );
+ temp -> setUsesDiagramFillColour(false);
+ }
+}
+
+void UMLView::selectionToggleShow(int sel)
+{
+ // loop through all selected items
+ for(UMLWidget *temp = (UMLWidget *)m_SelectedList.first();
+ temp; temp=(UMLWidget *)m_SelectedList.next()) {
+ Widget_Type type = temp->getBaseType();
+ ClassifierWidget *cw = dynamic_cast<ClassifierWidget*>(temp);
+
+ // toggle the show setting sel
+ switch (sel)
+ {
+ // some setting are only available for class, some for interface and some
+ // for both
+ case ListPopupMenu::mt_Show_Attributes_Selection:
+ if (type == wt_Class)
+ cw -> toggleShowAtts();
+ break;
+ case ListPopupMenu::mt_Show_Operations_Selection:
+ if (cw)
+ cw -> toggleShowOps();
+ break;
+ case ListPopupMenu::mt_Visibility_Selection:
+ if (cw)
+ cw -> toggleShowVisibility();
+ break;
+ case ListPopupMenu::mt_DrawAsCircle_Selection:
+ if (type == wt_Interface)
+ cw -> toggleDrawAsCircle();
+ break;
+ case ListPopupMenu::mt_Show_Operation_Signature_Selection:
+ if (cw)
+ cw -> toggleShowOpSigs();
+ break;
+ case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
+ if (type == wt_Class)
+ cw -> toggleShowAttSigs();
+ break;
+ case ListPopupMenu::mt_Show_Packages_Selection:
+ if (cw)
+ cw -> toggleShowPackage();
+ break;
+ case ListPopupMenu::mt_Show_Stereotypes_Selection:
+ if (type == wt_Class)
+ cw -> toggleShowStereotype();
+ break;
+ case ListPopupMenu::mt_Show_Public_Only_Selection:
+ if (cw)
+ cw -> toggleShowPublicOnly();
+ break;
+ default:
+ break;
+ } // switch (sel)
+ }
+}
+
+void UMLView::deleteSelection()
+{
+ /*
+ Don't delete text widget that are connect to associations as these will
+ be cleaned up by the associations.
+ */
+ UMLWidget * temp = 0;
+ for(temp=(UMLWidget *) m_SelectedList.first();
+ temp;
+ temp=(UMLWidget *)m_SelectedList.next())
+ {
+ if( temp -> getBaseType() == wt_Text &&
+ ((FloatingTextWidget *)temp) -> getRole() != tr_Floating )
+ {
+ m_SelectedList.remove(); // remove advances the iterator to the next position,
+ m_SelectedList.prev(); // let's allow for statement do the advancing
+ temp -> hide();
+ } else {
+ removeWidget(temp);
+ }
+ }
+
+ // Delete any selected associations.
+ AssociationWidgetListIt assoc_it( m_AssociationList );
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current())) {
+ ++assoc_it;
+ if( assocwidget-> getSelected() )
+ removeAssoc(assocwidget);
+ // MARK
+ }
+
+ /* we also have to remove selected messages from sequence diagrams */
+ MessageWidget * cur_msgWgt;
+
+ /* loop through all messages and check the selection state */
+ for (cur_msgWgt = m_MessageList.first(); cur_msgWgt;
+ cur_msgWgt = m_MessageList.next())
+ {
+ if (cur_msgWgt->getSelected() == true)
+ {
+ removeWidget(cur_msgWgt); // Remove message - it is selected.
+ }
+ }
+
+ // sometimes we miss one widget, so call this function again to remove it as
+ // well
+ if (m_SelectedList.count() != 0)
+ deleteSelection();
+
+ //make sure list empty - it should be anyway, just a check.
+ m_SelectedList.clear();
+}
+
+void UMLView::selectAll()
+{
+ selectWidgets(0, 0, canvas()->width(), canvas()->height());
+}
+
+Uml::IDType UMLView::getLocalID() {
+ m_nLocalID = UniqueID::gen();
+ return m_nLocalID;
+}
+
+bool UMLView::isSavedInSeparateFile() {
+ if (getOptionState().generalState.tabdiagrams) {
+ // Umbrello currently does not support external folders
+ // when tabbed diagrams are enabled.
+ return false;
+ }
+ const QString msgPrefix("UMLView::isSavedInSeparateFile(" + getName() + "): ");
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *lvItem = listView->findItem(m_nID);
+ if (lvItem == NULL) {
+ kError() << msgPrefix
+ << "listView->findUMLObject(this) returns false" << endl;
+ return false;
+ }
+ UMLListViewItem *parentItem = dynamic_cast<UMLListViewItem*>( lvItem->parent() );
+ if (parentItem == NULL) {
+ kError() << msgPrefix
+ << "parent item in listview is not a UMLListViewItem (?)" << endl;
+ return false;
+ }
+ const Uml::ListView_Type lvt = parentItem->getType();
+ if (! Model_Utils::typeIsFolder(lvt))
+ return false;
+ UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(parentItem->getUMLObject());
+ if (modelFolder == NULL) {
+ kError() << msgPrefix
+ << "parent model object is not a UMLFolder (?)" << endl;
+ return false;
+ }
+ QString folderFile = modelFolder->getFolderFile();
+ return !folderFile.isEmpty();
+}
+
+void UMLView::contentsMousePressEvent(QMouseEvent* ome) {
+ m_pToolBarState->mousePress(ome);
+ //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?
+ if (!m_bChildDisplayedDoc) {
+ UMLApp::app() -> getDocWindow() -> showDocumentation( this, true );
+ }
+ m_bChildDisplayedDoc = false;
+}
+
+void UMLView::makeSelected (UMLWidget * uw) {
+ if (uw == NULL)
+ return;
+ uw -> setSelected(true);
+ m_SelectedList.remove(uw); // make sure not in there
+ m_SelectedList.append(uw);
+}
+
+void UMLView::selectWidgetsOfAssoc (AssociationWidget * a) {
+ if (!a)
+ return;
+ a -> setSelected(true);
+ //select the two widgets
+ makeSelected( a->getWidget(A) );
+ makeSelected( a->getWidget(B) );
+ //select all the text
+ makeSelected( a->getMultiWidget(A) );
+ makeSelected( a->getMultiWidget(B) );
+ makeSelected( a->getRoleWidget(A) );
+ makeSelected( a->getRoleWidget(B) );
+ makeSelected( a->getChangeWidget(A) );
+ makeSelected( a->getChangeWidget(B) );
+}
+
+void UMLView::selectWidgets(int px, int py, int qx, int qy) {
+ clearSelected();
+
+ QRect 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);
+ }
+ UMLWidgetListIt it(m_WidgetList);
+ UMLWidget * temp = NULL;
+ while ( (temp = it.current()) != 0 ) {
+ int x = temp -> getX();
+ int y = temp -> getY();
+ int w = temp -> getWidth();
+ int h = temp -> getHeight();
+ QRect rect2(x, y, w, h);
+ ++it;
+ //see if any part of widget is in the rectangle
+ if( !rect.intersects(rect2) )
+ continue;
+ //if it is text that is part of an association then select the association
+ //and the objects that are connected to it.
+ if (temp -> getBaseType() == wt_Text) {
+ FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(temp);
+ Text_Role t = ft -> getRole();
+ LinkWidget *lw = ft->getLink();
+ MessageWidget * mw = dynamic_cast<MessageWidget*>(lw);
+ if (mw) {
+ makeSelected( mw );
+ makeSelected( mw->getWidget(A) );
+ makeSelected( mw->getWidget(B) );
+ } else if (t != tr_Floating) {
+ AssociationWidget * a = dynamic_cast<AssociationWidget*>(lw);
+ if (a)
+ selectWidgetsOfAssoc( a );
+ }
+ } else if(temp -> getBaseType() == wt_Message) {
+ MessageWidget *mw = static_cast<MessageWidget*>(temp);
+ makeSelected( mw -> getWidget(A) );
+ makeSelected( mw -> getWidget(B) );
+ }
+ if(temp -> isVisible()) {
+ makeSelected( temp );
+ }
+ }
+ selectAssociations( true );
+
+ //now do the same for the messagewidgets
+ MessageWidgetListIt itw( m_MessageList );
+ MessageWidget *w = 0;
+ while ( (w = itw.current()) != 0 ) {
+ ++itw;
+ if ( w -> getWidget(A) -> getSelected() &&
+ w -> getWidget(B) -> getSelected() ) {
+ makeSelected( w );
+ }//end if
+ }//end while
+}
+
+void UMLView::getDiagram(const QRect &rect, QPixmap & diagram) {
+ QPixmap pixmap(rect.x() + rect.width(), rect.y() + rect.height());
+ QPainter painter(&pixmap);
+ getDiagram(canvas()->rect(),painter);
+ bitBlt(&diagram, QPoint(0, 0), &pixmap, rect);
+}
+
+void UMLView::getDiagram(const QRect &area, QPainter & painter) {
+ //TODO unselecting and selecting later doesn't work now as the selection is
+ //cleared in UMLViewImageExporter. Check if the anything else than the
+ //following is needed and, if it works, remove the clearSelected in
+ //UMLViewImageExporter and UMLViewImageExporterModel
+ UMLWidget* widget = 0;
+ for (widget=(UMLWidget*)m_SelectedList.first(); widget; widget=(UMLWidget*)m_SelectedList.next()) {
+ widget->setSelected(false);
+ }
+ AssociationWidgetList selectedAssociationsList = getSelectedAssocs();
+ AssociationWidget* association = 0;
+ for (association=selectedAssociationsList.first(); association;
+ association=selectedAssociationsList.next()) {
+ association->setSelected(false);
+ }
+
+ // we don't want to get the grid
+ bool showSnapGrid = getShowSnapGrid();
+ setShowSnapGrid(false);
+
+ canvas()->drawArea(area, &painter);
+
+ setShowSnapGrid(showSnapGrid);
+
+ canvas()->setAllChanged();
+ //select again
+ for (widget=(UMLWidget *)m_SelectedList.first(); widget; widget=(UMLWidget *)m_SelectedList.next()) {
+ widget->setSelected( true );
+ }
+ for (association=selectedAssociationsList.first(); association;
+ association=selectedAssociationsList.next()) {
+ association->setSelected(true);
+ }
+
+ return;
+}
+
+UMLViewImageExporter* UMLView::getImageExporter() {
+ return m_pImageExporter;
+}
+
+void UMLView::slotActivate() {
+ m_pDoc->changeCurrentView(getID());
+}
+
+UMLObjectList UMLView::getUMLObjects() {
+ UMLObjectList list;
+ for (UMLWidgetListIt it(m_WidgetList); it.current(); ++it) {
+ UMLWidget *w = it.current();
+ switch (w->getBaseType()) //use switch for easy future expansion
+ {
+ case wt_Actor:
+ case wt_Class:
+ case wt_Interface:
+ case wt_Package:
+ case wt_Component:
+ case wt_Node:
+ case wt_Artifact:
+ case wt_UseCase:
+ case wt_Object:
+ list.append( w->getUMLObject() );
+ break;
+ default:
+ break;
+ }
+ }
+ return list;
+}
+
+void UMLView::activate() {
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget *obj;
+
+ //Activate Regular widgets then activate messages
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ //If this UMLWidget is already activated or is a MessageWidget then skip it
+ if(obj->isActivated() || obj->getBaseType() == wt_Message)
+ continue;
+
+ if (obj->activate()) {
+ obj->setVisible(true);
+ } else {
+ m_WidgetList.remove(obj);
+ delete obj;
+ }
+ }//end while
+
+ MessageWidgetListIt it2( m_MessageList );
+ //Activate Message widgets
+ while ( (obj = (UMLWidget*)it2.current()) != 0 ) {
+ ++it2;
+ //If this MessageWidget is already activated then skip it
+ if(obj->isActivated())
+ continue;
+
+ obj->activate(m_pDoc->getChangeLog());
+ obj->setVisible( true );
+
+ }//end while
+
+ // Activate all association widgets
+ AssociationWidget *aw;
+ for (AssociationWidgetListIt ait(m_AssociationList);
+ (aw = ait.current()); ++ait) {
+ 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 {
+ m_AssociationList.remove(aw);
+ }
+ }
+}
+
+int UMLView::getSelectCount(bool filterText) const {
+ if (!filterText)
+ return m_SelectedList.count();
+ int counter = 0;
+ const UMLWidget * temp = 0;
+ for (UMLWidgetListIt iter(m_SelectedList); (temp = iter.current()) != 0; ++iter) {
+ if (temp->getBaseType() == wt_Text) {
+ const FloatingTextWidget *ft = static_cast<const FloatingTextWidget*>(temp);
+ if (ft->getRole() == tr_Floating)
+ counter++;
+ } else {
+ counter++;
+ }
+ }
+ return counter;
+}
+
+
+bool UMLView::getSelectedWidgets(UMLWidgetList &WidgetList, bool filterText /*= true*/) {
+ const UMLWidget * temp = 0;
+ for (UMLWidgetListIt it(m_SelectedList); (temp = it.current()) != NULL; ++it) {
+ if (filterText && temp->getBaseType() == wt_Text) {
+ const FloatingTextWidget *ft = static_cast<const FloatingTextWidget*>(temp);
+ if (ft->getRole() == tr_Floating)
+ WidgetList.append(temp);
+ } else {
+ WidgetList.append(temp);
+ }
+ }//end for
+ return true;
+}
+
+AssociationWidgetList UMLView::getSelectedAssocs() {
+ AssociationWidgetList assocWidgetList;
+ AssociationWidgetListIt assoc_it( m_AssociationList );
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current())) {
+ ++assoc_it;
+ if( assocwidget -> getSelected() )
+ assocWidgetList.append(assocwidget);
+ }
+ return assocWidgetList;
+}
+
+bool UMLView::addWidget( UMLWidget * pWidget , bool isPasteOperation ) {
+ if( !pWidget ) {
+ return false;
+ }
+ Widget_Type type = pWidget->getBaseType();
+ if (isPasteOperation) {
+ if (type == Uml::wt_Message)
+ m_MessageList.append(static_cast<MessageWidget*>(pWidget));
+ else
+ m_WidgetList.append(pWidget);
+ return true;
+ }
+ if (!isPasteOperation && findWidget(pWidget->getID())) {
+ kError() << "UMLView::addWidget: Not adding "
+ << "(id=" << ID2STR(pWidget->getID())
+ << "/type=" << type << "/name=" << pWidget->getName()
+ << ") because it's already there" << endl;
+ return false;
+ }
+ //kDebug() << "UMLView::addWidget called for basetype " << type << endl;
+ IDChangeLog * log = m_pDoc -> getChangeLog();
+ if( isPasteOperation && (!log || !m_pIDChangesLog)) {
+ kError()<<" Cant addWidget to view in paste op because a log is not open"<<endl;
+ return false;
+ }
+ int wX = pWidget -> getX();
+ int wY = pWidget -> getY();
+ bool xIsOutOfRange = (wX <= 0 || wX >= FloatingTextWidget::restrictPositionMax);
+ bool yIsOutOfRange = (wY <= 0 || wY >= FloatingTextWidget::restrictPositionMax);
+ if (xIsOutOfRange || yIsOutOfRange) {
+ QString name = pWidget->getName();
+ if (name.isEmpty()) {
+ FloatingTextWidget *ft = dynamic_cast<FloatingTextWidget*>(pWidget);
+ if (ft)
+ name = ft->getDisplayText();
+ }
+ kDebug() << "UMLView::addWidget (" << name << " type="
+ << pWidget->getBaseType() << "): position (" << wX << ","
+ << wY << ") is out of range" << endl;
+ if (xIsOutOfRange) {
+ pWidget->setX(0);
+ wX = 0;
+ }
+ if (yIsOutOfRange) {
+ pWidget->setY(0);
+ wY = 0;
+ }
+ }
+ if( wX < m_Pos.x() )
+ m_Pos.setX( wX );
+ if( wY < m_Pos.y() )
+ m_Pos.setY( wY );
+
+ //see if we need a new id to match object
+ switch( type ) {
+
+ case wt_Class:
+ case wt_Package:
+ case wt_Component:
+ case wt_Node:
+ case wt_Artifact:
+ case wt_Interface:
+ case wt_Enum:
+ case wt_Entity:
+ case wt_Datatype:
+ case wt_Actor:
+ case wt_UseCase:
+ {
+ Uml::IDType id = pWidget -> getID();
+ Uml::IDType newID = log->findNewID( id );
+ if( newID == Uml::id_None ) { // happens after a cut
+ if (id == Uml::id_None)
+ return false;
+ newID = id; //don't stop paste
+ } else
+ pWidget -> setID( newID );
+ UMLObject * pObject = m_pDoc -> findObjectById( newID );
+ if( !pObject ) {
+ kDebug() << "addWidget: Can't find UMLObject for id "
+ << ID2STR(newID) << endl;
+ return false;
+ }
+ pWidget -> setUMLObject( pObject );
+ //make sure it doesn't already exist.
+ if (findWidget(newID)) {
+ kDebug() << "UMLView::addWidget: Not adding "
+ << "(id=" << ID2STR(pWidget->getID())
+ << "/type=" << pWidget->getBaseType()
+ << "/name=" << pWidget->getName()
+ << ") because it's already there" << endl;
+ delete pWidget; // Not nice but if _we_ don't do it nobody else will
+ return true;//don't stop paste just because widget found.
+ }
+ m_WidgetList.append( pWidget );
+ }
+ break;
+
+ case wt_Message:
+ case wt_Note:
+ case wt_Box:
+ case wt_Text:
+ case wt_State:
+ case wt_Activity:
+ {
+ Uml::IDType newID = m_pDoc->assignNewID( pWidget->getID() );
+ pWidget->setID(newID);
+ if (type != wt_Message) {
+ m_WidgetList.append( pWidget );
+ return true;
+ }
+ // CHECK
+ // Handling of wt_Message:
+ MessageWidget *pMessage = static_cast<MessageWidget *>( pWidget );
+ if (pMessage == NULL) {
+ kDebug() << "UMLView::addWidget(): pMessage is NULL" << endl;
+ return false;
+ }
+ ObjectWidget *objWidgetA = pMessage -> getWidget(A);
+ ObjectWidget *objWidgetB = pMessage -> getWidget(B);
+ Uml::IDType waID = objWidgetA -> getLocalID();
+ Uml::IDType wbID = objWidgetB -> getLocalID();
+ Uml::IDType newWAID = m_pIDChangesLog ->findNewID( waID );
+ Uml::IDType newWBID = m_pIDChangesLog ->findNewID( wbID );
+ if( newWAID == Uml::id_None || newWBID == Uml::id_None ) {
+ kDebug() << "Error with ids : " << ID2STR(newWAID)
+ << " " << ID2STR(newWBID) << endl;
+ return false;
+ }
+ // Assumption here is that the A/B objectwidgets and the textwidget
+ // are pristine in the sense that we may freely change their local IDs.
+ objWidgetA -> setLocalID( newWAID );
+ objWidgetB -> setLocalID( newWBID );
+ FloatingTextWidget *ft = pMessage->getFloatingTextWidget();
+ if (ft == NULL)
+ kDebug() << "UMLView::addWidget: FloatingTextWidget of Message is NULL" << endl;
+ else if (ft->getID() == Uml::id_None)
+ ft->setID( UniqueID::gen() );
+ else {
+ Uml::IDType newTextID = m_pDoc->assignNewID( ft->getID() );
+ ft->setID( newTextID );
+ }
+ m_MessageList.append( pMessage );
+ }
+ break;
+
+ case wt_Object:
+ {
+ ObjectWidget* pObjectWidget = static_cast<ObjectWidget*>(pWidget);
+ if (pObjectWidget == NULL) {
+ kDebug() << "UMLView::addWidget(): pObjectWidget is NULL" << endl;
+ return false;
+ }
+ Uml::IDType nNewLocalID = getLocalID();
+ Uml::IDType nOldLocalID = pObjectWidget -> getLocalID();
+ m_pIDChangesLog->addIDChange( nOldLocalID, nNewLocalID );
+ pObjectWidget -> setLocalID( nNewLocalID );
+ UMLObject *pObject = m_pDoc->findObjectById(pWidget->getID());
+ if( !pObject ) {
+ kDebug() << "addWidget::Can't find UMLObject" << endl;
+ return false;
+ }
+ pWidget -> setUMLObject( pObject );
+ m_WidgetList.append( pWidget );
+ }
+ break;
+
+ default:
+ kDebug() << "Trying to add an invalid widget type" << endl;
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+// Add the association, and its child widgets to this view
+bool UMLView::addAssociation(AssociationWidget* pAssoc , bool isPasteOperation) {
+
+ if (!pAssoc) {
+ return false;
+ }
+ const Association_Type type = pAssoc->getAssocType();
+
+ if( isPasteOperation )
+ {
+ IDChangeLog * log = m_pDoc -> getChangeLog();
+
+ if(!log )
+ return false;
+
+ Uml::IDType ida = Uml::id_None, idb = Uml::id_None;
+ if( getType() == dt_Collaboration || getType() == dt_Sequence ) {
+ //check local log first
+ ida = m_pIDChangesLog->findNewID( pAssoc->getWidgetID(A) );
+ idb = m_pIDChangesLog->findNewID( pAssoc->getWidgetID(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 && type == at_Anchor )
+ ida = log->findNewID(pAssoc->getWidgetID(A));
+ if( idb == Uml::id_None && type == at_Anchor )
+ idb = log->findNewID(pAssoc->getWidgetID(B));
+ } else {
+ Uml::IDType oldIdA = pAssoc->getWidgetID(A);
+ Uml::IDType oldIdB = pAssoc->getWidgetID(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->setWidget(findWidget(ida), A);
+ pAssoc->setWidget(findWidget(idb), B);
+ }
+
+ UMLWidget * pWidgetA = findWidget(pAssoc->getWidgetID(A));
+ UMLWidget * pWidgetB = findWidget(pAssoc->getWidgetID(B));
+ //make sure valid widget ids
+ if (!pWidgetA || !pWidgetB) {
+ return false;
+ }
+
+ //make sure valid
+ if (!isPasteOperation && !m_pDoc->loading() &&
+ !AssocRules::allowAssociation(type, pWidgetA, pWidgetB, false)) {
+ kWarning() << "UMLView::addAssociation: allowAssociation returns false "
+ << "for AssocType " << type << endl;
+ return false;
+ }
+
+ //make sure there isn't already the same assoc
+ AssociationWidgetListIt assoc_it( m_AssociationList );
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current())) {
+ ++assoc_it;
+ if( *pAssoc == *assocwidget )
+ // this is nuts. Paste operation wants to know if 'true'
+ // for duplicate, but loadFromXMI needs 'false' value
+ return (isPasteOperation? true: false);
+ }
+
+ m_AssociationList.append(pAssoc);
+
+ FloatingTextWidget *ft[5] = { pAssoc->getNameWidget(),
+ pAssoc->getRoleWidget(A),
+ pAssoc->getRoleWidget(B),
+ pAssoc->getMultiWidget(A),
+ pAssoc->getMultiWidget(B) };
+ for (int i = 0; i < 5; i++) {
+ FloatingTextWidget *flotxt = ft[i];
+ if (flotxt) {
+ flotxt->updateComponentSize();
+ addWidget(flotxt);
+ }
+ }
+
+ return true;
+}
+
+void UMLView::activateAfterLoad(bool bUseLog) {
+ if (m_bActivated)
+ return;
+ if( bUseLog ) {
+ beginPartialWidgetPaste();
+ }
+
+ //now activate them all
+ activate();
+
+ if( bUseLog ) {
+ endPartialWidgetPaste();
+ }
+ resizeCanvasToItems();
+ setZoom( getZoom() );
+ m_bActivated = true;
+}
+
+void UMLView::beginPartialWidgetPaste() {
+ delete m_pIDChangesLog;
+ m_pIDChangesLog = 0;
+
+ m_pIDChangesLog = new IDChangeLog();
+ m_bPaste = true;
+}
+
+void UMLView::endPartialWidgetPaste() {
+ delete m_pIDChangesLog;
+ m_pIDChangesLog = 0;
+
+ m_bPaste = false;
+}
+
+void UMLView::removeAssoc(AssociationWidget* pAssoc) {
+ if(!pAssoc)
+ return;
+
+ emit sigAssociationRemoved(pAssoc);
+
+ pAssoc->cleanup();
+ m_AssociationList.remove(pAssoc); // will delete our association
+ m_pDoc->setModified();
+}
+
+void UMLView::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->getAssocType() == at_Containment) {
+ UMLObject *objToBeMoved = a->getWidget(B)->getUMLObject();
+ if (objToBeMoved != NULL) {
+ UMLListView *lv = UMLApp::app()->getListView();
+ lv->moveObject( objToBeMoved->getID(),
+ Model_Utils::convert_OT_LVT(objToBeMoved),
+ lv->theLogicalView() );
+ // UMLListView::moveObject() will delete the containment
+ // AssociationWidget via UMLView::updateContainment().
+ } else {
+ kDebug() << "removeAssocInViewAndDoc(containment): "
+ << "objB is NULL" << endl;
+ }
+ } else {
+ // Remove assoc in doc.
+ m_pDoc->removeAssociation(a->getAssociation());
+ // Remove assoc in view.
+ removeAssoc(a);
+ }
+}
+
+/** Removes all the associations related to Widget */
+void UMLView::removeAssociations(UMLWidget* Widget) {
+ AssociationWidgetListIt assoc_it(m_AssociationList);
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current())) {
+ ++assoc_it;
+ if(assocwidget->contains(Widget)) {
+ removeAssoc(assocwidget);
+ }
+ }
+}
+
+void UMLView::selectAssociations(bool bSelect) {
+ AssociationWidgetListIt assoc_it(m_AssociationList);
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current())) {
+ ++assoc_it;
+ if(bSelect &&
+ assocwidget->getWidget(A) && assocwidget->getWidget(A)->getSelected() &&
+ assocwidget->getWidget(B) && assocwidget->getWidget(B)->getSelected() ) {
+ assocwidget->setSelected(true);
+ } else {
+ assocwidget->setSelected(false);
+ }
+ }//end while
+}
+
+void UMLView::getWidgetAssocs(UMLObject* Obj, AssociationWidgetList & Associations) {
+ if( ! Obj )
+ return;
+
+ AssociationWidgetListIt assoc_it(m_AssociationList);
+ AssociationWidget * assocwidget;
+ while((assocwidget = assoc_it.current())) {
+ if (assocwidget->getWidget(A)->getUMLObject() == Obj ||
+ assocwidget->getWidget(B)->getUMLObject() == Obj)
+ Associations.append(assocwidget);
+ ++assoc_it;
+ }//end while
+}
+
+void UMLView::closeEvent ( QCloseEvent * e ) {
+ QWidget::closeEvent(e);
+}
+
+void UMLView::removeAllAssociations() {
+ //Remove All association widgets
+ AssociationWidgetListIt assoc_it(m_AssociationList);
+ AssociationWidget* assocwidget = 0;
+ while((assocwidget=assoc_it.current()))
+ {
+ ++assoc_it;
+ removeAssoc(assocwidget);
+ }
+ m_AssociationList.clear();
+}
+
+
+void UMLView::removeAllWidgets() {
+ // Remove widgets.
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget * temp = 0;
+ while ( (temp = it.current()) != 0 ) {
+ ++it;
+ // I had to take this condition back in, else umbrello
+ // crashes on exit. Still to be analyzed. --okellogg
+ if( !( temp -> getBaseType() == wt_Text &&
+ ((FloatingTextWidget *)temp)-> getRole() != tr_Floating ) ) {
+ removeWidget( temp );
+ }
+ }
+ m_WidgetList.clear();
+}
+
+void UMLView::showDocumentation( UMLObject * object, bool overwrite ) {
+ UMLApp::app() -> getDocWindow() -> showDocumentation( object, overwrite );
+ m_bChildDisplayedDoc = true;
+}
+
+void UMLView::showDocumentation( UMLWidget * widget, bool overwrite ) {
+ UMLApp::app() -> getDocWindow() -> showDocumentation( widget, overwrite );
+ m_bChildDisplayedDoc = true;
+}
+
+void UMLView::showDocumentation( AssociationWidget * widget, bool overwrite ) {
+ UMLApp::app() -> getDocWindow() -> showDocumentation( widget, overwrite );
+ m_bChildDisplayedDoc = true;
+}
+
+void UMLView::updateDocumentation( bool clear ) {
+ UMLApp::app() -> getDocWindow() -> updateDocumentation( clear );
+}
+
+void UMLView::updateContainment(UMLCanvasObject *self) {
+ if (self == NULL)
+ 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 = NULL, *newParentWidget = NULL;
+ UMLPackage *newParent = self->getUMLPackage();
+ for (UMLWidgetListIt wit(m_WidgetList); wit.current(); ++wit) {
+ UMLWidget *w = wit.current();
+ UMLObject *o = w->getUMLObject();
+ if (o == self)
+ selfWidget = w;
+ else if (newParent != NULL && o == newParent)
+ newParentWidget = w;
+ }
+ if (selfWidget == NULL)
+ return;
+ // Remove possibly obsoleted containment association.
+ for (AssociationWidgetListIt it(m_AssociationList); it.current(); ++it) {
+ AssociationWidget *a = it.current();
+ if (a->getAssocType() != Uml::at_Containment)
+ continue;
+ // Container is at role A, containee at B.
+ // We only look at association for which we are B.
+ UMLWidget *wB = a->getWidget(B);
+ UMLObject *roleBObj = wB->getUMLObject();
+ if (roleBObj != self)
+ continue;
+ UMLWidget *wA = a->getWidget(A);
+ UMLObject *roleAObj = wA->getUMLObject();
+ if (roleAObj == newParent) {
+ // Wow, all done. Great!
+ return;
+ }
+ removeAssoc(a); // AutoDelete is true
+ // It's okay to break out because there can only be a single
+ // containing object.
+ break;
+ }
+ if (newParentWidget == NULL)
+ return;
+ // Create the new containment association.
+ AssociationWidget *a = new AssociationWidget(this, newParentWidget,
+ Uml::at_Containment, selfWidget);
+ a->calculateEndingPoints();
+ a->setActivated(true);
+ m_AssociationList.append(a);
+}
+
+void UMLView::createAutoAssociations( UMLWidget * widget ) {
+ if (widget == NULL ||
+ (m_Type != Uml::dt_Class &&
+ m_Type != Uml::dt_Component &&
+ m_Type != Uml::dt_Deployment &&
+ m_Type != Uml::dt_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->getUMLObject();
+ if (tmpUmlObj == NULL)
+ return;
+ UMLCanvasObject *umlObj = dynamic_cast<UMLCanvasObject*>(tmpUmlObj);
+ if (umlObj == NULL)
+ return;
+ const UMLAssociationList& umlAssocs = umlObj->getAssociations();
+ UMLAssociationListIt it(umlAssocs);
+ UMLAssociation *assoc = NULL;
+ Uml::IDType myID = umlObj->getID();
+ while ((assoc = it.current()) != NULL) {
+ ++it;
+ UMLCanvasObject *other = NULL;
+ UMLObject *roleAObj = assoc->getObject(A);
+ if (roleAObj == NULL) {
+ kDebug() << "createAutoAssociations: roleA object is NULL at UMLAssoc "
+ << ID2STR(assoc->getID()) << endl;
+ continue;
+ }
+ UMLObject *roleBObj = assoc->getObject(B);
+ if (roleBObj == NULL) {
+ kDebug() << "createAutoAssociations: roleB object is NULL at UMLAssoc "
+ << ID2STR(assoc->getID()) << endl;
+ continue;
+ }
+ if (roleAObj->getID() == myID) {
+ other = static_cast<UMLCanvasObject*>(roleBObj);
+ } else if (roleBObj->getID() == myID) {
+ other = static_cast<UMLCanvasObject*>(roleAObj);
+ } else {
+ kDebug() << "createAutoAssociations: Can't find own object "
+ << ID2STR(myID) << " in UMLAssoc "
+ << ID2STR(assoc->getID()) << endl;
+ continue;
+ }
+ // Now that we have determined the "other" UMLObject, seek it in
+ // this view's UMLWidgets.
+ Uml::IDType otherID = other->getID();
+ UMLWidget *pOtherWidget;
+ UMLWidgetListIt wit(m_WidgetList);
+ while ((pOtherWidget = wit.current()) != NULL) {
+ ++wit;
+ if (pOtherWidget->getID() == otherID)
+ break;
+ }
+ if (pOtherWidget == NULL)
+ continue;
+ // Both objects are represented in this view:
+ // Assign widget roles as indicated by the UMLAssociation.
+ UMLWidget *widgetA, *widgetB;
+ if (myID == roleAObj->getID()) {
+ widgetA = widget;
+ widgetB = pOtherWidget;
+ } else {
+ widgetA = pOtherWidget;
+ widgetB = widget;
+ }
+ // Check that the assocwidget does not already exist.
+ Uml::Association_Type 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, false)) {
+ kDebug() << "createAutoAssociations: not transferring assoc "
+ << "of type " << assocType << endl;
+ continue;
+ }
+ // Create the AssociationWidget.
+ assocwidget = new AssociationWidget( this );
+ assocwidget->setWidget(widgetA, A);
+ assocwidget->setWidget(widgetB, B);
+ assocwidget->setAssocType(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 this object is capable of containing nested objects then
+ Uml::Object_Type t = umlObj->getBaseType();
+ if (t == ot_Package || t == ot_Class || t == ot_Interface || t == ot_Component) {
+ // for each of the object's containedObjects
+ UMLPackage *umlPkg = static_cast<UMLPackage*>(umlObj);
+ UMLObjectList lst = umlPkg->containedObjects();
+ for (UMLObject *obj = lst.first(); obj; obj = lst.next()) {
+ // if the containedObject has a widget representation on this view then
+ Uml::IDType id = obj->getID();
+ for (UMLWidget *w = m_WidgetList.first(); w; w = m_WidgetList.next()) {
+ if (w->getID() != 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 = new AssociationWidget(this, widget,
+ at_Containment, w);
+ a->calculateEndingPoints();
+ a->setActivated(true);
+ if (! addAssociation(a))
+ delete a;
+ }
+ }
+ }
+ // if the UMLCanvasObject has a parentPackage then
+ UMLPackage *parent = umlObj->getUMLPackage();
+ if (parent == NULL)
+ return;
+ // if the parentPackage has a widget representation on this view then
+ Uml::IDType pkgID = parent->getID();
+ UMLWidget *pWidget;
+ UMLWidgetListIt wit(m_WidgetList);
+ while ((pWidget = wit.current()) != NULL) {
+ ++wit;
+ if (pWidget->getID() == pkgID)
+ break;
+ }
+ if (pWidget == NULL || pWidget->rect().contains(widget->rect()))
+ return;
+ // create the containment AssocWidget
+ AssociationWidget *a = new AssociationWidget(this, pWidget, at_Containment, widget);
+ a->calculateEndingPoints();
+ a->setActivated(true);
+ if (! addAssociation(a))
+ delete a;
+}
+
+void UMLView::createAutoAttributeAssociations(UMLWidget *widget) {
+ if (widget == NULL || m_Type != Uml::dt_Class)
+ 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->getUMLObject();
+ if (tmpUmlObj == NULL)
+ return;
+ // if the underlying model object is really a UMLClassifier then
+ if (tmpUmlObj->getBaseType() == Uml::ot_Datatype) {
+ UMLClassifier *dt = static_cast<UMLClassifier*>(tmpUmlObj);
+ while (dt->originType() != NULL) {
+ tmpUmlObj = dt->originType();
+ if (tmpUmlObj->getBaseType() != Uml::ot_Datatype)
+ break;
+ dt = static_cast<UMLClassifier*>(tmpUmlObj);
+ }
+ }
+ if (tmpUmlObj->getBaseType() != Uml::ot_Class)
+ return;
+ UMLClassifier * klass = static_cast<UMLClassifier*>(tmpUmlObj);
+ // for each of the UMLClassifier's UMLAttributes
+ UMLAttributeList attrList = klass->getAttributeList();
+ for (UMLAttributeListIt ait(attrList); ait.current(); ++ait) {
+ UMLAttribute *attr = ait.current();
+ 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);
+ }
+ */
+ }
+}
+
+void UMLView::createAutoAttributeAssociation(UMLClassifier *type, UMLAttribute *attr,
+ UMLWidget *widget /*, UMLClassifier * klass*/) {
+ if (type == NULL) {
+ // kDebug() << "UMLView::createAutoAttributeAssociations("
+ // << klass->getName() << "): type is NULL for "
+ // << "attribute " << attr->getName() << endl;
+ return;
+ }
+ Uml::Association_Type assocType = Uml::at_Composition;
+ UMLWidget *w = findWidget( type->getID() );
+ AssociationWidget *aw = NULL;
+ // if the attribute type has a widget representation on this view
+ if (w) {
+ aw = findAssocWidget(widget, w, attr->getName());
+ if ( aw == NULL &&
+ // if the current diagram type permits compositions
+ AssocRules::allowAssociation(assocType, widget, w, false) ) {
+ // Create a composition AssocWidget, or, if the attribute type is
+ // stereotyped <<CORBAInterface>>, create a UniAssociation widget.
+ if (type->getStereotype() == "CORBAInterface")
+ assocType = at_UniAssociation;
+ AssociationWidget *a = new AssociationWidget (this, widget, assocType, w, attr);
+ a->calculateEndingPoints();
+ a->setVisibility(attr->getVisibility(), B);
+ /*
+ if (assocType == at_Aggregation || assocType == at_UniAssociation)
+ a->setMulti("0..1", B);
+ */
+ a->setRoleName(attr->getName(), B);
+ a->setActivated(true);
+ if (! addAssociation(a))
+ delete a;
+ }
+ }
+ // if the attribute type is a Datatype then
+ if (type->getBaseType() == ot_Datatype) {
+ UMLClassifier *dt = static_cast<UMLClassifier*>(type);
+ // if the Datatype is a reference (pointer) type
+ if (dt->isReference()) {
+ //Uml::Association_Type assocType = Uml::at_Composition;
+ UMLClassifier *c = dt->originType();
+ UMLWidget *w = c ? findWidget( c->getID() ) : 0;
+ // if the referenced type has a widget representation on this view
+ if (w) {
+ aw = findAssocWidget(widget, w, attr->getName());
+ if (aw == NULL &&
+ // if the current diagram type permits aggregations
+ AssocRules::allowAssociation(at_Aggregation, widget, w, false)) {
+ // create an aggregation AssocWidget from the ClassifierWidget
+ // to the widget of the referenced type
+ AssociationWidget *a = new AssociationWidget
+ (this, widget, at_Aggregation, w, attr);
+ a->calculateEndingPoints();
+ a->setVisibility(attr->getVisibility(), B);
+ //a->setChangeability(true, B);
+ a->setMulti("0..1", B);
+ a->setRoleName(attr->getName(), B);
+ a->setActivated(true);
+ if (! addAssociation(a))
+ delete a;
+ }
+ }
+ }
+ }
+}
+
+void UMLView::findMaxBoundingRectangle(const FloatingTextWidget* ft, int& px, int& py, int& qx, int& qy)
+{
+ if (ft == NULL || !ft->isVisible())
+ return;
+
+ int x = ft -> getX();
+ int y = ft -> getY();
+ int x1 = x + ft -> getWidth() - 1;
+ int y1 = y + ft -> getHeight() - 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;
+}
+
+void UMLView::copyAsImage(QPixmap*& pix) {
+ //get the smallest rect holding the diagram
+ QRect rect = getDiagramRect();
+ QPixmap diagram( rect.width(), rect.height() );
+
+ //only draw what is selected
+ m_bDrawSelectedOnly = true;
+ selectAssociations(true);
+ getDiagram(rect, diagram);
+
+ //now get the selection cut
+ int px = -1, py = -1, qx = -1, qy = -1;
+
+ //first get the smallest rect holding the widgets
+ for (UMLWidget* temp = m_SelectedList.first(); temp; temp = m_SelectedList.next()) {
+ int x = temp -> getX();
+ int y = temp -> getY();
+ int x1 = x + temp -> width() - 1;
+ int 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
+ AssociationWidget *a;
+ AssociationWidgetListIt assoc_it(m_AssociationList);
+
+ //get each type of associations
+ //This needs to be reimplemented to increase the rectangle
+ //if a part of any association is not included
+ while ((a = assoc_it.current()) != NULL) {
+ ++assoc_it;
+ if (! a->getSelected())
+ continue;
+ const FloatingTextWidget* multiA = const_cast<FloatingTextWidget*>(a->getMultiWidget(A));
+ const FloatingTextWidget* multiB = const_cast<FloatingTextWidget*>(a->getMultiWidget(B));
+ const FloatingTextWidget* roleA = const_cast<FloatingTextWidget*>(a->getRoleWidget(A));
+ const FloatingTextWidget* roleB = const_cast<FloatingTextWidget*>(a->getRoleWidget(B));
+ const FloatingTextWidget* changeA = const_cast<FloatingTextWidget*>(a->getChangeWidget(A));
+ const FloatingTextWidget* changeB = const_cast<FloatingTextWidget*>(a->getChangeWidget(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 while
+
+ QRect imageRect; //area with respect to getDiagramRect()
+ //i.e. all widgets on the canvas. Was previously with
+ //respect to whole canvas
+
+ 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());
+ bitBlt(pix, QPoint(0, 0), &diagram, imageRect);
+ m_bDrawSelectedOnly = false;
+}
+
+void UMLView::setMenu() {
+ slotRemovePopupMenu();
+ ListPopupMenu::Menu_Type menu = ListPopupMenu::mt_Undefined;
+ switch( getType() ) {
+ case dt_Class:
+ menu = ListPopupMenu::mt_On_Class_Diagram;
+ break;
+
+ case dt_UseCase:
+ menu = ListPopupMenu::mt_On_UseCase_Diagram;
+ break;
+
+ case dt_Sequence:
+ menu = ListPopupMenu::mt_On_Sequence_Diagram;
+ break;
+
+ case dt_Collaboration:
+ menu = ListPopupMenu::mt_On_Collaboration_Diagram;
+ break;
+
+ case dt_State:
+ menu = ListPopupMenu::mt_On_State_Diagram;
+ break;
+
+ case dt_Activity:
+ menu = ListPopupMenu::mt_On_Activity_Diagram;
+ break;
+
+ case dt_Component:
+ menu = ListPopupMenu::mt_On_Component_Diagram;
+ break;
+
+ case dt_Deployment:
+ menu = ListPopupMenu::mt_On_Deployment_Diagram;
+ break;
+
+ case dt_EntityRelationship:
+ menu = ListPopupMenu::mt_On_EntityRelationship_Diagram;
+ break;
+
+ default:
+ kWarning() << "setMenu() called on unknown diagram type" << endl;
+ menu = ListPopupMenu::mt_Undefined;
+ break;
+ }//end switch
+ if( menu != ListPopupMenu::mt_Undefined ) {
+ m_pMenu = new ListPopupMenu(this, menu, this);
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ m_pMenu->popup( mapToGlobal( contentsToViewport(worldMatrix().map(m_Pos)) ) );
+ }
+}
+
+void UMLView::slotRemovePopupMenu() {
+ if(m_pMenu) {
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+void UMLView::slotMenuSelection(int sel) {
+ switch( (ListPopupMenu::Menu_Type)sel ) {
+ case ListPopupMenu::mt_Undo:
+ m_pDoc->loadUndoData();
+ break;
+
+ case ListPopupMenu::mt_Redo:
+ m_pDoc->loadRedoData();
+ break;
+
+ case ListPopupMenu::mt_Clear:
+ clearDiagram();
+ break;
+
+ case ListPopupMenu::mt_Export_Image:
+ m_pImageExporter->exportView();
+ break;
+
+ case ListPopupMenu::mt_FloatText:
+ {
+ FloatingTextWidget* ft = new FloatingTextWidget(this);
+ ft->changeTextDlg();
+ //if no text entered delete
+ if(!FloatingTextWidget::isTextValid(ft->getText())) {
+ delete ft;
+ } else {
+ ft->setID(UniqueID::gen());
+ setupNewWidget(ft);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_UseCase:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject( ot_UseCase );
+ break;
+
+ case ListPopupMenu::mt_Actor:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject( ot_Actor );
+ break;
+
+ case ListPopupMenu::mt_Class:
+ case ListPopupMenu::mt_Object:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject( ot_Class);
+ break;
+
+ case ListPopupMenu::mt_Package:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Package);
+ break;
+
+ case ListPopupMenu::mt_Component:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Component);
+ break;
+
+ case ListPopupMenu::mt_Node:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Node);
+ break;
+
+ case ListPopupMenu::mt_Artifact:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Artifact);
+ break;
+
+ case ListPopupMenu::mt_Interface:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Interface);
+ break;
+
+ case ListPopupMenu::mt_Enum:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Enum);
+ break;
+
+ case ListPopupMenu::mt_Entity:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Entity);
+ break;
+
+ case ListPopupMenu::mt_Datatype:
+ m_bCreateObject = true;
+ Object_Factory::createUMLObject(ot_Datatype);
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ //FIXME make this work for diagram's right click menu
+ if ( m_SelectedList.count() &&
+ UMLApp::app()->editCutCopy(true) ) {
+ deleteSelection();
+ m_pDoc->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Copy:
+ //FIXME make this work for diagram's right click menu
+ m_SelectedList.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_State:
+ {
+ bool ok = false;
+ QString name = KInputDialog::getText( i18n("Enter State Name"),
+ i18n("Enter the name of the new state:"),
+ i18n("new state"), &ok, UMLApp::app() );
+ 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:
+ {
+ bool ok = false;
+ QString name = KInputDialog::getText( i18n("Enter Activity Name"),
+ i18n("Enter the name of the new activity:"),
+ i18n("new activity"), &ok, UMLApp::app() );
+ if ( ok ) {
+ ActivityWidget* activity = new ActivityWidget( this, ActivityWidget::Normal );
+ activity->setName( name );
+ setupNewWidget(activity);
+ }
+ }
+ break;
+
+ case ListPopupMenu::mt_SnapToGrid:
+ toggleSnapToGrid();
+ m_pDoc->setModified();
+ break;
+
+ case ListPopupMenu::mt_ShowSnapGrid:
+ toggleShowGrid();
+ m_pDoc->setModified();
+ break;
+
+ case ListPopupMenu::mt_Properties:
+ if (showPropDialog() == true)
+ m_pDoc->setModified();
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ m_pDoc->removeDiagram( getID() );
+ break;
+
+ case ListPopupMenu::mt_Rename:
+ {
+ bool ok = false;
+ QString name = KInputDialog::getText( i18n("Enter Diagram Name"),
+ i18n("Enter the new name of the diagram:"),
+ getName(), &ok, UMLApp::app() );
+ if (ok) {
+ setName(name);
+ m_pDoc->signalDiagramRenamed(this);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void UMLView::slotCutSuccessful() {
+ if( m_bStartedCut ) {
+ deleteSelection();
+ m_bStartedCut = false;
+ }
+}
+
+void UMLView::slotShowView() {
+ m_pDoc -> changeCurrentView( getID() );
+}
+
+QPoint UMLView::getPastePoint() {
+ QPoint point = m_PastePoint;
+ point.setX( point.x() - m_Pos.x() );
+ point.setY( point.y() - m_Pos.y() );
+ return point;
+}
+
+void UMLView::resetPastePoint() {
+ m_PastePoint = m_Pos;
+}
+
+int UMLView::snappedX (int x) {
+ if (getSnapToGrid()) {
+ int gridX = getSnapX();
+ int modX = x % gridX;
+ x -= modX;
+ if (modX >= gridX / 2)
+ x += gridX;
+ }
+ return x;
+}
+
+int UMLView::snappedY (int y) {
+ if (getSnapToGrid()) {
+ int gridY = getSnapY();
+ int modY = y % gridY;
+ y -= modY;
+ if (modY >= gridY / 2)
+ y += gridY;
+ }
+ return y;
+}
+
+bool UMLView::showPropDialog() {
+ UMLViewDialog dlg( this, this );
+ if( dlg.exec() ) {
+ return true;
+ }
+ return false;
+}
+
+
+QFont UMLView::getFont() const {
+ return m_Options.uiState.font;
+}
+
+void UMLView::setFont(QFont font, bool changeAllWidgets /* = false */) {
+ m_Options.uiState.font = font;
+ if (!changeAllWidgets)
+ return;
+ for (UMLWidgetListIt wit(m_WidgetList); wit.current(); ++wit) {
+ UMLWidget *w = wit.current();
+ w->setFont(font);
+ }
+}
+
+void UMLView::setClassWidgetOptions( ClassOptionsPage * page ) {
+ UMLWidget * pWidget = 0;
+ UMLWidgetListIt wit( m_WidgetList );
+ while ( (pWidget = wit.current()) != 0 ) {
+ ++wit;
+ Uml::Widget_Type wt = pWidget->getBaseType();
+ if (wt == Uml::wt_Class || wt == Uml::wt_Interface) {
+ page -> setWidget( static_cast<ClassifierWidget *>(pWidget) );
+ page -> updateUMLWidget();
+ }
+ }
+}
+
+
+void UMLView::checkSelections() {
+ UMLWidget * pWA = 0, * pWB = 0, * pTemp = 0;
+ //check messages
+ for(pTemp=(UMLWidget *)m_SelectedList.first();pTemp;pTemp=(UMLWidget *)m_SelectedList.next()) {
+ if( pTemp->getBaseType() == wt_Message && pTemp -> getSelected() ) {
+ MessageWidget * pMessage = static_cast<MessageWidget *>( pTemp );
+ pWA = pMessage -> getWidget(A);
+ pWB = pMessage -> getWidget(B);
+ if( !pWA -> getSelected() ) {
+ pWA -> setSelectedFlag( true );
+ m_SelectedList.append( pWA );
+ }
+ if( !pWB -> getSelected() ) {
+ pWB -> setSelectedFlag( true );
+ m_SelectedList.append( pWB );
+ }
+ }//end if
+ }//end for
+ //check Associations
+ AssociationWidgetListIt it(m_AssociationList);
+ AssociationWidget * pAssoc = 0;
+ while((pAssoc = it.current())) {
+ ++it;
+ if( pAssoc -> getSelected() ) {
+ pWA = pAssoc -> getWidget(A);
+ pWB = pAssoc -> getWidget(B);
+ if( !pWA -> getSelected() ) {
+ pWA -> setSelectedFlag( true );
+ m_SelectedList.append( pWA );
+ }
+ if( !pWB -> getSelected() ) {
+ pWB -> setSelectedFlag( true );
+ m_SelectedList.append( pWB );
+ }
+ }//end if
+ }//end while
+}
+
+bool UMLView::checkUniqueSelection()
+{
+ // if there are no selected items, we return true
+ if (m_SelectedList.count() <= 0)
+ return true;
+
+ // get the first item and its base type
+ UMLWidget * pTemp = (UMLWidget *) m_SelectedList.first();
+ Widget_Type tmpType = pTemp -> getBaseType();
+
+ // check all selected items, if they have the same BaseType
+ for ( pTemp = (UMLWidget *) m_SelectedList.first();
+ pTemp;
+ pTemp = (UMLWidget *) m_SelectedList.next() ) {
+ if( pTemp->getBaseType() != tmpType)
+ {
+ return false; // the base types are different, the list is not unique
+ }
+ } // for ( through all selected items )
+
+ return true; // selected items are unique
+}
+
+void UMLView::clearDiagram() {
+ if( KMessageBox::Continue == KMessageBox::warningContinueCancel( this, i18n("You are about to delete "
+ "the entire diagram.\nAre you sure?"),
+ i18n("Delete Diagram?"),KGuiItem( i18n("&Delete"), "editdelete") ) ) {
+ removeAllWidgets();
+ }
+}
+
+void UMLView::toggleSnapToGrid() {
+ setSnapToGrid( !getSnapToGrid() );
+}
+
+void UMLView::toggleSnapComponentSizeToGrid() {
+ setSnapComponentSizeToGrid( !getSnapComponentSizeToGrid() );
+}
+
+void UMLView::toggleShowGrid() {
+ setShowSnapGrid( !getShowSnapGrid() );
+}
+
+void UMLView::setSnapToGrid(bool bSnap) {
+ m_bUseSnapToGrid = bSnap;
+ emit sigSnapToGridToggled( getSnapToGrid() );
+}
+
+void UMLView::setSnapComponentSizeToGrid(bool bSnap) {
+ m_bUseSnapComponentSizeToGrid = bSnap;
+ updateComponentSizes();
+ emit sigSnapComponentSizeToGridToggled( getSnapComponentSizeToGrid() );
+}
+
+bool UMLView::getShowSnapGrid() const {
+ return m_bShowSnapGrid;
+}
+
+void UMLView::setShowSnapGrid(bool bShow) {
+ m_bShowSnapGrid = bShow;
+ canvas()->setAllChanged();
+ emit sigShowGridToggled( getShowSnapGrid() );
+}
+
+bool UMLView::getShowOpSig() const {
+ return m_Options.classState.showOpSig;
+}
+
+void UMLView::setShowOpSig(bool bShowOpSig) {
+ m_Options.classState.showOpSig = bShowOpSig;
+}
+
+void UMLView::setZoom(int zoom) {
+ if (zoom < 10) {
+ zoom = 10;
+ } else if (zoom > 500) {
+ zoom = 500;
+ }
+
+ QWMatrix wm;
+ wm.scale(zoom/100.0,zoom/100.0);
+ setWorldMatrix(wm);
+
+ m_nZoom = currentZoom();
+ resizeCanvasToItems();
+}
+
+int UMLView::currentZoom() {
+ return (int)(worldMatrix().m11()*100.0);
+}
+
+void UMLView::zoomIn() {
+ QWMatrix wm = worldMatrix();
+ wm.scale(1.5,1.5); // adjust zooming step here
+ setZoom( (int)(wm.m11()*100.0) );
+}
+
+void UMLView::zoomOut() {
+ QWMatrix wm = worldMatrix();
+ wm.scale(2.0/3.0, 2.0/3.0); //adjust zooming step here
+ setZoom( (int)(wm.m11()*100.0) );
+}
+
+void UMLView::fileLoaded() {
+ setZoom( getZoom() );
+ resizeCanvasToItems();
+}
+
+void UMLView::setCanvasSize(int width, int height) {
+ setCanvasWidth(width);
+ setCanvasHeight(height);
+ canvas()->resize(width, height);
+}
+
+void UMLView::resizeCanvasToItems() {
+ QRect canvasSize = getDiagramRect();
+ int canvasWidth = canvasSize.right() + 5;
+ int canvasHeight = canvasSize.bottom() + 5;
+
+ //Find out the bottom right visible pixel and size to at least that
+ int contentsX, contentsY;
+ int contentsWMX, contentsWMY;
+ viewportToContents(viewport()->width(), viewport()->height(), contentsX, contentsY);
+ inverseWorldMatrix().map(contentsX, contentsY, &contentsWMX, &contentsWMY);
+
+ if (canvasWidth < contentsWMX) {
+ canvasWidth = contentsWMX;
+ }
+
+ if (canvasHeight < contentsWMY) {
+ canvasHeight = contentsWMY;
+ }
+
+ setCanvasSize(canvasWidth, canvasHeight);
+}
+
+void UMLView::show() {
+ QWidget::show();
+ resizeCanvasToItems();
+}
+
+void UMLView::updateComponentSizes() {
+ // update sizes of all components
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget *obj;
+ while ( (obj=(UMLWidget*)it.current()) != 0 ) {
+ ++it;
+ obj->updateComponentSize();
+ }
+}
+
+/**
+ * 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 UMLView::forceUpdateWidgetFontMetrics(QPainter * painter) {
+ UMLWidgetListIt it( m_WidgetList );
+ UMLWidget *obj;
+
+ while ((obj = it.current()) != 0 ) {
+ ++it;
+ obj->forceUpdateFontMetrics(painter);
+ }
+}
+
+void UMLView::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement viewElement = qDoc.createElement( "diagram" );
+ viewElement.setAttribute( "xmi.id", ID2STR(m_nID) );
+ viewElement.setAttribute( "name", getName() );
+ viewElement.setAttribute( "type", m_Type );
+ viewElement.setAttribute( "documentation", m_Documentation );
+ //optionstate uistate
+ viewElement.setAttribute( "fillcolor", m_Options.uiState.fillColor.name() );
+ viewElement.setAttribute( "linecolor", m_Options.uiState.lineColor.name() );
+ viewElement.setAttribute( "linewidth", m_Options.uiState.lineWidth );
+ viewElement.setAttribute( "usefillcolor", m_Options.uiState.useFillColor );
+ viewElement.setAttribute( "font", m_Options.uiState.font.toString() );
+ //optionstate classstate
+ viewElement.setAttribute( "showattsig", m_Options.classState.showAttSig );
+ viewElement.setAttribute( "showatts", m_Options.classState.showAtts);
+ viewElement.setAttribute( "showopsig", m_Options.classState.showOpSig );
+ viewElement.setAttribute( "showops", m_Options.classState.showOps );
+ viewElement.setAttribute( "showpackage", m_Options.classState.showPackage );
+ viewElement.setAttribute( "showscope", m_Options.classState.showVisibility );
+ viewElement.setAttribute( "showstereotype", m_Options.classState.showStereoType );
+ //misc
+ viewElement.setAttribute( "localid", ID2STR(m_nLocalID) );
+ viewElement.setAttribute( "showgrid", m_bShowSnapGrid );
+ viewElement.setAttribute( "snapgrid", m_bUseSnapToGrid );
+ viewElement.setAttribute( "snapcsgrid", m_bUseSnapComponentSizeToGrid );
+ viewElement.setAttribute( "snapx", m_nSnapX );
+ viewElement.setAttribute( "snapy", m_nSnapY );
+ viewElement.setAttribute( "zoom", m_nZoom );
+ viewElement.setAttribute( "canvasheight", m_nCanvasHeight );
+ viewElement.setAttribute( "canvaswidth", m_nCanvasWidth );
+ //now save all the widgets
+ UMLWidget * widget = 0;
+ UMLWidgetListIt w_it( m_WidgetList );
+ QDomElement widgetElement = qDoc.createElement( "widgets" );
+ while( ( widget = w_it.current() ) ) {
+ ++w_it;
+ // Having an exception is bad I know, but gotta work with
+ // system we are given.
+ // We DONT 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->getBaseType() != wt_Text ||
+ static_cast<FloatingTextWidget*>(widget)->getLink() == NULL)
+ widget->saveToXMI( qDoc, widgetElement );
+ }
+ viewElement.appendChild( widgetElement );
+ //now save the message widgets
+ MessageWidgetListIt m_it( m_MessageList );
+ QDomElement messageElement = qDoc.createElement( "messages" );
+ while( ( widget = m_it.current() ) ) {
+ ++m_it;
+ widget -> saveToXMI( qDoc, messageElement );
+ }
+ viewElement.appendChild( messageElement );
+ //now save the associations
+ QDomElement assocElement = qDoc.createElement( "associations" );
+ if ( m_AssociationList.count() ) {
+ // We guard against ( m_AssociationList.count() == 0 ) because
+ // this code could be reached as follows:
+ // ^ UMLView::saveToXMI()
+ // ^ UMLDoc::saveToXMI()
+ // ^ UMLDoc::addToUndoStack()
+ // ^ UMLDoc::setModified()
+ // ^ UMLDoc::createDiagram()
+ // ^ UMLDoc::newDocument()
+ // ^ UMLApp::newDocument()
+ // ^ main()
+ //
+ AssociationWidgetListIt a_it( m_AssociationList );
+ AssociationWidget * assoc = 0;
+ while( ( assoc = a_it.current() ) ) {
+ ++a_it;
+ assoc -> saveToXMI( qDoc, assocElement );
+ }
+ // kDebug() << "UMLView::saveToXMI() saved "
+ // << m_AssociationList.count() << " assocData." << endl;
+ }
+ viewElement.appendChild( assocElement );
+ qElement.appendChild( viewElement );
+}
+
+bool UMLView::loadFromXMI( QDomElement & qElement ) {
+ QString id = qElement.attribute( "xmi.id", "-1" );
+ m_nID = STR2ID(id);
+ if( m_nID == Uml::id_None )
+ return false;
+ setName( qElement.attribute( "name", "" ) );
+ QString type = qElement.attribute( "type", "0" );
+ m_Documentation = qElement.attribute( "documentation", "" );
+ QString localid = qElement.attribute( "localid", "0" );
+ //optionstate uistate
+ QString font = qElement.attribute( "font", "" );
+ if (!font.isEmpty()) {
+ m_Options.uiState.font.fromString( font );
+ m_Options.uiState.font.setUnderline(false);
+ }
+ QString fillcolor = qElement.attribute( "fillcolor", "" );
+ QString linecolor = qElement.attribute( "linecolor", "" );
+ QString linewidth = qElement.attribute( "linewidth", "" );
+ QString usefillcolor = qElement.attribute( "usefillcolor", "0" );
+ m_Options.uiState.useFillColor = (bool)usefillcolor.toInt();
+ //optionstate classstate
+ QString temp = qElement.attribute( "showattsig", "0" );
+ m_Options.classState.showAttSig = (bool)temp.toInt();
+ temp = qElement.attribute( "showatts", "0" );
+ m_Options.classState.showAtts = (bool)temp.toInt();
+ temp = qElement.attribute( "showopsig", "0" );
+ m_Options.classState.showOpSig = (bool)temp.toInt();
+ temp = qElement.attribute( "showops", "0" );
+ m_Options.classState.showOps = (bool)temp.toInt();
+ temp = qElement.attribute( "showpackage", "0" );
+ m_Options.classState.showPackage = (bool)temp.toInt();
+ temp = qElement.attribute( "showscope", "0" );
+ m_Options.classState.showVisibility = (bool)temp.toInt();
+ temp = qElement.attribute( "showstereotype", "0" );
+ m_Options.classState.showStereoType = (bool)temp.toInt();
+ //misc
+ QString showgrid = qElement.attribute( "showgrid", "0" );
+ m_bShowSnapGrid = (bool)showgrid.toInt();
+
+ QString snapgrid = qElement.attribute( "snapgrid", "0" );
+ m_bUseSnapToGrid = (bool)snapgrid.toInt();
+
+ QString snapcsgrid = qElement.attribute( "snapcsgrid", "0" );
+ m_bUseSnapComponentSizeToGrid = (bool)snapcsgrid.toInt();
+
+ QString snapx = qElement.attribute( "snapx", "10" );
+ m_nSnapX = snapx.toInt();
+
+ QString snapy = qElement.attribute( "snapy", "10" );
+ m_nSnapY = snapy.toInt();
+
+ QString zoom = qElement.attribute( "zoom", "100" );
+ m_nZoom = zoom.toInt();
+
+ QString height = qElement.attribute( "canvasheight", QString("%1").arg(UMLView::defaultCanvasSize) );
+ m_nCanvasHeight = height.toInt();
+
+ QString width = qElement.attribute( "canvaswidth", QString("%1").arg(UMLView::defaultCanvasSize) );
+ m_nCanvasWidth = width.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::dt_UseCase;
+ break;
+ case 401:
+ m_Type = Uml::dt_Collaboration;
+ break;
+ case 402:
+ m_Type = Uml::dt_Class;
+ break;
+ case 403:
+ m_Type = Uml::dt_Sequence;
+ break;
+ case 404:
+ m_Type = Uml::dt_State;
+ break;
+ case 405:
+ m_Type = Uml::dt_Activity;
+ break;
+ case 406:
+ m_Type = Uml::dt_Component;
+ break;
+ case 407:
+ m_Type = Uml::dt_Deployment;
+ break;
+ case 408:
+ m_Type = Uml::dt_EntityRelationship;
+ break;
+ default:
+ m_Type = Uml::dt_Undefined;
+ break;
+ }
+ } else {
+ m_Type = (Uml::Diagram_Type)nType;
+ }
+ if( !fillcolor.isEmpty() )
+ m_Options.uiState.fillColor = QColor( fillcolor );
+ if( !linecolor.isEmpty() )
+ m_Options.uiState.lineColor = QColor( linecolor );
+ if( !linewidth.isEmpty() )
+ m_Options.uiState.lineWidth = linewidth.toInt();
+ m_nLocalID = STR2ID(localid);
+
+ QDomNode node = qElement.firstChild();
+ bool widgetsLoaded = false, messagesLoaded = false, associationsLoaded = false;
+ while (!node.isNull()) {
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ if (element.tagName() == "widgets")
+ widgetsLoaded = loadWidgetsFromXMI( element );
+ else if (element.tagName() == "messages")
+ messagesLoaded = loadMessagesFromXMI( element );
+ else if (element.tagName() == "associations")
+ associationsLoaded = loadAssociationsFromXMI( element );
+ }
+ node = node.nextSibling();
+ }
+
+ if (!widgetsLoaded) {
+ kWarning() << "failed umlview load on widgets" << endl;
+ return false;
+ }
+ if (!messagesLoaded) {
+ kWarning() << "failed umlview load on messages" << endl;
+ return false;
+ }
+ if (!associationsLoaded) {
+ kWarning() << "failed umlview load on associations" << endl;
+ return false;
+ }
+ return true;
+}
+
+bool UMLView::loadWidgetsFromXMI( QDomElement & qElement ) {
+ UMLWidget* widget = 0;
+ QDomNode node = qElement.firstChild();
+ QDomElement widgetElement = node.toElement();
+ while( !widgetElement.isNull() ) {
+ widget = loadWidgetFromXMI(widgetElement);
+ if (widget) {
+ m_WidgetList.append( widget );
+ // In the interest of best-effort loading, in case of a
+ // (widget == NULL) we still go on.
+ // The individual widget's loadFromXMI method should
+ // already have generated an error message to tell the
+ // user that something went wrong.
+ }
+ node = widgetElement.nextSibling();
+ widgetElement = node.toElement();
+ }
+
+ return true;
+}
+
+UMLWidget* UMLView::loadWidgetFromXMI(QDomElement& widgetElement) {
+
+ if ( !m_pDoc ) {
+ kWarning() << "UMLView::loadWidgetFromXMI(): m_pDoc is NULL" << endl;
+ return 0L;
+ }
+
+ QString tag = widgetElement.tagName();
+ QString idstr = widgetElement.attribute( "xmi.id", "-1" );
+ UMLWidget* widget = Widget_Factory::makeWidgetFromXMI(tag, idstr, this);
+ if (widget == NULL)
+ return NULL;
+ if (!widget->loadFromXMI(widgetElement)) {
+ widget->cleanup();
+ delete widget;
+ return 0;
+ }
+ return widget;
+}
+
+bool UMLView::loadMessagesFromXMI( QDomElement & qElement ) {
+ MessageWidget * message = 0;
+ QDomNode node = qElement.firstChild();
+ QDomElement messageElement = node.toElement();
+ while( !messageElement.isNull() ) {
+ QString tag = messageElement.tagName();
+ if (tag == "messagewidget" ||
+ tag == "UML:MessageWidget" ) { // for bkwd compatibility
+ message = new MessageWidget(this, sequence_message_asynchronous,
+ Uml::id_Reserved);
+ if( !message -> loadFromXMI( messageElement ) ) {
+ delete message;
+ return false;
+ }
+ m_MessageList.append( message );
+ FloatingTextWidget *ft = message->getFloatingTextWidget();
+ if (ft)
+ m_WidgetList.append( ft );
+ else if (message->getSequenceMessageType() != sequence_message_creation)
+ kDebug() << "UMLView::loadMessagesFromXMI: ft is NULL"
+ << " for message " << ID2STR(message->getID()) << endl;
+ }
+ node = messageElement.nextSibling();
+ messageElement = node.toElement();
+ }
+ return true;
+}
+
+bool UMLView::loadAssociationsFromXMI( QDomElement & qElement ) {
+ QDomNode node = qElement.firstChild();
+ QDomElement assocElement = node.toElement();
+ int countr = 0;
+ while( !assocElement.isNull() ) {
+ QString tag = assocElement.tagName();
+ if (tag == "assocwidget" ||
+ tag == "UML:AssocWidget") { // for bkwd compatibility
+ countr++;
+ AssociationWidget *assoc = new AssociationWidget(this);
+ if( !assoc->loadFromXMI( assocElement ) ) {
+ kError() << "couldn't loadFromXMI association widget:"
+ << assoc << ", bad XMI file? Deleting from umlview."
+ << endl;
+ delete assoc;
+ /* return false;
+ Returning false here is a little harsh when the
+ rest of the diagram might load okay.
+ */
+ } else {
+ if(!addAssociation(assoc, false))
+ {
+ kError()<<"Couldnt addAssociation("<<assoc<<") to umlview, deleting."<<endl;
+ // assoc->cleanup();
+ delete assoc;
+ //return false; // soften error.. may not be that bad
+ }
+ }
+ }
+ node = assocElement.nextSibling();
+ assocElement = node.toElement();
+ }
+ return true;
+}
+
+void UMLView::addObject(UMLObject *object)
+{
+ m_bCreateObject = true;
+ if (m_pDoc->addUMLObject(object))
+ m_pDoc->signalUMLObjectCreated(object); // m_bCreateObject is reset by slotObjectCreated()
+ else
+ m_bCreateObject = false;
+}
+
+bool UMLView::loadUisDiagramPresentation(QDomElement & qElement) {
+ for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ QDomElement elem = node.toElement();
+ QString tag = elem.tagName();
+ if (! Uml::tagEq(tag, "Presentation")) {
+ kError() << "ignoring unknown UisDiagramPresentation tag "
+ << tag << endl;
+ 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();
+ kDebug() << "Presentation: tag = " << tag << endl;
+ if (Uml::tagEq(tag, "Presentation.geometry")) {
+ QDomNode gnode = e.firstChild();
+ QDomElement gelem = gnode.toElement();
+ QString csv = gelem.text();
+ QStringList dim = QStringList::split(",", csv);
+ x = dim[0].toInt();
+ y = dim[1].toInt();
+ w = dim[2].toInt();
+ h = dim[3].toInt();
+ } else if (Uml::tagEq(tag, "Presentation.style")) {
+ // TBD
+ } else if (Uml::tagEq(tag, "Presentation.model")) {
+ QDomNode mnode = e.firstChild();
+ QDomElement melem = mnode.toElement();
+ idStr = melem.attribute("xmi.idref", "");
+ } else {
+ kDebug() << "UMLView::uisLoadFromXMI: ignoring tag "
+ << tag << endl;
+ }
+ n = n.nextSibling();
+ e = n.toElement();
+ }
+ Uml::IDType id = STR2ID(idStr);
+ UMLObject *o = m_pDoc->findObjectById(id);
+ if (o == NULL) {
+ kError() << "UMLView::uisLoadFromXMI: Cannot find object for id "
+ << idStr << endl;
+ } else {
+ Uml::Object_Type ot = o->getBaseType();
+ kDebug() << "Create widget for model object of type " << ot << endl;
+ UMLWidget *widget = NULL;
+ switch (ot) {
+ case Uml::ot_Class:
+ widget = new ClassifierWidget(this, static_cast<UMLClassifier*>(o));
+ break;
+ case Uml::ot_Association:
+ {
+ UMLAssociation *umla = static_cast<UMLAssociation*>(o);
+ Uml::Association_Type at = umla->getAssocType();
+ UMLObject* objA = umla->getObject(Uml::A);
+ UMLObject* objB = umla->getObject(Uml::B);
+ if (objA == NULL || objB == NULL) {
+ kError() << "intern err 1" << endl;
+ return false;
+ }
+ UMLWidget *wA = findWidget(objA->getID());
+ UMLWidget *wB = findWidget(objB->getID());
+ if (wA != NULL && wB != NULL) {
+ AssociationWidget *aw =
+ new AssociationWidget(this, wA, at, wB, umla);
+ aw->syncToModel();
+ m_AssociationList.append(aw);
+ } else {
+ kError() << "cannot create assocwidget from ("
+ << wA << ", " << wB << ")" << endl;
+ }
+ break;
+ }
+ case Uml::ot_Role:
+ {
+ UMLRole *robj = static_cast<UMLRole*>(o);
+ 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:
+ kError() << "UMLView::uisLoadFromXMI: "
+ << "Cannot create widget of type "
+ << ot << endl;
+ }
+ if (widget) {
+ kDebug() << "Widget: x=" << x << ", y=" << y
+ << ", w=" << w << ", h=" << h << endl;
+ widget->setX(x);
+ widget->setY(y);
+ widget->setSize(w, h);
+ m_WidgetList.append(widget);
+ }
+ }
+ }
+ return true;
+}
+
+bool UMLView::loadUISDiagram(QDomElement & qElement) {
+ QString idStr = qElement.attribute( "xmi.id", "" );
+ if (idStr.isEmpty())
+ return false;
+ m_nID = STR2ID(idStr);
+ UMLListViewItem *ulvi = NULL;
+ for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ if (node.isComment())
+ continue;
+ QDomElement elem = node.toElement();
+ QString tag = elem.tagName();
+ if (tag == "uisDiagramName") {
+ setName( elem.text() );
+ if (ulvi)
+ ulvi->setText( getName() );
+ } else if (tag == "uisDiagramStyle") {
+ QString diagramStyle = elem.text();
+ if (diagramStyle != "ClassDiagram") {
+ kError() << "UMLView::uisLoadFromXMI: diagram style " << diagramStyle
+ << " is not yet implemented" << endl;
+ continue;
+ }
+ m_pDoc->setMainViewID(m_nID);
+ m_Type = Uml::dt_Class;
+ UMLListView *lv = UMLApp::app()->getListView();
+ ulvi = new UMLListViewItem( lv->theLogicalView(), getName(),
+ Uml::lvt_Class_Diagram, m_nID );
+ } else if (tag == "uisDiagramPresentation") {
+ loadUisDiagramPresentation(elem);
+ } else if (tag != "uisToolName") {
+ kDebug() << "UMLView::uisLoadFromXMI: ignoring tag " << tag << endl;
+ }
+ }
+ return true;
+}
+
+
+#include "umlview.moc"
diff --git a/umbrello/umbrello/umlview.h b/umbrello/umbrello/umlview.h
new file mode 100644
index 00000000..99a39198
--- /dev/null
+++ b/umbrello/umbrello/umlview.h
@@ -0,0 +1,1255 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEW_H
+#define UMLVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// system includes
+#include <kurl.h>
+#include <qdom.h>
+#include <qcanvas.h>
+
+//local includes
+#include "umlobjectlist.h"
+#include "umlwidgetlist.h"
+#include "associationwidgetlist.h"
+#include "messagewidgetlist.h"
+#include "optionstate.h"
+#include "worktoolbar.h"
+
+// forward declarations
+class ClassOptionsPage;
+class IDChangeLog;
+class ListPopupMenu;
+class FloatingTextWidget;
+class ObjectWidget;
+class UMLFolder;
+class UMLApp;
+class UMLDoc;
+class UMLAttribute;
+class UMLCanvasObject;
+class UMLClassifier;
+class UMLViewImageExporter;
+
+class KPrinter;
+class ToolBarState;
+class ToolBarStateFactory;
+
+/**
+ * UMLView instances represent diagrams.
+ * The UMLApp instance manages a QWidgetStack of UMLView instances.
+ * The visible diagram is at the top of stack.
+ * The UMLView class inherits from QCanvasView and it owns the
+ * objects displayed on its related QCanvas (see m_WidgetList.)
+ *
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLView : public QCanvasView {
+ Q_OBJECT
+public:
+ friend class UMLViewImageExporterModel;
+
+ /**
+ * Constructor
+ */
+ UMLView(UMLFolder *parentFolder);
+
+ /**
+ * Destructor
+ */
+ virtual ~UMLView();
+
+ // Accessors and other methods dealing with loaded/saved data
+
+ /**
+ * Return the UMLFolder in which this diagram lives.
+ */
+ UMLFolder *getFolder() {
+ return m_pFolder;
+ }
+
+ /**
+ * Set the UMLFolder in which this diagram lives.
+ */
+ void setFolder(UMLFolder *folder) {
+ m_pFolder = folder;
+ }
+
+ /**
+ * Return the documentation of the diagram.
+ */
+ QString getDoc() const {
+ return m_Documentation;
+ }
+
+ /**
+ * Set the documentation of the diagram.
+ */
+ void setDoc( const QString &doc ) {
+ m_Documentation = doc;
+ }
+
+ /**
+ * Return the name of the diagram.
+ */
+ QString getName() const;
+
+ /**
+ * Set the name of the diagram.
+ */
+ void setName(const QString &name);
+
+ /**
+ * Returns the type of the diagram.
+ */
+ Uml::Diagram_Type getType() const {
+ return m_Type;
+ }
+
+ /**
+ * Set the type of diagram.
+ */
+ void setType( Uml::Diagram_Type type ) {
+ m_Type = type;
+ }
+
+ /**
+ * Returns the fill color to use.
+ */
+ QColor getFillColor() const;
+
+ /**
+ * Set the background color.
+ *
+ * @param color The color to use.
+ */
+ void setFillColor( const QColor &color );
+
+ /**
+ * Returns the line color to use.
+ */
+ QColor getLineColor() const;
+
+ /**
+ * Sets the line color.
+ *
+ * @param color The color to use.
+ */
+ void setLineColor( const QColor &color );
+
+ /**
+ * Returns the line width to use.
+ */
+ uint getLineWidth() const;
+
+ /**
+ * Sets the line width.
+ *
+ * @param width The width to use.
+ */
+ void setLineWidth( uint width );
+
+ /**
+ * Returns the ID of the diagram.
+ */
+ Uml::IDType getID() const {
+ return m_nID;
+ }
+
+ /**
+ * Sets the ID of the diagram.
+ */
+ void setID( Uml::IDType id ) {
+ m_nID = id;
+ }
+
+ /**
+ * Returns the zoom of the diagram.
+ */
+ int getZoom() const {
+ return m_nZoom;
+ }
+
+ /**
+ * Sets the zoom of the diagram.
+ */
+ void setZoom(int zoom);
+
+ /**
+ * Returns the height of the diagram.
+ */
+ int getCanvasHeight() const {
+ return m_nCanvasHeight;
+ }
+
+ /**
+ * Sets the height of the diagram.
+ */
+ void setCanvasHeight(int height) {
+ m_nCanvasHeight = height;
+ }
+
+ /**
+ * Returns the width of the diagram.
+ */
+ int getCanvasWidth() const {
+ return m_nCanvasWidth;
+ }
+
+ /**
+ * Sets the height of the diagram.
+ */
+ void setCanvasWidth(int width) {
+ m_nCanvasWidth = width;
+ }
+
+ /**
+ * Return whether to use snap to grid.
+ */
+ bool getSnapToGrid() const {
+ return m_bUseSnapToGrid;
+ }
+
+ /**
+ * Sets whether to snap to grid.
+ */
+ void setSnapToGrid( bool bSnap );
+
+ /**
+ * Return whether to use snap to grid for component size.
+ */
+ bool getSnapComponentSizeToGrid() const {
+ return m_bUseSnapComponentSizeToGrid;
+ }
+
+ /**
+ * Returns the x grid size.
+ */
+ int getSnapX() const {
+ return m_nSnapX;
+ }
+
+ /**
+ * Returns the y grid size.
+ */
+ int getSnapY() const {
+ return m_nSnapY;
+ }
+
+ /**
+ * Returns the input coordinate with possible grid-snap applied.
+ */
+ int snappedX(int x);
+
+ /**
+ * Returns the input coordinate with possible grid-snap applied.
+ */
+ int snappedY(int y);
+
+ /**
+ * Returns whether to show snap grid or not.
+ */
+ bool getShowSnapGrid() const;
+
+ /**
+ * Sets whether to show snap grid.
+ */
+ void setShowSnapGrid( bool bShow );
+
+ /**
+ * Sets whether to snap to grid for component size.
+ */
+ void setSnapComponentSizeToGrid( bool bSnap );
+
+ /**
+ * Returns whether to use the fill/background color
+ */
+ bool getUseFillColor() const;
+
+ /**
+ * Sets whether to use the fill/background color
+ */
+ void setUseFillColor(bool ufc);
+
+ /**
+ * Returns the font to use
+ */
+ QFont getFont() const;
+
+ /**
+ * Sets the font for the view and optionally all the widgets on the view.
+ */
+ void setFont(QFont font, bool changeAllWidgets = false);
+
+ /**
+ * Returns whether to show operation signatures.
+ */
+ bool getShowOpSig() const;
+
+ /**
+ * Sets whether to show operation signatures.
+ */
+ void setShowOpSig(bool bShowOpSig);
+
+ /**
+ * Returns the options being used.
+ */
+ const Settings::OptionState& getOptionState() const {
+ return m_Options;
+ }
+
+ /**
+ * Sets the options to be used.
+ */
+ void setOptionState( const Settings::OptionState& options) {
+ m_Options = options;
+ }
+
+ /**
+ * Returns a reference to the association list.
+ */
+ AssociationWidgetList& getAssociationList() {
+ return m_AssociationList;
+ }
+
+ /**
+ * Returns a reference to the widget list.
+ */
+ UMLWidgetList& getWidgetList() {
+ return m_WidgetList;
+ }
+
+ /**
+ * Returns a reference to the message list.
+ */
+ MessageWidgetList& getMessageList() {
+ return m_MessageList;
+ }
+
+ // End of accessors and methods that only deal with loaded/saved data
+ ////////////////////////////////////////////////////////////////////////
+
+ /**
+ * return the current zoom factor
+ */
+ int currentZoom();
+
+ /**
+ * contains the implementation for printing functionality
+ */
+ void print(KPrinter *pPrinter, QPainter & pPainter);
+
+ /**
+ * Overrides the standard operation.
+ */
+ void hideEvent(QHideEvent *he);
+
+ /**
+ * Overrides the standard operation.
+ */
+ void showEvent(QShowEvent *se);
+
+ /**
+ * Sees if a message is relevant to the given widget. If it does delete it.
+ * @param w The widget to check messages against.
+ */
+ void checkMessages(ObjectWidget * w);
+
+ /**
+ * Finds a 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.
+ */
+ UMLWidget * findWidget(Uml::IDType id);
+
+ /**
+ * 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 * findAssocWidget(Uml::IDType id);
+
+ /**
+ * Finds an association widget with the given type and widgets.
+ *
+ * @param at The Association_Type 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 * findAssocWidget(Uml::Association_Type at,
+ UMLWidget *pWidgetA, UMLWidget *pWidgetB);
+
+ /**
+ * 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 * findAssocWidget(UMLWidget *pWidgetA,
+ UMLWidget *pWidgetB, const QString& roleNameB);
+
+ /**
+ * Remove a widget from view.
+ *
+ * @param o The widget to remove.
+ */
+ void removeWidget(UMLWidget * o);
+
+ /**
+ * Sets a widget to a selected state and adds it to a list of selected widgets.
+ *
+ * @param w The widget to set to selected.
+ * @param me The mouse event containing the information about the selection.
+ */
+ void setSelected(UMLWidget * w, QMouseEvent * me);
+
+ /**
+ * Clear the selected widgets list.
+ */
+ void clearSelected();
+
+ /**
+ * Move all the selected widgets by a relative X and Y offset.
+ *
+ * @param dX The distance to move horizontally.
+ * @param dY The distance to move vertically.
+ */
+ void moveSelectedBy(int dX, int dY);
+
+ /**
+ * 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 tr_Floating.)
+ * Default: Count all widgets.
+ * @return Number of widgets selected.
+ */
+ int getSelectCount(bool filterText = false) const;
+
+ /**
+ * Set the useFillColor variable to all selected widgets
+ *
+ * @param useFC The state to set the widget to.
+ */
+ void selectionUseFillColor(bool useFC);
+
+ /**
+ * Set the font for all the currently selected items.
+ */
+ void selectionSetFont( const QFont &font );
+
+ /**
+ * Set the line color for all the currently selected items.
+ */
+ void selectionSetLineColor( const QColor &color );
+
+ /**
+ * Set the line width for all the currently selected items.
+ */
+ void selectionSetLineWidth( uint width );
+
+ /**
+ * Set the fill color for all the currently selected items.
+ */
+ void selectionSetFillColor( const QColor &color );
+
+ /**
+ * Toggles the show setting sel of all selected items.
+ */
+ void selectionToggleShow(int sel);
+
+ /**
+ * Delete the selected widgets list and the widgets in it.
+ */
+ void deleteSelection();
+
+ /**
+ * Selects all widgets
+ */
+ void selectAll();
+
+ /**
+ * Return a unique ID for the diagram. Used by the @ref ObjectWidget class.
+ *
+ * @return Return a unique ID for the diagram.
+ */
+ Uml::IDType getLocalID();
+
+ /**
+ * Returns whether a widget is already on the diagram.
+ *
+ * @param id The id of the widget to check for.
+ *
+ * @return Returns true if the widget is already on the diagram, false if not.
+ */
+ bool widgetOnDiagram(Uml::IDType id);
+
+ /**
+ * Returns true if this diagram resides in an externalized folder.
+ * CHECK: It is probably cleaner to move this to the UMLListViewItem.
+ */
+ bool isSavedInSeparateFile();
+
+ /**
+ * Get the pos variable. Used internally to keep track of the cursor.
+ */
+ QPoint & getPos() {
+ return m_Pos;
+ }
+
+ /**
+ * Set the pos variable. Used internally to keep track of the cursor.
+ *
+ * @param _pos The position to set to.
+ */
+ void setPos(const QPoint &_pos) {
+ m_Pos = _pos;
+ }
+
+ /**
+ * Sets the popup menu to use when clicking on a diagram background
+ * (rather than a widget or listView).
+ */
+ void setMenu();
+
+ /**
+ * Reset the toolbar.
+ */
+ void resetToolbar() {
+ emit sigResetToolBar();
+ }
+
+ /**
+ * Returns the status on whether in a paste state.
+ *
+ * @return Returns the status on whether in a paste state.
+ */
+ bool getPaste() const {
+ return m_bPaste;
+ }
+
+ /**
+ * Sets the status on whether in a paste state.
+ */
+ void setPaste(bool paste) {
+ m_bPaste = paste;
+ }
+
+ /**
+ * Returns a List of all the UMLObjects(Use Cases, Concepts and Actors) in the View
+ */
+ UMLObjectList getUMLObjects();
+
+ /**
+ * Activate all the objects and associations after a load from the clipboard
+ */
+ void activate();
+
+ /**
+ * Returns a list with all the selected associations from the diagram
+ */
+ AssociationWidgetList getSelectedAssocs();
+
+ /**
+ * 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 WidgetList The UMLWidgetList to fill.
+ * @param filterText Don't append the text, unless their role is tr_Floating
+ */
+ bool getSelectedWidgets(UMLWidgetList& WidgetList, bool filterText = true);
+
+ /**
+ * Activate the view after a load a new file
+ */
+ void activateAfterLoad( bool bUseLog = false );
+
+ void endPartialWidgetPaste();
+ void beginPartialWidgetPaste();
+
+ /**
+ * Removes a AssociationWidget from a diagram
+ * Physically deletes the AssociationWidget passed in.
+ *
+ * @param pAssoc Pointer to the AssociationWidget.
+ */
+ void removeAssoc(AssociationWidget* pAssoc);
+
+ /**
+ * Removes all the associations related to Widget
+ *
+ * @param pWidget Pointer to the widget to remove.
+ */
+ void removeAssociations(UMLWidget* pWidget);
+
+ /**
+ * Sets each association as selected if the widgets it associates are selected
+ */
+ void selectAssociations(bool bSelect);
+
+ /**
+ * Fills Associations with all the associations that includes a widget related to object
+ */
+ void getWidgetAssocs(UMLObject* Obj, AssociationWidgetList & Associations);
+
+ /**
+ * Removes All the associations of the diagram
+ */
+ void removeAllAssociations();
+
+ /**
+ * Removes All the widgets of the diagram
+ */
+ void removeAllWidgets();
+
+ /**
+ * Calls the same method in the DocWindow.
+ */
+ void showDocumentation( UMLObject * object, bool overwrite );
+
+ /**
+ * Calls the same method in the DocWindow.
+ */
+ void showDocumentation( UMLWidget * widget, bool overwrite );
+
+ /**
+ * Calls the same method in the DocWindow.
+ */
+ void showDocumentation( AssociationWidget * widget, bool overwrite );
+
+ /**
+ * Calls the same method in the DocWindow.
+ */
+ void updateDocumentation( bool clear );
+
+ /**
+ * Returns the PNG picture of the paste operation.
+ *
+ * @param rect the area of the diagram to copy
+ * @param diagram the class to store PNG picture of the paste operation.
+ */
+ void getDiagram(const QRect &rect, QPixmap & diagram);
+
+ /**
+ * Paint diagram to the paint device
+ */
+ void getDiagram(const QRect &area, QPainter & painter);
+
+ /**
+ * Returns the PNG picture of the paste operation.
+ */
+ void copyAsImage(QPixmap*& pix);
+
+ /**
+ * Returns the imageExporter used to export the view.
+ *
+ * @return The imageExporter used to export the view.
+ */
+ UMLViewImageExporter* getImageExporter();
+
+ /**
+ * Adds an association to the view from the given data.
+ * Use this method when pasting.
+ */
+ bool addAssociation( AssociationWidget* pAssoc , bool isPasteOperation = false);
+
+ /**
+ * Removes an AssociationWidget from the association list
+ * and removes the corresponding UMLAssociation from the current UMLDoc.
+ */
+ void removeAssocInViewAndDoc(AssociationWidget* assoc);
+
+ /**
+ * Adds a widget to the view from the given data.
+ * Use this method when pasting.
+ */
+ bool addWidget( UMLWidget * pWidget , bool isPasteOperation = false);
+
+ /**
+ * 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.
+ */
+ QPoint getPastePoint();
+
+ /**
+ * Reset the paste point.
+ */
+ void resetPastePoint();
+
+ /**
+ * Called by the view or any of its children when they start a cut
+ * operation.
+ */
+ void setStartedCut() {
+ m_bStartedCut = true;
+ }
+
+ /**
+ * 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 createAutoAssociations( UMLWidget * widget );
+
+ /**
+ * If the m_Type of the given widget is Uml::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 createAutoAttributeAssociations(UMLWidget *widget);
+
+ /**
+ * 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 updateContainment(UMLCanvasObject *self);
+
+ /**
+ * Sets the x grid size.
+ */
+ void setSnapX( int x) {
+ m_nSnapX = x;
+ canvas() -> setAllChanged();
+ }
+
+ /**
+ * Sets the y grid size.
+ */
+ void setSnapY( int y) {
+ m_nSnapY = y;
+ canvas() -> setAllChanged();
+ }
+
+ /**
+ * Shows the properties dialog for the view.
+ */
+ bool showPropDialog();
+
+ /**
+ * Sets some options for all the @ref ClassifierWidget on the view.
+ */
+ void setClassWidgetOptions( ClassOptionsPage * page );
+
+ /**
+ * Call before copying/cutting selected widgets. This will make sure
+ * any associations/message selected will make sure both the widgets
+ * widgets they are connected to are selected.
+ */
+ void checkSelections();
+
+ /**
+ * This function checks if the currently selected items have all the same
+ * type (class, interface, ...). If true, the selection is unique and true
+ * will be returned.
+ * If there are no items selected, the function will return always true.
+ */
+ bool checkUniqueSelection();
+
+ /**
+ * Asks for confirmation and clears everything on the diagram.
+ * Called from menus.
+ */
+ void clearDiagram();
+
+ /**
+ * Changes snap to grid boolean.
+ * Called from menus.
+ */
+ void toggleSnapToGrid();
+
+ /**
+ * Changes snap to grid for component size boolean.
+ * Called from menus.
+ */
+ void toggleSnapComponentSizeToGrid();
+
+ /**
+ * Changes show grid boolean.
+ * Called from menus.
+ */
+ void toggleShowGrid();
+
+ /**
+ * Changes the zoom to the currently set level (now loaded from file)
+ * Called from UMLApp::slotUpdateViews()
+ */
+ void fileLoaded();
+
+ /**
+ * Sets the diagram width and height in pixels
+ */
+ void setCanvasSize(int width, int height);
+
+ /**
+ * Sets the size of the canvas to just fit on all the items
+ */
+ void resizeCanvasToItems();
+
+ /**
+ * The width and height of a diagram canvas in pixels.
+ */
+ static const int defaultCanvasSize;
+
+ // Load/Save interface:
+
+ /**
+ * Creates the "diagram" tag and fills it with the contents of the diagram.
+ */
+ virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ /**
+ * Loads the "diagram" tag.
+ */
+ virtual bool loadFromXMI( QDomElement & qElement );
+
+ /**
+ * Loads the "UISDiagram" tag of Unisys.IntegratePlus.2 generated files.
+ */
+ bool loadUISDiagram(QDomElement & qElement);
+
+ /**
+ * Loads a "widget" element from XMI, used by loadFromXMI() and the clipboard.
+ */
+ UMLWidget* loadWidgetFromXMI(QDomElement& widgetElement);
+
+ /**
+ * Add an object to the application, and update the view.
+ */
+ void addObject(UMLObject *object);
+
+ /**
+ * Selects all the widgets within an internally kept rectangle.
+ */
+ void selectWidgets(int px, int py, int qx, int qy);
+
+ /**
+ * Determine whether on a sequence diagram we have clicked on a line
+ * of an Object.
+ *
+ * @return The widget thats line was clicked on.
+ * Returns 0 if no line was clicked on.
+ */
+ ObjectWidget * onWidgetLine( const QPoint &point );
+
+ /**
+ * Return pointer to the first selected widget (for multi-selection)
+ */
+ UMLWidget* getFirstMultiSelectedWidget() {
+ return m_SelectedList.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.
+ * Does not use or modify the m_pOnWidget member.
+ */
+ UMLWidget *getWidgetAt(const QPoint& p);
+
+ /**
+ * Initialize and announce a newly created widget.
+ * Auxiliary to contentsMouseReleaseEvent().
+ */
+ void setupNewWidget(UMLWidget *w);
+
+ /**
+ * Return whether we are currently creating an object.
+ */
+ bool getCreateObject() const {
+ return m_bCreateObject;
+ }
+
+ /**
+ * Set whether we are currently creating an object.
+ */
+ void setCreateObject(bool bCreate) {
+ m_bCreateObject = bCreate;
+ }
+
+ /**
+ * Emit the sigRemovePopupMenu Qt signal.
+ */
+ void emitRemovePopupMenu() {
+ emit sigRemovePopupMenu();
+ }
+
+ /**
+ * Used for creating unique name of collaboration messages.
+ */
+ int generateCollaborationId();
+
+protected:
+
+ // Methods and members related to loading/saving
+
+ bool loadWidgetsFromXMI( QDomElement & qElement );
+
+ bool loadMessagesFromXMI( QDomElement & qElement );
+
+ bool loadAssociationsFromXMI( QDomElement & qElement );
+
+ bool loadUisDiagramPresentation(QDomElement & qElement);
+
+ /**
+ * Contains the unique ID to allocate to a widget that needs an
+ * ID for the view. @ref ObjectWidget is an example of this.
+ */
+ Uml::IDType m_nLocalID;
+
+ /**
+ * The ID of the view. Allocated by @ref UMLDoc
+ */
+ Uml::IDType m_nID;
+
+ /**
+ * The type of diagram to represent.
+ */
+ Uml::Diagram_Type m_Type;
+
+ /**
+ * The name of the diagram.
+ */
+ QString m_Name;
+
+ /**
+ * The documentation of the diagram.
+ */
+ QString m_Documentation;
+
+ /**
+ * Options used by view
+ */
+ Settings::OptionState m_Options;
+
+ /**
+ * Contains all the message widgets on the diagram.
+ */
+ MessageWidgetList m_MessageList;
+
+ /**
+ * Contains all the UMLWidgets on the diagram.
+ */
+ UMLWidgetList m_WidgetList;
+
+ /**
+ * Contains all the AssociationWidgets on the diagram.
+ */
+ AssociationWidgetList m_AssociationList;
+
+ /**
+ * The snap to grid x size.
+ */
+ int m_nSnapX;
+
+ /**
+ * The snap to grid y size.
+ */
+ int m_nSnapY;
+
+ /**
+ * Determines whether to use snap to grid. The default is off.
+ */
+ bool m_bUseSnapToGrid;
+
+ /**
+ * Determines whether to use snap to grid for component
+ * size. The default is off.
+ */
+ bool m_bUseSnapComponentSizeToGrid;
+
+ /**
+ * Determines whether to show the snap grid. The default will be on if the grid is on.
+ */
+ bool m_bShowSnapGrid;
+
+ /**
+ * The zoom level in percent, default 100
+ */
+ int m_nZoom;
+
+ /**
+ * Width of canvas in pixels
+ */
+ int m_nCanvasWidth;
+
+ /**
+ * Height of canvas in pixels
+ */
+ int m_nCanvasHeight;
+
+ // End of methods and members related to loading/saving
+ ////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Override standard method.
+ */
+ void closeEvent ( QCloseEvent * e );
+
+ /**
+ * Override standard method.
+ */
+ void contentsDragEnterEvent(QDragEnterEvent* mouseEvent);
+
+ /**
+ * Override standard method.
+ */
+ void contentsDropEvent(QDropEvent* mouseEvent);
+
+
+ /**
+ * Gets the smallest area to print.
+ *
+ * @return Returns the smallest area to print.
+ */
+ QRect getDiagramRect();
+
+
+ /**
+ * Initializes key variables.
+ */
+ void init();
+
+ /**
+ * Overrides the standard operation.
+ * Calls the same method in the current tool bar state.
+ */
+ void contentsMouseReleaseEvent(QMouseEvent* mouseEvent);
+
+ /**
+ * Overrides the standard operation.
+ * Calls the same method in the current tool bar state.
+ */
+ void contentsMouseMoveEvent(QMouseEvent* mouseEvent);
+
+ /**
+ * Override standard method.
+ * Calls the same method in the current tool bar state.
+ */
+ void contentsMouseDoubleClickEvent(QMouseEvent* mouseEvent);
+
+ /**
+ * Override standard method.
+ * Calls the same method in the current tool bar state.
+ */
+ void contentsMousePressEvent(QMouseEvent* mouseEvent);
+
+
+ /**
+ * Selects all the widgets of the given association widget.
+ */
+ void selectWidgetsOfAssoc (AssociationWidget * a);
+
+ /**
+ * Calls setSelected on the given UMLWidget and enters
+ * it into the m_SelectedList while making sure it is
+ * there only once.
+ */
+ void makeSelected (UMLWidget * uw);
+
+ /**
+ * Updates the size of all components in this view.
+ */
+ void updateComponentSizes();
+
+ /**
+ * 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 findMaxBoundingRectangle(const FloatingTextWidget* ft,
+ int& px, int& py, int& qx, int& qy);
+
+ void forceUpdateWidgetFontMetrics(QPainter *painter);
+
+ /**
+ * Used for creating unique name of collaboration messages.
+ */
+ int m_nCollaborationId;
+
+ QPoint m_Pos;
+ bool m_bCreateObject, m_bDrawSelectedOnly, m_bPaste;
+ ListPopupMenu * m_pMenu;
+ UMLWidgetList m_SelectedList;
+
+ /**
+ * Flag if view/children started cut operation.
+ */
+ bool m_bStartedCut;
+
+private:
+ /**
+ * The folder in which this UMLView is contained
+ */
+ UMLFolder *m_pFolder;
+
+ /**
+ * set to true when a child has used the showDocumentation method,
+ * thus when one clicks on a child widget.
+ * Reset to false when clicking in an empty region of the view.
+ */
+ bool m_bChildDisplayedDoc;
+
+ ToolBarStateFactory* m_pToolBarStateFactory;
+ ToolBarState* m_pToolBarState;
+
+ /**
+ * LocalID Changes Log for paste actions
+ */
+ IDChangeLog * m_pIDChangesLog;
+
+ /**
+ *
+ * True if the view was activated after the serialization(load)
+ */
+ bool m_bActivated;
+
+ /**
+ * Status of a popupmenu on view.
+ * true - a popup is on view
+ */
+ bool m_bPopupShowing;
+
+ /**
+ * The offset at which to paste the clipboard.
+ */
+ QPoint m_PastePoint;
+
+ /**
+ * Pointer to the UMLDoc
+ */
+ UMLDoc* m_pDoc;
+
+ /**
+ * The UMLViewImageExporter used to export the view.
+ */
+ UMLViewImageExporter* m_pImageExporter;
+
+ /**
+ * Create an association with the attribute attr associated with the UMLWidget
+ * widget if the UMLClassifier type is present on the current diagram.
+ */
+ void createAutoAttributeAssociation(UMLClassifier *type,
+ UMLAttribute *attr,
+ UMLWidget *widget);
+
+public slots:
+
+ void zoomIn();
+ void zoomOut();
+
+ /**
+ * Changes the current tool to the selected tool.
+ * The current tool is cleaned and the selected tool initialized.
+ */
+ void slotToolBarChanged(int c);
+ void slotObjectCreated(UMLObject * o);
+ void slotObjectRemoved(UMLObject * o);
+
+ /**
+ * When a menu selection has been made on the menu
+ * that this view created, this method gets called.
+ */
+ void slotMenuSelection(int sel);
+
+ /**
+ * This slot is entered when an event has occurred on the views display,
+ * most likely a mouse event. Before it sends out that mouse event everyone
+ * that displays a menu on the views surface (widgets and this ) thould remove any
+ * menu. This stops more then one menu bieing displayed.
+ */
+ void slotRemovePopupMenu();
+
+ /**
+ * makes this view the active view by asking the document to show us
+ */
+ void slotActivate();
+
+ /**
+ * 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 slotCutSuccessful();
+
+ /**
+ * Called by menu when to show the instance of the view.
+ */
+ void slotShowView();
+
+ /**
+ * Overrides standard method from QWidget to resize canvas when
+ * it's shown.
+ */
+ void show();
+
+signals:
+ void sigResetToolBar();
+ void sigColorChanged( Uml::IDType );
+ void sigRemovePopupMenu();
+ void sigClearAllSelected();
+ void sigLineWidthChanged( Uml::IDType );
+ void sigSnapToGridToggled(bool);
+ void sigSnapComponentSizeToGridToggled(bool);
+ void sigShowGridToggled(bool);
+
+ /**
+ * Emitted when an association is removed.
+ */
+ void sigAssociationRemoved(AssociationWidget*);
+
+ /**
+ * Emitted when a widget is removed.
+ */
+ void sigWidgetRemoved(UMLWidget*);
+};
+
+#endif // UMLVIEW_H
diff --git a/umbrello/umbrello/umlviewcanvas.cpp b/umbrello/umbrello/umlviewcanvas.cpp
new file mode 100644
index 00000000..15de4169
--- /dev/null
+++ b/umbrello/umbrello/umlviewcanvas.cpp
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlviewcanvas.h"
+
+// qt/kde includes
+#include <qpainter.h>
+
+// app includes
+#include "umlview.h"
+
+
+UMLViewCanvas::UMLViewCanvas( UMLView * pView ) : QCanvas( pView ) {
+ m_pView = pView;
+}
+
+UMLViewCanvas::~UMLViewCanvas() {}
+
+void UMLViewCanvas::drawBackground( QPainter & painter, const QRect & clip ) {
+ QCanvas::drawBackground( painter, clip );
+ if( m_pView -> getShowSnapGrid() ) {
+ painter.setPen( Qt::gray );
+ int gridX = m_pView -> getSnapX();
+ int gridY = m_pView -> getSnapY();
+ int numX = width() / gridX;
+ int numY = height() / gridY;
+ for( int x = 0; x <= numX; x++ )
+ for( int y = 0; y < numY; y++ )
+ painter.drawPoint( x * gridX, y * gridY );
+ }
+}
+
diff --git a/umbrello/umbrello/umlviewcanvas.h b/umbrello/umbrello/umlviewcanvas.h
new file mode 100644
index 00000000..78d7d4dd
--- /dev/null
+++ b/umbrello/umbrello/umlviewcanvas.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEWCANVAS_H
+#define UMLVIEWCANVAS_H
+
+#include <qcanvas.h>
+
+/**
+ *@author Paul Hensgen
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLView;
+
+class UMLViewCanvas : public QCanvas {
+public:
+ /**
+ * Constructor
+ */
+ UMLViewCanvas( UMLView * pView );
+
+ /**
+ * Deconstructor
+ */
+ virtual ~UMLViewCanvas();
+
+protected:
+
+ /**
+ * Overrides default method.
+ */
+ virtual void drawBackground( QPainter & painter, const QRect & clip );
+
+ /**
+ * The view the canvas is associated with.
+ */
+ UMLView * m_pView;
+};
+
+#endif
diff --git a/umbrello/umbrello/umlviewimageexporter.cpp b/umbrello/umbrello/umlviewimageexporter.cpp
new file mode 100644
index 00000000..251d0ffb
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexporter.cpp
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlviewimageexporter.h"
+
+// include files for Qt
+#include <qstring.h>
+#include <qstringlist.h>
+
+//kde include files
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+// application specific includes
+#include "umlviewimageexportermodel.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+
+
+UMLViewImageExporter::UMLViewImageExporter(UMLView* view) {
+ m_view = view;
+ m_imageMimeType = UMLApp::app()->getImageMimeType();
+}
+
+void UMLViewImageExporter::exportView() {
+ if (!prepareExportView()) {
+ return;
+ }
+
+ UMLApp *app = UMLApp::app();
+
+ // export the view
+ app->getDocument()->writeToStatusBar(i18n("Exporting view..."));
+ QString error = UMLViewImageExporterModel().exportView(m_view,
+ UMLViewImageExporterModel::mimeTypeToImageType(m_imageMimeType), m_imageURL);
+ if (!error.isNull()) {
+ KMessageBox::error(app, i18n("An error happened when exporting the image:\n") + error);
+ }
+ app->getDocument()->writeToStatusBar(i18n("Ready."));
+}
+
+bool UMLViewImageExporter::prepareExportView() {
+ bool exportPrepared = false;
+
+ do {
+ if (!getParametersFromUser()) {
+ return false;
+ }
+
+ // check if the file exists
+ if (KIO::NetAccess::exists(m_imageURL, true, UMLApp::app())) {
+ int wantSave = KMessageBox::warningContinueCancel(0,
+ i18n("The selected file %1 exists.\nDo you want to overwrite it?").arg(m_imageURL.prettyURL()),
+ i18n("File Already Exists"), i18n("&Overwrite"));
+ if (wantSave == KMessageBox::Continue) {
+ exportPrepared = true;
+ }
+ } else {
+ exportPrepared = true;
+ }
+ } while (!exportPrepared);
+
+ return true;
+}
+
+bool UMLViewImageExporter::getParametersFromUser() {
+ UMLApp *app = UMLApp::app();
+
+ // configure & show the file dialog
+ KFileDialog fileDialog(QString::null, QString::null, m_view,
+ ":export-image", true);
+ prepareFileDialog(fileDialog);
+ fileDialog.exec();
+
+ if (fileDialog.selectedURL().isEmpty())
+ return false;
+ m_view->clearSelected(); // Thanks to Peter Soetens for the idea
+
+ // update image url and mime type
+ m_imageMimeType = fileDialog.currentMimeFilter();
+ app->setImageMimeType(m_imageMimeType);
+ m_imageURL = fileDialog.selectedURL();
+
+ // check if the extension is the extension of the mime type
+ QFileInfo info(m_imageURL.filename());
+ QString ext = info.extension(false);
+ QString extDef = UMLViewImageExporterModel::mimeTypeToImageType(m_imageMimeType);
+ if(ext != extDef) {
+ m_imageURL.setFileName(m_imageURL.fileName() + '.' + extDef);
+ }
+
+ return true;
+}
+
+void UMLViewImageExporter::prepareFileDialog(KFileDialog &fileDialog) {
+ // get all supported mime types
+ QStringList mimeTypes = UMLViewImageExporterModel::supportedMimeTypes();
+
+ fileDialog.setCaption(i18n("Save As"));
+ fileDialog.setOperationMode(KFileDialog::Saving);
+ fileDialog.setMimeFilter(mimeTypes, m_imageMimeType);
+
+ // set a sensible default filename
+ if (m_imageURL.isEmpty()) {
+ KURL docURL = UMLApp::app()->getDocument()->URL();
+ KURL directory = docURL;
+ directory.setPath(docURL.directory());
+
+ fileDialog.setURL(directory);
+ fileDialog.setSelection(m_view->getName() + '.' + UMLViewImageExporterModel::mimeTypeToImageType(m_imageMimeType));
+ } else {
+ fileDialog.setURL(m_imageURL);
+ fileDialog.setSelection(m_imageURL.fileName());
+ }
+}
diff --git a/umbrello/umbrello/umlviewimageexporter.h b/umbrello/umbrello/umlviewimageexporter.h
new file mode 100644
index 00000000..2400213b
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexporter.h
@@ -0,0 +1,122 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEWIMAGEEXPORTER_H
+#define UMLVIEWIMAGEEXPORTER_H
+
+#include <qstring.h>
+#include <kurl.h>
+
+class UMLView;
+class KFileDialog;
+
+/**
+ * Exports the view as an image.
+ * This class takes care of asking the user the needed parameters and
+ * then exports the view.
+ */
+class UMLViewImageExporter {
+public:
+
+ /**
+ * Constructor for UMLViewImageExporter
+ */
+ UMLViewImageExporter(UMLView* view);
+
+ /**
+ * Destructor for UMLViewImageExporter
+ */
+ virtual ~UMLViewImageExporter() {
+ }
+
+ /**
+ * Shows a save dialog to the user to get the needed parameters and then exports
+ * the view.
+ * If the selected file already exists, an overwrite confirmation
+ * dialog is shown. If the user doesn't want to overwrite the file,
+ * the save dialog is shown again.
+ * The dialog remembers values between calls (in the same application instance,
+ * although it's not persistent between Umbrello executions).
+ *
+ * The status bar shows an information message until the export finishes.
+ *
+ * If something went wrong while exporting, an error dialog is shown to the
+ * user with the error message explaining the problem that happened.
+ */
+ void exportView();
+
+ /**
+ * Returns the URL used to save the image.
+ *
+ * @return The URL used to save the image.
+ */
+ KURL getImageURL() const {
+ return m_imageURL;
+ }
+
+ /**
+ * Returns the mime type used to save the image.
+ *
+ * @return The mime type used to save the image.
+ */
+ QString getImageMimeType() const {
+ return m_imageMimeType;
+ }
+
+private:
+
+ /**
+ * The view to export.
+ */
+ UMLView* m_view;
+
+ /**
+ * The URL used to save the image.
+ */
+ KURL m_imageURL;
+
+ /**
+ * The mime type used to save the image.
+ */
+ QString m_imageMimeType;
+
+ /**
+ * Shows a save file dialog to the user to get the parameters used
+ * to export the view.
+ * If the selected file already exists, an overwrite confirmation
+ * dialog is shown. If the user doesn't want to overwrite the file,
+ * the save dialog is shown again.
+ *
+ * @return True if the user wants to save the image,
+ * false if the operation is cancelled.
+ */
+ bool prepareExportView();
+
+ /**
+ * Shows a save file dialog to the user to get the parameters used
+ * to export the view and updates the attributes with the parameters got.
+ *
+ * @return True if the user wants to save the image,
+ * false if the operation is cancelled.
+ */
+ bool getParametersFromUser();
+
+ /**
+ * Prepares the save file dialog.
+ * Sets the mime type filter, sensible default values...
+ *
+ * @param fileDialog The dialog to prepare.
+ */
+ void prepareFileDialog(KFileDialog &fileDialog);
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umlviewimageexporterall.cpp b/umbrello/umbrello/umlviewimageexporterall.cpp
new file mode 100644
index 00000000..fceb6aa3
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexporterall.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlviewimageexporterall.h"
+
+// include files for Qt
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qcheckbox.h>
+
+// kde include files
+#include <klocale.h>
+#include <kurl.h>
+#include <kurlrequester.h>
+#include <kfilefiltercombo.h>
+#include <kmessagebox.h>
+
+// application specific includes
+#include "dialogs/exportallviewsdialog.h"
+#include "umlviewimageexportermodel.h"
+#include "uml.h"
+#include "umldoc.h"
+
+UMLViewImageExporterAll::UMLViewImageExporterAll() {
+ m_dialog = new ExportAllViewsDialog(0, "exportAllViewsDialog", false, 0, UMLApp::app()->getImageMimeType());
+}
+
+UMLViewImageExporterAll::~UMLViewImageExporterAll() {
+ delete m_dialog;
+}
+
+void UMLViewImageExporterAll::exportAllViews() {
+ UMLApp* app = UMLApp::app();
+ UMLDoc* umlDoc = app->getDocument();
+
+ // default url can't be set when creating the action because the
+ // document wasn't loaded
+ if (m_dialog->m_kURL->url().isEmpty()) {
+ m_dialog->m_kURL->setURL(umlDoc->URL().directory());
+ }
+
+ if (m_dialog->exec() == QDialog::Rejected) {
+ return;
+ }
+
+ app->setImageMimeType(m_dialog->m_imageType->currentFilter());
+
+ // export all views
+ umlDoc->writeToStatusBar(i18n("Exporting all views..."));
+ QStringList errors = UMLViewImageExporterModel().exportAllViews(
+ UMLViewImageExporterModel::mimeTypeToImageType(m_dialog->m_imageType->currentFilter()),
+ KURL(m_dialog->m_kURL->url()), m_dialog->m_useFolders->isChecked());
+ if (!errors.empty()) {
+#if KDE_IS_VERSION(3,4,0)
+ KMessageBox::errorList(app, i18n("Some errors happened when exporting the images:"), errors);
+#else
+ QString errorsCaption;
+ for (QStringList::Iterator it = errors.begin(); it != errors.end(); ++it) {
+ errorsCaption += "\n" + *it;
+ }
+ KMessageBox::error(app, i18n("Some errors happened when exporting the images:") + errorsCaption);
+#endif
+ }
+ umlDoc->writeToStatusBar(i18n("Ready."));
+}
diff --git a/umbrello/umbrello/umlviewimageexporterall.h b/umbrello/umbrello/umlviewimageexporterall.h
new file mode 100644
index 00000000..d2368921
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexporterall.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEWIMAGEEXPORTERALL_H
+#define UMLVIEWIMAGEEXPORTERALL_H
+
+class ExportAllViewsDialog;
+
+/**
+ * Exports all the views in the UML document as images.
+ * This class takes care of asking the user the needed parameters and
+ * then exports the views using UMLViewImageExporterModel.
+ */
+class UMLViewImageExporterAll {
+public:
+
+ /**
+ * Constructor for UMLViewImageExporterAll
+ */
+ UMLViewImageExporterAll();
+
+ /**
+ * Destructor for UMLViewImageExporterAll
+ */
+ virtual ~UMLViewImageExporterAll();
+
+ /**
+ * Shows a dialog to the user to get the needed parameters and then exports
+ * the views.
+ * The dialog remembers values between calls (in the same application instance,
+ * although it's not persistent between Umbrello executions).
+ *
+ * Once the export begins, it can't be stopped until it ends itself. The status
+ * bar shows an information message until the export finishes.
+ *
+ * If something went wrong while exporting, an error dialog is shown to the
+ * user with the error messages explaining the problems occurred.
+ */
+ void exportAllViews();
+
+private:
+
+ /**
+ * The dialog to get the needed parameters from the user.
+ */
+ ExportAllViewsDialog* m_dialog;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umlviewimageexportermodel.cpp b/umbrello/umbrello/umlviewimageexportermodel.cpp
new file mode 100644
index 00000000..e829a3f7
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexportermodel.cpp
@@ -0,0 +1,366 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlviewimageexportermodel.h"
+
+// system includes
+#include <math.h>
+
+// include files for Qt
+#include <qstringlist.h>
+#include <qrect.h>
+#include <qimage.h>
+#include <qpicture.h>
+#include <qpainter.h>
+#include <qprinter.h>
+#include <qdir.h>
+#include <qregexp.h>
+
+// kde include files
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kapplication.h>
+#include <kio/netaccess.h>
+
+// application specific includes
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+
+static QStringList supportedImageTypesList;
+static QStringList supportedMimeTypesList;
+
+QStringList UMLViewImageExporterModel::supportedImageTypes() {
+ if (!supportedImageTypesList.size()) {
+ // specific supported formats
+ supportedImageTypesList << "eps";
+ supportedImageTypesList << "svg";
+
+ // QT supported formats
+ QStrList qImageFormats = QImage::outputFormats();
+ for (const char* format = qImageFormats.first(); format; format = qImageFormats.next()) {
+ supportedImageTypesList << QString(format).lower();
+ }
+ }
+
+ return supportedImageTypesList;
+}
+
+QStringList UMLViewImageExporterModel::supportedMimeTypes() {
+ if (!supportedMimeTypesList.size()) {
+ QStringList imageTypes = UMLViewImageExporterModel::supportedImageTypes();
+ for(QStringList::Iterator it = imageTypes.begin(); it != imageTypes.end(); ++it ) {
+ QString mimeType = imageTypeToMimeType(*it);
+ if (!mimeType.isNull())
+ supportedMimeTypesList.append(mimeType);
+ }
+ }
+
+ return supportedMimeTypesList;
+}
+
+QString UMLViewImageExporterModel::imageTypeToMimeType(const QString& imageType) {
+ const QString imgType = imageType.lower();
+ if (QString("bmp") == imgType) return "image/x-bmp";
+ if (QString("jpeg") == imgType) return "image/jpeg";
+ if (QString("pbm") == imgType) return "image/x-portable-bitmap";
+ if (QString("pgm") == imgType) return "image/x-portable-greymap";
+ if (QString("png") == imgType) return "image/png";
+ if (QString("ppm") == imgType) return "image/x-portable-pixmap";
+ if (QString("xbm") == imgType) return "image/x-xbm";
+ if (QString("xpm") == imgType) return "image/x-xpm";
+ if (QString("eps") == imgType) return "image/x-eps";
+ if (QString("svg") == imgType) return "image/svg+xml";
+ return QString::null;
+}
+
+QString UMLViewImageExporterModel::mimeTypeToImageType(const QString& mimeType) {
+ if (QString("image/x-bmp") == mimeType) return "bmp";
+ if (QString("image/jpeg") == mimeType) return "jpeg";
+ if (QString("image/x-portable-bitmap") == mimeType) return "pbm";
+ if (QString("image/x-portable-greymap") == mimeType) return "pgm";
+ if (QString("image/png") == mimeType) return "png";
+ if (QString("image/x-portable-pixmap") == mimeType) return "ppm";
+ if (QString("image/x-xbm") == mimeType) return "xbm";
+ if (QString("image/x-xpm") == mimeType) return "xpm";
+ if (QString("image/x-eps") == mimeType) return "eps";
+ if (QString("image/svg+xml") == mimeType) return "svg";
+ return QString::null;
+}
+
+QStringList UMLViewImageExporterModel::exportAllViews(const QString &imageType, const KURL &directory, bool useFolders) const {
+ UMLApp *app = UMLApp::app();
+
+ // contains all the error messages returned by exportView calls
+ QStringList errors;
+
+ UMLViewList views = app->getDocument()->getViewIterator();
+ for(UMLView *view = views.first(); view; view = views.next()) {
+ KURL url = directory;
+ url.addPath(getDiagramFileName(view, imageType, useFolders));
+
+ QString returnString = exportView(view, imageType, url);
+ if (!returnString.isNull()) {
+ errors.append(view->getName() + ": " + returnString);
+ }
+ }
+
+ return errors;
+}
+
+QString UMLViewImageExporterModel::exportView(UMLView* view, const QString &imageType, const KURL &url) const {
+ // create the needed directories
+ if (!prepareDirectory(url)) {
+ return i18n("Can not create directory: %1").arg(url.directory());
+ }
+
+ // The fileName will be used when exporting the image. If the url isn't local,
+ // the fileName is the name of a temporal local file to export the image to, and then
+ // upload it to its destiny
+ QString fileName;
+ // tmpFile needs to be unlinked before exiting the method!!!
+ KTempFile tmpFile;
+ if (url.isLocalFile()) {
+ fileName = url.path();
+ } else {
+ fileName = tmpFile.name();
+ }
+
+ // check that the diagram isn't empty
+ QRect rect = view->getDiagramRect();
+ if (rect.isEmpty()) {
+ tmpFile.unlink();
+ return i18n("Can not save an empty diagram");
+ }
+
+ // exporting the view to the file
+ if (!exportViewTo(view, imageType, fileName)) {
+ tmpFile.unlink();
+ return i18n("A problem occured while saving diagram in %1").arg(fileName);
+ }
+
+ // if the file wasn't local, upload the temp file to the target
+ if (!url.isLocalFile()) {
+ if (!KIO::NetAccess::upload(tmpFile.name(), url, UMLApp::app())) {
+ tmpFile.unlink();
+ return i18n("There was a problem saving file: %1").arg(url.path());
+ }
+ } //!isLocalFile
+
+ tmpFile.unlink();
+ return QString::null;
+}
+
+QString UMLViewImageExporterModel::getDiagramFileName(UMLView *view, const QString &imageType, bool useFolders /* = false */) const {
+ QString name = view->getName() + '.' + imageType.lower();
+
+ if (!useFolders) {
+ return name;
+ }
+
+ kapp->processEvents();
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem* listViewItem = listView->findItem(view->getID());
+ // skip the name of the first item because it's the View
+ listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
+
+ // Relies on the tree structure of the UMLListView. There are a base "Views" folder
+ // and five children, one for each view type (Logical, use case, components, deployment
+ // and entity relationship)
+ while (listView->rootView(listViewItem->getType()) == NULL) {
+ name.insert(0, listViewItem->getText() + '/');
+ listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
+ if (listViewItem == NULL)
+ break;
+ }
+ return name;
+}
+
+bool UMLViewImageExporterModel::prepareDirectory(const KURL &url) const {
+ // the KURL is copied to get protocol, user and so on and then the path is cleaned
+ KURL directory = url;
+ directory.setPath("");
+
+ // creates the directory and any needed parent directories
+ QStringList dirs = QStringList::split(QDir::separator(), url.directory());
+ for (QStringList::ConstIterator it = dirs.begin() ; it != dirs.end(); ++it ) {
+ directory.addPath(*it);
+
+ if (!KIO::NetAccess::exists(directory, true, UMLApp::app())) {
+
+ if (!KIO::NetAccess::mkdir(directory, UMLApp::app())) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool UMLViewImageExporterModel::exportViewTo(UMLView* view, const QString &imageType, const QString &fileName) const {
+ // remove 'blue squares' from exported picture.
+ view->clearSelected();
+
+ QString imageMimeType = UMLViewImageExporterModel::imageTypeToMimeType(imageType);
+ if (imageMimeType == "image/x-eps") {
+ if (!exportViewToEps(view, fileName, true)) {
+ return false;
+ }
+ } else if (imageMimeType == "image/svg+xml") {
+ if (!exportViewToSvg(view, fileName)) {
+ return false;
+ }
+ } else {
+ if (!exportViewToPixmap(view, imageType, fileName)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool UMLViewImageExporterModel::exportViewToEps(UMLView* view, const QString &fileName, bool isEPS) const {
+ bool exportSuccessful = true;
+
+ // print the image to a normal postscript file,
+ // do not clip so that everything ends up in the file
+ // regardless of "paper size"
+
+ // because we want to work with postscript
+ // user-coordinates, set to the resolution
+ // of the printer (which should be 72dpi here)
+ QPrinter *printer;
+
+ if (isEPS == false) {
+ printer = new QPrinter(QPrinter::PrinterResolution);
+ } else {
+ printer = new QPrinter(QPrinter::ScreenResolution);
+ }
+ printer->setOutputToFile(true);
+ printer->setOutputFileName(fileName);
+ printer->setColorMode(QPrinter::Color);
+
+ // do not call printer.setup(); because we want no user
+ // interaction here
+ QPainter *painter = new QPainter(printer);
+
+ // make sure the widget sizes will be according to the
+ // actually used printer font, important for getDiagramRect()
+ // and the actual painting
+ view->forceUpdateWidgetFontMetrics(painter);
+
+ QRect rect = view->getDiagramRect();
+ painter->translate(-rect.x(),-rect.y());
+ view->getDiagram(rect,*painter);
+
+ int resolution = printer->resolution();
+
+ // delete painter and printer before we try to open and fix the file
+ delete painter;
+ delete printer;
+ if (isEPS) {
+ // modify bounding box from screen to eps resolution.
+ rect.setWidth( int(ceil(rect.width() * 72.0/resolution)) );
+ rect.setHeight( int(ceil(rect.height() * 72.0/resolution)) );
+ exportSuccessful = fixEPS(fileName,rect);
+ }
+ // next painting will most probably be to a different device (i.e. the screen)
+ view->forceUpdateWidgetFontMetrics(0);
+
+ return exportSuccessful;
+}
+
+bool UMLViewImageExporterModel::fixEPS(const QString &fileName, const QRect& rect) const {
+ // now open the file and make a correct eps out of it
+ QFile epsfile(fileName);
+ if (! epsfile.open(IO_ReadOnly)) {
+ return false;
+ }
+ // read
+ QTextStream ts(&epsfile);
+ QString fileContent = ts.read();
+ epsfile.close();
+
+ // read information
+ QRegExp rx("%%BoundingBox:\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)");
+ const int pos = rx.search(fileContent);
+ if (pos < 0) {
+ kError() << "UMLViewImageExporterModel::fixEPS(" << fileName
+ << "): cannot find %%BoundingBox" << endl;
+ return false;
+ }
+
+ // write new content to file
+ if (! epsfile.open(IO_WriteOnly | IO_Truncate)) {
+ kError() << "UMLViewImageExporterModel::fixEPS(" << fileName
+ << "): cannot open file for writing" << endl;
+ return false;
+ }
+
+ // be careful when rounding (ceil/floor) the BB, these roundings
+ // were mainly obtained experimentally...
+ const double epsleft = rx.cap(1).toFloat();
+ const double epstop = rx.cap(4).toFloat();
+ const int left = int(floor(epsleft));
+ const int right = int(ceil(epsleft)) + rect.width();
+ const int top = int(ceil(epstop)) + 1;
+ const int bottom = int(floor(epstop)) - rect.height() + 1;
+
+ // modify content
+ fileContent.replace(pos,rx.cap(0).length(),
+ QString("%%BoundingBox: %1 %2 %3 %4").arg(left).arg(bottom).arg(right).arg(top));
+
+ ts << fileContent;
+ epsfile.close();
+
+ return true;
+}
+
+bool UMLViewImageExporterModel::exportViewToSvg(UMLView* view, const QString &fileName) const {
+ bool exportSuccesful;
+
+ QPicture* diagram = new QPicture();
+
+ // do not call printer.setup(); because we want no user
+ // interaction here
+ QPainter* painter = new QPainter();
+ painter->begin( diagram );
+
+ // make sure the widget sizes will be according to the
+ // actually used printer font, important for getDiagramRect()
+ // and the actual painting
+ view->forceUpdateWidgetFontMetrics(painter);
+
+ QRect rect = view->getDiagramRect();
+ painter->translate(-rect.x(),-rect.y());
+ view->getDiagram(rect,*painter);
+ painter->end();
+ exportSuccesful = diagram->save(fileName, QString("SVG").ascii());
+
+ // delete painter and printer before we try to open and fix the file
+ delete painter;
+ delete diagram;
+ // next painting will most probably be to a different device (i.e. the screen)
+ view->forceUpdateWidgetFontMetrics(0);
+
+ return exportSuccesful;
+}
+
+bool UMLViewImageExporterModel::exportViewToPixmap(UMLView* view, const QString &imageType, const QString &fileName) const {
+ QRect rect = view->getDiagramRect();
+ QPixmap diagram(rect.width(), rect.height());
+ view->getDiagram(rect, diagram);
+ return diagram.save(fileName, imageType.upper().ascii());
+}
diff --git a/umbrello/umbrello/umlviewimageexportermodel.h b/umbrello/umbrello/umlviewimageexportermodel.h
new file mode 100644
index 00000000..d69796ac
--- /dev/null
+++ b/umbrello/umbrello/umlviewimageexportermodel.h
@@ -0,0 +1,214 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLVIEWIMAGEEXPORTERMODEL_H
+#define UMLVIEWIMAGEEXPORTERMODEL_H
+
+#include <qstringlist.h>
+#include <qrect.h>
+
+// forward declarations
+class UMLView;
+
+// KDE forward declarations
+class KTempFile;
+class KURL;
+
+/**
+ * Exports an UMLView in various image formats.
+ * It can also export all the views in the current document.
+ *
+ * The methods in this class don't communicate with the user, so asking the format
+ * to save the images in, checking if the target file exists and so on must be done before
+ * calling those methods, if needed.
+ * The only exception is asking passwords for example when KIO slaves are used, as this
+ * operation is made automatically by the KIO classes.
+ */
+class UMLViewImageExporterModel {
+public:
+
+ /**
+ * Returns a QStringList containing all the supported image types to use when exporting.
+ * All the types will be lower case.
+ *
+ * @return A QStringList containing all the supported image types to use when exporting.
+ */
+ static QStringList supportedImageTypes();
+
+ /**
+ * Returns a QStringList containing all the supported mime types to use when exporting.
+ * All the types will be lower case.
+ *
+ * @return A QStringList containing all the supported mime types to use when exporting.
+ */
+ static QStringList supportedMimeTypes();
+
+ /**
+ * Returns the mime type for an image type.
+ * The supported image types are those that the diagrams can be exported to.
+ *
+ * @param imageType The type of the image.
+ * @return A QString with the equivalent mime type, or QString::null if
+ * it's unknown.
+ */
+ static QString imageTypeToMimeType(const QString& imageType);
+
+ /**
+ * Returns the image type for a mime type.
+ * The supported image types are those that the diagrams can be exported to.
+ *
+ * @param mimeType The mime type.
+ * @return A lowercase QString with the equivalent image type, or QString::null
+ * if it's unknown.
+ */
+ static QString mimeTypeToImageType(const QString& mimeType);
+
+ /**
+ * Constructor for UMLViewImageExporterModel.
+ */
+ UMLViewImageExporterModel() {
+ }
+
+ /**
+ * Destructor for UMLViewImageExporterModel.
+ */
+ virtual ~UMLViewImageExporterModel() {
+ }
+
+ /**
+ * Exports all the views in the document to the directory specified in the url
+ * using the 'imageType' for the images.
+ * The name of the exported images will be like their view's name and using the
+ * 'imageType' as extension.
+ *
+ * The views are stored in folders in the document. The same tree structure used
+ * in the document to store the views can be created in the target directory with
+ * 'useFolders'. Only the folders made by the user are created in the target
+ * directory (Logical view, use case view and so on aren't created).
+ *
+ * This method creates the specified target directory if needed. If there was an
+ * existing file with the same path as one to be created overwrites it without asking.
+ * The url used can be local or remote, using supported KIO slaves.
+ *
+ * @param imageType The type of the images the views will be exported to.
+ * @param directory The url of the directory where the images will be saved.
+ * @param useFolders If the tree structure of the views in the document must be created
+ * in the target directory.
+ * @return A QStringList with all the error messages that occurred during export.
+ * If the list is empty, all the views were exported successfully.
+ */
+ QStringList exportAllViews(const QString &imageType, const KURL &directory, bool useFolders) const;
+
+ /**
+ * Exports the view to the url using the 'imageType' for the image.
+ *
+ * This method creates the needed directories, if any. If there was an existing
+ * file in the specified url overwrites it without asking.
+ * The url used can be local or remote, using supported KIO slaves.
+ *
+ * If some problem occurs when exporting, an error message is returned.
+ *
+ * @param view The view to export.
+ * @param imageType The type of the image the view will be exported to.
+ * @param url The url where the image will be saved.
+ * @return The message error if some problem occurred when exporting, or
+ * QString::null if all went fine.
+ */
+ QString exportView(UMLView* view, const QString &imageType, const KURL &url) const;
+
+private:
+
+ /**
+ * Returns the name of the file where the view will be exported to.
+ * The name of the exported images will be like their view's name and using the
+ * 'imageType' as extension. It can also include the parent folders of the view.
+ *
+ * The views are stored in folders in the document. The same tree structure used
+ * in the document to store the views can be created with 'useFolders', so the file name
+ * will include recursively also its parent folders. Only the folders made by the user
+ * are included in the file name (Logical view, use case view and so on aren't created).
+ *
+ * @param view The view to export.
+ * @param imageType The type of the image the view will be exported to.
+ * @param useFolders If the tree structure of the views in the document must be included
+ * in the file name.
+ * @return The name of the file where the view will be exported to.
+ */
+ QString getDiagramFileName(UMLView *view, const QString &imageType, bool useFolders = false) const;
+
+ /**
+ * Creates, if it doesn't exist, the directory to save the file.
+ * It also creates all the needed parent directories.
+ *
+ * @param url The url where the image will be saved.
+ * @return True if the operation was successful,
+ * false if the directory didn't exist and couldn't be created.
+ */
+ bool prepareDirectory(const KURL &url) const;
+
+ /**
+ * Exports the view to the file 'fileName' as the specified type.
+ *
+ * @param view The view to export.
+ * @param imageType The type of the image the view will be exported to.
+ * @param fileName The name of the file where the image will be saved.
+ * @return True if the operation was successful,
+ * false if a problem occurred while exporting.
+ */
+ bool exportViewTo(UMLView* view, const QString &imageType, const QString &fileName) const;
+
+ /**
+ * Exports the view to the file 'fileName' as EPS.
+ *
+ * @param view The view to export.
+ * @param fileName The name of the file where the image will be saved.
+ * @param isEPS The file is an eps file and needs adjusting
+ * of the eps bounding box values.
+ * @return True if the operation was successful,
+ * false if a problem occurred while exporting.
+ */
+ bool exportViewToEps(UMLView* view, const QString &fileName, bool isEPS) const;
+
+ /**
+ * Fix the file 'fileName' to be a valid EPS containing the
+ * specified area (rect) of the diagram.
+ * Corrects the bounding box.
+ *
+ * @return True if the operation was successful,
+ * false if a problem occurred while exporting.
+ */
+ bool fixEPS(const QString &fileName, const QRect& rect) const;
+
+ /**
+ * Exports the view to the file 'fileName' as SVG.
+ *
+ * @param view The view to export.
+ * @param fileName The name of the file where the image will be saved.
+ * @return True if the operation was successful,
+ * false if a problem occurred while exporting.
+ */
+ bool exportViewToSvg(UMLView* view, const QString &fileName) const;
+
+ /**
+ * Exports the view to the file 'fileName' as a pixmap of the specified type.
+ * The valid types are those supported by QPixmap save method.
+ *
+ * @param view The view to export.
+ * @param imageType The type of the image the view will be exported to.
+ * @param fileName The name of the file where the image will be saved.
+ * @return True if the operation was successful,
+ * false if a problem occurred while exporting.
+ */
+ bool exportViewToPixmap(UMLView* view, const QString &imageType, const QString &fileName) const;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/umlviewlist.h b/umbrello/umbrello/umlviewlist.h
new file mode 100644
index 00000000..90d5e199
--- /dev/null
+++ b/umbrello/umbrello/umlviewlist.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ umlviewlist.h - description
+ -------------------
+ begin : Sat Dec 29 2001
+ copyright : (C) 2001 by Gustavo Madrigal
+ email : gmadrigal@nextphere.com
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMLVIEWLIST_H
+#define UMLVIEWLIST_H
+
+//#include "umlview.h"
+
+class UMLView;
+
+typedef QPtrList<UMLView> UMLViewList;
+typedef QPtrListIterator<UMLView> UMLViewListIt;
+
+#endif
diff --git a/umbrello/umbrello/umlwidget.cpp b/umbrello/umbrello/umlwidget.cpp
new file mode 100644
index 00000000..3e947cd1
--- /dev/null
+++ b/umbrello/umbrello/umlwidget.cpp
@@ -0,0 +1,1025 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header file
+#include "umlwidget.h"
+// system includes
+#include <qpainter.h>
+#include <qcolor.h>
+#include <kdebug.h>
+#include <kcolordialog.h>
+#include <kfontdialog.h>
+#include <kmessagebox.h>
+// local includes
+#include "umlwidgetcontroller.h"
+#include "umlobject.h"
+#include "classifier.h"
+#include "uniqueid.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umlclassifierlistitemlist.h"
+#include "codegenerator.h"
+#include "codegenerators/simplecodegenerator.h"
+#include "listpopupmenu.h"
+#include "associationwidget.h"
+#include "dialogs/settingsdlg.h"
+#include "codedocument.h"
+#include "floatingtextwidget.h"
+#include "docwindow.h"
+#include "dialogs/classpropdlg.h"
+#include "clipboard/idchangelog.h"
+
+using namespace Uml;
+
+
+UMLWidget::UMLWidget( UMLView * view, UMLObject * o, UMLWidgetController *widgetController /* = 0*/ )
+ : WidgetBase(view), QCanvasRectangle( view->canvas() ),
+ m_pMenu(0)
+{
+ if (widgetController) {
+ m_widgetController = widgetController;
+ } else {
+ m_widgetController = new UMLWidgetController(this);
+ }
+ init();
+ m_pObject = o;
+ if(m_pObject) {
+ connect( m_pObject, SIGNAL(modified()), this, SLOT(updateWidget()) );
+ m_nId = m_pObject->getID();
+ }
+}
+
+UMLWidget::UMLWidget(UMLView * view, Uml::IDType id /* = Uml::id_None */, UMLWidgetController *widgetController /* = 0*/)
+ : WidgetBase(view), QCanvasRectangle( view->canvas() ),
+ m_pMenu(0)
+{
+ if (widgetController) {
+ m_widgetController = widgetController;
+ } else {
+ m_widgetController = new UMLWidgetController(this);
+ }
+ init();
+ if (id == Uml::id_None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+}
+
+UMLWidget::~UMLWidget() {
+ //slotRemovePopupMenu();
+ delete m_widgetController;
+ cleanup();
+}
+
+UMLWidget& UMLWidget::operator=(const UMLWidget& other) {
+ if (this == &other)
+ return *this;
+
+ // assign members loaded/saved
+ m_bUseFillColour = other.m_bUseFillColour;
+ m_nId = other.m_nId;
+ m_Type = other.m_Type;
+ setX( other.getX() );
+ setY( other.getY() );
+ m_Assocs = other.m_Assocs;
+ m_Font = other.m_Font;
+ QCanvasRectangle::setSize( other.width(), other.height() );
+ m_bUsesDiagramFillColour = other.m_bUsesDiagramFillColour;
+ m_bUsesDiagramLineColour = other.m_bUsesDiagramLineColour;
+ m_bUsesDiagramLineWidth = other.m_bUsesDiagramLineWidth;
+ m_bUsesDiagramUseFillColour = other.m_bUsesDiagramUseFillColour;
+ m_LineColour = other.m_LineColour;
+ m_LineWidth = other.m_LineWidth;
+ m_FillColour = other.m_FillColour;
+ m_bIsInstance = other.m_bIsInstance;
+ m_instanceName = other.m_instanceName;
+
+ // assign volatile (non-saved) members
+ m_bSelected = other.m_bSelected;
+ m_bStartMove = other.m_bStartMove;
+ m_nPosX = other.m_nPosX;
+ m_pObject = other.m_pObject;
+ m_pView = other.m_pView;
+ m_pMenu = other.m_pMenu;
+ m_bResizable = other.m_bResizable;
+ for (unsigned i = 0; i < FT_INVALID; i++)
+ m_pFontMetrics[i] = other.m_pFontMetrics[i];
+ m_bActivated = other.m_bActivated;
+ m_bIgnoreSnapToGrid = other.m_bIgnoreSnapToGrid;
+ m_bIgnoreSnapComponentSizeToGrid = other.m_bIgnoreSnapComponentSizeToGrid;
+ return *this;
+}
+
+bool UMLWidget::operator==(const UMLWidget& other) {
+ if( this == &other )
+ return true;
+
+ if(m_Type != other.m_Type) {
+ return false;
+ }
+
+ if (getID() != other.getID())
+ return false;
+
+ /* Testing the associations is already an exaggeration, no?
+ The type and ID should uniquely identify an UMLWidget.
+ */
+ if (m_Assocs.count() != other.m_Assocs.count()) {
+ return false;
+ }
+
+ // if(getBaseType() != wt_Text) // DON'T do this for floatingtext widgets, an infinite loop will result
+ // {
+ AssociationWidgetListIt assoc_it( m_Assocs );
+ AssociationWidgetListIt assoc_it2( other.m_Assocs );
+ AssociationWidget * assoc = 0, *assoc2 = 0;
+ while ( ((assoc=assoc_it.current()) != 0) && ((assoc2=assoc_it2.current()) != 0)) {
+ ++assoc_it;
+ ++assoc_it2;
+ if(!(*assoc == *assoc2)) {
+ return false;
+ }
+ }
+ // }
+ return true;
+ // NOTE: In the comparison tests we are going to do, we don't need these values.
+ // They will actually stop things functioning correctly so if you change these, be aware of that.
+ /*
+ if(m_bUseFillColour != other.m_bUseFillColour)
+ return false;
+ if(m_nId != other.m_nId)
+ return false;
+ if( m_Font != other.m_Font )
+ return false;
+ if(m_nX != other.m_nX)
+ return false;
+ if(m_nY != other.m_nY)
+ return false;
+ */
+}
+
+void UMLWidget::mouseMoveEvent(QMouseEvent* me) {
+ m_widgetController->mouseMoveEvent(me);
+}
+
+void UMLWidget::mousePressEvent(QMouseEvent *me) {
+ m_widgetController->mousePressEvent(me);
+}
+
+void UMLWidget::updateWidget()
+{
+ updateComponentSize();
+ adjustAssocs( getX(), getY() ); //adjust assoc lines.
+ if (m_Type == Uml::wt_Class) {
+ m_pView->createAutoAttributeAssociations(this);
+ }
+ if(isVisible())
+ update();
+}
+
+QSize UMLWidget::calculateSize() {
+ return QSize(20, 20);
+}
+
+void UMLWidget::constrain(int& width, int& height) {
+ const QSize minSize = calculateSize();
+ if (width < minSize.width())
+ width = minSize.width();
+ if (height < minSize.height())
+ height = minSize.height();
+}
+
+void UMLWidget::mouseReleaseEvent(QMouseEvent *me) {
+ m_widgetController->mouseReleaseEvent(me);
+}
+
+void UMLWidget::init() {
+ m_nId = Uml::id_None;
+ m_bIsInstance = false;
+ if (m_pView) {
+ m_bUseFillColour = true;
+ m_bUsesDiagramFillColour = true;
+ m_bUsesDiagramUseFillColour = true;
+ const Settings::OptionState& optionState = m_pView->getOptionState();
+ m_FillColour = optionState.uiState.fillColor;
+ m_Font = optionState.uiState.font;
+ m_bShowStereotype = optionState.classState.showStereoType;
+ } else {
+ kError() << "UMLWidget::init: SERIOUS PROBLEM - m_pView is NULL" << endl;
+ m_bUseFillColour = false;
+ m_bUsesDiagramFillColour = false;
+ m_bUsesDiagramUseFillColour = false;
+ m_bShowStereotype = false;
+ }
+
+ for (int i = 0; i < (int)FT_INVALID; ++i)
+ m_pFontMetrics[(UMLWidget::FontType)i] = 0;
+
+ m_bResizable = true;
+
+ m_bSelected = false;
+ m_bStartMove = false;
+ m_bActivated = false;
+ m_bIgnoreSnapToGrid = false;
+ m_bIgnoreSnapComponentSizeToGrid = false;
+ m_pMenu = 0;
+ m_pDoc = UMLApp::app()->getDocument();
+ m_nPosX = 0;
+ connect( m_pView, SIGNAL( sigRemovePopupMenu() ), this, SLOT( slotRemovePopupMenu() ) );
+ connect( m_pView, SIGNAL( sigClearAllSelected() ), this, SLOT( slotClearAllSelected() ) );
+
+ connect( m_pView, SIGNAL(sigColorChanged(Uml::IDType)), this, SLOT(slotColorChanged(Uml::IDType)));
+ connect( m_pView, SIGNAL(sigLineWidthChanged(Uml::IDType)), this, SLOT(slotLineWidthChanged(Uml::IDType)));
+
+
+ // connect( m_pView, SIGNAL(sigColorChanged(int)), this, SLOT(slotColorChanged(int)));
+ m_pObject = NULL;
+ setZ(m_origZ = 2); // default for most widgets
+}
+
+void UMLWidget::slotMenuSelection(int sel) {
+ QFont font;
+ QColor newColour;
+ const Uml::Widget_Type wt = m_Type;
+ UMLWidget* widget = 0; // use for select the first object properties (fill, line color)
+
+ switch(sel) {
+ case ListPopupMenu::mt_Rename:
+ m_pDoc -> renameUMLObject(m_pObject);
+ // adjustAssocs( getX(), getY() );//adjust assoc lines
+ break;
+
+ case ListPopupMenu::mt_Delete:
+ //remove self from diagram
+ m_pView -> removeWidget(this);
+ break;
+
+ //UMLWidgetController::doMouseDoubleClick relies on this implementation
+ case ListPopupMenu::mt_Properties:
+ if (wt == wt_Actor || wt == wt_UseCase ||
+ wt == wt_Package || wt == wt_Interface || wt == wt_Datatype ||
+ wt == wt_Component || wt == wt_Artifact ||
+ wt == wt_Node || wt == wt_Enum || wt == wt_Entity ||
+ (wt == wt_Class && m_pView -> getType() == dt_Class)) {
+ showProperties();
+ } else if (wt == wt_Object) {
+ m_pObject->showProperties();
+ } else {
+ kWarning() << "making properties dialog for unknown widget type" << endl;
+ }
+ // adjustAssocs( getX(), getY() );//adjust assoc lines
+ break;
+
+ case ListPopupMenu::mt_Line_Color:
+ case ListPopupMenu::mt_Line_Color_Selection:
+ widget = m_pView->getFirstMultiSelectedWidget();
+ if (widget) { newColour = widget->getLineColor(); }
+ if( KColorDialog::getColor(newColour) ) {
+ m_pView -> selectionSetLineColor( newColour );
+ m_pDoc -> setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Fill_Color:
+ case ListPopupMenu::mt_Fill_Color_Selection:
+ widget = m_pView->getFirstMultiSelectedWidget();
+ if (widget) { newColour = widget->getFillColour(); }
+ if ( KColorDialog::getColor(newColour) ) {
+ m_pView -> selectionSetFillColor( newColour );
+ m_pDoc -> setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Use_Fill_Color:
+ m_bUseFillColour = !m_bUseFillColour;
+ m_bUsesDiagramUseFillColour = false;
+ m_pView->selectionUseFillColor( m_bUseFillColour );
+ break;
+ case ListPopupMenu::mt_Show_Attributes_Selection:
+ case ListPopupMenu::mt_Show_Operations_Selection:
+ case ListPopupMenu::mt_Visibility_Selection:
+ case ListPopupMenu::mt_DrawAsCircle_Selection:
+ case ListPopupMenu::mt_Show_Operation_Signature_Selection:
+ case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
+ case ListPopupMenu::mt_Show_Packages_Selection:
+ case ListPopupMenu::mt_Show_Stereotypes_Selection:
+ case ListPopupMenu::mt_Show_Public_Only_Selection:
+ m_pView->selectionToggleShow(sel);
+ m_pDoc->setModified(true);
+ break;
+
+ case ListPopupMenu::mt_ViewCode: {
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(m_pObject);
+ if(c)
+ {
+ UMLApp::app()->viewCodeDocument(c);
+ }
+ break;
+ }
+
+ case ListPopupMenu::mt_Delete_Selection:
+ m_pView -> deleteSelection();
+ break;
+
+ case ListPopupMenu::mt_Change_Font:
+ font = getFont();
+ if( KFontDialog::getFont( font, false, m_pView ) )
+ {
+ setFont( font );
+ m_pDoc->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Change_Font_Selection:
+ font = getFont();
+ if( KFontDialog::getFont( font, false, m_pView ) )
+ {
+ m_pView -> selectionSetFont( font );
+ m_pDoc->setModified(true);
+ }
+ break;
+
+ case ListPopupMenu::mt_Cut:
+ m_pView -> 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(dynamic_cast<UMLClassifier*>(m_pObject))
+ {
+ UMLApp::app()->refactor(static_cast<UMLClassifier*>(m_pObject));
+ }
+ break;
+
+ case ListPopupMenu::mt_Clone:
+ // In principle we clone all the uml objects.
+ {
+ UMLObject *pClone = m_pObject->clone();
+ m_pView->addObject(pClone);
+ }
+ 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<FloatingTextWidget*>(this);
+ ft->handleRename();
+ break;
+ }
+ }
+}
+
+void UMLWidget::slotWidgetMoved(Uml::IDType /*id*/) {}
+
+void UMLWidget::slotColorChanged(Uml::IDType viewID) {
+ //only change if on the diagram concerned
+ if(m_pView->getID() != viewID) {
+ return;
+ }
+ if ( m_bUsesDiagramFillColour ) {
+ m_FillColour = m_pView->getFillColor();
+ }
+ if ( m_bUsesDiagramLineColour ) {
+ m_LineColour = m_pView->getLineColor();
+ }
+ if ( m_bUsesDiagramUseFillColour ) {
+ m_bUseFillColour = m_pView->getUseFillColor();
+ }
+ update();
+}
+
+void UMLWidget::slotLineWidthChanged(Uml::IDType viewID) {
+ //only change if on the diagram concerned
+ if(m_pView->getID() != viewID) {
+ return;
+ }
+ if ( m_bUsesDiagramLineWidth ) {
+ m_LineWidth = m_pView->getLineWidth();
+ }
+ update();
+}
+
+void UMLWidget::mouseDoubleClickEvent( QMouseEvent * me ) {
+ m_widgetController->mouseDoubleClickEvent(me);
+}
+
+void UMLWidget::setUseFillColour(bool fc) {
+ m_bUseFillColour = fc;
+ m_bUsesDiagramUseFillColour = false;
+ update();
+}
+
+void UMLWidget::setLineColor(const QColor &colour) {
+ WidgetBase::setLineColor(colour);
+ update();
+}
+
+void UMLWidget::setLineWidth(uint width) {
+ WidgetBase::setLineWidth(width);
+ update();
+}
+
+void UMLWidget::setFillColour(const QColor &colour) {
+ m_FillColour = colour;
+ m_bUsesDiagramFillColour = false;
+ update();
+}
+
+void UMLWidget::drawSelected(QPainter * p, int offsetX, int offsetY) {
+ int w = width();
+ int h = height();
+ int s = 4;
+ QBrush brush(Qt::blue);
+ p -> fillRect(offsetX, offsetY, s, s, brush);
+ p -> fillRect(offsetX, offsetY + h - s, s, s, brush);
+ p -> fillRect(offsetX + w - s, offsetY, s, s, brush);
+
+ // Draw the resize anchor in the lower right corner.
+ if (m_bResizable) {
+ brush.setColor(Qt::red);
+ const int right = offsetX + w;
+ const int bottom = offsetY + h;
+ p->drawLine(right - s, offsetY + h - 1, offsetX + w - 1, offsetY + h - s);
+ p->drawLine(right - (s*2), bottom - 1, right - 1, bottom - (s*2) );
+ p->drawLine(right - (s*3), bottom - 1, right - 1, bottom - (s*3) );
+ } else {
+ p->fillRect(offsetX + w - s, offsetY + h - s, s, s, brush);
+ }
+}
+
+bool UMLWidget::activate(IDChangeLog* /*ChangeLog = 0 */) {
+ if (widgetHasUMLObject(m_Type) && m_pObject == NULL) {
+ m_pObject = m_pDoc->findObjectById(m_nId);
+ if (m_pObject == NULL) {
+ kError() << "UMLWidget::activate: cannot find UMLObject with id="
+ << ID2STR(m_nId) << endl;
+ return false;
+ }
+ }
+ setFont(m_Font);
+ setSize(getWidth(), getHeight());
+ m_bActivated = true;
+ updateComponentSize();
+ if (m_pView->getPaste()) {
+ FloatingTextWidget * ft = 0;
+ QPoint point = m_pView -> getPastePoint();
+ int x = point.x() + getX();
+ int y = point.y() + getY();
+ x = x < 0?0:x;
+ y = y < 0?0:y;
+ if( m_pView -> getType() == dt_Sequence ) {
+ switch( getBaseType() ) {
+ case wt_Object:
+ case wt_Message:
+ setY( getY() );
+ setX( x );
+ break;
+
+ case wt_Text:
+ ft = static_cast<FloatingTextWidget *>( this );
+ if (ft->getRole() == tr_Seq_Message) {
+ setX( x );
+ setY( getY() );
+ } else {
+ setX( getX() );
+ setY( getY() );
+ }
+ break;
+
+ default:
+ setY( y );
+ break;
+ }//end switch base type
+ }//end if sequence
+ else {
+ setX( x );
+ setY( y );
+ }
+ }//end if pastepoint
+ else {
+ setX( getX() );
+ setY( getY() );
+ }
+ if ( m_pView -> getPaste() )
+ m_pView -> createAutoAssociations( this );
+ updateComponentSize();
+ return true;
+}
+
+/** Read property of bool m_bActivated. */
+bool UMLWidget::isActivated() {
+ return m_bActivated;
+}
+
+void UMLWidget::setActivated(bool Active /*=true*/) {
+ m_bActivated = Active;
+}
+
+void UMLWidget::addAssoc(AssociationWidget* pAssoc) {
+ if (pAssoc && !m_Assocs.contains(pAssoc)) {
+ m_Assocs.append(pAssoc);
+ }
+}
+
+void UMLWidget::removeAssoc(AssociationWidget* pAssoc) {
+ if(pAssoc) {
+ m_Assocs.remove(pAssoc);
+ }
+}
+
+void UMLWidget::adjustAssocs(int x, int y)
+{
+ // 2004-04-30: Achim Spangler
+ // don't adjust Assocs on file load, as
+ // the original positions, which are stored in XMI
+ // should be reproduced exactly
+ // ( don't try to reposition assocs as long
+ // as file is only partly loaded -> reposition
+ // could be misguided )
+ /// @todo avoid trigger of this event during load
+ if ( m_pDoc->loading() ) {
+ // don't recalculate the assocs during load of XMI
+ // -> return immediately without action
+ return;
+ }
+ AssociationWidgetListIt assoc_it(m_Assocs);
+ AssociationWidget* assocwidget = 0;
+ while ((assocwidget = assoc_it.current())) {
+ ++assoc_it;
+ assocwidget->saveIdealTextPositions();
+ }
+ assoc_it.toFirst();
+ while ((assocwidget = assoc_it.current())) {
+ ++assoc_it;
+ assocwidget->widgetMoved(this, x, y);
+ }
+}
+
+void UMLWidget::adjustUnselectedAssocs(int x, int y)
+{
+ AssociationWidgetListIt assoc_it(m_Assocs);
+ AssociationWidget* assocwidget = 0;
+ while ((assocwidget = assoc_it.current())) {
+ ++assoc_it;
+ if(!assocwidget->getSelected())
+ assocwidget->saveIdealTextPositions();
+ }
+ assoc_it.toFirst();
+ while ((assocwidget = assoc_it.current())) {
+ ++assoc_it;
+ if(!assocwidget->getSelected())
+ assocwidget->widgetMoved(this, x, y);
+ }
+}
+
+void UMLWidget::showProperties() {
+ // will already be selected so make sure docWindow updates the doc
+ // back it the widget
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation( false );
+ ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this);
+
+ if (dlg->exec()) {
+ docwindow->showDocumentation( getUMLObject() , true );
+ m_pDoc->setModified(true);
+ }
+ dlg->close(true); //wipe from memory
+}
+
+void UMLWidget::startPopupMenu( const QPoint &At) {
+ slotRemovePopupMenu();
+
+ //if in a multi- selection to a specific m_pMenu for that
+ // NEW: ask UMLView to count ONLY the widgets and not their floatingtextwidgets
+ int count = m_pView->getSelectCount(true);
+ //a MessageWidget when selected will select its text widget and vice versa
+ //so take that into account for popup menu.
+
+ // determine multi state
+ bool multi = (m_bSelected && count > 1);
+
+ // if multiple selected items have the same type
+ bool unique = false;
+
+ // if multiple items are selected, we have to check if they all have the same
+ // base type
+ if (multi == true)
+ unique = m_pView -> checkUniqueSelection();
+
+ // create the right click context menu
+ m_pMenu = new ListPopupMenu(m_pView, this, multi, unique);
+
+ // disable the "view code" menu for simple code generators
+ CodeGenerator * currentCG = UMLApp::app()->getGenerator();
+ if(currentCG && dynamic_cast<SimpleCodeGenerator*>(currentCG))
+ m_pMenu->setItemEnabled(ListPopupMenu::mt_ViewCode, false);
+
+ m_pMenu->popup(At);
+
+ connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+}
+
+void UMLWidget::slotRemovePopupMenu() {
+ if(m_pMenu) {
+ disconnect(m_pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuSelection(int)));
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+int UMLWidget::onWidget(const QPoint & p) {
+ const int w = width();
+ const int h = height();
+ const int left = getX();
+ const int right = left + w;
+ const int top = getY();
+ const int bottom = top + h;
+ if (p.x() < left || p.x() > right ||
+ p.y() < top || p.y() > bottom) // Qt coord.sys. origin in top left corner
+ return 0;
+ return (w + h) / 2;
+}
+
+void UMLWidget::moveBy(int dx, int dy) {
+ int newX = getX() + dx;
+ int newY = getY() + dy;
+ setX(newX);
+ setY(newY);
+ adjustAssocs(newX, newY);
+}
+
+void UMLWidget::setPen(QPainter & p) {
+ p.setPen( QPen(m_LineColour, m_LineWidth) );
+}
+
+void UMLWidget::drawShape(QPainter &p ) {
+ draw( p, getX(), getY() );
+}
+
+void UMLWidget::setSelected(bool _select) {
+ const Uml::Widget_Type wt = m_Type;
+ if( _select ) {
+ if( m_pView -> getSelectCount() == 0 ) {
+ if ( widgetHasUMLObject(wt) ) {
+ m_pView->showDocumentation(m_pObject, false);
+ } else {
+ m_pView->showDocumentation(this, false);
+ }
+ }//end if
+ /* if (wt != wt_Text && wt != wt_Box) {
+ setZ(9);//keep text on top and boxes behind so don't touch Z value
+ } */
+ } else {
+ /* if (wt != wt_Text && wt != wt_Box) {
+ setZ(m_origZ);
+ } */
+ if( m_bSelected )
+ m_pView -> updateDocumentation( true );
+ }
+ m_bSelected = _select;
+
+ const QPoint pos(getX(), getY());
+ UMLWidget *bkgnd = m_pView->getWidgetAt(pos);
+ if (bkgnd && bkgnd != this && _select) {
+ kDebug() << "UMLWidget::setSelected: setting Z to "
+ << bkgnd->getZ() + 1 << ", SelectState: " << _select << endl;
+ setZ( bkgnd->getZ() + 1 );
+ } else {
+ setZ( m_origZ );
+ }
+
+ update();
+
+ /* selection changed, we have to make sure the copy and paste items
+ * are correctly enabled/disabled */
+ UMLApp::app()->slotCopyChanged();
+}
+
+void UMLWidget::slotClearAllSelected()
+{
+ setSelected( false );
+}
+
+void UMLWidget::setView(UMLView * v) {
+ //remove signals from old view - was probably 0 anyway
+ disconnect( m_pView, SIGNAL( sigRemovePopupMenu() ), this, SLOT( slotRemovePopupMenu() ) );
+ disconnect( m_pView, SIGNAL( sigClearAllSelected() ), this, SLOT( slotClearAllSelected() ) );
+ disconnect( m_pView, SIGNAL(sigColorChanged(Uml::IDType)), this, SLOT(slotColorChanged(Uml::IDType)));
+ disconnect( m_pView, SIGNAL(sigLineWidthChanged(Uml::IDType)), this, SLOT(slotLineWidthChanged(Uml::IDType)));
+ m_pView = v;
+ connect( m_pView, SIGNAL( sigRemovePopupMenu() ), this, SLOT( slotRemovePopupMenu() ) );
+ connect( m_pView, SIGNAL( sigClearAllSelected() ), this, SLOT( slotClearAllSelected() ) );
+ connect( m_pView, SIGNAL(sigColorChanged(Uml::IDType)), this, SLOT(slotColorChanged(Uml::IDType)));
+ connect( m_pView, SIGNAL(sigLineWidthChanged(Uml::IDType)), this, SLOT(slotLineWidthChanged(Uml::IDType)));
+}
+
+void UMLWidget::setX( int x ) {
+ if (!m_bIgnoreSnapToGrid) {
+ x = m_pView->snappedX(x);
+ }
+ QCanvasItem::setX( (double)x );
+}
+
+void UMLWidget::setY( int y ) {
+ if (!m_bIgnoreSnapToGrid){
+ y = m_pView->snappedX(y);
+ }
+ QCanvasItem::setY( (double)y );
+}
+
+void UMLWidget::setZ(int z) {
+ m_origZ = getZ();
+ QCanvasItem::setZ(z);
+}
+
+void UMLWidget::setName(const QString &strName) {
+ if (m_pObject)
+ m_pObject->setName(strName);
+ else
+ m_Text = strName;
+ updateComponentSize();
+ adjustAssocs( getX(), getY() );
+}
+
+QString UMLWidget::getName() const {
+ if (m_pObject)
+ return m_pObject->getName();
+ return m_Text;
+}
+
+void UMLWidget::cleanup() {
+}
+
+void UMLWidget::slotSnapToGrid( ) {
+ setX( getX() );
+ setY( getY() );
+}
+
+bool UMLWidget::widgetHasUMLObject(Uml::Widget_Type type) {
+ if (type == wt_Actor ||
+ type == wt_UseCase ||
+ type == wt_Class ||
+ type == wt_Interface ||
+ type == wt_Enum ||
+ type == wt_Datatype ||
+ type == wt_Package ||
+ type == wt_Component ||
+ type == wt_Node ||
+ type == wt_Artifact ||
+ type == wt_Object) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void UMLWidget::setIgnoreSnapToGrid(bool to) {
+ m_bIgnoreSnapToGrid = to;
+}
+
+bool UMLWidget::getIgnoreSnapToGrid() const {
+ return m_bIgnoreSnapToGrid;
+}
+
+void UMLWidget::setSize(int width,int height) {
+ // snap to the next larger size that is a multiple of the grid
+ if (!m_bIgnoreSnapComponentSizeToGrid
+ && m_pView -> getSnapComponentSizeToGrid() )
+ {
+ // integer divisions
+ int numX = width / m_pView->getSnapX();
+ int numY = height / m_pView->getSnapY();
+ // snap to the next larger valid value
+ if (width > numX * m_pView->getSnapX())
+ width = (numX + 1) * m_pView->getSnapX();
+ if (height > numY * m_pView->getSnapY())
+ height = (numY + 1) * m_pView->getSnapY();
+ }
+
+ QCanvasRectangle::setSize(width,height);
+}
+
+void UMLWidget::updateComponentSize() {
+ if (m_pDoc->loading())
+ return;
+ const QSize minSize = calculateSize();
+ const int w = minSize.width();
+ const int h = minSize.height();
+ setSize(w, h);
+ adjustAssocs( getX(), getY() ); // adjust assoc lines
+}
+
+void UMLWidget::setDefaultFontMetrics(UMLWidget::FontType fontType) {
+ setupFontType(m_Font, fontType);
+ setFontMetrics(fontType, QFontMetrics(m_Font));
+}
+
+void UMLWidget::setupFontType(QFont &font, UMLWidget::FontType fontType) {
+ switch(fontType){
+ case FT_NORMAL:
+ font.setBold(false);
+ font.setItalic(false);
+ font.setUnderline(false);
+ break;
+ case FT_BOLD:
+ font.setBold(true);
+ font.setItalic(false);
+ font.setUnderline(false);
+ break;
+ case FT_ITALIC:
+ font.setBold(false);
+ font.setItalic(true);
+ font.setUnderline(false);
+ break;
+ case FT_UNDERLINE:
+ font.setBold(false);
+ font.setItalic(false);
+ font.setUnderline(true);
+ break;
+ case FT_BOLD_ITALIC:
+ font.setBold(true);
+ font.setItalic(true);
+ font.setUnderline(false);
+ break;
+ case FT_BOLD_UNDERLINE:
+ font.setBold(true);
+ font.setItalic(false);
+ font.setUnderline(true);
+ break;
+ case FT_ITALIC_UNDERLINE:
+ font.setBold(false);
+ font.setItalic(true);
+ font.setUnderline(true);
+ break;
+ case FT_BOLD_ITALIC_UNDERLINE:
+ font.setBold(true);
+ font.setItalic(true);
+ font.setUnderline(true);
+ break;
+ default: return;
+ }
+}
+
+void UMLWidget::setDefaultFontMetrics(UMLWidget::FontType fontType, QPainter &painter) {
+ setupFontType(m_Font, fontType);
+ painter.setFont(m_Font);
+ setFontMetrics(fontType, painter.fontMetrics());
+}
+
+//FIXME this is probably the source of problems with widgets not being wide enough
+QFontMetrics &UMLWidget::getFontMetrics(UMLWidget::FontType fontType) {
+ if (m_pFontMetrics[fontType] == 0) {
+ setDefaultFontMetrics(fontType);
+ }
+ return *m_pFontMetrics[fontType];
+}
+
+void UMLWidget::setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm) {
+ delete m_pFontMetrics[fontType];
+ m_pFontMetrics[fontType] = new QFontMetrics(fm);
+}
+
+QFont UMLWidget::getFont() const {
+ return m_Font;
+}
+
+void UMLWidget::setFont( QFont font ) {
+ m_Font = font;
+ forceUpdateFontMetrics(0);
+ if (m_pDoc->loading())
+ return;
+ update();
+}
+
+void UMLWidget::forceUpdateFontMetrics(QPainter *painter) {
+ if (painter == 0) {
+ for (int i = 0; i < (int)UMLWidget::FT_INVALID; ++i) {
+ if (m_pFontMetrics[(UMLWidget::FontType)i]!=0)
+ setDefaultFontMetrics((UMLWidget::FontType)i);
+ }
+ } else {
+ for (int i2 = 0; i2 < (int)UMLWidget::FT_INVALID; ++i2) {
+ if (m_pFontMetrics[(UMLWidget::FontType)i2]!=0)
+ setDefaultFontMetrics((UMLWidget::FontType)i2,*painter);
+ }
+ }
+ // calculate the size, based on the new font metric
+ updateComponentSize();
+}
+
+void UMLWidget::setShowStereotype(bool _status) {
+ m_bShowStereotype = _status;
+ updateComponentSize();
+ update();
+}
+
+bool UMLWidget::getShowStereotype() const {
+ return m_bShowStereotype;
+}
+
+void UMLWidget::moveEvent(QMoveEvent* /*me*/) {
+}
+
+void UMLWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ /*
+ Call after required actions in child class.
+ Type must be set in the child class.
+ */
+ WidgetBase::saveToXMI(qDoc, qElement);
+ qElement.setAttribute( "xmi.id", ID2STR(getID()) );
+ qElement.setAttribute( "font", m_Font.toString() );
+ qElement.setAttribute( "usefillcolor", m_bUseFillColour );
+ qElement.setAttribute( "x", getX() );
+ qElement.setAttribute( "y", getY() );
+ qElement.setAttribute( "width", getWidth() );
+ qElement.setAttribute( "height", getHeight() );
+ // for consistency the following attributes now use american spelling for "color"
+ qElement.setAttribute( "usesdiagramfillcolor", m_bUsesDiagramFillColour );
+ qElement.setAttribute( "usesdiagramusefillcolor", m_bUsesDiagramUseFillColour );
+ if (m_bUsesDiagramFillColour) {
+ qElement.setAttribute( "fillcolor", "none" );
+ } else {
+ qElement.setAttribute( "fillcolor", m_FillColour.name() );
+ }
+ qElement.setAttribute("isinstance", m_bIsInstance);
+ if (!m_instanceName.isEmpty())
+ qElement.setAttribute("instancename", m_instanceName);
+ if (m_bShowStereotype)
+ qElement.setAttribute("showstereotype", m_bShowStereotype);
+}
+
+bool UMLWidget::loadFromXMI( QDomElement & qElement ) {
+ WidgetBase::loadFromXMI(qElement);
+ QString id = qElement.attribute( "xmi.id", "-1" );
+ QString font = qElement.attribute( "font", "" );
+ QString usefillcolor = qElement.attribute( "usefillcolor", "1" );
+ QString x = qElement.attribute( "x", "0" );
+ QString y = qElement.attribute( "y", "0" );
+ QString h = qElement.attribute( "height", "0" );
+ QString w = qElement.attribute( "width", "0" );
+ /*
+ 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 fillColour = qElement.attribute( "fillcolour", "none" );
+ fillColour = qElement.attribute( "fillcolor", fillColour );
+ QString usesDiagramFillColour = qElement.attribute( "usesdiagramfillcolour", "1" );
+ usesDiagramFillColour = qElement.attribute( "usesdiagramfillcolor", usesDiagramFillColour );
+ QString usesDiagramUseFillColour = qElement.attribute( "usesdiagramusefillcolour", "1" );
+ usesDiagramUseFillColour = qElement.attribute( "usesdiagramusefillcolor", usesDiagramUseFillColour );
+
+ m_nId = STR2ID(id);
+
+ if( !font.isEmpty() ) {
+ //QFont newFont;
+ m_Font.fromString(font);
+ //setFont(newFont);
+ } else {
+ kWarning() << "Using default font " << m_Font.toString()
+ << " for widget with xmi.id " << ID2STR(m_nId) << endl;
+ //setFont( m_Font );
+ }
+ m_bUseFillColour = (bool)usefillcolor.toInt();
+ m_bUsesDiagramFillColour = (bool)usesDiagramFillColour.toInt();
+ m_bUsesDiagramUseFillColour = (bool)usesDiagramUseFillColour.toInt();
+ setSize( w.toInt(), h.toInt() );
+ setX( x.toInt() );
+ setY( y.toInt() );
+ if (fillColour != "none") {
+ m_FillColour = QColor(fillColour);
+ }
+ QString isinstance = qElement.attribute("isinstance", "0");
+ m_bIsInstance = (bool)isinstance.toInt();
+ m_instanceName = qElement.attribute("instancename", "");
+ QString showstereo = qElement.attribute("showstereotype", "0");
+ m_bShowStereotype = (bool)showstereo.toInt();
+ return true;
+}
+
+UMLWidgetController* UMLWidget::getWidgetController() {
+ return m_widgetController;
+}
+
+#include "umlwidget.moc"
diff --git a/umbrello/umbrello/umlwidget.h b/umbrello/umbrello/umlwidget.h
new file mode 100644
index 00000000..7ed472a9
--- /dev/null
+++ b/umbrello/umbrello/umlwidget.h
@@ -0,0 +1,728 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLWIDGET_H
+#define UMLWIDGET_H
+
+#include <qcanvas.h>
+#include <qdatetime.h>
+#include <qfont.h>
+
+#include "umlnamespace.h"
+#include "widgetbase.h"
+#include "associationwidgetlist.h"
+#include "optionstate.h"
+
+class UMLWidgetController;
+
+class UMLObject;
+class UMLView;
+class UMLDoc;
+class ListPopupMenu;
+class IDChangeLog;
+
+class QPainter;
+class QFont;
+class QFontMetrics;
+
+/**
+ * This is the base class for nearly all graphical widgets.
+ *
+ * @short The base class for graphical UML objects.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UMLWidget : public WidgetBase, public QCanvasRectangle {
+ Q_OBJECT
+public:
+ friend class UMLWidgetController;
+
+ /**
+ * Creates a UMLWidget object.
+ *
+ * @param view The view to be displayed on.
+ * @param o The UMLObject to represent.
+ * @param widgetController The UMLWidgetController of this UMLWidget
+ */
+ UMLWidget( UMLView * view, UMLObject * o, UMLWidgetController *widgetController = 0 );
+
+ /**
+ * Creates a UMLWidget object.
+ *
+ * @param view The view to be displayed on.
+ * @param id The id of the widget.
+ * The default value (id_None) will prompt generation of a new ID.
+ * @param widgetController The UMLWidgetController of this UMLWidget
+ */
+ explicit UMLWidget( UMLView * view, Uml::IDType id = Uml::id_None, UMLWidgetController *widgetController = 0 );
+
+ /**
+ * Standard deconstructor
+ */
+ virtual ~UMLWidget();
+
+ /**
+ * Copy constructor
+ */
+ UMLWidget(const UMLWidget& other);
+
+ /**
+ * Assignment operator
+ */
+ virtual UMLWidget& operator=(const UMLWidget& other);
+
+ /**
+ * Overload '==' operator
+ */
+ virtual bool operator==(const UMLWidget& other);
+
+ /**
+ * Calls the method with the same name in UMLWidgetController.
+ * @see UMLWidgetController#mouseReleaseEvent
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseReleaseEvent(QMouseEvent * me);
+
+ /**
+ * Calls the method with the same name in UMLWidgetController.
+ * @see UMLWidgetController#mouseDoubleClickEvent
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseDoubleClickEvent(QMouseEvent *me);
+
+ /**
+ * Set the status of using fill color.
+ *
+ * @param fc the status of using fill color.
+ */
+ void setUseFillColour(bool fc);
+
+ /**
+ * Read property of bool m_bUseFillColour.
+ */
+ bool getUseFillColour() const {
+ return m_bUseFillColour;
+ }
+
+ /**
+ * Overrides the method from WidgetBase.
+ */
+ void setLineColor(const QColor &colour);
+
+ /**
+ * Overrides the method from WidgetBase.
+ */
+ void setLineWidth(uint width);
+
+ /**
+ * Sets the background fill colour
+ *
+ * @param colour the new fill colour
+ */
+ void setFillColour(const QColor &colour);
+
+ /**
+ * Read property of QColor m_FillColour.
+ */
+ QColor getFillColour() const {
+ return m_FillColour;
+ }
+
+ /**
+ * Calls the method with the same name in UMLWidgetController.
+ * @see UMLWidgetController#mouseMoveEvent
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseMoveEvent(QMouseEvent* me);
+
+ /**
+ * Returns whether this is a line of text.
+ * Used for transparency in printing.
+ *
+ * @return always false
+ */
+ virtual bool isText() {
+ return false;
+ }
+
+ /**
+ * Sets the state of whether the widget is selected.
+ *
+ * @param _select The state of whether the widget is selected.
+ */
+ virtual void setSelected(bool _select);
+
+ /**
+ * Returns the state of whether the widget is selected.
+ *
+ * @return Returns the state of whether the widget is selected.
+ */
+ bool getSelected() const {
+ return m_bSelected;
+ }
+
+ void setSelectedFlag(bool _select) {
+ m_bSelected = _select;
+ }
+
+ /**
+ * Sets the view the widget is on.
+ *
+ * @param v The view the widget is on.
+ */
+ void setView(UMLView * v);
+
+ /**
+ * Activate the object after serializing it from a QDataStream
+ *
+ * @param ChangeLog
+ * @return true for success
+ */
+ virtual bool activate(IDChangeLog* ChangeLog = 0);
+
+ /**
+ * Returns 0 if the given point is not in the boundaries of the widget,
+ * else returns a number which is proportional to the size of the widget.
+ *
+ * @param p Point to be checked.
+ *
+ * @return 0 if the given point is not in the boundaries of the widget;
+ * (width()+height())/2 if the point is within the boundaries.
+ */
+ virtual int onWidget(const QPoint & p);
+
+ /**
+ * Draws the UMLWidget on the given paint device
+ *
+ * @param p The painter for the drawing device
+ * @param offsetX x position to start the drawing.
+ * @param offsetY y position to start the drawing.
+ *
+ */
+ virtual void draw(QPainter & p, int offsetX, int offsetY) = 0;
+
+ /**
+ * Set the pen.
+ */
+ void setPen(QPainter & p);
+
+ /**
+ * Sets the font the widget is to use.
+ *
+ * @param font Font to be set.
+ */
+ virtual void setFont( QFont font );
+
+ /**
+ * Returns the font the widget is to use.
+ */
+ virtual QFont getFont() const;
+
+ /**
+ * Returns whether we triggered the update of position movement.
+ * If so, you probably don't want to move it.
+ *
+ * @return The moving state.
+ */
+ bool getStartMove() {
+ return m_bStartMove;
+ }
+
+ /**
+ * Sets the x-coordinate.
+ * Currently, the only class that reimplements this method is
+ * ObjectWidget.
+ *
+ * @param x The x-coordinate to be set.
+ */
+ virtual void setX( int x );
+
+ /**
+ * Sets the y-coordinate.
+ * Currently, the only class that reimplements this method is
+ * ObjectWidget.
+ *
+ * @param y The y-coordinate to be set.
+ */
+ virtual void setY( int y );
+
+ /**
+ * Sets the z-coordinate.
+ *
+ * @param z The z-coordinate to be set.
+ */
+ virtual void setZ( int z );
+
+ /**
+ * Gets the x-coordinate.
+ */
+ int getX() const {
+ return (int)QCanvasItem::x();
+ }
+
+ /**
+ * Gets the y-coordinate.
+ */
+ int getY() const {
+ return (int)QCanvasItem::y();
+ }
+
+ /**
+ * Gets the z-coordinate.
+ */
+ int getZ() const {
+ return (int)QCanvasItem::z();
+ }
+
+ /**
+ * Returns the height of widget.
+ */
+ int getHeight() const {
+ return QCanvasRectangle::height();
+ }
+
+ /**
+ * Returns the width of the widget.
+ */
+ int getWidth() const {
+ return QCanvasRectangle::width();
+ }
+
+ /**
+ * Sets the size.
+ * If m_pView->getSnapComponentSizeToGrid() is true, then
+ * set the next larger size that snaps to the grid.
+ */
+ void setSize(int width,int height);
+
+ /**
+ * Set m_bIgnoreSnapToGrid.
+ */
+ void setIgnoreSnapToGrid(bool to);
+
+ /**
+ * Return the value of m_bIgnoreSnapToGrid.
+ */
+ bool getIgnoreSnapToGrid() const;
+
+ /**
+ * Move the widget by an X and Y offset relative to
+ * the current position.
+ */
+ void moveBy(int dx, int dy);
+
+ /**
+ * Removes an already created association from the list of
+ * associations that include this UMLWidget
+ */
+ void removeAssoc(AssociationWidget* pAssoc);
+
+ /**
+ * Adds an already created association to the list of
+ * associations that include this UMLWidget
+ */
+ void addAssoc(AssociationWidget* pAssoc);
+
+ /**
+ * Returns the list of associations connected to this widget.
+ */
+ AssociationWidgetList & getAssocList() {
+ return m_Assocs;
+ }
+
+ /**
+ * Returns m_bUsesDiagramFillColour
+ */
+ bool getUsesDiagramFillColour() const {
+ return m_bUsesDiagramFillColour;
+ }
+
+ /**
+ * Returns m_bUsesDiagramUseFillColour
+ */
+ bool getUsesDiagramUseFillColour() const {
+ return m_bUsesDiagramUseFillColour;
+ }
+
+ /**
+ * Sets m_bUsesDiagramFillColour
+ */
+ void setUsesDiagramFillColour(bool usesDiagramFillColour) {
+ m_bUsesDiagramFillColour = usesDiagramFillColour;
+ }
+
+ /**
+ * Sets m_bUsesDiagramUseFillColour
+ */
+ void setUsesDiagramUseFillColour(bool usesDiagramUseFillColour) {
+ m_bUsesDiagramUseFillColour = usesDiagramUseFillColour;
+ }
+
+ /**
+ * Write property of bool m_bIsInstance
+ */
+ void setIsInstance(bool isInstance) {
+ m_bIsInstance = isInstance;
+ }
+
+ /**
+ * Read property of bool m_bIsInstance
+ */
+ bool getIsInstance() const {
+ return m_bIsInstance;
+ }
+
+ /**
+ * Write property of m_instanceName
+ */
+ void setInstanceName(const QString &instanceName) {
+ m_instanceName = instanceName;
+ }
+
+ /**
+ * Read property of m_instanceName
+ */
+ QString getInstanceName() const {
+ return m_instanceName;
+ }
+
+ /**
+ * Returns the status of whether to show Stereotype.
+ *
+ * @return True if stereotype is shown.
+ */
+ bool getShowStereotype() const;
+
+ /**
+ * Set the status of whether to show Stereotype.
+ *
+ * @param _status True if stereotype shall be shown.
+ */
+ virtual void setShowStereotype(bool _status);
+
+ /**
+ * Show a properties dialog for a UMLWidget.
+ */
+ virtual void showProperties();
+
+ /**
+ * Returns true if the Activate method has been called for this instance
+ *
+ * @return The activate status.
+ */
+ bool isActivated();
+
+ /**
+ * Sets the name in the corresponding UMLObject.
+ * Sets the local m_Text if m_pObject is NULL.
+ *
+ * @param strName The name to be set.
+ */
+ virtual void setName(const QString &strName);
+
+ /**
+ * Gets the name from the corresponding UMLObject.
+ * Returns the local m_Text if m_pObject is NULL.
+ *
+ * @return The currently set name.
+ */
+ virtual QString getName() const;
+
+ /**
+ * Starts the popup menu.
+ *
+ * @param At The Point where the diagram is to be coming up.
+ */
+ void startPopupMenu( const QPoint &At );
+
+ /**
+ * Adjusts associations with the given co-ordinates
+ *
+ * @param x The x-coordinate.
+ * @param y The y-coordinate.
+ */
+ virtual void adjustAssocs(int x, int y);
+
+ /**
+ * Adjusts all unselected associations with the given co-ordinates
+ *
+ * @param x The x-coordinate.
+ * @param y The y-coordinate.
+ */
+ void adjustUnselectedAssocs(int x, int y);
+
+ /**
+ * Set the m_bActivated flag of a widget but does not perform the Activate method
+ *
+ * @param Active Status of activation is to be set.
+ */
+ void setActivated(bool Active = true);
+
+ /**
+ * Used to cleanup any other widget it may need to delete.
+ * Used by child classes. This should be called before deleting a widget of a diagram.
+ */
+ virtual void cleanup();
+
+ /**
+ * Returns whether the widget type has an associated UMLObject
+ */
+ static bool widgetHasUMLObject(Uml::Widget_Type type);
+
+ /**
+ * Update the size of this widget.
+ */
+ void updateComponentSize();
+
+ /**
+ * @note For performance Reasons, only FontMetrics for already used
+ * font types are updated. Not yet used font types will not get a font metric
+ * and will get the same font metric as if painter was zero.
+ * This behaviour is acceptable, because diagrams will always be showed on Display
+ * first before a special painter like a printer device is used.
+ */
+ void forceUpdateFontMetrics(QPainter *painter);
+
+ /**
+ * Calls the method with the same name in UMLWidgetController.
+ * @see UMLWidgetController#mousePressEvent
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mousePressEvent(QMouseEvent *me);
+
+ /**
+ * Overrides the standard operation.
+ *
+ * @param me The move event.
+ */
+ virtual void moveEvent(QMoveEvent *me);
+
+ virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ virtual bool loadFromXMI( QDomElement & qElement );
+
+ /**
+ * Returns the UMLWdigetController for this widget.
+ */
+ UMLWidgetController* getWidgetController();
+
+protected:
+ /**
+ * Apply possible constraints to the given candidate width and height.
+ * The default implementation calls calculateSize() and
+ * assigns the returned values if they are greater than the
+ * input values.
+ *
+ * @param width input value, may be modified by the constraint
+ * @param height input value, may be modified by the constraint
+ */
+ virtual void constrain(int& width, int& height);
+
+ /**
+ * Draws that the widget is selected.
+ *
+ * @param p Device on which is the selection is to be drawn.
+ * @param offsetX The x-coordinate for drawing.
+ * @param offsetY The y-coordinate for drawing.
+ */
+ virtual void drawSelected(QPainter * p, int offsetX, int offsetY);
+
+ /**
+ * Overrides default method.
+ *
+ * @param p Device on which the shape has to be drawn.
+ */
+ virtual void drawShape(QPainter &p );
+
+ /**
+ * Compute the minimum possible width and height.
+ * The default implementation returns width=20, height=20.
+ *
+ * @return QSize(mininum_width, minimum_height)
+ */
+ virtual QSize calculateSize();
+
+ typedef enum {
+ FT_NORMAL = 0,
+ FT_BOLD = 1,
+ FT_ITALIC = 2,
+ FT_UNDERLINE = 3,
+ FT_BOLD_ITALIC = 4,
+ FT_BOLD_UNDERLINE = 5,
+ FT_ITALIC_UNDERLINE = 6,
+ FT_BOLD_ITALIC_UNDERLINE = 7,
+ FT_INVALID = 8
+ } FontType;
+
+ /** Template Method, override this to set the default
+ * font metric.
+ */
+ virtual void setDefaultFontMetrics(UMLWidget::FontType fontType);
+ virtual void setDefaultFontMetrics(UMLWidget::FontType fontType, QPainter &painter);
+
+ /** Returns the font metric used by this object for Text which uses bold/italic fonts*/
+ QFontMetrics &getFontMetrics(UMLWidget::FontType fontType);
+ /** set the font metric to use */
+ void setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm);
+ void setupFontType(QFont &font, UMLWidget::FontType fontType);
+
+ /**
+ * Initializes key attributes of the class.
+ */
+ void init();
+
+ ///////////////// Data Loaded/Saved /////////////////////////////////
+
+ /**
+ * This flag indicates if the UMLWidget uses the Diagram FillColour
+ */
+ bool m_bUseFillColour;
+
+ /**
+ * true by default, false if the colours have
+ * been explicitly set for this widget
+ */
+ bool m_bUsesDiagramFillColour;
+ bool m_bUsesDiagramUseFillColour;
+
+ /**
+ * Color of the background of the widget
+ */
+ QColor m_FillColour;
+
+ /**
+ * A list of AssociationWidgets between the UMLWidget and other UMLWidgets in the diagram
+ */
+ AssociationWidgetList m_Assocs;
+
+ /**
+ * getName() returns the name from the UMLObject if this widget has an
+ * underlying UMLObject; if it does not, then getName() returns the local
+ * m_Text (notably the case for FloatingTextWidget.)
+ */
+ QString m_Text;
+
+ /**
+ * The font the widget will use.
+ */
+ QFont m_Font;
+
+ /**
+ * Holds whether this widget is a component instance (i.e. on a deployment diagram)
+ */
+ bool m_bIsInstance;
+
+ /**
+ * The instance name (used if on a deployment diagram)
+ */
+ QString m_instanceName;
+
+ /**
+ * Should the stereotype be displayed
+ */
+ bool m_bShowStereotype;
+
+ ///////////////// End of Data Loaded/Saved //////////////////////////
+
+ bool m_bSelected, m_bStartMove;
+
+ int m_nPosX, m_origZ;
+ ListPopupMenu *m_pMenu;
+ UMLDoc *m_pDoc; ///< shortcut for UMLApp::app()->getDocument()
+ bool m_bResizable;
+ QFontMetrics *m_pFontMetrics[FT_INVALID];
+
+ /**
+ * It is true if the Activate Function has been called for this
+ * class instance
+ */
+ bool m_bActivated;
+
+ /**
+ * Change Widget Behaviour
+ */
+ bool m_bIgnoreSnapToGrid;
+ bool m_bIgnoreSnapComponentSizeToGrid;
+
+ /**
+ * Controller for user interaction events.
+ */
+ UMLWidgetController *m_widgetController;
+
+public slots:
+
+ /**
+ * This slot is entered when an event has occurred on the views display,
+ * most likely a mouse event. Before it sends out that mouse event all
+ * children should make sure that they don't have a menu active or there
+ * could be more than one popup menu displayed.
+ */
+ virtual void slotRemovePopupMenu();
+
+ /**
+ * When a widget changes this slot captures that signal.
+ */
+ virtual void updateWidget();
+
+
+ /**
+ * Captures any popup menu signals for menus it created.
+ *
+ * @param sel The command which has to be executed.
+ */
+ virtual void slotMenuSelection(int sel);
+
+ /**
+ * Captures when another widget moves if it is link to it that signal.
+ *
+ * @param id The id of object behind the widget.
+ */
+ virtual void slotWidgetMoved(Uml::IDType id);
+
+ /**
+ * Captures a color change signal.
+ *
+ * @param viewID The id of the object behind the widget.
+ */
+ virtual void slotColorChanged(Uml::IDType viewID);
+
+ /**
+ * Captures a linewidth change signal.
+ *
+ * @param viewID The id of the object behind the widget.
+ */
+ virtual void slotLineWidthChanged(Uml::IDType viewID);
+
+ /**
+ * Captures a sigClearAllSelected signal sent by @ref UMLView
+ */
+ void slotClearAllSelected();
+
+ /**
+ * Tells the widget to snap to grid.
+ * Will use the grid settings of the @ref UMLView it belongs to.
+ */
+ void slotSnapToGrid();
+
+signals:
+ /**
+ * Emit when the widget moves its' position.
+ *
+ * @param id The id of the object behind the widget.
+ */
+ void sigWidgetMoved(Uml::IDType id);
+};
+
+#endif
diff --git a/umbrello/umbrello/umlwidgetcontroller.cpp b/umbrello/umbrello/umlwidgetcontroller.cpp
new file mode 100644
index 00000000..29ca98a1
--- /dev/null
+++ b/umbrello/umbrello/umlwidgetcontroller.cpp
@@ -0,0 +1,540 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlwidgetcontroller.h"
+
+// qt includes
+#include <qevent.h>
+#include <qpoint.h>
+
+// kde includes
+#include <kcursor.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+// app includes
+#include "umlwidget.h"
+#include "umlwidgetlist.h"
+#include "umlnamespace.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "umlobject.h"
+#include "listpopupmenu.h"
+#include "classifierwidget.h"
+#include "associationwidget.h"
+#include "messagewidget.h"
+
+using namespace Uml;
+
+UMLWidgetController::UMLWidgetController(UMLWidget *widget) {
+ m_widget = widget;
+
+ m_pressOffsetX = m_pressOffsetY = 0;
+ m_oldX = m_oldY = 0;
+ m_oldW = m_oldH = 0;
+ m_minSelectedX = m_minSelectedY = m_maxSelectedX = m_maxSelectedY = 0;
+
+ m_shiftPressed = false;
+ m_leftButtonDown = m_middleButtonDown = m_rightButtonDown = false;
+ m_inMoveArea = m_inResizeArea = 0;
+ m_wasSelected = m_moved = m_resized = 0;
+}
+
+UMLWidgetController::~UMLWidgetController() {
+}
+
+void UMLWidgetController::mousePressEvent(QMouseEvent *me) {
+ // If there is a button pressed already ignore other press events
+ if (m_leftButtonDown || m_middleButtonDown || m_rightButtonDown) {
+ return;
+ }
+
+ if (me->button() == Qt::LeftButton) {
+ m_leftButtonDown = true;
+ } else if (me->button() == Qt::RightButton) {
+ m_rightButtonDown = true;
+ } else {
+ m_middleButtonDown = true;
+ return;
+ }
+
+ //There is no harm in saving all the values of the widget even when
+ //they aren't going to be used
+ saveWidgetValues(me);
+
+ m_oldStatusBarMsg = UMLApp::app()->getStatusBarMsg();
+
+ if (me->state() == Qt::ShiftButton || me->state() == Qt::ControlButton) {
+ m_shiftPressed = true;
+
+ if (me->button() == Qt::LeftButton) {
+ m_inMoveArea = true;
+ }
+
+ if (!m_widget->m_bSelected) {
+ selectMultiple(me);
+ } else if (!m_rightButtonDown) {
+ m_wasSelected = false;
+ }
+ return;
+ }
+
+ m_shiftPressed = false;
+
+ int count = m_widget->m_pView->getSelectCount(true);
+ if (me->button() == Qt::LeftButton) {
+ if (m_widget->m_bSelected && count > 1) {
+ //Single selection is made in release event if the widget wasn't moved
+ m_inMoveArea = true;
+ lastUpdate.start();
+ return;
+ }
+
+ if (isInResizeArea(me)) {
+ m_inResizeArea = true;
+ } else {
+ m_inMoveArea = true;
+ }
+ }
+
+ //If widget wasn't selected, or it was selected but with other widgets also selected
+ if (!m_widget->m_bSelected || count > 1) {
+ selectSingle(me);
+ } else if (!m_rightButtonDown) {
+ m_wasSelected = false;
+ }
+}
+
+void UMLWidgetController::mouseMoveEvent(QMouseEvent* me) {
+ if (!m_leftButtonDown)
+ return;
+
+ if (m_inResizeArea) {
+ resize(me);
+ return;
+ }
+
+ if (!m_moved) {
+ UMLApp::app()->getDocument()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel move."));
+
+ m_moved = true;
+ //Maybe needed by AssociationWidget
+ m_widget->m_bStartMove = true;
+
+ setSelectionBounds();
+ }
+
+ QPoint position = getPosition(me);
+ int diffX = position.x() - m_widget->getX();
+ int diffY = position.y() - m_widget->getY();
+
+ if ((me->state() & Qt::ShiftButton) && (me->state() & Qt::ControlButton)) {
+ //Move in Y axis
+ diffX = 0;
+ } else if ((me->state() & Qt::ShiftButton) || (me->state() & Qt::ControlButton)) {
+ //Move in X axis
+ diffY = 0;
+ }
+
+ // kDebug() << "UMLWidgetController::mouseMoveEvent before constrainMovementForAllWidgets:"
+ // << " diffX=" << diffX << ", diffY=" << diffY << endl;
+ constrainMovementForAllWidgets(diffX, diffY);
+ // kDebug() << "UMLWidgetController::mouseMoveEvent after constrainMovementForAllWidgets:"
+ // << " diffX=" << diffX << ", diffY=" << diffY << endl;
+
+ //Nothing to move
+ if (diffX == 0 && diffY == 0) {
+ return;
+ }
+
+ UMLWidgetListIt it(m_selectedWidgetsList);
+ UMLWidget* widget;
+ it.toFirst();
+
+ bool update = false;
+ if (lastUpdate.elapsed() > 25) {
+ update = true;
+ lastUpdate.restart();
+
+ m_widget->adjustUnselectedAssocs(m_widget->getX(), m_widget->getY());
+ }
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->getWidgetController()->moveWidgetBy(diffX, diffY);
+ }
+ // kDebug() << endl;
+
+ // Move any selected associations.
+ AssociationWidgetList awl = m_widget->m_pView->getSelectedAssocs();
+ AssociationWidget *aw = NULL;
+ for (AssociationWidgetListIt ai(awl); (aw = ai.current()) != NULL; ++ai) {
+ if (aw->getSelected()) {
+ aw->moveEntireAssoc(diffX, diffY);
+ }
+ }
+
+ m_widget->m_pView->resizeCanvasToItems();
+ updateSelectionBounds(diffX, diffY);
+}
+
+void UMLWidgetController::mouseReleaseEvent(QMouseEvent *me) {
+ if (me->button() != Qt::LeftButton && me->button() != Qt::RightButton) {
+ if (m_middleButtonDown) {
+ m_middleButtonDown = false;
+ resetSelection();
+ }
+ } else if (me->button() == Qt::LeftButton) {
+ if (m_leftButtonDown) {
+ m_leftButtonDown = false;
+
+ if (!m_moved && !m_resized) {
+ if (!m_shiftPressed && (m_widget->m_pView->getSelectCount(true) > 1)) {
+ selectSingle(me);
+ } else if (!m_wasSelected) {
+ deselect(me);
+ }
+ } else {
+ if (m_moved) {
+ m_moved = false;
+
+ //Ensure associations are updated (the timer could prevent the
+ //adjustment in the last move event before the release)
+ UMLWidgetListIt it(m_selectedWidgetsList);
+ UMLWidget* widget;
+ it.toFirst();
+ while ((widget = it.current()) != 0) {
+ ++it;
+ widget->adjustAssocs(widget->getX(), widget->getY());
+ }
+
+ m_widget->m_bStartMove = false;
+ } else {
+ m_resized = false;
+ }
+
+ if ((m_inMoveArea && wasPositionChanged()) ||
+ (m_inResizeArea && wasSizeChanged())) {
+ m_widget->m_pDoc->setModified(true);
+ }
+
+ UMLApp::app()->getDocument()->writeToStatusBar(m_oldStatusBarMsg);
+ }
+
+ if (m_inResizeArea) {
+ m_inResizeArea = false;
+ m_widget->m_pView->setCursor(KCursor::arrowCursor());
+ } else {
+ m_inMoveArea = false;
+ }
+ }
+ } else if (me->button() == Qt::RightButton) {
+ if (m_rightButtonDown) {
+ m_rightButtonDown = false;
+ showPopupMenu(me);
+ } else if (m_leftButtonDown) {
+ //Cancel move/edit
+ QMouseEvent move(QMouseEvent::MouseMove,
+ QPoint(m_oldX + m_pressOffsetX, m_oldY + m_pressOffsetY),
+ Qt::LeftButton, Qt::NoButton);
+ mouseMoveEvent(&move);
+ QMouseEvent release(QMouseEvent::MouseButtonRelease,
+ QPoint(m_oldX + m_pressOffsetX, m_oldY + m_pressOffsetY),
+ Qt::LeftButton, Qt::NoButton);
+ mouseReleaseEvent(&release);
+ }
+ }
+
+ //TODO Copied from old code. Does it really work as intended?
+ UMLWidget *bkgnd = m_widget->m_pView->getWidgetAt(me->pos());
+ if (bkgnd) {
+ //kDebug() << "UMLWidgetController::mouseReleaseEvent: setting Z to "
+ // << bkgnd->getZ() + 1 << endl;
+ m_widget->setZ(bkgnd->getZ() + 1);
+ } else {
+ m_widget->setZ(0);
+ }
+}
+
+void UMLWidgetController::mouseDoubleClickEvent(QMouseEvent *me) {
+ if (me->button() != Qt::LeftButton) {
+ return;
+ }
+
+ selectSingle(me);
+
+ doMouseDoubleClick(me);
+}
+
+bool UMLWidgetController::isInResizeArea(QMouseEvent *me) {
+ const int m = 10;
+
+ if (m_widget->m_bResizable &&
+ me->x() >= (m_widget->getX() + m_widget->width() - m) &&
+ me->y() >= (m_widget->getY() + m_widget->height() - m)) {
+ m_widget->m_pView->setCursor(getResizeCursor());
+ return true;
+ } else {
+ m_widget->m_pView->setCursor(KCursor::arrowCursor());
+ return false;
+ }
+}
+
+QCursor UMLWidgetController::getResizeCursor() {
+ return KCursor::sizeFDiagCursor();
+}
+
+void UMLWidgetController::resizeWidget(int newW, int newH) {
+ m_widget->setSize(newW, newH);
+}
+
+void UMLWidgetController::moveWidgetBy(int diffX, int diffY) {
+ m_widget->setX(m_widget->getX() + diffX);
+ m_widget->setY(m_widget->getY() + diffY);
+}
+
+void UMLWidgetController::constrainMovementForAllWidgets(int &/*diffX*/, int &/*diffY*/) {
+}
+
+void UMLWidgetController::doMouseDoubleClick(QMouseEvent *) {
+ if (!m_widget || !m_widget->m_pMenu)
+ return;
+ m_widget->slotMenuSelection(ListPopupMenu::mt_Properties);
+}
+
+void UMLWidgetController::resetSelection() {
+ m_widget->m_pView->clearSelected();
+ m_widget->m_pView->resetToolbar();
+ m_widget->setSelected(false);
+
+ m_wasSelected = false;
+}
+
+void UMLWidgetController::selectSingle(QMouseEvent *me) {
+ m_widget->m_pView->clearSelected();
+
+ //Adds the widget to the selected widgets list, but as it has been cleared
+ //only the current widget is selected
+ selectMultiple(me);
+}
+
+void UMLWidgetController::selectMultiple(QMouseEvent *me) {
+ m_widget->m_bSelected = true;
+ m_widget->setSelected(m_widget->m_bSelected);
+ m_widget->m_pView->setSelected(m_widget, me);
+
+ m_wasSelected = true;
+}
+
+void UMLWidgetController::deselect(QMouseEvent *me) {
+ m_widget->m_bSelected = false;
+ m_widget->setSelected(m_widget->m_bSelected);
+ m_widget->m_pView->setSelected(m_widget, me);
+ //m_wasSelected is false implicitly, no need to set it again
+}
+
+void UMLWidgetController::saveWidgetValues(QMouseEvent *me) {
+ m_pressOffsetX = me->x() - m_widget->getX();
+ m_pressOffsetY = me->y() - m_widget->getY();
+
+ m_oldX = m_widget->getX();
+ m_oldY = m_widget->getY();
+
+ m_oldW = m_widget->width();
+ m_oldH = m_widget->height();
+}
+
+void UMLWidgetController::setSelectionBounds() {
+ if (m_widget->m_pView->getSelectCount() > 0) {
+ m_selectedWidgetsList.clear();
+ m_widget->m_pView->getSelectedWidgets(m_selectedWidgetsList, false);
+
+ updateSelectionBounds(1, 1);
+ }
+}
+
+//TODO optimize it
+void UMLWidgetController::updateSelectionBounds(int diffX, int diffY) {
+ if (diffX != 0) {
+ m_minSelectedX = getSmallestX(m_selectedWidgetsList);
+ m_maxSelectedX = getBiggestX(m_selectedWidgetsList);
+ }
+ if (diffY != 0) {
+ m_minSelectedY = getSmallestY(m_selectedWidgetsList);
+ m_maxSelectedY = getBiggestY(m_selectedWidgetsList);
+ }
+}
+
+void UMLWidgetController::resize(QMouseEvent *me) {
+ UMLApp::app()->getDocument()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel resize."));
+
+ m_resized = true;
+
+ int newW = m_oldW + me->x() - m_widget->getX() - m_pressOffsetX;
+ int newH = m_oldH + me->y() - m_widget->getY() - m_pressOffsetY;
+
+ if ((me->state() & Qt::ShiftButton) && (me->state() & Qt::ControlButton)) {
+ //Move in Y axis
+ newW = m_oldW;
+ } else if ((me->state() & Qt::ShiftButton) || (me->state() & Qt::ControlButton)) {
+ //Move in X axis
+ newH = m_oldH;
+ }
+
+ m_widget->constrain(newW, newH);
+ resizeWidget(newW, newH);
+ m_widget->adjustAssocs(m_widget->getX(), m_widget->getY());
+
+ m_widget->m_pView->resizeCanvasToItems();
+}
+
+//TODO refactor with AlignToolbar method.
+int UMLWidgetController::getSmallestX(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ widget = it.toFirst();
+ // leave function upon empty widget list
+ if (NULL == widget) return 0;
+ int smallestX = widget->getX();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (smallestX > widget->getX())
+ smallestX = widget->getX();
+ }
+
+ return smallestX;
+}
+
+//TODO refactor with AlignToolbar method.
+int UMLWidgetController::getSmallestY(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ widget = it.toFirst();
+ // leave function upon empty widget list
+ if (NULL == widget) return 0;
+ int smallestY = widget->getY();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (smallestY > widget->getY())
+ smallestY = widget->getY();
+ }
+
+ return smallestY;
+}
+
+//TODO refactor with AlignToolbar method.
+int UMLWidgetController::getBiggestX(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ widget = it.toFirst();
+ // leave function upon empty widget list
+ if (NULL == widget) return 0;
+ int biggestX = widget->getX();
+ biggestX += it.current()->getWidth();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (biggestX < widget->getX() + widget->getWidth())
+ biggestX = widget->getX() + widget->getWidth();
+ }
+
+ return biggestX;
+}
+
+//TODO refactor with AlignToolbar method.
+int UMLWidgetController::getBiggestY(const UMLWidgetList &widgetList) {
+ UMLWidgetListIt it(widgetList);
+ UMLWidget* widget;
+
+ widget = it.toFirst();
+ // leave function upon empty widget list
+ if (NULL == widget) return 0;
+ int biggestY = widget->getY();
+ biggestY += it.current()->getHeight();
+ ++it;
+
+ while ((widget = it.current()) != 0) {
+ ++it;
+ if (biggestY < widget->getY() + widget->getHeight())
+ biggestY = widget->getY() + widget->getHeight();
+ }
+
+ return biggestY;
+}
+
+QPoint UMLWidgetController::getPosition(QMouseEvent* me) {
+ /*
+ kDebug() << "UMLWidgetController::getPosition: me->x=" << me->x()
+ << " m_widget->getX=" << m_widget->getX() << ", m_oldX=" << m_oldX
+ << ", m_pressOffsetX=" << m_pressOffsetX << endl;
+ kDebug() << "UMLWidgetController::getPosition: me->y=" << me->y()
+ << " m_widget->getY=" << m_widget->getY() << ", m_oldY=" << m_oldY
+ << ", m_pressOffsetY=" << m_pressOffsetY << endl;
+ */
+ int newX = me->x() + m_widget->getX() - m_oldX - m_pressOffsetX;
+ int newY = me->y() + m_widget->getY() - m_oldY - m_pressOffsetY;
+ int maxX = m_widget->m_pView->canvas()->width();
+ int maxY = m_widget->m_pView->canvas()->height();
+
+ m_oldX = newX;
+ m_oldY = newY;
+
+ if (newX + (m_minSelectedX - m_widget->getX()) < 0) {
+ //kDebug() << "UMLWidgetController::getPosition: got into cond.1" << endl;
+ newX = m_widget->getX() - m_minSelectedX;
+ }
+ if (newY + (m_minSelectedY - m_widget->getY()) < 0) {
+ //kDebug() << "UMLWidgetController::getPosition: got into cond.2" << endl;
+ newY = m_widget->getY() - m_minSelectedY;
+ }
+ if (newX + (m_maxSelectedX - m_widget->getX()) > maxX) {
+ //kDebug() << "UMLWidgetController::getPosition: got into cond.3" << endl;
+ newX = maxX - (m_maxSelectedX - m_widget->getX());
+ }
+ if (newY + (m_maxSelectedY - m_widget->getY()) > maxY) {
+ //kDebug() << "UMLWidgetController::getPosition: got into cond.4" << endl;
+ newY = maxY - (m_maxSelectedY - m_widget->getY());
+ }
+ return QPoint(newX, newY);
+}
+
+QPoint UMLWidgetController::getPositionDifference(QMouseEvent* me) {
+ QPoint newPoint = getPosition(me);
+ const int diffX = newPoint.x() - m_widget->getX();
+ const int diffY = newPoint.y() - m_widget->getY();
+ return QPoint(diffX, diffY);
+}
+
+void UMLWidgetController::showPopupMenu(QMouseEvent *me) {
+ //TODO why this condition?
+ if (m_widget->m_pMenu) {
+ return;
+ }
+ m_widget->startPopupMenu(me->globalPos());
+}
+
+bool UMLWidgetController::wasSizeChanged() {
+ return m_oldW != m_widget->getWidth() || m_oldH != m_widget->getHeight();
+}
+
+bool UMLWidgetController::wasPositionChanged() {
+ return m_oldX != m_widget->getX() || m_oldY != m_widget->getY();
+}
diff --git a/umbrello/umbrello/umlwidgetcontroller.h b/umbrello/umbrello/umlwidgetcontroller.h
new file mode 100644
index 00000000..552ea174
--- /dev/null
+++ b/umbrello/umbrello/umlwidgetcontroller.h
@@ -0,0 +1,476 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UMLWIDGETCONTROLLER_H
+#define UMLWIDGETCONTROLLER_H
+
+// qt includes
+#include <qdatetime.h>
+
+// app includes
+#include "umlwidgetlist.h"
+
+class QCursor;
+class QMouseEvent;
+class QMoveEvent;
+class QPoint;
+
+class UMLWidget;
+
+/**
+ * Controller for UMLWidget
+ * This class takes care of user interaction with UMLWidgets: select, deselect,
+ * move, resize...
+ * Those actions are done using events. There are handlers for mousePressEvent,
+ * mouseMoveEvent, mouseReleaseEvent and mouseDoubleClickEvent. There's more
+ * information about each of them in their respective documentation.
+ *
+ * Behaviour of this class can be customized overriding the handlers themselves
+ * (which isn't recommended) or, better, overriding the virtual protected
+ * methods.
+ *
+ * The area that is considered as "resize area" can be customized with
+ * isInResizeArea, so when there's a pressed button in this area, mouseMoveEvent
+ * will resize the widget.
+ * Also, if the resize area doesn't need to be modified, but the cursor to be
+ * used when the mouse is in that area can be done with getResizeCursor.
+ * When a widget is being resized, it's done using resizeWidget, so overriding
+ * it makes possible to, for example, constrain the resizing only in one axis
+ * no matter how the mouse was moved.
+ *
+ * Widget move can also be customized. The widgets are moved in mouseMoveEvent
+ * using the moveWidgetBy method of the controller of each selected widget.
+ * Overriding this method widget movement can be, for example, constrained to
+ * an axis, no matter if the widget is being moved explicitly or as part of a
+ * selection.
+ * On the other hand, the move of all the selected widgets can be constrained
+ * with constrainMovementForAllWidgets. This method, called in the controller
+ * that is handling the mouseMoveEvent, modifies the difference between the
+ * current position of the widgets and the new position to be moved to. For
+ * example, if a widget shouldn't be moved in X axis, it's receiving the
+ * mouseMoveEvents and there are other widgets selected, those other widgets
+ * shouldn't be allowed either to be moved in X axis.
+ *
+ * The behaviour when double clicking on the widget after it's selected can be
+ * customized with doMouseDoubleClick.
+ *
+ * @author Umbrello UML Modeller Authors <uml-devel@lists.sourceforge.net>
+ */
+class UMLWidgetController {
+public:
+
+ /**
+ * Constructor for UMLWidgetController.
+ *
+ * @param widget The widget which uses the controller.
+ */
+ UMLWidgetController(UMLWidget *widget);
+
+ /**
+ * Destructor for UMLWidgetController.
+ */
+ virtual ~UMLWidgetController();
+
+ /**
+ * Handles a mouse press event.
+ * It'll select the widget (or mark it to be deselected) and prepare it to
+ * be moved or resized. Go on reading for more info about this.
+ *
+ * Widget values and message bar status are saved.
+ *
+ * If shift or control buttons are pressed, we're in move area no matter
+ * where the button was pressed in the widget. Moreover, if the widget
+ * wasn't already selected, it's added to the selection. If already selected,
+ * it's marked to be deselected when releasing the button (provided it isn't
+ * moved).
+ * Also, if the widget is already selected with other widgets but shift nor
+ * control buttons are pressed, we're in move area. If finally we don't move
+ * the widget, it's selected and the other widgets deselected when releasing
+ * the left button.
+ *
+ * If shift nor control buttons are pressed, we're facing a single selection.
+ * Depending on the position of the cursor, we're in move or in resize area.
+ * If the widget wasn't selected (both when there are no widgets selected, or
+ * when there're other widgets selected but not the one receiving the press
+ * event) it's selected and the others deselected, if any. If already selected,
+ * it's marked to be deselected when releasing the button (provided it wasn't
+ * moved or resized).
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mousePressEvent(QMouseEvent *me);
+
+ /**
+ * Handles a mouse move event.
+ * It resizes or moves the widget, depending on where the cursor is pressed
+ * on the widget. Go on reading for more info about this.
+ *
+ * If resizing, the widget is resized using resizeWidget (where specific
+ * widget resize constrain can be applied), and then the associations are
+ * adjusted.
+ * The resizing can be constrained also to an specific axis using control
+ * and shift buttons. If on or another is pressed, it's constrained to X axis.
+ * If both are pressed, it's constrained to Y axis.
+ *
+ * If not resizing, the widget is being moved. If the move is being started,
+ * the selection bounds are set (which includes updating the list of selected
+ * widgets).
+ * The difference between the previous position of the selection and the new
+ * one is got (taking in account the selection bounds so widgets don't go
+ * beyond the canvas limits). Then, it's constrained to X or Y axis depending
+ * on shift and control buttons.
+ * A further constrain is made using constrainMovementForAllWidgets (for example,
+ * if the widget that receives the event can only be moved in Y axis, with this
+ * method the movement of all the widgets in the selection can be constrained to
+ * be moved only in Y axis).
+ * Then, all the selected widgets are moved using moveWidgetBy (where specific
+ * widget movement constrain can be applied) and, if an specific amount of time
+ * passed from the last move event, the associations are also updated (they're
+ * not updated always to be easy on the CPU). Finally, the canvas is resized,
+ * and selection bounds updated.
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseMoveEvent(QMouseEvent* me);
+
+ /**
+ * Handles a mouse release event.
+ * It selects or deselects the widget and cancels or confirms the move or
+ * resize. Go on reading for more info about this.
+ * No matter which tool is selected, Z position of widget is updated.
+ *
+ * Middle button release resets the selection.
+ * Left button release, if it wasn't moved nor resized, selects the widget
+ * and deselect the others if it wasn't selected and there were other widgets
+ * selected. If the widget was marked to be deselected, deselects it.
+ * If it was moved or resized, the document is set to modified if position
+ * or size changed. Also, if moved, all the associations are adjusted because
+ * the timer could have prevented the adjustment in the last move event before
+ * the release.
+ * If mouse was pressed in resize area, cursor is set again to normal cursor
+ * Right button release if right button was pressed shows the pop up menu for
+ * the widget.
+ * If left button was pressed, it cancels the move or resize with a mouse move
+ * event at the same position than the cursor was when pressed. Another left
+ * button release is also sent.
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseReleaseEvent(QMouseEvent * me);
+
+ /**
+ * Handles a mouse double click event.
+ * If the button wasn't left button it does nothing. Otherwise, it selects
+ * the widget (deselecting other selected widgets, if any) and executes
+ * doMouseDoubleClick.
+ * @see doMouseDoubleClick
+ *
+ * @param me The QMouseEvent event.
+ */
+ virtual void mouseDoubleClickEvent(QMouseEvent *me);
+
+protected:
+
+ /**
+ * Saves the values of the widget needed for move/resize.
+ * The values saved are: the offset from the cursor respect to the upper left
+ * corner of the widget in m_pressOffsetX/Y, the position in m_oldX/Y and the
+ * size in m_oldW/H.
+ *
+ * It can be overridden to save subclass specific values whenever a move or
+ * resize begins. However, parent method (that is, this method) must be
+ * called in the overridden method.
+ *
+ * @param me The QMouseEvent to get the offset from.
+ */
+ virtual void saveWidgetValues(QMouseEvent *me);
+
+ /**
+ * Checks if the mouse is in resize area (right bottom corner), and sets
+ * the cursor depending on that.
+ * The cursor used when resizing is gotten from getResizeCursor().
+ *
+ * @param me The QMouseEVent to check.
+ * @return true if the mouse is in resize area, false otherwise.
+ */
+ virtual bool isInResizeArea(QMouseEvent *me);
+
+ /**
+ * Returns the cursor to be shown when resizing the widget.
+ *
+ * Default cursor is KCursor::sizeFDiagCursor().
+ *
+ * @return The cursor to be shown when resizing the widget.
+ */
+ virtual QCursor getResizeCursor();
+
+ /**
+ * Resizes the widget.
+ * It's called from resize, after the values are constrained and before
+ * the associations are adjusted.
+ *
+ * Default behaviour is resize the widget using the new size values.
+ * @see resize
+ *
+ * @param newW The new width for the widget.
+ * @param newH The new height for the widget.
+ */
+ virtual void resizeWidget(int newW, int newH);
+
+ /**
+ * Moves the widget to a new position using the difference between the
+ * current position and the new position.
+ * This method doesn't adjust associations. It only moves the widget.
+ *
+ * It can be overridden to constrain movement of m_widget only in one axis even when
+ * the user isn't constraining the movement with shift or control buttons, for example.
+ * The movement policy set here is applied whenever the widget is moved, being it
+ * moving it explicitly, or as a part of a selection but not receiving directly the
+ * mouse events.
+ *
+ * Default behaviour is move the widget to the new position using the diffs.
+ * @see constrainMovementForAllWidgets
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void moveWidgetBy(int diffX, int diffY);
+
+ /**
+ * Modifies the value of the diffX and diffY variables used to move the widgets.
+ *
+ * It can be overridden to constrain movement of all the selected widgets only in one
+ * axis even when the user isn't constraining the movement with shift or control
+ * buttons, for example.
+ * The difference with moveWidgetBy is that the diff positions used here are
+ * applied to all the selected widgets instead of only to m_widget, and that
+ * moveWidgetBy, in fact, moves the widget, and here simply the diff positions
+ * are modified.
+ *
+ * Default behaviour is do nothing.
+ * @see moveWidgetBy
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ virtual void constrainMovementForAllWidgets(int &diffX, int &diffY);
+
+ /**
+ * Executes the action for double click in the widget.
+ * It's called only if the button used was left button.
+ * Before calling this method, the widget is selected.
+ *
+ * Default behaviour is show the properties dialog for the widget using
+ * m_widget->slotMenuSelection(ListPopupMenu::mt_Properties);
+ * If the widget doesn't have a property dialog (from the Widget_Type enum, those that
+ * don't have an UMLObject representation) there's no need to override
+ * the method, it simply does nothing.
+ *
+ * @param me The QMouseEvent which triggered the double click event.
+ */
+ virtual void doMouseDoubleClick(QMouseEvent *me);
+
+ /**
+ * Clears the selection, resets the toolbar and deselects the widget.
+ */
+ void resetSelection();
+
+ /**
+ * Selects the widget and clears the other selected widgets, if any.
+ *
+ * @param me The QMouseEvent which made the selection.
+ */
+ void selectSingle(QMouseEvent *me);
+
+ /**
+ * Selects the widget and adds it to the list of selected widgets.
+ *
+ * @param me The QMouseEvent which made the selection.
+ */
+ void selectMultiple(QMouseEvent *me);
+
+ /**
+ * Deselects the widget and removes it from the list of selected widgets.
+ *
+ * @param me The QMouseEvent which made the selection.
+ */
+ void deselect(QMouseEvent *me);
+
+ /**
+ * Fills m_selectedWidgetsList and sets the selection bounds ((m_min/m_max)X/Y attributes).
+ */
+ void setSelectionBounds();
+
+ /**
+ * Updates the selection bounds based on the movement made.
+ * If it was only a vertical movement, there's no need to update horizontal bounds,
+ * and vice versa.
+ *
+ * @param diffX The difference between current X position and new X position.
+ * @param diffY The difference between current Y position and new Y position.
+ */
+ void updateSelectionBounds(int diffX, int diffY);
+
+ /**
+ * Resizes the widget and adjusts the associations.
+ * It's called when a mouse move event happens and the cursor was
+ * in resize area when pressed.
+ * Resizing can be constrained to an specific axis using control and shift buttons.
+ *
+ * @param me The QMouseEvent to get the values from.
+ */
+ void resize(QMouseEvent *me);
+
+ /**
+ * Returns the smallest X position of all the widgets in the list.
+ *
+ * @param widgetList A list with UMLWidgets.
+ * @return The smallest X position.
+ */
+ int getSmallestX(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the smallest Y position of all the widgets in the list.
+ *
+ * @param widgetList A list with UMLWidgets.
+ * @return The smallest Y position.
+ */
+ int getSmallestY(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the biggest X position of all the widgets in the list.
+ *
+ * @param widgetList A list with UMLWidgets.
+ * @return The biggest X position.
+ */
+ int getBiggestX(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the biggest Y position of all the widgets in the list.
+ *
+ * @param widgetList A list with UMLWidgets.
+ * @return The biggest Y position.
+ */
+ int getBiggestY(const UMLWidgetList &widgetList);
+
+ /**
+ * Returns the adjusted position for the given mouse event.
+ * The adjusted position is computed using the current widget position
+ * m_widget->get{X,Y}(), the previous position m_old{X,Y}, and the
+ * mouse press offset m_pressOffset{X,Y}.
+ *
+ * @param me The QMouseEvent for which to get the adjusted position.
+ * @return A QPoint with the adjusted position.
+ */
+ QPoint getPosition(QMouseEvent *me);
+
+ /**
+ * Returns a QPoint with the new X and Y position difference of the mouse event
+ * respect to the position of the widget.
+ *
+ * @param me The QMouseEvent to get the position to compare.
+ * @return A QPoint with the position difference.
+ */
+ QPoint getPositionDifference(QMouseEvent *me);
+
+ /**
+ * Shows the widget popup menu where the mouse event points to.
+ *
+ * @param me The QMouseEvent which triggered the showing.
+ */
+ void showPopupMenu(QMouseEvent *me);
+
+ /**
+ * Checks if the size of the widget changed respect to the size that
+ * it had when press event was fired.
+ *
+ * @return true if was resized, false otherwise.
+ */
+ bool wasSizeChanged();
+
+ /**
+ * Checks if the position of the widget changed respect to the position that
+ * it had when press event was fired.
+ *
+ * @return true if was moved, false otherwise.
+ */
+ bool wasPositionChanged();
+
+ /**
+ * The widget which uses the controller.
+ */
+ UMLWidget *m_widget;
+
+ /**
+ * Timer that prevents excessive updates (be easy on the CPU).
+ */
+ QTime lastUpdate;
+
+ /**
+ * A list containing the selected widgets.
+ * It's filled by setSelectionBounds method. It must be filled again if
+ * selected widgets changed. It is cleared only in setSelectionBounds, just
+ * before filling it.
+ * Select, deselect and so on methods DON'T modify this list.
+ */
+ UMLWidgetList m_selectedWidgetsList;
+
+ /**
+ * The text in the status bar when the cursor was pressed.
+ */
+ QString m_oldStatusBarMsg;
+
+ /**
+ * The X/Y offset from the position of the cursor when it was pressed to the
+ * upper left corner of the widget.
+ */
+ int m_pressOffsetX, m_pressOffsetY;
+
+ /**
+ * The X/Y position the widget had when the movement started.
+ */
+ int m_oldX, m_oldY;
+
+ /**
+ * The width/height the widget had when the resize started.
+ */
+ int m_oldW, m_oldH;
+
+ /**
+ * The minimum/maximum X/Y position of all the selected widgets.
+ */
+ int m_minSelectedX, m_minSelectedY, m_maxSelectedX, m_maxSelectedY;
+
+ /**
+ * If shift or control button were pressed in mouse press event.
+ */
+ bool m_shiftPressed;
+
+ /**
+ * If the left/middle/right button is pressed.
+ */
+ bool m_leftButtonDown, m_middleButtonDown, m_rightButtonDown;
+
+ /**
+ * If cursor was in move/resize area when left button was pressed (and no
+ * other widgets were selected).
+ */
+ bool m_inMoveArea, m_inResizeArea;
+
+ /**
+ * If the widget was selected/moved/resized in the press and release cycle.
+ * Moved/resized is true if the widget was moved/resized even if the final
+ * position/size is the same as the starting one.
+ */
+ bool m_wasSelected, m_moved, m_resized;
+};
+
+#endif
diff --git a/umbrello/umbrello/umlwidgetlist.h b/umbrello/umbrello/umlwidgetlist.h
new file mode 100644
index 00000000..45a9db6b
--- /dev/null
+++ b/umbrello/umbrello/umlwidgetlist.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ umlwidgetlist.h - description
+ -------------------
+ begin : Sat Dec 29 2001
+ copyright : (C) 2001 by Gustavo Madrigal
+ email : gmadrigal@nextphere.com
+ Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef UMLWIDGETLIST_H
+#define UMLWIDGETLIST_H
+
+#include <qptrlist.h>
+
+class UMLWidget;
+
+typedef QPtrList<UMLWidget> UMLWidgetList;
+typedef QPtrListIterator<UMLWidget> UMLWidgetListIt;
+
+#endif
diff --git a/umbrello/umbrello/uniqueid.cpp b/umbrello/umbrello/uniqueid.cpp
new file mode 100644
index 00000000..ce4dc117
--- /dev/null
+++ b/umbrello/umbrello/uniqueid.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "uniqueid.h"
+
+// system includes
+#include <kapplication.h>
+
+namespace UniqueID {
+
+/**
+ * Each model object gets assigned a unique ID.
+ */
+Uml::IDType m_uniqueID;
+
+Uml::IDType gen() {
+ static char buf[20];
+ int length = 12;
+ int i = 0;
+ // Source: KDE4 kdelibs/kdecore/krandom.cpp KRandom::randomString()
+ while (length--) {
+ int r = kapp->random() % 62;
+ r += 48;
+ if (r > 57)
+ r += 7;
+ if (r > 90)
+ r += 6;
+ buf[i++] = char(r);
+ }
+ buf[i] = '\0';
+ m_uniqueID = std::string(buf);
+ return m_uniqueID;
+}
+
+void init() {
+ m_uniqueID = Uml::id_Reserved;
+}
+
+Uml::IDType get() {
+ return m_uniqueID;
+}
+
+void set(Uml::IDType id) {
+ m_uniqueID = id;
+}
+
+} // end namespace UniqueID
+
diff --git a/umbrello/umbrello/uniqueid.h b/umbrello/umbrello/uniqueid.h
new file mode 100644
index 00000000..7dcbd4bb
--- /dev/null
+++ b/umbrello/umbrello/uniqueid.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef UNIQUEID_H
+#define UNIQUEID_H
+
+#include "umlnamespace.h"
+
+namespace UniqueID {
+
+ /**
+ * MAIN FUNCTION: Return a new unique ID.
+ */
+ Uml::IDType gen();
+
+
+ /////////// auxiliary functions ////////////////////////////////////
+ // Only required by code that does special operations on unique IDs.
+ // NB Try to avoid these functions if possible because their
+ // implementation and/or programming interface may change.
+
+ /**
+ * Reinitialize the unique ID counter.
+ * Should not normally be required because the ID counter is
+ * initialized by default anyway.
+ */
+ void init();
+
+ /**
+ * Return the last generated unique ID without generating a new one.
+ */
+ Uml::IDType get();
+
+ /**
+ * Explicitly set a new ID value.
+ */
+ void set(Uml::IDType id);
+
+} // end namespace UniqueID
+
+#endif
+
diff --git a/umbrello/umbrello/usecase.cpp b/umbrello/umbrello/usecase.cpp
new file mode 100644
index 00000000..526f533b
--- /dev/null
+++ b/umbrello/umbrello/usecase.cpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "usecase.h"
+
+UMLUseCase::UMLUseCase(const QString & name, Uml::IDType id)
+ : UMLCanvasObject(name, id) {
+ init();
+}
+
+UMLUseCase::~UMLUseCase() {}
+
+void UMLUseCase::init() {
+ m_BaseType = Uml::ot_UseCase;
+}
+
+UMLObject* UMLUseCase::clone() const {
+ UMLUseCase *clone = new UMLUseCase();
+ UMLObject::copyInto(clone);
+ return clone;
+}
+
+void UMLUseCase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement) {
+ QDomElement usecaseElement = UMLObject::save("UML:UseCase", qDoc);
+ qElement.appendChild(usecaseElement);
+}
+
+bool UMLUseCase::load(QDomElement& ) {
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/usecase.h b/umbrello/umbrello/usecase.h
new file mode 100644
index 00000000..5c262b10
--- /dev/null
+++ b/umbrello/umbrello/usecase.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef USECASE_H
+#define USECASE_H
+
+#include "umlcanvasobject.h"
+
+/**
+ * This class contains the non-graphical information required for a UML UseCase.
+ * This class inherits from @ref UMLCanvasObject which contains most of the information.
+ *
+ * @short Information for a non-graphical UML UseCase.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class UMLUseCase : public UMLCanvasObject {
+public:
+ /**
+ * Creates a UseCase object
+ *
+ * @param name The name of the object.
+ * @param id The id of the object.
+ */
+ explicit UMLUseCase(const QString & name = "", Uml::IDType id = Uml::id_None);
+
+ /**
+ * Standard deconstructor
+ */
+ ~UMLUseCase();
+
+ /**
+ * Initializes key variables of the class.
+ */
+ virtual void init();
+
+ /**
+ * Make a clone of this object.
+ */
+ virtual UMLObject* clone() const;
+
+ /**
+ * Creates the <UML:UseCase> element.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+protected:
+ /**
+ * Loads the <UML:UseCase> element (empty.)
+ */
+ bool load( QDomElement & element );
+};
+
+#endif
diff --git a/umbrello/umbrello/usecasewidget.cpp b/umbrello/umbrello/usecasewidget.cpp
new file mode 100644
index 00000000..f7564036
--- /dev/null
+++ b/umbrello/umbrello/usecasewidget.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header file
+#include "usecasewidget.h"
+// system includes
+#include <qpainter.h>
+#include <kdebug.h>
+// local includes
+#include "usecase.h"
+#include "umlview.h"
+
+
+UseCaseWidget::UseCaseWidget(UMLView * view, UMLUseCase *o) : UMLWidget(view, o) {
+ UMLWidget::setBaseType(Uml::wt_UseCase);
+ //updateComponentSize(); Doing this during loadFromXMI() gives futile updates.
+ // Instead, it is done afterwards by UMLWidget::activate()
+}
+
+UseCaseWidget::~UseCaseWidget() {}
+
+void UseCaseWidget::draw(QPainter & p, int offsetX, int offsetY) {
+ UMLWidget::setPen(p);
+ if ( UMLWidget::getUseFillColour() )
+ p.setBrush( UMLWidget::getFillColour() );
+ QFont font = UMLWidget::getFont();
+ font.setUnderline(false);
+ font.setBold(false);
+ font.setItalic( m_pObject->getAbstract() );
+ p.setFont( font );
+ const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
+ const int fontHeight = fm.lineSpacing();
+ const int w = width();
+ const int h = height();
+ //int middleX = w / 2;
+ const int textStartY = (h / 2) - (fontHeight / 2);
+
+ p.drawEllipse(offsetX, offsetY, w, h);
+ p.setPen(Qt::black);
+ p.drawText(offsetX + UC_MARGIN, offsetY + textStartY, w - UC_MARGIN * 2, fontHeight, Qt::AlignCenter, getName());
+ UMLWidget::setPen(p);
+ if(m_bSelected)
+ drawSelected(&p, offsetX, offsetY);
+}
+
+QSize UseCaseWidget::calculateSize() {
+ const UMLWidget::FontType ft = ( m_pObject->getAbstract() ? FT_BOLD_ITALIC : FT_BOLD );
+ const QFontMetrics &fm = UMLWidget::getFontMetrics(ft);
+ const int fontHeight = fm.lineSpacing();
+ const int textWidth = fm.width(getName());
+ int width = textWidth > UC_WIDTH?textWidth:UC_WIDTH;
+ int height = UC_HEIGHT + fontHeight + UC_MARGIN;
+
+ width += UC_MARGIN * 2;
+
+ return QSize(width, height);
+}
+
+void UseCaseWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+ QDomElement usecaseElement = qDoc.createElement( "usecasewidget" );
+ UMLWidget::saveToXMI( qDoc, usecaseElement );
+ qElement.appendChild( usecaseElement );
+}
+
diff --git a/umbrello/umbrello/usecasewidget.h b/umbrello/umbrello/usecasewidget.h
new file mode 100644
index 00000000..509ff7a5
--- /dev/null
+++ b/umbrello/umbrello/usecasewidget.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef USECASEWIDGET_H
+#define USECASEWIDGET_H
+#include "umlwidget.h"
+
+#define UC_MARGIN 5
+#define UC_WIDTH 60
+#define UC_HEIGHT 30
+
+
+class UMLUseCase;
+
+/**
+ * This class is the graphical version of a UMLUseCase. A UseCaseWidget is created
+ * by a @ref UMLView. An UseCaseWidget belongs to only one @ref UMLView instance.
+ * When the @ref UMLView instance that this class belongs to, it will be automatically deleted.
+ *
+ * If the @ref UseCase class that this UseCaseWidget is displaying is deleted, the @ref UMLView will
+ * make sure that this instance is also deleted.
+ *
+ * The UseCaseWidget class inherits from the @ref UMLWidget class which adds most of the functionality
+ * to this class.
+ *
+ * @short A graphical version of a UMLUseCase.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class UseCaseWidget : public UMLWidget {
+public:
+
+ /**
+ * Creates a UseCase widget.
+ *
+ * @param view The parent of the widget.
+ * @param o The UMLObject to represent.
+ */
+ UseCaseWidget(UMLView * view, UMLUseCase *o);
+
+
+ /**
+ * destructor
+ */
+ virtual ~UseCaseWidget();
+
+ /**
+ * Overrides the standard paint event.
+ */
+ void draw(QPainter & p, int offsetX, int offsetY);
+
+ /**
+ * Saves this UseCase to file.
+ */
+ void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ // For loading we can use the loadFromXMI() inherited from UMLWidget.
+
+protected:
+ /**
+ * Overrides method from UMLWidget
+ */
+ QSize calculateSize();
+};
+
+#endif
diff --git a/umbrello/umbrello/widget_factory.cpp b/umbrello/umbrello/widget_factory.cpp
new file mode 100644
index 00000000..5bb8eeae
--- /dev/null
+++ b/umbrello/umbrello/widget_factory.cpp
@@ -0,0 +1,241 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "widget_factory.h"
+
+// qt/kde includes
+#include <kdebug.h>
+
+// app includes
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "object_factory.h"
+#include "floatingtextwidget.h"
+#include "classifierwidget.h"
+#include "classifier.h"
+#include "packagewidget.h"
+#include "package.h"
+#include "folder.h"
+#include "componentwidget.h"
+#include "component.h"
+#include "nodewidget.h"
+#include "node.h"
+#include "artifactwidget.h"
+#include "artifact.h"
+#include "datatypewidget.h"
+#include "enumwidget.h"
+#include "enum.h"
+#include "entitywidget.h"
+#include "entity.h"
+#include "actorwidget.h"
+#include "actor.h"
+#include "usecasewidget.h"
+#include "usecase.h"
+#include "notewidget.h"
+#include "boxwidget.h"
+#include "associationwidget.h"
+#include "messagewidget.h"
+#include "objectwidget.h"
+#include "statewidget.h"
+#include "forkjoinwidget.h"
+#include "activitywidget.h"
+#include "seqlinewidget.h"
+
+namespace Widget_Factory {
+
+UMLWidget *createWidget(UMLView *view, UMLObject *o) {
+ QPoint pos = view->getPos();
+ int y = pos.y();
+ Uml::Diagram_Type diagramType = view->getType();
+ Uml::Object_Type type = o->getBaseType();
+ UMLWidget *newWidget = NULL;
+ switch (type) {
+ case Uml::ot_Actor:
+ if (diagramType == Uml::dt_Sequence) {
+ ObjectWidget *ow = new ObjectWidget(view, o, view->getLocalID());
+ ow->setDrawAsActor(true);
+ y = ow->topMargin();
+ newWidget = ow;
+ } else
+ newWidget = new ActorWidget(view, static_cast<UMLActor*>(o));
+ break;
+ case Uml::ot_UseCase:
+ newWidget = new UseCaseWidget(view, static_cast<UMLUseCase*>(o));
+ break;
+ case Uml::ot_Package:
+ newWidget = new PackageWidget(view, static_cast<UMLPackage*>(o));
+ break;
+ case Uml::ot_Component:
+ newWidget = new ComponentWidget(view, static_cast<UMLComponent*>(o));
+ if (diagramType == Uml::dt_Deployment) {
+ newWidget->setIsInstance(true);
+ }
+ break;
+ case Uml::ot_Node:
+ newWidget = new NodeWidget(view, static_cast<UMLNode*>(o));
+ break;
+ case Uml::ot_Artifact:
+ newWidget = new ArtifactWidget(view, static_cast<UMLArtifact*>(o));
+ break;
+ case Uml::ot_Datatype:
+ newWidget = new DatatypeWidget(view, static_cast<UMLClassifier*>(o));
+ break;
+ case Uml::ot_Enum:
+ newWidget = new EnumWidget(view, static_cast<UMLEnum*>(o));
+ break;
+ case Uml::ot_Entity:
+ newWidget = new EntityWidget(view, static_cast<UMLEntity*>(o));
+ break;
+ case Uml::ot_Interface:
+ if (diagramType == Uml::dt_Sequence || diagramType == Uml::dt_Collaboration) {
+ ObjectWidget *ow = new ObjectWidget(view, o, view->getLocalID() );
+ if (diagramType == Uml::dt_Sequence) {
+ y = ow->topMargin();
+ }
+ newWidget = ow;
+ } else {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ ClassifierWidget* interfaceWidget = new ClassifierWidget(view, c);
+ if (diagramType == Uml::dt_Component || diagramType == Uml::dt_Deployment) {
+ interfaceWidget->setDrawAsCircle(true);
+ }
+ newWidget = interfaceWidget;
+ }
+ break;
+ case Uml::ot_Class:
+ //see if we really want an object widget or class widget
+ if (diagramType == Uml::dt_Class || diagramType == Uml::dt_Component) {
+ UMLClassifier *c = static_cast<UMLClassifier*>(o);
+ ClassifierWidget *cw = new ClassifierWidget(view, c);
+ if (diagramType == Uml::dt_Component)
+ cw->setDrawAsCircle(true);
+ newWidget = cw;
+ } else {
+ ObjectWidget *ow = new ObjectWidget(view, o, view->getLocalID() );
+ if (diagramType == Uml::dt_Sequence) {
+ y = ow->topMargin();
+ }
+ newWidget = ow;
+ }
+ break;
+ default:
+ kWarning() << "trying to create an invalid widget" << endl;
+ }
+
+ if (newWidget) {
+ newWidget->setX( pos.x() );
+ newWidget->setY( y );
+ }
+ return newWidget;
+}
+
+bool validateObjType(Uml::Object_Type expected, UMLObject* &o, Uml::IDType id) {
+ if (o == NULL) {
+ kDebug() << "Widget_Factory::validateObjType: creating new object of type "
+ << expected << endl;
+ QString artificialName = "LOST_" + ID2STR(id);
+ o = Object_Factory::createUMLObject(expected, artificialName, NULL, false);
+ if (o == NULL)
+ return false;
+ o->setID(id);
+ UMLPackage *parentPkg = o->getUMLPackage();
+ parentPkg->addObject(o);
+ return true;
+ }
+ Uml::Object_Type actual = o->getBaseType();
+ if (actual == expected)
+ return true;
+ kError() << "validateObjType(" << o->getName()
+ << "): expected type " << expected << ", actual type "
+ << actual << endl;
+ return false;
+}
+
+UMLWidget* makeWidgetFromXMI(const QString& tag,
+ const QString& idStr, UMLView *view) {
+ UMLWidget *widget = NULL;
+
+ // 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 == "statewidget" || tag == "UML:StateWidget") {
+ widget = new StateWidget(view, StateWidget::Normal, Uml::id_Reserved);
+ } else if (tag == "notewidget" || tag == "UML:NoteWidget") {
+ widget = new NoteWidget(view, Uml::id_Reserved);
+ } else if (tag == "boxwidget") {
+ widget = new BoxWidget(view, Uml::id_Reserved);
+ } else if (tag == "floatingtext" || tag == "UML:FloatingTextWidget") {
+ widget = new FloatingTextWidget(view, Uml::tr_Floating, "", Uml::id_Reserved);
+ } else if (tag == "activitywidget" || tag == "UML:ActivityWidget") {
+ widget = new ActivityWidget(view, ActivityWidget::Initial, Uml::id_Reserved);
+ } else if (tag == "messagewidget") {
+ widget = new MessageWidget(view, Uml::sequence_message_asynchronous, Uml::id_Reserved);
+ } else if (tag == "forkjoin") {
+ widget = new ForkJoinWidget(view, false, Uml::id_Reserved);
+ } else {
+ // Loading of widgets which represent an UMLObject
+
+ // Find the UMLObject and create the Widget to represent it
+ Uml::IDType id = STR2ID(idStr);
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLObject *o = umldoc->findObjectById(id);
+ if (o == NULL) {
+ kDebug() << "makeWidgetFromXMI: cannot find object with id "
+ << ID2STR(id) << endl;
+ }
+
+ if (tag == "actorwidget" || tag == "UML:ActorWidget") {
+ if (validateObjType(Uml::ot_Actor, o, id))
+ widget = new ActorWidget(view, static_cast<UMLActor*>(o));
+ } else if (tag == "usecasewidget" || tag == "UML:UseCaseWidget") {
+ if (validateObjType(Uml::ot_UseCase, o, id))
+ widget = new UseCaseWidget(view, static_cast<UMLUseCase*>(o));
+ } else if (tag == "classwidget" || tag == "UML:ClassWidget") {
+ if (validateObjType(Uml::ot_Class, o, id))
+ widget = new ClassifierWidget(view, static_cast<UMLClassifier*>(o));
+ } else if (tag == "packagewidget") {
+ if (validateObjType(Uml::ot_Package, o, id))
+ widget = new PackageWidget(view, static_cast<UMLPackage*>(o));
+ } else if (tag == "componentwidget") {
+ if (validateObjType(Uml::ot_Component, o, id))
+ widget = new ComponentWidget(view, static_cast<UMLComponent*>(o));
+ } else if (tag == "nodewidget") {
+ if (validateObjType(Uml::ot_Node, o, id))
+ widget = new NodeWidget(view, static_cast<UMLNode*>(o));
+ } else if (tag == "artifactwidget") {
+ if (validateObjType(Uml::ot_Artifact, o, id))
+ widget = new ArtifactWidget(view, static_cast<UMLArtifact*>(o));
+ } else if (tag == "interfacewidget") {
+ if (validateObjType(Uml::ot_Interface, o, id))
+ widget = new ClassifierWidget(view, static_cast<UMLClassifier*>(o));
+ } else if (tag == "datatypewidget") {
+ if (validateObjType(Uml::ot_Datatype, o, id))
+ widget = new DatatypeWidget(view, static_cast<UMLClassifier*>(o));
+ } else if (tag == "enumwidget") {
+ if (validateObjType(Uml::ot_Enum, o, id))
+ widget = new EnumWidget(view, static_cast<UMLEnum*>(o));
+ } else if (tag == "entitywidget") {
+ if (validateObjType(Uml::ot_Entity, o, id))
+ widget = new EntityWidget(view, static_cast<UMLEntity*>(o));
+ } else if (tag == "objectwidget" || tag == "UML:ObjectWidget") {
+ widget = new ObjectWidget(view, o );
+ } else {
+ kWarning() << "Trying to create an unknown widget:" << tag << endl;
+ }
+ }
+ return widget;
+}
+
+} // end namespace Widget_Factory
+
diff --git a/umbrello/umbrello/widget_factory.h b/umbrello/umbrello/widget_factory.h
new file mode 100644
index 00000000..ed8c30b7
--- /dev/null
+++ b/umbrello/umbrello/widget_factory.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * *
+ * 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 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef WIDGET_FACTORY_H
+#define WIDGET_FACTORY_H
+
+#include <qstring.h>
+
+// forward declarations
+class UMLView;
+class UMLObject;
+class UMLWidget;
+
+/**
+ * Widget factory methods.
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Widget_Factory {
+
+ /**
+ * Create a UMLWidget in the given view and representing the given document object.
+ */
+ UMLWidget *createWidget(UMLView *view, UMLObject *docObj);
+
+ /**
+ * Create a UMLWidget according to the given XMI tag.
+ */
+ UMLWidget* makeWidgetFromXMI(const QString& tag,
+ const QString& idStr, UMLView *view);
+
+} // end namespace Widget_Factory
+
+#endif
diff --git a/umbrello/umbrello/widget_utils.cpp b/umbrello/umbrello/widget_utils.cpp
new file mode 100644
index 00000000..b022d828
--- /dev/null
+++ b/umbrello/umbrello/widget_utils.cpp
@@ -0,0 +1,110 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "widget_utils.h"
+
+// qt/kde includes
+#include <qcanvas.h>
+#include <qbrush.h>
+#include <qpen.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+// app includes
+#include "uml.h"
+#include "umlview.h"
+#include "umlwidget.h"
+#include "objectwidget.h"
+
+namespace Widget_Utils {
+
+UMLWidget* findWidget(Uml::IDType id,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* pMessages /* = NULL */)
+{
+ UMLWidgetListIt it( widgets );
+ UMLWidget * obj = NULL;
+ while ( (obj = it.current()) != NULL ) {
+ ++it;
+ if (obj->getBaseType() == Uml::wt_Object) {
+ if (static_cast<ObjectWidget *>(obj)->getLocalID() == id)
+ return obj;
+ } else if (obj->getID() == id) {
+ return obj;
+ }
+ }
+
+ if (pMessages == NULL)
+ return NULL;
+
+ MessageWidgetListIt mit( *pMessages );
+ while ( (obj = (UMLWidget*)mit.current()) != NULL ) {
+ ++mit;
+ if( obj -> getID() == id )
+ return obj;
+ }
+ return NULL;
+}
+
+QIconSet iconSet(Uml::Diagram_Type dt) {
+ QIconSet diagramIconSet;
+ switch (dt) {
+ case Uml::dt_UseCase:
+ diagramIconSet = BarIconSet("umbrello_diagram_usecase");
+ break;
+ case Uml::dt_Collaboration:
+ diagramIconSet = BarIconSet("umbrello_diagram_collaboration");
+ break;
+ case Uml::dt_Class:
+ diagramIconSet = BarIconSet("umbrello_diagram_class");
+ break;
+ case Uml::dt_Sequence:
+ diagramIconSet = BarIconSet("umbrello_diagram_sequence");
+ break;
+ case Uml::dt_State:
+ diagramIconSet = BarIconSet("umbrello_diagram_state");
+ break;
+ case Uml::dt_Activity:
+ diagramIconSet = BarIconSet("umbrello_diagram_activity");
+ break;
+ case Uml::dt_Component:
+ diagramIconSet = BarIconSet("umbrello_diagram_component");
+ break;
+ case Uml::dt_Deployment:
+ diagramIconSet = BarIconSet("umbrello_diagram_deployment");
+ break;
+ case Uml::dt_EntityRelationship:
+ diagramIconSet = BarIconSet("umbrello_diagram_entityrelationship");
+ break;
+ default:
+ kDebug() << "Widget_Utils::iconSet: unknown diagram type " << dt << endl;
+ diagramIconSet = BarIconSet("unknown");
+ }
+ return diagramIconSet;
+}
+
+QCanvasRectangle *decoratePoint(const QPoint& p) {
+ const int SIZE = 4;
+ UMLView *currentView = UMLApp::app()->getCurrentView();
+ QCanvasRectangle *rect;
+ rect = new QCanvasRectangle(p.x() - SIZE / 2,
+ p.y() - SIZE / 2,
+ SIZE, SIZE, currentView->canvas());
+ rect->setBrush( QBrush(Qt::blue) );
+ rect->setPen( QPen(Qt::blue) );
+ rect->setVisible(true);
+ return rect;
+}
+
+
+} // namespace Widget_Utils
+
diff --git a/umbrello/umbrello/widget_utils.h b/umbrello/umbrello/widget_utils.h
new file mode 100644
index 00000000..419f9d99
--- /dev/null
+++ b/umbrello/umbrello/widget_utils.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * *
+ * 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-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef WIDGET_UTILS_H
+#define WIDGET_UTILS_H
+
+#include <qiconset.h>
+#include <qpoint.h>
+#include "umlnamespace.h"
+#include "umlwidgetlist.h"
+#include "messagewidgetlist.h"
+
+// forward declarations
+class QCanvasRectangle;
+
+/**
+ * General purpose widget utilities.
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+namespace Widget_Utils {
+
+/**
+ * Find the widget identified by the given ID in the given widget
+ * or message list.
+ *
+ * @param id The unique ID to find.
+ * @param widgets The UMLWidgetList to search in.
+ * @param pMessages Optional pointer to a MessageWidgetList to
+ * search in.
+ */
+UMLWidget* findWidget(Uml::IDType id,
+ const UMLWidgetList& widgets,
+ const MessageWidgetList* pMessages = NULL);
+
+/**
+ * Return the icon corresponding to the given Diagram_Type.
+ */
+QIconSet iconSet(Uml::Diagram_Type dt);
+
+QCanvasRectangle *decoratePoint(const QPoint& p);
+
+}
+
+#endif
diff --git a/umbrello/umbrello/widgetbase.cpp b/umbrello/umbrello/widgetbase.cpp
new file mode 100644
index 00000000..225f5848
--- /dev/null
+++ b/umbrello/umbrello/widgetbase.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "widgetbase.h"
+
+#include <kdebug.h>
+#include "umlview.h"
+#include "umlobject.h"
+#include "optionstate.h"
+
+WidgetBase::WidgetBase(UMLView *view) : QObject(view) {
+ init(view);
+}
+
+void WidgetBase::init(UMLView *view, Uml::Widget_Type type /* = Uml::wt_UMLWidget */) {
+ m_pView = view;
+ m_Type = type;
+ m_pObject = NULL;
+ if (m_pView) {
+ m_bUsesDiagramLineColour = true;
+ m_bUsesDiagramLineWidth = true;
+ const Settings::OptionState& optionState = m_pView->getOptionState();
+ m_LineColour = optionState.uiState.lineColor;
+ m_LineWidth = optionState.uiState.lineWidth;
+ } else {
+ kError() << "WidgetBase constructor: SERIOUS PROBLEM - m_pView is NULL" << endl;
+ m_bUsesDiagramLineColour = false;
+ m_bUsesDiagramLineWidth = false;
+ m_LineColour = QColor("black");
+ m_LineWidth = 0; // initialize with 0 to have valid start condition
+ }
+}
+
+void WidgetBase::setBaseType( Uml::Widget_Type type ) {
+ m_Type = type;
+}
+
+Uml::Widget_Type WidgetBase::getBaseType() const {
+ return m_Type;
+}
+
+UMLObject *WidgetBase::getUMLObject() {
+ return m_pObject;
+}
+
+void WidgetBase::setUMLObject(UMLObject * o) {
+ m_pObject = o;
+}
+
+void WidgetBase::setID(Uml::IDType id) {
+ if (m_pObject) {
+ if (m_pObject->getID() != Uml::id_None)
+ kWarning() << "WidgetBase::setID(): changing old UMLObject "
+ << ID2STR(m_pObject->getID()) << " to "
+ << ID2STR(id) << endl;
+ m_pObject->setID(id);
+ }
+ m_nId = id;
+}
+
+Uml::IDType WidgetBase::getID() const {
+ if (m_pObject)
+ return m_pObject->getID();
+ return m_nId;
+}
+
+QString WidgetBase::getDoc() const {
+ if (m_pObject != NULL)
+ return m_pObject->getDoc();
+ return m_Doc;
+}
+
+void WidgetBase::setDoc( const QString &doc ) {
+ if (m_pObject != NULL)
+ m_pObject->setDoc( doc );
+ else
+ m_Doc = doc;
+}
+
+void WidgetBase::setLineColor(const QColor &colour) {
+ m_LineColour = colour;
+ m_bUsesDiagramLineColour = false;
+}
+
+void WidgetBase::setLineWidth(uint width) {
+ m_LineWidth = width;
+ m_bUsesDiagramLineWidth = false;
+}
+
+void WidgetBase::saveToXMI( QDomDocument & /*qDoc*/, QDomElement & qElement ) {
+ if (m_bUsesDiagramLineColour) {
+ qElement.setAttribute( "linecolor", "none" );
+ } else {
+ qElement.setAttribute( "linecolor", m_LineColour.name() );
+ }
+ if (m_bUsesDiagramLineWidth) {
+ qElement.setAttribute( "linewidth", "none" );
+ } else {
+ qElement.setAttribute( "linewidth", m_LineWidth );
+ }
+}
+
+bool WidgetBase::loadFromXMI( 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( "linecolour", "none" );
+ lineColor = qElement.attribute( "linecolor", lineColor );
+
+ QString lineWidth = qElement.attribute( "linewidth", "none" );
+ if (lineColor != "none") {
+ setLineColor( QColor(lineColor) );
+ m_bUsesDiagramLineColour = false;
+ } else if (m_Type != Uml::wt_Box && m_pView != NULL) {
+ setLineColor( m_pView->getLineColor() );
+ m_bUsesDiagramLineColour = true;
+ }
+ if (lineWidth != "none") {
+ setLineWidth( lineWidth.toInt() );
+ m_bUsesDiagramLineWidth = false;
+ } else if ( m_pView ) {
+ setLineWidth( m_pView->getLineWidth() );
+ m_bUsesDiagramLineWidth = true;
+ }
+ return true;
+}
+
+#include "widgetbase.moc"
diff --git a/umbrello/umbrello/widgetbase.h b/umbrello/umbrello/widgetbase.h
new file mode 100644
index 00000000..5051418e
--- /dev/null
+++ b/umbrello/umbrello/widgetbase.h
@@ -0,0 +1,201 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef WIDGETBASE_H
+#define WIDGETBASE_H
+
+#include <qobject.h>
+#include <qcolor.h>
+#include <qdom.h>
+
+#include "umlnamespace.h"
+
+// forward declarations
+class UMLView;
+class UMLObject;
+
+/**
+ * @short Common base class for UMLWidget and AssociationWidget
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class WidgetBase : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Creates a WidgetBase object.
+ *
+ * @param view The view to be displayed on.
+ */
+ WidgetBase(UMLView * view);
+
+ /**
+ * Standard deconstructor
+ */
+ virtual ~WidgetBase() {}
+
+ /**
+ * Write property of m_Type.
+ */
+ void setBaseType(Uml::Widget_Type type);
+
+ /**
+ * Read property of m_Type.
+ */
+ Uml::Widget_Type getBaseType() const;
+
+ /**
+ * Returns the @ref UMLObject set to represent.
+ *
+ * @return the UMLObject to represent.
+ */
+ UMLObject *getUMLObject();
+
+ /**
+ * Deliver a const pointer to the connected UMLView
+ * ( needed esp. by event handling of LinePath )
+ */
+ const UMLView *getUMLView() const { return m_pView; }
+
+ /**
+ * Sets the @ref UMLObject to represent.
+ *
+ * @param o The object to represent.
+ */
+ virtual void setUMLObject(UMLObject * o);
+
+ /**
+ * Used by some child classes to get documentation.
+ *
+ * @return The documentation from the UMLObject (if m_pObject is set.)
+ */
+ virtual QString getDoc() const;
+
+ /**
+ * Used by some child classes to set documentation.
+ *
+ * @param doc The documentation to be set in the UMLObject
+ * (if m_pObject is set.)
+ */
+ virtual void setDoc( const QString &doc );
+
+ /**
+ * Sets the line colour
+ *
+ * @param colour the new line colour
+ */
+ virtual void setLineColor(const QColor &colour);
+
+ /**
+ * Sets the line width
+ *
+ * @param width the new line width
+ */
+ virtual void setLineWidth(uint width);
+
+ /**
+ * Read property of m_LineColour.
+ */
+ QColor getLineColor() const {
+ return m_LineColour;
+ }
+
+ /**
+ * Read property of m_LineWidth.
+ */
+ uint getLineWidth() const {
+ return m_LineWidth;
+ }
+
+ /**
+ * Returns m_bUsesDiagramLineColour
+ */
+ bool getUsesDiagramLineColour() const {
+ return m_bUsesDiagramLineColour;
+ }
+
+ /**
+ * Returns m_bUsesDiagramLineWidth
+ */
+ bool getUsesDiagramLineWidth() const {
+ return m_bUsesDiagramLineWidth;
+ }
+
+ /**
+ * Sets m_bUsesDiagramLineColour
+ */
+ void setUsesDiagramLineColour(bool usesDiagramLineColour) {
+ m_bUsesDiagramLineColour = usesDiagramLineColour;
+ }
+
+ /**
+ * Sets m_bUsesDiagramLineWidth
+ */
+ void setUsesDiagramLineWidth(bool usesDiagramLineWidth) {
+ m_bUsesDiagramLineWidth = usesDiagramLineWidth;
+ }
+
+ /**
+ * Write property of m_nId.
+ */
+ void setID( Uml::IDType id );
+
+ /**
+ * Read property of m_nId.
+ */
+ Uml::IDType getID() const;
+
+ virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+
+ virtual bool loadFromXMI( QDomElement & qElement );
+
+protected:
+ /**
+ * Initialize members.
+ */
+ void init(UMLView *view, Uml::Widget_Type type = Uml::wt_UMLWidget);
+
+ /**
+ * Type of widget.
+ */
+ Uml::Widget_Type m_Type;
+
+ UMLView *m_pView;
+ UMLObject *m_pObject;
+ QString m_Doc; ///< Only used if m_pObject is not set.
+
+ /**
+ * This ID is only used when the widget does not have a
+ * corresponding UMLObject (i.e. the m_pObject pointer is NULL.)
+ * For UMLObjects, the ID from the UMLObject is used.
+ */
+ Uml::IDType m_nId;
+
+ /**
+ * Color of the lines of the widget. Is saved to XMI.
+ */
+ QColor m_LineColour;
+
+ /**
+ * Width of the lines of the widget. Is saved to XMI.
+ */
+ uint m_LineWidth;
+
+ /**
+ * true by default, false if the colours have
+ * been explicitly set for this widget.
+ * These are saved to XMI.
+ */
+ bool m_bUsesDiagramLineColour, m_bUsesDiagramLineWidth;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/worktoolbar.cpp b/umbrello/umbrello/worktoolbar.cpp
new file mode 100644
index 00000000..0f27be80
--- /dev/null
+++ b/umbrello/umbrello/worktoolbar.cpp
@@ -0,0 +1,315 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "worktoolbar.h"
+
+// qt/kde include files
+#include <qmainwindow.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ktoolbarbutton.h>
+
+// application specific includes
+#include "uml.h"
+#include "umldoc.h"
+#include "umlview.h"
+#include "worktoolbar.h"
+
+
+WorkToolBar::WorkToolBar(QMainWindow *parentWindow, const char*name)
+ : KToolBar(parentWindow,Qt::DockRight,false,name) {
+ m_CurrentButtonID = tbb_Undefined;
+ loadPixmaps();
+ m_Type = Uml::dt_Class; /* first time in just want it to load arrow,
+ needs anything but dt_Undefined */
+ setOrientation( Qt::Vertical );
+ setVerticalStretchable( true );
+ // initialize old tool map, everything starts with select tool (arrow)
+ m_map.insert(Uml::dt_UseCase,tbb_Arrow);
+ m_map.insert(Uml::dt_Collaboration,tbb_Arrow);
+ m_map.insert(Uml::dt_Class,tbb_Arrow);
+ m_map.insert(Uml::dt_Sequence,tbb_Arrow);
+ m_map.insert(Uml::dt_State,tbb_Arrow);
+ m_map.insert(Uml::dt_Activity,tbb_Arrow);
+ m_map.insert(Uml::dt_Undefined,tbb_Arrow);
+
+ slotCheckToolBar( Uml::dt_Undefined );
+ connect( this, SIGNAL( released( int ) ), this, SLOT( buttonChanged (int ) ) );
+}
+
+WorkToolBar::~WorkToolBar() {
+ disconnect(this, SIGNAL(released(int)),this,SLOT(buttonChanged(int)));
+}
+
+void WorkToolBar::insertHotBtn(ToolBar_Buttons tbb) {
+ insertButton(m_ToolButtons[tbb].Symbol, tbb, true, m_ToolButtons[tbb].Label);
+ setToggle(tbb, true);
+}
+
+void WorkToolBar::insertBasicAssociations() {
+ insertHotBtn(tbb_Association);
+ if (m_Type == Uml::dt_Class || m_Type == Uml::dt_UseCase) {
+ insertHotBtn(tbb_UniAssociation);
+ }
+ insertHotBtn(tbb_Dependency);
+ insertHotBtn(tbb_Generalization);
+}
+
+void WorkToolBar::slotCheckToolBar(Uml::Diagram_Type dt) {
+ if ( dt == m_Type )
+ return;
+ clear();
+ m_Type = dt;
+
+ if ( m_Type == Uml::dt_Undefined )
+ return;
+
+ //insert note, anchor and lines of text on all diagrams
+ insertHotBtn(tbb_Arrow);
+ toggleButton(tbb_Arrow);
+ m_CurrentButtonID = tbb_Arrow;
+
+ insertHotBtn(tbb_Note);
+ insertHotBtn(tbb_Anchor);
+ insertHotBtn(tbb_Text);
+ insertHotBtn(tbb_Box);
+
+ //insert diagram specific tools
+ switch (m_Type) {
+ case Uml::dt_UseCase:
+ insertHotBtn(tbb_Actor);
+ insertHotBtn(tbb_UseCase);
+ insertBasicAssociations();
+ break;
+
+ case Uml::dt_Class:
+ insertHotBtn(tbb_Class);
+ insertHotBtn(tbb_Interface);
+ insertHotBtn(tbb_Datatype);
+ insertHotBtn(tbb_Enum);
+ insertHotBtn(tbb_Package);
+ insertBasicAssociations();
+ insertHotBtn(tbb_Composition);
+ insertHotBtn(tbb_Aggregation);
+ insertHotBtn(tbb_Containment);
+ break;
+
+ case Uml::dt_Sequence:
+ insertHotBtn(tbb_Object);
+ insertHotBtn(tbb_Seq_Message_Synchronous);
+ insertHotBtn(tbb_Seq_Message_Asynchronous);
+ break;
+
+ case Uml::dt_Collaboration:
+ insertHotBtn(tbb_Object);
+ insertHotBtn(tbb_Coll_Message);
+ break;
+
+ case Uml::dt_State:
+ insertHotBtn(tbb_Initial_State);
+ insertHotBtn(tbb_State);
+ insertHotBtn(tbb_End_State);
+ insertHotBtn(tbb_State_Transition);
+ //insertHotBtn(tbb_DeepHistory); //NotYetImplemented
+ //insertHotBtn(tbb_ShallowHistory); //NotYetImplemented
+ //insertHotBtn(tbb_Join); //NotYetImplemented
+ insertHotBtn(tbb_StateFork);
+ //insertHotBtn(tbb_Junction); //NotYetImplemented
+ //insertHotBtn(tbb_Choice); //NotYetImplemented
+ //insertHotBtn(tbb_Andline); //NotYetImplemented
+ break;
+
+ case Uml::dt_Activity:
+ insertHotBtn(tbb_Initial_Activity);
+ insertHotBtn(tbb_Activity);
+ insertHotBtn(tbb_End_Activity);
+ insertHotBtn(tbb_Branch);
+ insertHotBtn(tbb_Fork);
+ insertHotBtn(tbb_Activity_Transition);
+ break;
+
+ case Uml::dt_Component:
+ insertHotBtn(tbb_Interface);
+ insertHotBtn(tbb_Component);
+ insertHotBtn(tbb_Artifact);
+ insertBasicAssociations();
+ break;
+
+ case Uml::dt_Deployment:
+ insertHotBtn(tbb_Object);
+ insertHotBtn(tbb_Interface);
+ insertHotBtn(tbb_Component);
+ insertHotBtn(tbb_Node);
+ insertBasicAssociations();
+ break;
+
+ case Uml::dt_EntityRelationship:
+ insertHotBtn(tbb_Entity);
+ insertHotBtn(tbb_Relationship);
+ break;
+
+ default:
+ kWarning() << "slotCheckToolBar() on unknown diagram type:"
+ << m_Type << endl;
+ break;
+ }
+}
+
+void WorkToolBar::buttonChanged(int b) {
+ UMLView* view = UMLApp::app()->getCurrentView();
+
+ //if trying to turn off arrow - stop it
+ ToolBar_Buttons tbb = (ToolBar_Buttons)b;
+ if (tbb == tbb_Arrow && m_CurrentButtonID == tbb_Arrow) {
+ toggleButton(tbb_Arrow);
+
+ // signal needed, in the case ( when switching diagrams ) that
+ // Arrow Button gets activated, but the toolBarState of the Views may be different
+ emit sigButtonChanged( m_CurrentButtonID );
+
+ view->setCursor( currentCursor() );
+ return;
+ }
+
+ //if toggling off a button set to arrow
+ if (tbb == m_CurrentButtonID) {
+ m_map[m_Type] = m_CurrentButtonID; // store old tool for this diagram type
+ toggleButton(tbb_Arrow);
+ m_CurrentButtonID = tbb_Arrow;
+ emit sigButtonChanged(m_CurrentButtonID);
+ view->setCursor( currentCursor() );
+ return;
+ }
+ m_map[m_Type] = m_CurrentButtonID;
+ toggleButton(m_CurrentButtonID);
+ m_CurrentButtonID = tbb;
+ emit sigButtonChanged(m_CurrentButtonID);
+ view->setCursor( currentCursor() );
+}
+
+QCursor WorkToolBar::currentCursor() {
+ return m_ToolButtons[m_CurrentButtonID].Cursor;
+}
+
+void WorkToolBar::slotResetToolBar() {
+ if (m_CurrentButtonID == tbb_Arrow)
+ return;//really shouldn't occur
+ toggleButton(m_CurrentButtonID);
+ m_CurrentButtonID = tbb_Arrow;
+ toggleButton(m_CurrentButtonID);
+ emit sigButtonChanged(m_CurrentButtonID);
+
+ QCursor curs;
+ curs.setShape(Qt::ArrowCursor);
+
+ UMLView* view = UMLApp::app()->getCurrentView();
+ if (view != NULL) {
+ view -> setCursor(curs);
+ }
+}
+
+void WorkToolBar::setOldTool() {
+ KToolBarButton *b = (KToolBarButton*) getWidget(m_map[m_Type]);
+ if (b)
+ b -> animateClick();
+}
+
+void WorkToolBar::setDefaultTool() {
+ KToolBarButton *b = (KToolBarButton*) getWidget(tbb_Arrow);
+ if (b)
+ b -> animateClick();
+}
+
+QPixmap WorkToolBar::load(const QString & fileName) {
+ QPixmap pxm;
+ pxm.load(fileName);
+ return pxm;
+}
+
+void WorkToolBar::loadPixmaps() {
+ const struct ButtonInfo {
+ const ToolBar_Buttons tbb;
+ const QString btnName;
+ const char *pngName;
+ } buttonInfo[] = {
+ { tbb_Object, i18n("Object"), "object.png" },
+ { tbb_Seq_Message_Synchronous, i18n("Synchronous Message"), "message-synchronous.png" },
+ { tbb_Seq_Message_Asynchronous, i18n("Asynchronous Message"), "message-asynchronous.png" },
+ { tbb_Association, i18n("Association"), "association.png" },
+ { tbb_Containment, i18n("Containment"), "containment.png" },
+ { tbb_Anchor, i18n("Anchor"), "anchor.png" },
+ { tbb_Text, i18n("Label"), "text.png" },
+ { tbb_Note, i18n("Note"), "note.png" },
+ { tbb_Box, i18n("Box"), "box.png" },
+ { tbb_Actor, i18n("Actor"), "actor.png" },
+ { tbb_Dependency, i18n("Dependency"), "dependency.png" },
+ { tbb_Aggregation, i18n("Aggregation"), "aggregation.png" },
+ { tbb_Relationship, i18n("Relationship"), "relationship.png" },
+ { tbb_UniAssociation, i18n("Directional Association"), "uniassociation.png" },
+ { tbb_Generalization, i18n("Implements (Generalisation/Realisation)"), "generalisation.png" },
+ { tbb_Composition, i18n("Composition"), "composition.png" },
+ { tbb_UseCase, i18n("Use Case"), "usecase.png" },
+ { tbb_Class, i18n("Class"), "class.png" },
+ { tbb_Initial_State, i18n("Initial State"), "initial_state.png" },
+ { tbb_End_State, i18n("End State"), "end_state.png" },
+ { tbb_Branch, i18n("Branch/Merge"), "branch.png" },
+ { tbb_Fork, i18n("Fork/Join"), "fork.png" },
+ { tbb_Package, i18n("Package"), "package.png" },
+ { tbb_Component, i18n("Component"), "component.png" },
+ { tbb_Node, i18n("Node"), "node.png" },
+ { tbb_Artifact, i18n("Artifact"), "artifact.png" },
+ { tbb_Interface, i18n("Interface"), "interface.png" },
+ { tbb_Datatype, i18n("Datatype"), "datatype.png" },
+ { tbb_Enum, i18n("Enum"), "enum.png" },
+ { tbb_Entity, i18n("Entity"), "entity.png" },
+ { tbb_DeepHistory, i18n("Deep History"), "deep-history.png" }, //NotYetImplemented
+ { tbb_ShallowHistory, i18n("Shallow History"), "shallow-history.png" }, //NotYetImplemented
+ { tbb_Join, i18n("Join"), "join.png" }, //NotYetImplemented
+ { tbb_StateFork, i18n("Fork"), "state-fork.png" },
+ { tbb_Junction, i18n("Junction"), "junction.png" }, //NotYetImplemented
+ { tbb_Choice, i18n("Choice"), "choice-round.png" }, //NotYetImplemented
+ //:TODO: let the user decide which symbol he wants (setting an option)
+ // { tbb_Choice, i18n("Choice"), "choice-rhomb.png" }, //NotYetImplemented
+ //{ tbb_Andline, i18n("And Line"), "andline.png" }, //NotYetImplemented
+ { tbb_State_Transition, i18n("State Transition"), "uniassociation.png" },
+ { tbb_Activity_Transition, i18n("Activity Transition"), "uniassociation.png" },
+ { tbb_Activity, i18n("Activity"), "usecase.png" },
+ { tbb_State, i18n("State"), "usecase.png" },
+ { tbb_End_Activity, i18n("End Activity"), "end_state.png" },
+ { tbb_Initial_Activity, i18n("Initial Activity"), "initial_state.png" },
+ { tbb_Coll_Message, i18n("Message"), "message-asynchronous.png" }
+ };
+ KStandardDirs * dirs = KGlobal::dirs();
+ QString dataDir = dirs->findResourceDir( "data", "umbrello/pics/object.png" );
+ dataDir += "/umbrello/pics/";
+ const size_t n_buttonInfos = sizeof(buttonInfo) / sizeof(ButtonInfo);
+
+ m_ToolButtons.insert(tbb_Undefined,
+ ToolButton(i18n("UNDEFINED"),
+ 0,
+ QCursor()) );
+ m_ToolButtons.insert(tbb_Arrow,
+ ToolButton(i18n("Select"),
+ load(dataDir + "arrow.png"),
+ QCursor()) );
+ kDebug() << "WorkToolBar::loadPixmaps: n_buttonInfos = " << n_buttonInfos << endl;
+ for (uint i = 0; i < n_buttonInfos; i++) {
+ const ButtonInfo& info = buttonInfo[i];
+ m_ToolButtons.insert(info.tbb,
+ ToolButton(info.btnName,
+ load(dataDir + info.pngName),
+ QCursor(load(dataDir + "cursor-" + info.pngName), 9, 9)));
+ }
+}
+
+#include "worktoolbar.moc"
diff --git a/umbrello/umbrello/worktoolbar.h b/umbrello/umbrello/worktoolbar.h
new file mode 100644
index 00000000..92012dde
--- /dev/null
+++ b/umbrello/umbrello/worktoolbar.h
@@ -0,0 +1,183 @@
+/***************************************************************************
+ * *
+ * 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-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef WORKTOOLBAR_H
+#define WORKTOOLBAR_H
+
+#include <qmap.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <ktoolbar.h>
+
+#include "umlnamespace.h"
+
+class QMainWindow;
+
+
+/**
+ * This is the toolbar that is displayed on the right-hand side of the program
+ * window. For each type of diagram it will change to suit that document.
+ *
+ * To add a new tool button do the following:
+ * - create a button pixmap (symbol)
+ * - create a cursor pixmap
+ * - add an element to the ToolBar_Buttons enum
+ * - adjust function loadPixmaps
+ * - adjust function slotCheckToolBar
+ *
+ * @short The toolbar that is different for each type of diagram.
+ * @author Paul Hensgen <phensgen@techie.com>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+
+class WorkToolBar : public KToolBar {
+ Q_OBJECT
+public:
+
+ /**
+ * Creates a work tool bar.
+ *
+ * @param parentWindow The parent of the toolbar.
+ */
+ WorkToolBar(QMainWindow *parentWindow, const char *name);
+
+ /**
+ * Standard deconstructor.
+ */
+ ~WorkToolBar();
+
+ /**
+ * Sets the current tool to the previously used Tool. This is just
+ * as if the user had pressed the button for the other tool.
+ */
+ void setOldTool();
+
+ /**
+ * Sets the current tool to the default tool. (select tool)
+ * Calling this function is as if the user had pressed the "arrow"
+ * button on the toolbar.
+ */
+ void setDefaultTool();
+
+ /**
+ * Enumeration of all available toolbar buttons.
+ */
+ enum ToolBar_Buttons
+ {
+ tbb_Undefined = -1,
+ tbb_Arrow,
+ tbb_Generalization,
+ tbb_Aggregation,
+ tbb_Dependency,
+ tbb_Association,
+ tbb_Containment,
+ tbb_Coll_Message,
+ tbb_Seq_Message_Synchronous,
+ tbb_Seq_Message_Asynchronous,
+ tbb_Composition,
+ tbb_Relationship,
+ tbb_UniAssociation,
+ tbb_State_Transition,
+ tbb_Activity_Transition,
+ tbb_Anchor,//keep anchor as last association until code uses better algorithm for testing
+ tbb_Note,
+ tbb_Box,
+ tbb_Text,
+ tbb_Actor,
+ tbb_UseCase,
+ tbb_Class,
+ tbb_Interface,
+ tbb_Datatype,
+ tbb_Enum,
+ tbb_Entity,
+ tbb_Package,
+ tbb_Component,
+ tbb_Node,
+ tbb_Artifact,
+ tbb_Object,
+ tbb_Initial_State,
+ tbb_State,
+ tbb_End_State,
+ tbb_Initial_Activity,
+ tbb_Activity,
+ tbb_End_Activity,
+ tbb_Branch,
+ tbb_Fork,
+ tbb_DeepHistory,
+ tbb_ShallowHistory,
+ tbb_Join,
+ tbb_StateFork,
+ tbb_Junction,
+ tbb_Choice,
+ tbb_Andline
+ };
+
+private:
+
+ typedef QMap<Uml::Diagram_Type,ToolBar_Buttons> OldToolMap;
+
+ /**
+ * This inner class holds label, symbol, and cursor of a tool button.
+ */
+ class ToolButton {
+ public:
+ QString Label;
+ QPixmap Symbol;
+ QCursor Cursor;
+ ToolButton() : Label(QString("?")), Symbol(QPixmap()), Cursor(QCursor()) { }
+ ToolButton(const QString& lbl, const QPixmap& smb, const QCursor& cur) :
+ Label(lbl), Symbol(smb), Cursor(cur) { }
+ };
+
+ typedef QMap<ToolBar_Buttons, ToolButton> ToolButtonMap;
+
+ ToolBar_Buttons m_CurrentButtonID;
+ OldToolMap m_map;
+ Uml::Diagram_Type m_Type;
+ ToolButtonMap m_ToolButtons;
+
+ /**
+ * Loads a pixmap from file
+ */
+ QPixmap load(const QString &fileName);
+
+ /**
+ * Loads toolbar icon and mouse cursor images from disk
+ */
+ void loadPixmaps();
+
+ /**
+ * Returns the current cursor depending on m_CurrentButtonID
+ */
+ QCursor currentCursor();
+
+ /**
+ * Inserts the button corresponding to the tbb value given
+ * and activates the toggle.
+ */
+ void insertHotBtn(ToolBar_Buttons tbb);
+
+ /**
+ * Inserts most associations, just reduces some string
+ * duplication (nice to translators)
+ */
+ void insertBasicAssociations();
+
+signals:
+ void sigButtonChanged(int);
+public slots:
+ void slotCheckToolBar(Uml::Diagram_Type dt);
+ void buttonChanged(int b);
+ void slotResetToolBar();
+};
+
+#endif
diff --git a/umbrello/umbrello/x-umbrello.desktop b/umbrello/umbrello/x-umbrello.desktop
new file mode 100644
index 00000000..d8aaeb50
--- /dev/null
+++ b/umbrello/umbrello/x-umbrello.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=application/x-uml
+Icon=umbrellofile
+DefaultApp=umbrello
+Patterns=*.xmi;*.XMI;*.xmi.tgz;*.xmi.tar.bz2;
+Comment=Umbrello UML Modeller File
+Comment[bg]=Файл Umbrello UML Modeller
+Comment[bs]=Umbrello UML modeler datoteka
+Comment[ca]=Fitxer de model UML
+Comment[cs]=Soubor UML modeláře Umbrello
+Comment[cy]=Ffeil Modelydd UML Umbrello
+Comment[da]=Umbrello UML-fil
+Comment[de]=Umbrello-Datei
+Comment[el]=ΑÏχείο μοντελοποιητή UML Umbrello
+Comment[eo]=Dosiero de Umbrello UML-Modelilo
+Comment[es]=Archivo del modeladore UML Umbrello
+Comment[et]=Umbrello UML-fail
+Comment[eu]=Umbrello UML modelatzaile fitxategia
+Comment[fa]=پروندۀ مدل‌ساز Umbrello UML
+Comment[fi]=Umbrello UML -mallinnustiedosto
+Comment[fr]=Fichier du modeleur UML Umbrello
+Comment[ga]=Comhad le haghaidh an Mhúnlóra UML Umbrello
+Comment[gl]=Ficheiro UML de Umbrello
+Comment[hi]=अमà¥à¤¬à¤°à¥ˆà¤²à¥‹ यूà¤à¤®à¤à¤² मॉडलर फ़ाइल
+Comment[hu]=Umbrello UML-fájl
+Comment[is]=Umbrello UML Modeller Skrá
+Comment[it]=File del modellatore UML Umbrello
+Comment[ja]=Umbrello UML モデラーファイル
+Comment[ka]=Umbrello UML მáƒáƒ“ელერის ფáƒáƒ˜áƒšáƒ˜
+Comment[kk]=Umbrello UML үлгілегішінің файлы
+Comment[lt]=Umbrello UML Modeller byla
+Comment[ms]=Fail Pemodel Umbrello UML
+Comment[nb]=Umbrello UML-modelleringsfil
+Comment[nds]=UML-Modellmaker-Datei vun Umbrello
+Comment[ne]=अमà¥à¤¬à¥à¤°à¥‡à¤²à¥‹ यूà¤à¤®à¤à¤² मोडेलर फाइल
+Comment[nl]=Umbrello UML Modeller-bestand
+Comment[nn]=Umbrello UML-modelleringsfil
+Comment[pl]=Plik modelera UML Umbrello
+Comment[pt]=Ficheiro do Modelador de UML Umbrello
+Comment[pt_BR]=Arquivo de Modelador UML Umbrello
+Comment[ru]=Файл Ð¼Ð¾Ð´ÐµÐ»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ UML Umbrello
+Comment[sk]=Súbor pre Umbrello modelár UML
+Comment[sl]=Datoteka za modelirnik Umbrello UML
+Comment[sr]=Фајл Umbrello-а, UML моделара
+Comment[sr@Latn]=Fajl Umbrello-a, UML modelara
+Comment[sv]=Umbrello UML-modelleringsfil
+Comment[ta]= à®…à®®à¯à®°à®²à¯à®²à¯‹ UML மாடà¯à®²à®°à¯ கோபà¯à®ªà¯
+Comment[tg]=Файли моделкунонии UML Umbrello
+Comment[tr]=Umbrello UML Modelleyici Dosyası
+Comment[uk]=Файл Ð¼Ð¾Ð´ÐµÐ»ÑŽÐ²Ð°Ð½Ð½Ñ UML Umbrello
+Comment[zh_CN]=Umbrello UML 建模工具文件
+Comment[zh_TW]=Umbrello UML Modeller 檔案
diff --git a/umbrello/uml.kdevprj b/umbrello/uml.kdevprj
new file mode 100644
index 00000000..284aee44
--- /dev/null
+++ b/umbrello/uml.kdevprj
@@ -0,0 +1,2154 @@
+[Config for BinMakefileAm]
+addcxxflags=
+bin_program=umbrello
+cflags=
+cppflags=
+cxxflags=\s-O0 -g3 -Wall
+ldadd=-lfl $(LIB_KDEPRINT) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+ldflags=\s -Iuml/classparser -Iuml/dialogs -Iuml/clipboard
+
+[General]
+AMChanged=true
+author=Umbrello UML Modeller Authors
+configure_args=\s--build=i386-linux --host=i386-linux --target=i386-linux --prefix=/opt/kde3 --enable-debug\s
+email=uml-devel@lists.sourceforge.net
+kdevprj_version=1.3
+lfv_open_groups=
+make_options=\s-j1
+makefiles=uml.spec.in,Makefile.am,uml/Makefile.am,doc/Makefile.am,doc/en/Makefile.am,po/Makefile.am,uml/classparser/Makefile.am,uml/clipboard/Makefile.am,uml/dialogs/Makefile.am,uml/pics/Makefile.am,doc/en/pics/Makefile.am,uml/codegenerators/Makefile.am,uml/headings/Makefile.am,doc/de/Makefile.am,doc/de/pics/Makefile.am
+modifyMakefiles=true
+project_name=Umbrello
+project_type=normal_kde2
+short_info=Umbrello UML Modeller
+showNonProjectFiles=true
+sub_dir=uml/
+version=1.1rc1
+version_control=CVS
+workspace=1
+
+[KPP]
+kpp_appgrp=
+kpp_bldroot=
+kpp_icon=0
+kpp_license=5
+kpp_summary=
+kpp_url=
+kpp_version=1.1
+
+[LFV Groups]
+Headers=*.h,*.hh,*.hxx,*.hpp,*.H
+Others=*
+Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l
+Translations=*.po
+User Interface=*.kdevdlg,*.ui,*.rc,*.dlg
+groups=Headers,Sources,User Interface,Translations,Others
+
+[Makefile.am]
+files=uml.kdevprj,admin,uml.spec.in
+sub_dirs=uml,po,doc
+type=normal
+
+[admin]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/Makefile.am]
+sub_dirs=en,de
+type=normal
+
+[doc/de/Makefile.am]
+files=doc/de/authors.docbook,doc/de/code_import_and_generation.docbook,doc/de/faq.docbook,doc/de/index.docbook,doc/de/installation.docbook,doc/de/introduction.docbook,doc/de/working_with_umbrello.docbook,doc/de/menu_reference.docbook,doc/de/other_features.docbook,doc/de/uml_basics.docbook
+sub_dirs=pics
+type=normal
+
+[doc/de/authors.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/code_import_and_generation.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/faq.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/index.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/installation.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/introduction.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/menu_reference.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/other_features.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/pics/Makefile.am]
+files=doc/de/pics/activity-diagram.png,doc/de/pics/add-remove-languages.png,doc/de/pics/aggregation.png,doc/de/pics/association.png,doc/de/pics/class-diagram.png,doc/de/pics/class.png,doc/de/pics/code-import.png,doc/de/pics/collaboration-diagram.png,doc/de/pics/composition.png,doc/de/pics/folders.png,doc/de/pics/generalization.png,doc/de/pics/generation-options.png,doc/de/pics/sequence-diagram.png,doc/de/pics/state-diagram.png,doc/de/pics/umbrello-main-screen.png,doc/de/pics/umbrello-ui-clean.png,doc/de/pics/umbrello-ui.png,doc/de/pics/use-case-diagram.png
+sub_dirs=
+type=normal
+
+[doc/de/pics/activity-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/activity-diagram.png
+type=DATA
+
+[doc/de/pics/add-remove-languages.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/add-remove-languages.png
+type=DATA
+
+[doc/de/pics/aggregation.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/aggregation.png
+type=DATA
+
+[doc/de/pics/association.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/association.png
+type=DATA
+
+[doc/de/pics/class-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/class-diagram.png
+type=DATA
+
+[doc/de/pics/class.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/class.png
+type=DATA
+
+[doc/de/pics/code-import.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/code-import.png
+type=DATA
+
+[doc/de/pics/collaboration-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/collaboration-diagram.png
+type=DATA
+
+[doc/de/pics/composition.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/composition.png
+type=DATA
+
+[doc/de/pics/folders.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/folders.png
+type=DATA
+
+[doc/de/pics/generalization.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/generalization.png
+type=DATA
+
+[doc/de/pics/generation-options.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/generation-options.png
+type=DATA
+
+[doc/de/pics/sequence-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/sequence-diagram.png
+type=DATA
+
+[doc/de/pics/state-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/state-diagram.png
+type=DATA
+
+[doc/de/pics/umbrello-main-screen.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/umbrello-main-screen.png
+type=DATA
+
+[doc/de/pics/umbrello-ui-clean.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/umbrello-ui-clean.png
+type=DATA
+
+[doc/de/pics/umbrello-ui.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/umbrello-ui.png
+type=DATA
+
+[doc/de/pics/use-case-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/de/umbrello/pics/use-case-diagram.png
+type=DATA
+
+[doc/de/uml_basics.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/de/working_with_umbrello.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/Makefile.am]
+files=doc/en/index.docbook,doc/en/introduction.docbook,doc/en/uml_basics.docbook,doc/en/installation.docbook,doc/en/faq.docbook,doc/en/menu_reference.docbook,doc/en/code_import_and_generation.docbook,doc/en/authors.docbook,doc/en/error_msgs.docbook,doc/en/working_with_umbrello.docbook,doc/en/other_features.docbook
+sub_dirs=pics
+type=normal
+
+[doc/en/authors.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/code_import_and_generation.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/error_msgs.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/faq.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/index.docbook]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/index.docbook
+type=DATA
+
+[doc/en/installation.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/introduction.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/menu_reference.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/other_features.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/pics/Makefile.am]
+files=doc/en/pics/add-remove-languages.png,doc/en/pics/aggregation.png,doc/en/pics/association.png,doc/en/pics/class-diagram.png,doc/en/pics/class.png,doc/en/pics/code-import.png,doc/en/pics/collaboration-diagram.png,doc/en/pics/composition.png,doc/en/pics/folders.png,doc/en/pics/generalization.png,doc/en/pics/generation-options.png,doc/en/pics/sequence-diagram.png,doc/en/pics/state-diagram.png,doc/en/pics/umbrello-main-screen.png,doc/en/pics/umbrello-ui.png,doc/en/pics/umbrello-ui-clean.png,doc/en/pics/activity-diagram.png,doc/en/pics/use-case-diagram.png
+sub_dirs=
+type=normal
+
+[doc/en/pics/activity-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/activity-diagram.png
+type=DATA
+
+[doc/en/pics/add-remove-languages.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/add-remove-languages.png
+type=DATA
+
+[doc/en/pics/aggregation.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/aggregation.png
+type=DATA
+
+[doc/en/pics/association.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/association.png
+type=DATA
+
+[doc/en/pics/class-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/class-diagram.png
+type=DATA
+
+[doc/en/pics/class.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/class.png
+type=DATA
+
+[doc/en/pics/code-import.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/code-import.png
+type=DATA
+
+[doc/en/pics/collaboration-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/collaboration-diagram.png
+type=DATA
+
+[doc/en/pics/composition.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/composition.png
+type=DATA
+
+[doc/en/pics/folders.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/folders.png
+type=DATA
+
+[doc/en/pics/generalization.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/generalization.png
+type=DATA
+
+[doc/en/pics/generation-options.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/generation-options.png
+type=DATA
+
+[doc/en/pics/sequence-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/sequence-diagram.png
+type=DATA
+
+[doc/en/pics/state-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/state-diagram.png
+type=DATA
+
+[doc/en/pics/umbrello-main-screen.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/umbrello-main-screen.png
+type=DATA
+
+[doc/en/pics/umbrello-ui-clean.png]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/pics/umbrello-ui.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/umbrello-ui.png
+type=DATA
+
+[doc/en/pics/use-case-diagram.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/umbrello/pics/use-case-diagram.png
+type=DATA
+
+[doc/en/uml_basics.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[doc/en/working_with_umbrello.docbook]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[po/Makefile.am]
+sub_dirs=
+type=po
+
+[uml.kdevprj]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[uml.spec.in]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[uml/Makefile.am]
+files=uml/actor.h,uml/actorwidgetdata.h,uml/actorwidget.h,uml/associationwidgetdata.h,uml/associationwidgetdatalist.h,uml/associationwidget.h,uml/assocrules.h,uml/attribute.h,uml/concept.h,uml/conceptwidgetdata.h,uml/conceptwidget.h,uml/docwindow.h,uml/floatingtextdata.h,uml/floatingtext.h,uml/infowidget.h,uml/kstartuplogo.h,uml/linepath.h,uml/listpopupmenu.h,uml/messagewidgetdata.h,uml/messagewidget.h,uml/actor.cpp,uml/actorwidget.cpp,uml/actorwidgetdata.cpp,uml/associationwidget.cpp,uml/associationwidgetdata.cpp,uml/assocrules.cpp,uml/attribute.cpp,uml/concept.cpp,uml/conceptwidget.cpp,uml/conceptwidgetdata.cpp,uml/docwindow.cpp,uml/floatingtext.cpp,uml/floatingtextdata.cpp,uml/infowidget.cpp,uml/kstartuplogo.cpp,uml/linepath.cpp,uml/listpopupmenu.cpp,uml/main.cpp,uml/messagewidget.cpp,uml/messagewidgetdata.cpp,uml/notewidget.cpp,uml/notewidgetdata.cpp,uml/notewidgetdata.h,uml/notewidget.h,uml/objectwidget.cpp,uml/objectwidgetdata.cpp,uml/objectwidgetdata.h,uml/objectwidget.h,uml/operation.cpp,uml/operation.h,uml/statewidget.cpp,uml/statewidgetdata.cpp,uml/statewidgetdata.h,uml/statewidget.h,uml/uml.cpp,uml/umldoc.cpp,uml/umldoc.h,uml/uml.h,uml/umlnamespace.cpp,uml/umlnamespace.h,uml/umlobject.cpp,uml/umlobject.h,uml/umlobjectlist.h,uml/umlviewcanvas.cpp,uml/umlviewcanvas.h,uml/umlview.cpp,uml/umlviewdata.cpp,uml/umlviewdata.h,uml/umlview.h,uml/umlviewlist.h,uml/umlwidget.cpp,uml/umlwidgetdata.cpp,uml/umlwidgetdata.h,uml/umlwidget.h,uml/umlwidgetlist.h,uml/usecase.cpp,uml/usecase.h,uml/usecasewidget.cpp,uml/usecasewidgetdata.cpp,uml/usecasewidgetdata.h,uml/usecasewidget.h,uml/worktoolbar.cpp,uml/worktoolbar.h,uml/hi16-app-uml.png,uml/hi32-app-uml.png,uml/lo16-app-uml.png,uml/lo32-app-uml.png,uml/tips,uml/uml.desktop,uml/umlui.rc,uml/x-uml.desktop,uml/activitywidgetdata.cpp,uml/activitywidgetdata.h,uml/activitywidget.cpp,uml/activitywidget.h,uml/codegenerator.cpp,uml/codegenerator.h,uml/seqlinewidget.cpp,uml/seqlinewidget.h,uml/umllistview.cpp,uml/umllistview.h,uml/umllistviewitem.cpp,uml/umllistviewitem.h,uml/umllistviewitemdata.cpp,uml/umllistviewitemdata.h,uml/umllistviewitemdatalist.h,uml/classimport.cpp,uml/classimport.h,uml/umllistviewitemlist.h
+sub_dirs=classparser,clipboard,dialogs,pics,codegenerators,headings
+type=prog_main
+
+[uml/activitywidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/activitywidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/activitywidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/activitywidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/actor.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/actor.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/actorwidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/actorwidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/actorwidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/actorwidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/associationwidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/associationwidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/associationwidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/associationwidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/associationwidgetdatalist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/assocrules.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/assocrules.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/attribute.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/attribute.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classimport.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classimport.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ClassParser.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ClassParser.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ClassStore.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ClassStore.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ClassTreeNode.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ClassTreeNode.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/Makefile.am]
+files=uml/classparser/ClassParser.h,uml/classparser/ClassStore.h,uml/classparser/ClassTreeNode.h,uml/classparser/ParsedArgument.h,uml/classparser/ParsedAttribute.h,uml/classparser/ParsedClassContainer.h,uml/classparser/ParsedClass.h,uml/classparser/ParsedContainer.h,uml/classparser/ParsedItem.h,uml/classparser/ParsedMethod.h,uml/classparser/ParsedParent.h,uml/classparser/ParsedScopeContainer.h,uml/classparser/ParsedSignalSlot.h,uml/classparser/ParsedStruct.h,uml/classparser/PersistantClassStore.h,uml/classparser/ProgrammingByContract.h,uml/classparser/tokenizer.h,uml/classparser/ClassParser.cc,uml/classparser/ClassStore.cc,uml/classparser/ClassTreeNode.cc,uml/classparser/ParsedArgument.cc,uml/classparser/ParsedAttribute.cc,uml/classparser/ParsedClass.cc,uml/classparser/ParsedClassContainer.cc,uml/classparser/ParsedContainer.cc,uml/classparser/ParsedItem.cc,uml/classparser/ParsedMethod.cc,uml/classparser/ParsedParent.cc,uml/classparser/ParsedScopeContainer.cc,uml/classparser/ParsedSignalSlot.cc,uml/classparser/ParsedStruct.cc,uml/classparser/PersistantClassStore.cc,uml/classparser/tokenizer.cc
+sharedlib_LDFLAGS=
+sharedlib_rootname=
+sub_dirs=
+type=static_library
+
+[uml/classparser/ParsedArgument.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedArgument.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedAttribute.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedAttribute.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedClass.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedClass.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedClassContainer.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedClassContainer.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedContainer.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedContainer.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedItem.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedItem.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedMethod.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedMethod.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedParent.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedParent.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedScopeContainer.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedScopeContainer.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedSignalSlot.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedSignalSlot.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ParsedStruct.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/ParsedStruct.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/PersistantClassStore.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/PersistantClassStore.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/ProgrammingByContract.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/classparser/tokenizer.cc]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/classparser/tokenizer.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/clipboard/Makefile.am]
+files=uml/clipboard/idchangelog.cpp,uml/clipboard/idchangelog.h,uml/clipboard/umlclipboard.cpp,uml/clipboard/umlclipboard.h,uml/clipboard/umldrag.cpp,uml/clipboard/umldrag.h
+sharedlib_LDFLAGS=-version-info 0:0:0
+sharedlib_rootname=clipboard
+sub_dirs=
+type=static_library
+
+[uml/clipboard/idchangelog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/clipboard/idchangelog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/clipboard/umlclipboard.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/clipboard/umlclipboard.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/clipboard/umldrag.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/clipboard/umldrag.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/codegenerator.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/codegenerator.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/codegenerators/Makefile.am]
+files=uml/codegenerators/cppwriter.cpp,uml/codegenerators/cppwriter.h,uml/codegenerators/factory.cpp,uml/codegenerators/javawriter.cpp,uml/codegenerators/javawriter.h,uml/codegenerators/phpwriter.cpp,uml/codegenerators/phpwriter.h
+sharedlib_LDFLAGS=-module
+sharedlib_rootname=codegenerator
+sub_dirs=
+type=shared_library
+
+[uml/codegenerators/cppwriter.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/codegenerators/cppwriter.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/codegenerators/factory.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/codegenerators/javawriter.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/codegenerators/javawriter.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/codegenerators/phpwriter.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/codegenerators/phpwriter.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/concept.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/concept.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/conceptwidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/conceptwidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/conceptwidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/conceptwidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/Makefile.am]
+files=uml/dialogs/assocpage.cpp,uml/dialogs/assocpage.h,uml/dialogs/assocpropdlg.cpp,uml/dialogs/assocpropdlg.h,uml/dialogs/classattpage.cpp,uml/dialogs/classattpage.h,uml/dialogs/classgenpage.cpp,uml/dialogs/classgenpage.h,uml/dialogs/classopspage.cpp,uml/dialogs/classopspage.h,uml/dialogs/classoptionspage.cpp,uml/dialogs/classoptionspage.h,uml/dialogs/classpropdlg.cpp,uml/dialogs/classpropdlg.h,uml/dialogs/diagramprintpage.cpp,uml/dialogs/diagramprintpage.h,uml/dialogs/parmpropdlg.cpp,uml/dialogs/parmpropdlg.h,uml/dialogs/selectopdlg.cpp,uml/dialogs/selectopdlg.h,uml/dialogs/settingsdlg.cpp,uml/dialogs/settingsdlg.h,uml/dialogs/statedialog.cpp,uml/dialogs/statedialog.h,uml/dialogs/umlattributedialog.h,uml/dialogs/umloperationdialog.h,uml/dialogs/umlviewdialog.h,uml/dialogs/umlwidgetcolorpage.h,uml/dialogs/umlattributedialog.cpp,uml/dialogs/umloperationdialog.cpp,uml/dialogs/umlviewdialog.cpp,uml/dialogs/umlwidgetcolorpage.cpp,uml/dialogs/activitypage.cpp,uml/dialogs/activitypage.h,uml/dialogs/activitydialog.cpp,uml/dialogs/activitydialog.h,uml/dialogs/notedialog.cpp,uml/dialogs/notedialog.h,uml/dialogs/configcodegenerators.cpp,uml/dialogs/configcodegenerators.h,uml/dialogs/configgeneratorsbase.ui,uml/dialogs/classwizard.cpp,uml/dialogs/classwizard.h,uml/dialogs/sellanguagesbase.ui,uml/dialogs/selectlanguagesdlg.cpp,uml/dialogs/selectlanguagesdlg.h,uml/dialogs/codegenerationoptionsbase.ui,uml/dialogs/codegenerationwizardbase.ui,uml/dialogs/codegenerationoptionspage.cpp,uml/dialogs/codegenerationoptionspage.h,uml/dialogs/codegenerationwizard.cpp,uml/dialogs/codegenerationwizard.h,uml/dialogs/overwritedialogue.cpp,uml/dialogs/overwritedialogue.h
+sharedlib_LDFLAGS=-version-info 0:0:0
+sharedlib_rootname=dialogs
+sub_dirs=
+type=static_library
+
+[uml/dialogs/activitydialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/activitydialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/activitypage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/activitypage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/assocpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/assocpage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/assocpropdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/assocpropdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classattpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classattpage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classgenpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classgenpage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classopspage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classopspage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classoptionspage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classoptionspage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classpropdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classpropdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classselectionpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classselectionpage.h]
+dist=false
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/classwizard.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/classwizard.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/codegenerationoptionsbase.ui]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codegenerationoptionspage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codegenerationoptionspage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/codegenerationwizard.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codegenerationwizard.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/codegenerationwizardbase.ui]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codegenwizard.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codegenwizard.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/codeoptionspage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/codeoptionspage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/configcodegenerators.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/configcodegenerators.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/configgeneratorsbase.ui]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/diagramprintpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/diagramprintpage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/notedialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/notedialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/overwritedialogue.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/overwritedialogue.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/parmpropdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/parmpropdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/selectlanguagesdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/selectlanguagesdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/selectopdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/selectopdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/sellanguagesbase.ui]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/settingsdlg.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/settingsdlg.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/statedialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/statedialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/umlattributedialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/umlattributedialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/umloperationdialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/umloperationdialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/umlviewdialog.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/umlviewdialog.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/dialogs/umlwidgetcolorpage.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/dialogs/umlwidgetcolorpage.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/docwindow.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/docwindow.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/floatingtext.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/floatingtext.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/floatingtextdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/floatingtextdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/headings/Makefile.am]
+files=uml/headings/heading.java,uml/headings/heading.h,uml/headings/template.cpp,uml/headings/heading.php,uml/headings/heading.cpp
+sub_dirs=
+type=normal
+
+[uml/headings/heading.cpp]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/headings/heading.cpp
+type=SOURCE
+
+[uml/headings/heading.h]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/headings/heading.h
+type=DATA
+
+[uml/headings/heading.java]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/headings/heading.java
+type=DATA
+
+[uml/headings/heading.php]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/headings/heading.php
+type=DATA
+
+[uml/headings/template.cpp]
+dist=false
+install=false
+install_location=$$(kde_datadir)/umbrello/headings/template.cpp
+type=DATA
+
+[uml/hi16-app-uml.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/hicolor/16x16/apps/umbrello.png
+type=DATA
+
+[uml/hi32-app-uml.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/hicolor/32x32/apps/umbrello.png
+type=DATA
+
+[uml/infowidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/infowidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/kstartuplogo.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/kstartuplogo.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/linepath.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/linepath.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/listpopupmenu.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/listpopupmenu.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/lo16-app-uml.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/locolor/16x16/apps/umbrello.png
+type=DATA
+
+[uml/lo32-app-uml.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/locolor/32x32/apps/umbrello.png
+type=DATA
+
+[uml/main.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/messagewidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/messagewidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/messagewidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/messagewidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/notewidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/notewidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/notewidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/notewidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/objectwidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/objectwidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/objectwidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/objectwidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/operation.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/operation.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/pics/CVglobal_meth.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVglobal_meth.png
+type=DATA
+
+[uml/pics/CVglobal_var.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVglobal_var.png
+type=DATA
+
+[uml/pics/CVnamespace.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVnamespace.png
+type=DATA
+
+[uml/pics/CVprivate_meth.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprivate_meth.png
+type=DATA
+
+[uml/pics/CVprivate_signal.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprivate_signal.png
+type=DATA
+
+[uml/pics/CVprivate_slot.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprivate_slot.png
+type=DATA
+
+[uml/pics/CVprivate_var.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprivate_var.png
+type=DATA
+
+[uml/pics/CVprotected_meth.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprotected_meth.png
+type=DATA
+
+[uml/pics/CVprotected_signal.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprotected_signal.png
+type=DATA
+
+[uml/pics/CVprotected_slot.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprotected_slot.png
+type=DATA
+
+[uml/pics/CVprotected_var.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVprotected_var.png
+type=DATA
+
+[uml/pics/CVpublic_meth.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVpublic_meth.png
+type=DATA
+
+[uml/pics/CVpublic_signal.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVpublic_signal.png
+type=DATA
+
+[uml/pics/CVpublic_slot.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVpublic_slot.png
+type=DATA
+
+[uml/pics/CVpublic_var.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVpublic_var.png
+type=DATA
+
+[uml/pics/CVstruct.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/CVstruct.png
+type=DATA
+
+[uml/pics/Makefile.am]
+files=uml/pics/actor.xpm,uml/pics/aggregation.xpm,uml/pics/anchor.xpm,uml/pics/arrow.xpm,uml/pics/association.xpm,uml/pics/broom.xpm,uml/pics/case.xpm,uml/pics/classicon.xpm,uml/pics/component.xpm,uml/pics/composition.xpm,uml/pics/constraint.xpm,uml/pics/CVglobal_meth.png,uml/pics/CVglobal_var.png,uml/pics/CVnamespace.png,uml/pics/CVprivate_meth.png,uml/pics/CVprivate_signal.png,uml/pics/CVprivate_slot.png,uml/pics/CVprivate_var.png,uml/pics/CVprotected_meth.png,uml/pics/CVprotected_signal.png,uml/pics/CVprotected_slot.png,uml/pics/CVprotected_var.png,uml/pics/CVpublic_meth.png,uml/pics/CVpublic_signal.png,uml/pics/CVpublic_slot.png,uml/pics/CVpublic_var.png,uml/pics/CVstruct.png,uml/pics/dependency.xpm,uml/pics/end_state.xpm,uml/pics/folder_green_open.png,uml/pics/folder_green.png,uml/pics/folder_grey_open.png,uml/pics/folder_grey.png,uml/pics/folder_home.png,uml/pics/generalization.xpm,uml/pics/hline.xpm,uml/pics/implements.xpm,uml/pics/initial_state.xpm,uml/pics/interface.xpm,uml/pics/largepackage.xpm,uml/pics/lifeline.xpm,uml/pics/line.xpm,uml/pics/message.xpm,uml/pics/note.xpm,uml/pics/object.xpm,uml/pics/output_win.xpm,uml/pics/realizes.xpm,uml/pics/rectangle.xpm,uml/pics/smallpackage.xpm,uml/pics/snapshot.xpm,uml/pics/startlogo.png,uml/pics/text.xpm,uml/pics/umlclass_template.xpm,uml/pics/umlclass.xpm,uml/pics/uniassoc.xpm,uml/pics/usecaserelation.xpm,uml/pics/vline.xpm,uml/pics/branch.xpm,uml/pics/fork.xpm
+sub_dirs=
+type=normal
+
+[uml/pics/actor.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/actor.xpm
+type=DATA
+
+[uml/pics/aggregation.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/aggregation.xpm
+type=DATA
+
+[uml/pics/anchor.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/anchor.xpm
+type=DATA
+
+[uml/pics/arrow.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/arrow.xpm
+type=DATA
+
+[uml/pics/association.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/association.xpm
+type=DATA
+
+[uml/pics/branch.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/branch.xpm
+type=DATA
+
+[uml/pics/broom.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/broom.xpm
+type=DATA
+
+[uml/pics/case.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/case.xpm
+type=DATA
+
+[uml/pics/classicon.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/classicon.xpm
+type=DATA
+
+[uml/pics/component.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/component.xpm
+type=DATA
+
+[uml/pics/composition.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/composition.xpm
+type=DATA
+
+[uml/pics/constraint.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/constraint.xpm
+type=DATA
+
+[uml/pics/dependency.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/dependency.xpm
+type=DATA
+
+[uml/pics/end_state.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/end_state.xpm
+type=DATA
+
+[uml/pics/folder_green.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/folder_green.png
+type=DATA
+
+[uml/pics/folder_green_open.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/folder_green_open.png
+type=DATA
+
+[uml/pics/folder_grey.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/folder_grey.png
+type=DATA
+
+[uml/pics/folder_grey_open.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/folder_grey_open.png
+type=DATA
+
+[uml/pics/folder_home.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/folder_home.png
+type=DATA
+
+[uml/pics/fork.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/fork.xpm
+type=DATA
+
+[uml/pics/generalization.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/generalization.xpm
+type=DATA
+
+[uml/pics/hline.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/hline.xpm
+type=DATA
+
+[uml/pics/implements.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/implements.xpm
+type=DATA
+
+[uml/pics/initial_state.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/initial_state.xpm
+type=DATA
+
+[uml/pics/interface.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/interface.xpm
+type=DATA
+
+[uml/pics/largepackage.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/largepackage.xpm
+type=DATA
+
+[uml/pics/lifeline.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/lifeline.xpm
+type=DATA
+
+[uml/pics/line.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/line.xpm
+type=DATA
+
+[uml/pics/message.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/message.xpm
+type=DATA
+
+[uml/pics/note.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/note.xpm
+type=DATA
+
+[uml/pics/object.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/object.xpm
+type=DATA
+
+[uml/pics/output_win.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/output_win.xpm
+type=DATA
+
+[uml/pics/realizes.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/realizes.xpm
+type=DATA
+
+[uml/pics/rectangle.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/rectangle.xpm
+type=DATA
+
+[uml/pics/smallpackage.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/smallpackage.xpm
+type=DATA
+
+[uml/pics/snapshot.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/snapshot.xpm
+type=DATA
+
+[uml/pics/startlogo.png]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/startlogo.png
+type=DATA
+
+[uml/pics/text.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/text.xpm
+type=DATA
+
+[uml/pics/umlclass.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/umlclass.xpm
+type=DATA
+
+[uml/pics/umlclass_template.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/umlclass_template.xpm
+type=DATA
+
+[uml/pics/uniassoc.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/uniassoc.xpm
+type=DATA
+
+[uml/pics/usecaserelation.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/usecaserelation.xpm
+type=DATA
+
+[uml/pics/vline.xpm]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/pics/vline.xpm
+type=DATA
+
+[uml/seqlinewidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/seqlinewidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/statewidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/statewidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/statewidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/statewidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/tips]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/tips
+type=DATA
+
+[uml/uml.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/uml.desktop]
+dist=true
+install=true
+install_location=$$(kde_appsdir)/Development/umbrello.desktop
+type=DATA
+
+[uml/uml.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umldoc.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umldoc.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umllistview.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umllistview.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umllistviewitem.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umllistviewitem.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umllistviewitemdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umllistviewitemdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umllistviewitemdatalist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umllistviewitemlist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlnamespace.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlnamespace.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlobject.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlobject.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlobjectlist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlui.rc]
+dist=true
+install=true
+install_location=$$(kde_datadir)/umbrello/umbrelloui.rc
+type=DATA
+
+[uml/umlview.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlview.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlviewcanvas.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlviewcanvas.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlviewdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlviewdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlviewlist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlwidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlwidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlwidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/umlwidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/umlwidgetlist.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/usecase.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/usecase.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/usecasewidget.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/usecasewidget.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/usecasewidgetdata.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/usecasewidgetdata.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/worktoolbar.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[uml/worktoolbar.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[uml/x-uml.desktop]
+dist=true
+install=true
+install_location=$$(kde_mimedir)/application/x-uml.desktop
+type=DATA
diff --git a/umbrello/uml.lsm b/umbrello/uml.lsm
new file mode 100644
index 00000000..9c8af94f
--- /dev/null
+++ b/umbrello/uml.lsm
@@ -0,0 +1,14 @@
+Begin3
+Title: Umbrello UML Modeller
+Version: 1.5.8
+Entered-date:
+Description: A UML diagram Modeller
+Keywords: uml diagram modeller
+Author: Paul Hensgen <phensgen @ users.sourceforge.net>
+Maintained-by: Umbrello UML Modeller developers <uml-devel @ lists.sourceforge.net>
+Primary-site: http://uml.sf.net
+Home-page: http://uml.sf.net
+Original-site:
+Platforms: KDE 3.3+
+Copying-policy: GPL
+End