Changeset 365

Show
Ignore:
Timestamp:
06/26/04 11:12:59 (4 years ago)
Author:
arjanmol
Message:

*** empty log message ***

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/gaphor/ChangeLog

    r364 r365  
     12004-06-23  Arjan Molenaar  <arjanmolenaar@hetnet.nl> 
     2 
     3        * gaphor/ui/mainwindow.py, gaphor/ui/toolbox.py: explicitly import 
     4        actions. 
     5        * doc/plugin.txt: explenation how plugins work 
     6        * setup.py: Boost version to 0.5.0. 
     7 
    182004-06-22  Arjan Molenaar  <arjanmolenaar@hetnet.nl> 
    29 
  • trunk/gaphor/TODO

    r363 r365  
    2626#  not differ. 
    2727 
    28 - Exporting diagrams to UML XMI, code, images (SVG/png), etc. 
     28- Exporting diagrams to UML XMI, code, images (SVG/png), etc. - make a plugin! 
    2929 
    3030#- Set up a plugin architecture. Since the internals of gaphor are pretty 
     
    7474- Profiles are reusable and its common to share them with different models. 
    7575- Stereotypes can only be owned by Profiles, not by (normal) Packages. 
    76 - I think having associations in this one is not very useful, though. 
    7776- We have to do a lookup if a MetaClass is actually part of the model. 
    7877- a stereotype can contain an image, that can be used in stead of its name 
    79 - Profiles should be saved with the model too. 
     78- Profiles should be saved with the model too. And iit should be possible to 
     79  "update" a profile within a model. 
    8080 
    8181Maybe it would be nice to create Stereotypes without creating the diagrams. 
  • trunk/gaphor/data/plugins/checkmetamodel/__init__.py

    r363 r365  
    11# vim:sw=4:et 
    22 
    3 print 'plugin',__file__ 
    4  
    53import gaphor.plugin 
     4from checkmodelgui import CheckModelWindow 
     5from checkmodel import check_associations, check_attributes 
    66 
    77class CheckMetamodelAction(gaphor.plugin.Action): 
    88 
    9     def init(self, window): 
    10         self._window = window 
    11  
    129    def execute(self): 
    13         print 'UMLSanityCheck' 
    14  
     10        print 'CheckMetamodelAction' 
     11        # TODO: override checkmodel.report 
     12        cw = CheckModelWindow() 
     13        cw.construct() 
     14        self.window.add_transient_window(cw) 
     15        cw.run() 
  • trunk/gaphor/data/plugins/checkmetamodel/plugin.xml

    r363 r365  
    55        version="0.1" 
    66        author="Arjan Molenaar"> 
     7  <description> 
     8    This plugin provides a means to check the consistency of an UML model. The 
     9    rules have been optimized to work with the data model (gaphor/UML/uml2.gaphor), 
     10    so their might not be much use, except for hackers. 
     11 
     12    Also this plugin is a template for future plugins. 
     13  </description> 
     14 
    715  <require> 
    816    <!-- 
     
    1422    --> 
    1523  </require> 
     24 
    1625  <provide> 
    1726    <!-- 
     
    2029    <action id="CheckMetamodel" 
    2130            label="Check UML metamodel" 
    22             icon-file="uml.png" 
    2331            tooltip="Check the UML meta model for errors" 
    2432            class="CheckMetamodelAction" slot="WindowSlot"> 
  • trunk/gaphor/doc/plugins.txt

    r364 r365  
    1414   removal. 
    1515 
     16A typical plugin.xml file looks like this: 
     17 
     18<?xml version="1.0"?> 
     19<plugin name="UML metamodel sanity check" 
     20        version="0.1" 
     21        author="Arjan Molenaar"> 
     22  <description> 
     23    A description of what this thing does. 
     24  </description> 
     25 
     26  <require> 
     27    <!-- 
     28      Define modules and plugins that are needed for this plugin to function 
     29      properly. 
     30    --> 
     31    <module name="os.path"/> 
     32    <plugin name="anotherPlugin"/> 
     33  </require> 
     34 
     35  <provide> 
     36    <!-- 
     37      Actions should be defined on the module's toplevel (like in __init__.py). 
     38    --> 
     39    <action id="MyPlugin" 
     40            label="Do a typical thing with the plugin" 
     41            icon-file="myicon.png" 
     42            tooltip="bla bla" 
     43            class="MyPluginAction" slot="WindowSlot"> 
     44      <!-- 
     45        Add optional dependencies to this action. The action is then updated 
     46        when actions defined in the depends tag are executed. 
     47      --> 
     48      <depends action="ItemFocus"/> 
     49    </action> 
     50  </provide> 
     51</plugin> 
     52 
     53 
     54A plugin contains three sections: 
     55description 
     56        A description of the plugin (could be shown in a plugin browser for example) 
     57        This is just a text field. 
     58require 
     59        Prerequisits for this plugin (such as exptic modules and other plugins) 
     60provide 
     61        Actions that are provided by this plugin 
     62         
     63The require section can contain modules and plugins that are needed for this plugin 
     64to work. 
     65 
     66The <provide> section contains the actions that can be added to the application. 
     67An action is a Python class that extends gaphor.plugin.Action (or CheckAction for 
     68checkbox actions or RadioAction for radiobutton actions). An action has an 
     69id 
     70        Id is a unique identifier for the action 
     71label 
     72        A label that is shown in the menu 
     73tooltip 
     74        some extra information 
     75icon-file 
     76        A file containing a nice (24x24) image, preferbly a PNG image. 
     77class 
     78        The Action class to load from the module. The Action class should be 
     79        visible through __init__.py (class names like 'test.TestAction' do not 
     80        work) 
     81slot 
     82        Slots are predefined places in a menu where new actions can be added. 
     83 
     84Slots 
     85----- 
     86Currently the following slots are defined: 
     87 
     88Main window 
     89 
     90main menu: 
     91        slot name               menu            comment 
     92        FileOpenSlot            File            after the 'Open' item 
     93        FileSaveSlot            File            after the 'Save' item 
     94        FileExportSlot          File/Export      
     95        FileSlot                File            After the 'Close' item 
     96        EditSlot                Edit 
     97        DiagramSlot             Diagram 
     98        WindowSlot              Window 
     99        HelpSlot                Help 
     100 
     101Items in a diagram can have additional actions too: 
     102 
     103        item:   slot name: 
     104        Class   ClassPopupSlot 
     105 
     106More slots are likely to be defined in the future. 
     107 
  • trunk/gaphor/gaphor/UML/uml2.gaphor

    r356 r365  
    11<?xml version="1.0"?> 
    2 <gaphor version="3.0" gaphor_version="0.4.0"><Association id="DCE:12A2B620-4B3C-11D7-B391-02BBFE4396CE"><memberEnd><reflist><ref refid="DCE:12A3CA4C-4B3C-11D7-B391-02BBFE4396CE"/><ref refid="DCE:12A397CC-4B3C-11D7-B391-02BBFE4396CE"/></reflist></memberEnd><ownedEnd><reflist><ref refid="DCE:12A397CC-4B3C-11D7-B391-02BBFE4396CE"/></reflist></ownedEnd><package><ref refid="DCE:E085A412-45CE-11D7-B5CA-613352B2821F"/></package> 
     2<gaphor version="3.0" gaphor_version="0.5.0"><Association id="DCE:12A2B620-4B3C-11D7-B391-02BBFE4396CE"><memberEnd><reflist><ref refid="DCE:12A3CA4C-4B3C-11D7-B391-02BBFE4396CE"/><ref refid="DCE:12A397CC-4B3C-11D7-B391-02BBFE4396CE"/></reflist></memberEnd><ownedEnd><reflist><ref refid="DCE:12A397CC-4B3C-11D7-B391-02BBFE4396CE"/></reflist></ownedEnd><package><ref refid="DCE:E085A412-45CE-11D7-B5CA-613352B2821F"/></package> 
    33<presentation><reflist><ref refid="DCE:110D08A6-4B3C-11D7-B391-02BBFE4396CE"/></reflist></presentation></Association><LiteralSpecification id="DCE:68F38E44-A419-11D8-B4C8-00061BC22919"></LiteralSpecification><Generalization id="DCE:84C5B02A-464D-11D7-AA08-1B85D5275D8A"><general><ref refid="DCE:FF594BE0-464C-11D7-AA08-1B85D5275D8A"/></general> 
    44<presentation><reflist><ref refid="DCE:8360FB04-464D-11D7-AA08-1B85D5275D8A"/></reflist></presentation><specific><ref refid="DCE:7D753EF0-464D-11D7-AA08-1B85D5275D8A"/></specific> 
     
    267267<orthogonal><val>0</val></orthogonal> 
    268268<horizontal><val>1</val></horizontal> 
    269 <points><val>[(8.4073254559594375, 5.135696545495648), (62.0, 6.0)]</val></points> 
     269<points><val>[(8.4073254559594659, 5.135696545495648), (62.0, 6.0)]</val></points> 
    270270<head_connection><ref refid="DCE:5138249A-863A-11D7-8239-5A25B8C2F569"/></head_connection> 
    271271<tail_connection><ref refid="DCE:91252432-863B-11D7-8239-5A25B8C2F569"/></tail_connection> 
     
    680680<grid_ofs_x><val>0.0</val></grid_ofs_x> 
    681681<grid_ofs_y><val>0.0</val></grid_ofs_y> 
    682 <grid_color><val>33023</val></grid_color> 
     682<grid_color><val>255</val></grid_color> 
    683683<grid_bg><val>4294967295</val></grid_bg> 
    684684<root_affine><val>(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)</val></root_affine> 
     
    792792<orthogonal><val>0</val></orthogonal> 
    793793<horizontal><val>1</val></horizontal> 
    794 <points><val>[(-21.0, -1.0), (-80.41605839416053, 87.0)]</val></points> 
     794<points><val>[(-21.0, -1.0), (-80.41605839416053, 87.000000000000057)]</val></points> 
    795795<head_connection><ref refid="DCE:2DF0AAAC-8404-11D8-82A2-7B88E55A3BEC"/></head_connection> 
    796796<tail_connection><ref refid="DCE:96EB8F86-8404-11D8-82A2-7B88E55A3BEC"/></tail_connection> 
     
    971971<presentation><reflist><ref refid="DCE:98E2A71C-6690-11D7-A84E-6C8643AD0CA4"/><ref refid="DCE:726CA564-8402-11D8-82A2-7B88E55A3BEC"/><ref refid="DCE:CAD809C6-4B33-11D7-B391-02BBFE4396CE"/><ref refid="DCE:7D1DB338-4B37-11D7-B391-02BBFE4396CE"/><ref refid="DCE:20C7308A-8323-11D8-8D1E-00C00C03A405"/></reflist></presentation></Class><Property id="DCE:DAE8A050-97BB-11D8-9E3B-00C00C03A405"><aggregation><val><![CDATA[composite]]></val></aggregation> 
    972972<association><ref refid="DCE:DAE7507E-97BB-11D8-9E3B-00C00C03A405"/></association> 
    973 <isDerived><val>0</val></isDerived> 
    974973<lowerValue><ref refid="DCE:DAE8B2DE-97BB-11D8-9E3B-00C00C03A405"/></lowerValue> 
     974<name><val><![CDATA[owiningProfile]]></val></name> 
    975975<owningAssociation><ref refid="DCE:DAE7507E-97BB-11D8-9E3B-00C00C03A405"/></owningAssociation> 
    976 <presentation><reflist></reflist></presentation><type><ref refid="DCE:3DB14614-97BA-11D8-9E36-00C00C03A405"/></type> 
     976<presentation><reflist></reflist></presentation><taggedValue><ref refid="DCE:71DB0EA4-C536-11D8-BC38-487DAB7CBA3E"/></taggedValue> 
     977<type><ref refid="DCE:3DB14614-97BA-11D8-9E36-00C00C03A405"/></type> 
     978<upperValue><ref refid="DCE:71D046EC-C536-11D8-BC38-487DAB7CBA3E"/></upperValue> 
    977979</Property><Property id="DCE:99C69A58-4A89-11D7-B090-133D836EF880"><aggregation><val><![CDATA[none]]></val></aggregation> 
    978980<association><ref refid="DCE:99C5AF80-4A89-11D7-B090-133D836EF880"/></association> 
     
    13081310<orthogonal><val>0</val></orthogonal> 
    13091311<horizontal><val>1</val></horizontal> 
    1310 <points><val>[(26.158798283262286, -4.9999999999999432), (19.456414519257578, 94.257510729613728)]</val></points> 
     1312<points><val>[(26.158798283262058, -5.0), (19.456414519257578, 94.257510729613728)]</val></points> 
    13111313<head_connection><ref refid="DCE:7DDC7BDC-4B3D-11D7-B391-02BBFE4396CE"/></head_connection> 
    13121314<tail_connection><ref refid="DCE:22D09ADC-863B-11D7-8239-5A25B8C2F569"/></tail_connection> 
     
    13251327<orthogonal><val>0</val></orthogonal> 
    13261328<horizontal><val>1</val></horizontal> 
    1327 <points><val>[(22.7456546708122, -2.4537838083979295), (42.0, 0.0)]</val></points> 
     1329<points><val>[(22.745654670811973, -2.4537838083979295), (42.0, 0.0)]</val></points> 
    13281330<head_connection><ref refid="DCE:2D5B72FE-863B-11D7-8239-5A25B8C2F569"/></head_connection> 
    13291331<tail_connection><ref refid="DCE:50CA96AC-863B-11D7-8239-5A25B8C2F569"/></tail_connection> 
     
    14111413</Property><LiteralSpecification id="DCE:ED5F90A2-4864-11D8-A4FB-20895068F46E"></LiteralSpecification><Property id="DCE:99C62C12-4A89-11D7-B090-133D836EF880"><aggregation><val><![CDATA[composite]]></val></aggregation> 
    14121414<association><ref refid="DCE:99C5AF80-4A89-11D7-B090-133D836EF880"/></association> 
     1415<isDerived><val>0</val></isDerived> 
    14131416<lowerValue><ref refid="DCE:23A3A6E4-DB15-11D7-8BD0-27F1E06F5E9F"/></lowerValue> 
    1414 <name><val><![CDATA[namespace]]></val></name> 
     1417<name><val><![CDATA[namespace_]]></val></name> 
    14151418<owningAssociation><ref refid="DCE:99C5AF80-4A89-11D7-B090-133D836EF880"/></owningAssociation> 
    14161419<presentation><reflist></reflist></presentation><taggedValue><ref refid="DCE:ED02710C-4864-11D8-A4FB-20895068F46E"/></taggedValue> 
     
    21162119</LiteralString><Diagram id="DCE:DA033CF8-45CE-11D7-B5CA-613352B2821F"><name><val><![CDATA[overview]]></val></name> 
    21172120<package><ref refid="DCE:DA01D45A-45CE-11D7-B5CA-613352B2821F"/></package> 
    2118 <canvas><extents><val>(32.0, 73.0, 798.0, 725.0)</val></extents> 
     2121<canvas><extents><val>(32.0, 73.0, 798.0, 741.0)</val></extents> 
    21192122<static_extents><val>0</val></static_extents> 
    21202123<snap_to_grid><val>0</val></snap_to_grid> 
     
    22062209</item><item id="DCE:55703BCA-6690-11D7-A84E-6C8643AD0CA4" type="PackageItem"><affine><val>(1.0, 0.0, 0.0, 1.0, 623.0, 442.0)</val></affine> 
    22072210<width><val>146.0</val></width> 
    2208 <height><val>65.0</val></height> 
     2211<height><val>66.0</val></height> 
    22092212<auto-resize><val>0</val></auto-resize> 
    22102213<subject><ref refid="DCE:5573D924-6690-11D7-A84E-6C8643AD0CA4"/></subject> 
     
    23082311</item><item id="DCE:7FCE206A-B7DE-11D8-8AD1-9AC43285B64C" type="PackageItem"><affine><val>(1.0, 0.0, 0.0, 1.0, 217.0, 674.0)</val></affine> 
    23092312<width><val>130.0</val></width> 
    2310 <height><val>50.0</val></height> 
     2313<height><val>66.0</val></height> 
    23112314<auto-resize><val>0</val></auto-resize> 
    23122315<subject><ref refid="DCE:81009F78-B7DE-11D8-8AD1-9AC43285B64C"/></subject> 
     
    27622765<grid_ofs_x><val>0.0</val></grid_ofs_x> 
    27632766<grid_ofs_y><val>0.0</val></grid_ofs_y> 
    2764 <grid_color><val>33023</val></grid_color> 
     2767<grid_color><val>255</val></grid_color> 
    27652768<grid_bg><val>4294967295</val></grid_bg> 
    27662769<root_affine><val>(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)</val></root_affine> 
     
    43014304</Generalization><Generalization id="DCE:D0D99FA6-50A1-11D7-807A-302CB4EF44FD"><general><ref refid="DCE:7D753EF0-464D-11D7-AA08-1B85D5275D8A"/></general> 
    43024305<presentation><reflist><ref refid="DCE:CD87C290-50A1-11D7-807A-302CB4EF44FD"/></reflist></presentation><specific><ref refid="DCE:B445FB00-4695-11D7-B567-379CA7034986"/></specific> 
    4303 </Generalization><LiteralSpecification id="DCE:ECCE6C10-4864-11D8-A4FB-20895068F46E"><value><val><![CDATA[subsets ownedMember]]></val></value> 
     4306</Generalization><LiteralSpecification id="DCE:ECCE6C10-4864-11D8-A4FB-20895068F46E"><value><val><![CDATA[subsets ownedMember, 
     4307     ownedRule]]></val></value> 
    43044308</LiteralSpecification><LiteralSpecification id="DCE:EE1BB08C-4864-11D8-A4FB-20895068F46E"><value><val><![CDATA[subsets context, 
    43054309namespace]]></val></value> 
     
    66406644<orthogonal><val>0</val></orthogonal> 
    66416645<horizontal><val>1</val></horizontal> 
    6642 <points><val>[(-3.0, -1.0), (-3.0, 134.0)]</val></points> 
     6646<points><val>[(-3.0, -1.0000000000000284), (-3.0, 134.0)]</val></points> 
    66436647<head_connection><ref refid="DCE:D7075AD6-65C5-11D7-89A9-9C62884CFFDE"/></head_connection> 
    66446648<tail_connection><ref refid="DCE:84BAC096-65CE-11D7-89A9-9C62884CFFDE"/></tail_connection> 
     
    66626666<orthogonal><val>0</val></orthogonal> 
    66636667<horizontal><val>1</val></horizontal> 
    6664 <points><val>[(0.0, -1.0), (97.0, 134.0)]</val></points> 
     6668<points><val>[(0.0, -1.0000000000000284), (97.0, 134.0)]</val></points> 
    66656669<head_connection><ref refid="DCE:D7075AD6-65C5-11D7-89A9-9C62884CFFDE"/></head_connection> 
    66666670<tail_connection><ref refid="DCE:8C12C8AE-65CE-11D7-89A9-9C62884CFFDE"/></tail_connection> 
     
    68856889<orthogonal><val>0</val></orthogonal> 
    68866890<horizontal><val>1</val></horizontal> 
    6887 <points><val>[(1.0, -24.0), (10.124999999999943, -66.0)]</val></points> 
     6891<points><val>[(1.0, -24.0), (10.124999999999943, -65.999999999999943)]</val></points> 
    68886892<head_connection><ref refid="DCE:80BB31C2-84DD-11D8-9086-B4BC0648889A"/></head_connection> 
    68896893<tail_connection><ref refid="DCE:403F722A-78D6-11D7-B68E-7835A4497977"/></tail_connection> 
     
    72187222<presentation><reflist></reflist></presentation><type><ref refid="DCE:109C134E-8402-11D8-82A2-7B88E55A3BEC"/></type> 
    72197223<upperValue><ref refid="DCE:0466D3A2-8C98-11D8-8032-00C00C03A405"/></upperValue> 
    7220 </Property><LiteralSpecification id="DCE:EF1D46B2-4864-11D8-A4FB-20895068F46E"></LiteralSpecification><Property id="DCE:54F95920-6692-11D7-A84E-6C8643AD0CA4"><association><ref refid="DCE:54F91F8E-6692-11D7-A84E-6C8643AD0CA4"/></association> 
     7224</Property><LiteralSpecification id="DCE:EF1D46B2-4864-11D8-A4FB-20895068F46E"><value><val><![CDATA[subsets namespace]]></val></value> 
     7225</LiteralSpecification><Property id="DCE:54F95920-6692-11D7-A84E-6C8643AD0CA4"><association><ref refid="DCE:54F91F8E-6692-11D7-A84E-6C8643AD0CA4"/></association> 
    72217226<isDerived><val>0</val></isDerived> 
    72227227<name><val><![CDATA[]]></val></name> 
     
    72867291<presentation><reflist><ref refid="DCE:FDB348C2-6690-11D7-A84E-6C8643AD0CA4"/></reflist></presentation></Association><Diagram id="DCE:71EC6E5E-6690-11D7-A84E-6C8643AD0CA4"><name><val><![CDATA[UseCases]]></val></name> 
    72877292<package><ref refid="DCE:5573D924-6690-11D7-A84E-6C8643AD0CA4"/></package> 
    7288 <canvas><extents><val>(53.0, 88.0, 917.0, 596.0)</val></extents> 
     7293<canvas><extents><val>(20.965517241379274, 88.0, 917.0, 596.0)</val></extents> 
    72897294<static_extents><val>0</val></static_extents> 
    72907295<snap_to_grid><val>0</val></snap_to_grid> 
     
    72937298<grid_ofs_x><val>0.0</val></grid_ofs_x> 
    72947299<grid_ofs_y><val>0.0</val></grid_ofs_y> 
    7295 <grid_color><val>33023</val></grid_color> 
     7300<grid_color><val>255</val></grid_color> 
    72967301<grid_bg><val>4294967295</val></grid_bg> 
    72977302<root_affine><val>(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)</val></root_affine> 
     
    81888193<grid_ofs_x><val>0.0</val></grid_ofs_x> 
    81898194<grid_ofs_y><val>0.0</val></grid_ofs_y> 
    8190 <grid_color><val>255</val></grid_color> 
     8195<grid_color><val>33023</val></grid_color> 
    81918196<grid_bg><val>4294967295</val></grid_bg> 
    81928197<root_affine><val>(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)</val></root_affine> 
     
    83548359<upperValue><ref refid="DCE:E4353950-BE19-11D8-BBAB-00C00C03A405"/></upperValue> 
    83558360</Property><LiteralSpecification id="DCE:D2015C82-BE19-11D8-BBAB-00C00C03A405"></LiteralSpecification><LiteralSpecification id="DCE:E4353950-BE19-11D8-BBAB-00C00C03A405"><value><val><![CDATA[*]]></val></value> 
    8356 </LiteralSpecification><LiteralSpecification id="DCE:E43E0DBC-BE19-11D8-BBAB-00C00C03A405"></LiteralSpecification></gaphor> 
     8361</LiteralSpecification><LiteralSpecification id="DCE:E43E0DBC-BE19-11D8-BBAB-00C00C03A405"></LiteralSpecification><LiteralSpecification id="DCE:71D046EC-C536-11D8-BC38-487DAB7CBA3E"><value><val><![CDATA[1]]></val></value> 
     8362</LiteralSpecification><LiteralSpecification id="DCE:71DB0EA4-C536-11D8-BC38-487DAB7CBA3E"><value><val><![CDATA[subsets namespace]]></val></value> 
     8363</LiteralSpecification></gaphor> 
  • trunk/gaphor/gaphor/UML/uml2.override

    r356 r365  
    8080%% 
    8181override Classifier.general 
    82 Classifier.general = derivedunion('inheritedMember', 0, '*') 
     82def classifier_general(self): 
     83    return [g.general for g in self.generalization] 
     84 
     85Classifier.general = property(classifier_general, doc="") 
     86del classifier_general 
     87%% 
     88override Class.superClass 
     89Class.superClass = Classifier.general 
    8390%% 
    8491override Namespace.importedMember 
  • trunk/gaphor/gaphor/__init__.py

    r363 r365  
    4646    import gtk 
    4747    # Load plugin definitions: 
     48    import diagram 
    4849    import pluginmanager 
    49     from ui import MainWindow 
     50    from ui.mainwindow import MainWindow 
    5051 
    5152    resource('PluginManager').bootstrap() 
    5253 
    5354    # should we set a default icon here or something? 
    54     main_window = MainWindow(
     55    main_window = resource(MainWindow
    5556    main_window.construct() 
    5657    # When the state changes to CLOSED, quit the application 
    5758    main_window.connect(lambda win: win.get_state() == MainWindow.STATE_CLOSED and gtk.main_quit()) 
    5859    # Make the mainwindow accessable as a resource 
    59     resource('MainWindow', main_window) 
    6060    #gtk.threads_init() 
    6161    #gtk.threads_enter() 
  • trunk/gaphor/gaphor/diagram/interface.py

    r359 r365  
    1818 
    1919class InterfaceItem(NamedItem): 
     20    """This item represents an interface drawn as a dot. The class-like 
     21    representation is provided by ClassItem. These representations can be switched 
     22    by using the Fold and Unfold actions. 
     23 
     24    TODO: Provided interfaces are shown by a Implementation dependency, 
     25          Required interfaces are shown by a Usage dependency (not association). 
     26           
     27          Interfaces may also be used to specify required interfaces, which are 
     28          specified by a usage dependency between the classifier and the 
     29          corresponding interfaces. Required interfaces specify services that a 
     30          classifier needs in order to perform its function and fulfill its own 
     31          obligations to its clients. 
     32    """ 
    2033    RADIUS=10 
    2134 
     
    5467 
    5568    def on_update(self, affine): 
     69 
     70        # Figure out if this interface represents a required, provided or wired look. 
    5671        self.association_items = 0 
    5772        self.implementation_items = 0 
     
    6580                    gaphor.diagram.implementation.ImplementationItem): 
    6681                self.implementation_items += 1 
    67  
    68  
    6982 
    7083        # Center the text 
     
    94107 
    95108    def on_handle_motion(self, handle, wx, wy, mask): 
    96         """Make sure the element works with diacanavs2 <= 0.12.0. 
    97         """ 
     109        # Make sure the element works with diacanavs2 <= 0.12.0. 
    98110        if handle not in self.handles[:7]: 
    99111            return wx, wy 
     
    114126            yield s 
    115127 
     128    def on_connect_handle(self, handle): 
     129        self.request_update() 
     130        return NamedItem.on_connect_handle(self, handle) 
     131 
     132    def on_disconnect_handle(self, handle): 
     133        self.request_update() 
     134        return NamedItem.on_disconnect_handle(self, handle) 
    116135 
    117136    def _getLookType(self): 
     
    126145 
    127146 
    128 #    def on_editable_start_editing(self, shape): 
    129 #        NamedItem.on_editable_start_editing(self, shape) 
    130 #        self._name.set_max_width(0) 
    131  
    132147initialize_item(InterfaceItem, UML.Interface) 
  • trunk/gaphor/gaphor/diagram/klass.py

    r361 r365  
    106106        'separator', 
    107107        'ShowAttributes', 
    108         'ShowOperations' 
     108        'ShowOperations', 
     109        '<ClassPopupSlot>' 
    109110    ) 
    110111 
     
    146147 
    147148    def get_popup_menu(self): 
    148         from itemactions import ApplyStereotypeAction, register_action 
    149         # TODO: We should find the Stereotypes who have an Extension relationship 
    150         #       with a Class who's name is the name of this class or one of its 
    151         #       supertypes. 
    152         NamedElement = UML.NamedElement 
    153         Class = UML.Class 
    154  
     149        """In the popup menu a submenu is created with Stereotypes than can be 
     150        applied to this classifier (Class, Interface). 
     151        If the class itself is a metaclass, an option is added to check if the class 
     152        exists. 
     153        """ 
    155154        stereotype_list = self.stereotype_list 
    156155        stereotype_list[:] = [] 
    157         _mro = filter(lambda e:issubclass(e, NamedElement), type(self.subject).__mro__) 
    158         names = map(getattr, _mro, ['__name__'] * len(_mro)) 
    159         classes = self._subject._factory.select(lambda e: e.isKindOf(Class) and e.name in names) 
    160         for class_ in classes: 
    161             for extension in class_.extension: 
    162                 stereotype = extension.ownedEnd.type 
    163                 stereotype_action = ApplyStereotypeAction(stereotype) 
    164                 register_action(stereotype_action, 'ItemFocus') 
    165                 stereotype_list.append(stereotype_action.id) 
     156        if isinstance(subject, UML.Class) and subject.extension: 
     157            # Add an action that can be used to check if the metaclass is an 
     158            # existing metaclass 
     159            pass 
     160        else: 
     161            from itemactions import ApplyStereotypeAction, register_action 
     162            NamedElement = UML.NamedElement 
     163            Class = UML.Class 
     164 
     165            # Find classes that are superclasses of our subject 
     166            _mro = filter(lambda e:issubclass(e, NamedElement), type(self.subject).__mro__) 
     167            # Find out their names 
     168            names = map(getattr, _mro, ['__name__'] * len(_mro)) 
     169            # Find stereotypes that extend out metaclass 
     170            classes = self._subject._factory.select(lambda e: e.isKindOf(Class) and e.name in names) 
     171 
     172            for class_ in classes: 
     173                for extension in class_.extension: 
     174                    stereotype = extension.ownedEnd.type 
     175                    stereotype_action = ApplyStereotypeAction(stereotype) 
     176                    register_action(stereotype_action, 'ItemFocus') 
     177                    stereotype_list.append(stereotype_action.id) 
    166178        return NamedItem.get_popup_menu(self) 
    167179 
  • trunk/gaphor/gaphor/plugin.py

    r363 r365  
     1# vim:sw=4:et 
    12"""This module provides everything needed to create a plugin. 
    23 
    34resource - Get/set application wide resources 
     5 
     6Classes to construct Actions: 
     7    Action 
     8    CheckAction (Checkbutton Action) 
     9    RadioAction (RadioButton Action, should set the group attribute) 
     10    ObjectAction (this is not an action, but it contains some code to make 
     11                  instances of Actions behave like Action classes) 
     12 
     13Each action is initialized. The window containing the action can be accessed 
     14by the 'window' property. 
    415""" 
    516 
    617from gaphor import resource 
    718 
    8 from gaphor.misc.action import Action, CheckAction, RadioAction, ObjectAction 
     19from gaphor.misc.action import Action as _Action 
     20from gaphor.misc.action import CheckAction as _CheckAction 
     21from gaphor.misc.action import RadioAction as _RadioAction 
     22from gaphor.misc.action import ObjectAction 
    923 
     24 
     25class _ActionMixIn(object): 
     26    """Handle initialization of actions in a way that the main window 
     27    can properly initialize the action. 
     28    """ 
     29 
     30    def init(self, window): 
     31        self._window = window 
     32 
     33    def get_window(self): 
     34        return self._window 
     35 
     36    window = property(get_window) 
     37 
     38class Action(_Action, _ActionMixIn): pass 
     39class CheckAction(_CheckAction, _ActionMixIn): pass 
     40class RadioAction(_RadioAction, _ActionMixIn): pass 
     41 
     42del _Action, _CheckAction, _RadioAction, _ActionMixIn 
     43 
  • trunk/gaphor/gaphor/pluginmanager.py

    r363 r365  
    11# vim:sw=4 
    2 """Manage plugins. 
     2"""Plugin Manager. 
     3 
     4The plugin manager is used to manage (register/unregister) plugins. 
     5 
     6A Plugin is presented as a directory. This directory contains two files: 
     7 - plugin.xml contains a description of the plugin 
     8 - __init__.py is needed since the plugin is loaded as a module 
     9  
     10The following classes are provided by this module: 
     11 
     12PluginManager - The main class. PluginManager.bootstrap() loads all plugins 
     13        from the default plugin dirs ($PREFIX/share/gaphor/plugins and 
     14        $HOME/.gaphor/plugins). 
     15Plugin - This class represents a plugin. It contains data from plugin.xml 
     16        as well as data gathered during the plugin loading process (such as 
     17        the module that was created when the plugin is imported. 
     18PluginAction - Defines an gaphor.plugin.Action instance. 
     19PluginLoader - SAX parser used to read the plugin.xml file of a plugin. This 
     20        class creates a Plugin instance from the xml file. 
    321""" 
    422 
     
    927from gaphor.parser import ParserException 
    1028from gaphor.misc.action import register_action_for_slot 
     29from gaphor.misc.odict import odict 
    1130 
    1231XMLNS='http://gaphor.sourceforge.net/gaphor/plugin' 
     
    2544        self.required_actions = [] 
    2645        self.provided_actions = [] 
     46        self.description = '' 
    2747        self.initialized = False 
    2848        self.path = '' 
    2949        self.module = None 
    3050        self.status = '' 
     51 
     52    def requirements_met(self, manager): 
     53        """Check if all <require>-ments are met to load the plugin. 
     54        """ 
     55        if self.initialized: 
     56            return False 
     57 
     58        for mod in self.required_modules: 
     59            try: 
     60                # TODO: How to find out if a module exists without loading it? 
     61                __import__(mod, globals(), locals(), []) 
     62            except ImportError: 
     63                self.initialized = True 
     64                self.status = 'Could not initialize plugin: module %s could not be imported' % mod 
     65                log.debug(self.status) 
     66                return False 
     67 
     68        pluginstatus = {} 
     69        for p in manager.plugins.itervalues(): 
     70            pluginstatus[p.name] = bool(p.initialized) 
     71        for p in self.required_plugins: 
     72            if not pluginstatus.get(p): 
     73                self.status = 'Plugin %s is required by this plugin' % p 
     74                log.debug(self.status) 
     75                return False 
     76 
     77        return True 
     78 
     79    def import_plugin(self): 
     80        """Do the actual import of the plugin module. 
     81        """ 
     82        mod = __import__(self.path, globals(), locals(), []) 
     83        self.module = mod 
     84        self.initialized = True 
     85        self.status = 'Imported' 
     86 
     87        for action in self.provided_actions: 
     88            try: 
     89                action.import_action(self) 
     90            except Exception, e: 
     91                log.error('Failed to import action %s' % (action.id or action.class_), e) 
     92 
    3193 
    3294class PluginAction(object): 
     
    45107        self.depends = [] 
    46108 
     109    def import_action(self, plugin): 
     110        """Import and register one action in the plugin. 
     111        """ 
     112        # Create an icon for the plugin 
     113        if self.icon_file: 
     114            from gaphor.ui.stock import add_stock_icon 
     115            self.stock_id = 'gaphor-plugin-' + self.id 
     116            add_stock_icon(self.stock_id, plugin.path, [self.icon_file]) 
     117 
     118        # Fetch the action class 
     119        action_class = getattr(plugin.module, self.class_) 
     120 
     121        # Copy attributes from the plugin to the class 
     122        for attr in ('id', 'label', 'stock_id', 'tooltip', 'accel'): 
     123            val = getattr(self, attr, None) 
     124            if val: 
     125                setattr(action_class, attr, val) 
     126 
     127        register_action_for_slot(action_class, self.slot, *self.depends) 
     128        log.debug('Providing action %s for slot %s' % (action_class, self.slot)) 
    47129 
    48130class PluginLoader(handler.ContentHandler): 
     
    53135    PROVIDE = 2 
    54136    ACTION = 3 
     137    DESCRIPTION = 4 
    55138 
    56139    def __init__(self): 
     
    77160                self.plugin.version = attrs['version'] 
    78161                self.plugin.author = attrs['author'] 
     162            elif name == 'description': 
     163                self.mode = self.DESCRIPTION 
    79164            if name == 'require': 
    80165                self.mode = self.REQUIRE 
     
    111196 
    112197    def endElement(self, name): 
    113         if self.mode in (self.REQUIRE, self.PROVIDE) and \ 
    114            name in ('require', 'provide'): 
     198        if self.mode in (self.REQUIRE, self.PROVIDE, self.DESCRIPTION) and \ 
     199           name in ('description', 'require', 'provide'): 
    115200            self.mode = self.TOPLEVEL 
    116201        elif self.mode == self.ACTION and name == 'action': 
     
    134219    def characters(self, content): 
    135220        """Read characters.""" 
    136         pass 
     221        if self.mode == self.DESCRIPTION: 
     222            self.plugin.description += content 
    137223 
    138224 
     
    142228 
    143229    def __init__(self): 
    144         self.plugins = {} 
     230        self.plugins = odict() 
    145231        self.bootstrapped = False 
    146232 
     
    164250            import_done = False 
    165251            for plugin in self.plugins.itervalues(): 
    166                 if self.requirements_met(plugin): 
     252                if plugin.requirements_met(self): 
    167253                    try: 
    168                         self.import_plugin(plugin
     254                        plugin.import_plugin(
    169255                    except Exception, e: 
    170256                        plugin.status = 'Failed to load plugin %s: %s' % (plugin.name, e) 
     
    193279                log.error('Could not load plugin definition %s' % plugin_xml, e) 
    194280 
    195     def requirements_met(self, plugin): 
    196         """Check if all <require>-ments are met to load the plugin. 
    197         """ 
    198         if plugin.initialized: 
    199             return False 
    200  
    201         for mod in plugin.required_modules: 
    202             try: 
    203                 # TODO: How to find out if a module exists without loading it? 
    204                 __import__(mod, globals(), locals(), []) 
    205             except ImportError: 
    206                 plugin.initialized = True 
    207                 plugin.status = 'Could not initialize plugin: module %s could not be imported' % mod 
    208                 log.debug(plugin.status) 
    209                 return False 
    210  
    211         pluginstatus = {} 
    212         for p in self.plugins.itervalues(): 
    213             pluginstatus[p.name] = bool(p.initialized) 
    214         for p in plugin.required_plugins: 
    215             if not pluginstatus.get(p): 
    216                 plugin.status = 'Plugin %s is required by this plugin' % p 
    217                 log.debug(plugin.status) 
    218                 return False 
    219  
    220         return True 
    221  
    222     def import_plugin(self, plugin): 
    223         """Do the actual import of the plugin module. 
    224         """ 
    225         mod = __import__(plugin.path, globals(), locals(), []) 
    226         plugin.module = mod 
    227         plugin.initialized = True 
    228         plugin.status = 'Imported' 
    229  
    230         for action in plugin.provided_actions: 
    231             try: 
    232                 self.import_action(action, plugin) 
    233             except Exception, e: 
    234                 log.error('Failed to import action %s' % (action.id or action.class_), e) 
    235  
    236     def import_action(self, action, plugin): 
    237         """Import and register one action in the plugin. 
    238         """ 
    239         # Create an icon for the plugin 
    240         if action.icon_file: 
    241             from gaphor.ui.stock import add_stock_icon 
    242             action.stock_id = 'gaphor-plugin-' + action.id 
    243             add_stock_icon(action.stock_id, plugin.path, [action.icon_file]) 
    244  
    245         # Fetch the action class 
    246         action_class = getattr(plugin.module, action.class_) 
    247  
    248         # Copy attributes from the plugin to the class 
    249         for attr in ('id', 'label', 'stock_id', 'tooltip', 'accel'): 
    250             val = getattr(action, attr, None) 
    251             if val: 
    252                 setattr(action_class, attr, val) 
    253  
    254         register_action_for_slot(action_class, action.slot, *action.depends) 
    255         log.debug('Providing entry %s for slot <%s>' % (action_class, action.slot)) 
    256281 
    257282# Make one default plugin manager 
  • trunk/gaphor/gaphor/ui/__init__.py

    r363 r365  
    99 
    1010# Should we do this: 
    11 from abstractwindow import AbstractWindow 
    12 from mainwindow import MainWindow 
    13 from diagramview import DiagramView 
    14 from editorwindow import EditorWindow 
     11#from abstractwindow import AbstractWindow 
     12#from mainwindow import MainWindow 
     13#from diagramview import DiagramView 
     14#from editorwindow import EditorWindow 
    1515 
    1616# Create stock items 
  • trunk/gaphor/gaphor/ui/diagramtab.py

    r304 r365  
    66from abstractwindow import AbstractWindow 
    77from gaphor.diagram.itemtool import ItemTool 
     8 
     9import diagramactions 
     10import gaphor.diagram.actions 
    811 
    912class DiagramTab(object): 
     
    140143            #self.get_window().set_title(self.diagram.name or '<None>') 
    141144 
    142 import diagramactions 
    143 import gaphor.diagram.actions 
  • trunk/gaphor/gaphor/ui/mainactions.py

    r338 r365  
    278278 
    279279    def execute(self): 
    280         from gaphor.ui import EditorWindow 
     280        from gaphor.ui.editorwindow import EditorWindow 
    281281         
    282282        ew = EditorWindow() 
     
    305305 
    306306register_action(OpenConsoleWindowAction) 
    307  
    308  
    309 class OpenStereotypeWindowAction(Action): 
    310     id = 'OpenStereotypeWindow' 
    311     label = 'S_tereotypes' 
    312     tooltip = 'Open the Gaphor Stereotypes' 
    313  
    314     def init(self, window): 
    315         self._window = window 
    316  
    317     def execute(self): 
    318         from gaphor.ui.stereotypewindow import StereotypeWindow 
    319          
    320         ew = StereotypeWindow() 
    321         #ew.construct(self._window.get_window()) 
    322         ew.run(self._window.get_window()) 
    323         #self._window.add_transient_window(ew) 
    324         #self._window.set_message('Stereortypes launched') 
    325  
    326 register_action(OpenStereotypeWindowAction) 
    327307 
    328308 
     
    411391        element = self._window.get_tree_view().get_selected_element() 
    412392        if isinstance(element, UML.Diagram): 
    413             # Try to find an existing window/tab and let it get focus: 
    414             for tab in self._window.get_tabs(): 
    415                 if tab.get_diagram() is element: 
    416                     self._window.set_current_page(tab) 
    417                     return 
    418             # Import here to avoid cyclic references 
    419             from gaphor.ui.diagramtab import DiagramTab 
    420             diagram_tab = DiagramTab(self._window) 
    421             #diagram_tab.set_owning_window(self._window) 
    422             #diagram_tab.sub_window = False 
    423