PyAttributes let's you add arbitrary attributes to any object in a Dia diagram. Objects are anything in a diagram that you can select, like boxes, arrows, text etc. The attributes have a name and can store different kinds of information, some can even do actions like running a external command, loading a file or.. uhm, well anything.
Confused? We'll maybe an example will set you straight. We take a diagram containing two boxes and a zig-zag line.
There is a dialog for adding attributes to objects in the menu, 'Dialog/Setup Attributes...'. You choose one or more objects then choose the type of the Attribute and fill in the name.
After setting up the attributes you can view and update them through the object view. Just select a object and in the menu choose 'Dialogs/Object View...'. With it you can view and fill in new values of attributes.
As you probably figured out by now the extra attributes doesn't change the diagram at all. They are metadata, only meaningful for you, and they don't get printed with the diagram. So what's their use? They can be quite useful for extra information about what the objects in the diagram really represents, for example; take a network diagram with computers and routers etc. you can give everything having a IP number in reality a attribute of the type IP with the name 'address'. You could also give them attributes like name and room. The fun does not stop there, you can add attributes that perform actions, like a SSH prompt, ping or a web page view of a wiki pointing at different pages depending on which object you're on. You could easily make a documenting and administrating tool from your diagram.
To save a diagram with the extra information you have to use a special save function 'Save with PyAtt', the same goes for loading. You can load a diagram saved with PyAttributes in Dia without the plugin. This way you just don't get the extra attributes.
Every attribute has a name and a type. Some attributes requires more than a name for setup and some are to large to display it's value in the Object Views list of attributes. Large values gets a whole new tab for themselves, just double click on the name of the attribute in the list. Selecting it and pressing the 'View' button results in the same thing.
These are some fundamental attributes and should cover quite alot, but if you need something else it's easy to write your own in python. Tutorial is coming.
The Terminal attribute runs any command that's in your path in a bash prompt and functions otherwise as an ordinary xterm. When adding a Terminal to your objects it requires that you give it a command as well as a name. If you make a typo or change your mind you can change the command in the Object View, just click on the line in the attribute list where the command is displayed. The Terminal does not fit the list for obvious reasons so you'll have to activate it with a double click or the 'View' button in the Object View. Some things you can do is run emacs, ssh, ping, lynx against a wikiw, a sql client, etc etc..
The Webpage attribute uses the Gecko engine from Mozilla, through the Gtk+ widget GtkMozEmbed. In other words it's like Firefox, but without any buttons :-) The Webpage attribute needs an URL on setup as well as a name and ,as the Terminal attribute, you can change it in the Object View later if you want. It also needs a tab and you open it by double clicking in the list or the 'View' button in the Object View.
The attribute creates a temporary directory, ordinarily in /tmp, to store it's cookies and cache.
So, you want to make your own attribute, eh? Well it ain't too hard, but you'll need to know how to program in Python, go to http://www.python.org and enlighten yourself. Ok, let's make a new attribute, step by step.
We'll make a Boolean attribute that can have either the value 'False' or 'True'. Nothing else. For this
we're going to need two python classes, one for the attribute and one for the view (GUI) of the attribute.
Both of these are going to subclass classes in the module pyattributes
, which resides in the
file pyattributes/attribute.py
. When in doubt, use the source Luke.
So fire up your favourite text editor (emacs,vim,gedit etc) and create a new file named boolean_attribute.py
or whatever you like. Copy and paste or download the code here. The first class:
First we need to import the module with the class that we want to subclass, which is pyattributes.Attribute
.
import pyattributes
Then we define the class and set some class attributes:
class BooleanAttribute(pyattributes.Attribute):
type = 'Boolean'
desc = 'A Boolean, can either be True or False'
type
is the name of the attribute and must be unique, and desc
is a short description.
The constructor is as follows:
First we call the super classes and then we set two important attributes.
def __init__(self,name):
#call the superclass
pyattributes.Attribute.__init__(self,name)
#default value is False
self.value = False
self.can_parse = True
can_parse
acts as a flag, if
set to True
the method parse(self,txt)
must be implemented. As you can see we set our
BooleanAttribute to always start with the value False.
Next we define a method that returns the view of the BooleanAttribute, the second class we haven't made yet:
Nothing fancy, just instantiates a new view and returns it.
def get_view(self):
""" Returns a view of this attribute. """
return BooleanView(self)
Since we set can_parse
to True
we need to implement the method parse
.
In the Object View there is a list of all attributes that is bound to that object, in this list the
attributes string representation is shown, in our case that will be either 'True' or 'False'. The user
can click on the value to edit the it directly in the list bypassing it's view, that's where the parse
method comes in. It's suppose to try to parse the user supplied string. If it's successful it changes the value
of the attribute and returns True
, if not it only has to return False
.
We want the attribute to change when the user inputs something we can interpret as a boolean.
def parse(self,txt):
""" Parses user input to determine if they mean True or False
True,T,true,t and 1 makes True
False,F,false and 0 makes False
"""
if txt in ['True','T','t','true','1']:
self.value = True
return True
elif txt in ['False','F','false','f','0']:
self.value = False
return True
return False #didn't parse
And as a final touch we add the __str__
method so that the string representation of our BooleanAttribute is
correct. This is already defined in the super class, but it's good to know about.
That's all for the first class, now let's have a look at the view.
def __str__(self):
""" The string representation of the value. Used in lists."""
return str(self.value)
The view also needs the pyattributes
module, but it also needs PyGtk. The whole code for the class is:
As you can see in the class definition our view inherits both
import pygtk
pygtk.require('2.0')
import gtk
class BooleanView(gtk.VBox,pyattributes.AttributeView):
def __init__(self,att):
#call the superclasses
gtk.VBox.__init__(self)
pyattributes.AttributeView.__init__(self,att)
#let's use a dialog instead of a tab in the ObjectView since it's a small value
self.has_dialog = True
#the value is shown with two radio buttons
self.__rb_T = gtk.RadioButton(None,'True')
rb_F = gtk.RadioButton(self.__rb_T,'False')
self.pack_start(self.__rb_T)
self.pack_start(rb_F)
#set active button
self.__rb_T.set_active(att.value)
rb_F.set_active(not att.value)
#we listen to the 'toggled' signal and change the value accordinly
self.__rb_T.connect('toggled',self.on_toggle)
def on_toggle(self,rb_butt):
""" Changes the value of the attribute when a button is toggled """
self.attribute.value = self.__rb_T.get_active()
def close(self):
""" Used for cleanup when the dialog containing this view is closed"""
#we don't need to do anything
pass
gtk.VBox
and AttributeView
.
All view must inherit both gtk.Widget
and AttributeView
. The view of the BooleanAttribute
can be shown in two ways, either as dialogue or as new tab in the Object View, it's up to has_dialog
.
Since this is a small value it need not a whole tab. The view consist of two radio buttons inside, we don't need
to worry about windows and such for the dialogue, that is taken care of in the AttributeView
class.
The method on_toggle
listens to the 'toggled' signal from one of the buttons and changes the value
of the BooleanAttribute accordingly.
The last thing we need to do is to register the BooleanAttribute with pyattributes.AttributeFactory
.
To get it working just put the script in
#register the attribute
pyattributes.AttributeFactory.get_instance().register_attribute(BooleanAttribute)
$HOME/.dia/python/
. Dia will then automatically import it at
start and the attribute will be registered!
For examples of more advanced classes do look at the code, especially at the classes Attribute
,
AttributeView
and SimpleSetupView
.
Happy coding!