Writing an extension for Thuban basically means to implement the extra functionality in Python with all of the Thuban classes, methods and variables available.
All classes and their methods are documented in the source code (see their doc-strings). Here is an example from Thuban/Model/layer.py that describes some of the methods of a Layer object:
class BaseLayer(TitledObject, Modifiable): """Base class for the layers.""" def __init__(self, title, visible = True, projection = None): """Initialize the layer. title -- the title visible -- boolean. If true the layer is visible. """ TitledObject.__init__(self, title) Modifiable.__init__(self) self.visible = visible self.projection = projection def Visible(self): """Return true if layer is visible""" return self.visible def SetVisible(self, visible): """Set the layer's visibility.""" self.visible = visible self.issue(LAYER_VISIBILITY_CHANGED, self) def HasClassification(self): """Determine if this layer support classifications.""" ...
This example intends to give you an impression of the source-code-level documentation. You have to make yourself familiar with the Python programming language to understand some special code elements.
Traditionally, the first example should welcome the world. Most of the code handles the frame for integrating a menu item into Thuban while the actual raising of a message is done in a single line.
# Copyright (C) 2003 by Intevation GmbH # Authors: # Jan-Oliver Wagner <email@example.com> # # This program is free software under the GPL (>=v2) # Read the file COPYING coming with Thuban for details. """ Extend Thuban with a sample Hello World to demonstrate simple extensions. """ __version__ = '$Revision: 1.23 $' # use _() already now for all strings that may later be translated from Thuban import _ # Thuban has named commands which can be registered in the central # instance registry. from Thuban.UI.command import registry, Command # The instance of the main menu of the Thuban application # See Thuban/UI/menu.py for the API of the Menu class from Thuban.UI.mainwindow import main_menu def hello_world_dialog(context): """Just raise a simple dialog to greet the world. context -- The Thuban context. """ context.mainwindow.RunMessageBox(_('Hello World'), _('Hello World!')) # create a new command and register it registry.Add(Command('hello_world', _('Hello World'), hello_world_dialog, helptext = _('Welcome everyone on this planet'))) # find the extensions menu (create it anew if not found) extensions_menu = main_menu.find_menu('extensions') if extensions_menu is None: extensions_menu = main_menu.InsertMenu('extensions', _('E&xtensions')) # finally bind the new command with an entry in the extensions menu extensions_menu.InsertItem('hello_world')
Mainly, our new function has to be registered to the Thuban framework in order to connect it to the menu. A registered command can also be connected to e.g. a toolbar button.
The instances and classes for this are imported at the beginning. Any code not inside a method or class is directly executed when the source-code module is imported. Therefore, the second part of this example consist of the plain statements to create a new Command and to add it to the menu.
By convention, it looks for a menu registered as ``extensions'' to insert the new command. If it does not exist yet, it gets created. It is advisable to copy this code for any of your extensions.
A registered command that is called, always receives the Thuban context. This instance provides our method with hook references to all important components of the Thuban application.
In the example hello_world.py, our function uses the mainwindow component which offers a method to raise a message dialog. In total there are three hooks:
application: This object is the instance of the Thuban Application class. Except maybe for loading or savinf sessions, you will not need this object for a simple extension. See Thuban/UI/application.py for the API.
session: The instance of the current session. It manages the sessions' map and tables. You can set and remove the map or tables. In may also get the map object. However, you should know that internally it is already prepared to handle many maps. Therfore, currently you would always receive a list with exactlty one element. In the future, if there are more than one map, you will not know which one is the currently display one and therefore you should use the mainwindow as hook to find the currently displayed map. See Thuban/Model/session.py for the API.
mainwindow: The mainwindow object is central to manage various GUI things such as the Legend sub-window. Most notably, you get access to the canvas which is the window part where the map is drawn. The canvas knows, which map it currently draws and therefore you get the current map via context.mainwindow.canvas.Map(). See Thuban/UI/mainwindow.py for the API.