Log In
New Account
  
Home My Page Project Cloud Code Snippets Project Openings Hermes
Summary Lists News SCM
1 #
2 # WimpWorks (for Python)                (c) Andrew Flegg 2009.
3 # ~~~~~~~~~~~~~~~~~~~~~~                Released under the Artistic Licence.
4 #                                       http://www.bleb.org/
6 import gtk, gobject
7 import re
8 import thread
9 import os.path
11 # -- Work out environment...
12 #
13 try:
14   import hildon
15   _have_hildon = True
16 except ImportError:
17   _have_hildon = False
18   
19 try:
20   import osso
21   _have_osso = True
22 except ImportError:
23   _have_osso = False
24   
25 try:
26   import gnome.gconf
27   _have_gconf = True
28 except ImportError:
29   _have_gconf = False
31 gobject.threads_init()
33 # -- Main class...
34 #
35 class WimpWorks:
36   '''A framework for creating easy-to-use graphical user interfaces using
37      GTK+, Python, DBus and more.
38      
39      This is the base class. It should be constructed with a DBus name
40      and a version.
41        
42      Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
43      Released under the Artistic Licence.'''
46   # -----------------------------------------------------------------------
47   def __init__(self, application, version = '1.0.0', dbus_name = None):
48     '''Constructor. Initialises the gconf connection, DBus, OSSO and more.
49     
50        @param application User-facing name of the application.
51        @param version Version string of the application.
52        @param dbus_name Name to register with DBus. If unspecified, no
53               DBus registration will be performed.'''
54     
55     self.name = application
56     self.dbus_name = dbus_name
57     self.menu = None
59     if _have_gconf:
60       self.gconf = gnome.gconf.client_get_default()
61     
62     if _have_hildon:
63       self.app = hildon.Program()
64       self.main_window = hildon.Window()
65       gtk.set_application_name(application)
66     else:
67       self.app = None
68       self.main_window = gtk.Window()
70     self.main_window.set_title(application)
71     self.main_window.connect("delete-event", gtk.main_quit)
72     
73     if _have_osso and dbus_name:
74       self.osso_context = osso.Context(dbus_name, version, False)
75       
76     if self.app:
77       self.app.add_window(self.main_window)
78       
79     if _have_hildon:
80       self._expose_hid = self.main_window.connect('expose-event', self._take_screenshot)
82       
83   # -----------------------------------------------------------------------
84   def set_background(self, file, window = None):
85     '''Set the background of the given (or main) window to that contained in
86        'file'.
87        
88        @param file File name to set. If not an absolute path, typical application
89                    directories will be checked.
90        @param window Window to set background of. If unset, will default to the
91                      main application window.'''
92     
93     # TODO Handle other forms of path
94     file = "/opt/%s/share/%s" % (re.sub('[^a-z0-9_]', '', self.name.lower()), file)
95     if not window:
96       window = self.main_window
97       
98     self._background, mask = gtk.gdk.pixbuf_new_from_file(file).render_pixmap_and_mask()
99     window.realize()
100     window.window.set_back_pixmap(self._background, False)
102     
103   # -----------------------------------------------------------------------
104   def add_menu_action(self, title, window = None):
105     '''Add a menu action to the given (or main) window. Once add_menu_action()
106        has been called with all the properties, 'self.menu.show_all()' should be
107        called.'''
109     if not window:
110       window = self.main_window
111       
112     if not self.menu:
113       if _have_hildon:
114         self.menu = hildon.AppMenu()
115         window.set_app_menu(self.menu)
116       else:
117         raise Exception("Menu needs to be created, and no Hildon present")
118         
119     button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
120     button.set_label(title)
121     button.connect("clicked", self.callback, title)
122     self.menu.append(button)
125   # -----------------------------------------------------------------------
126   def run(self):
127     '''Once the application has been initialised, this will show the main window
128        and run the mainloop.'''
129        
130     self.main_window.show_all()
131     gtk.main()
134   # -----------------------------------------------------------------------
135   def _take_screenshot(self, event = None, data = None):
136     '''Used to provide a quick-loading screen.
137     
138        @see http://maemo.org/api_refs/5.0/5.0-final/hildon/hildon-Additions-to-GTK+.html#hildon-gtk-window-take-screenshot'''
139     
140     self.main_window.disconnect(self._expose_hid)
141     if not os.path.isfile("/home/user/.cache/launch/%s.pvr" % (self.dbus_name)):
142       gobject.timeout_add(80, hildon.hildon_gtk_window_take_screenshot, self.main_window, True)
144     
145   # -----------------------------------------------------------------------
146   def callback(self, event, method):
147     '''Call a method on this object, using the given string to derive
148        the name. If no method is found, no action is taken.
149        
150        @param event Event which triggered the callback.
151        @param method String which will be lowercased to form a method
152               called 'do_method'.'''
154     method = re.sub('[^a-z0-9_]', '', method.lower())
155     getattr(self, "do_%s" % (method))(event.window)
157     
158   # -----------------------------------------------------------------------
159   def new_checkbox(self, label, box = None):
160     '''Create a new checkbox, adding it to the given container.
161     
162        @param label Label for the checkbox.
163        @param box Optional container to add the created checkbox to.
164        @return The newly created checkbox.'''
165        
166     checkbox = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
167     checkbox.set_label(label)
168     if box:
169       box.add(checkbox)
170     return checkbox
173   # -----------------------------------------------------------------------
174   def new_indent(self, box):
175     '''Create an indent which can be used to show items related to each other.
176     
177        @param box Container to add the indent to.'''
178        
179     outer = gtk.HBox()
180     indent = gtk.VBox()
181     outer.pack_start(indent, padding=48)
182     box.add(outer)
183     return indent
185  
186   # -----------------------------------------------------------------------
187   def new_input(self, label, box = None, password = False):
188     '''Create a new input with the given label, optionally adding it to a
189        container.
190        
191        @param label Text describing the purpose of the input field.
192        @param box Optional container to add the input to.
193        @param password Boolean indicating if the input is used for passwords.
194        @return The newly created input.'''
195        
196     input = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
197     input.set_placeholder(label)
198     input.set_property('is-focus', False)
199     
200     if password:
201       input.set_property('hildon-input-mode', gtk.HILDON_GTK_INPUT_MODE_FULL | gtk.HILDON_GTK_INPUT_MODE_INVISIBLE)
202     else:
203       input.set_property('hildon-input-mode', gtk.HILDON_GTK_INPUT_MODE_FULL)
204       
205     if box:
206       box.add(input)
207     return input
210   # -----------------------------------------------------------------------
211   def link_control(self, checkbox, ctrl, box = None):
212     '''Link a checkbox to a control, such that the editability of the
213        control is determined by the checkbox state.
214        
215        @param checkbox Checkbox which will control the state.
216        @param ctrl Control to add.
217        @param box Optional container to add 'ctrl' to.
218        @return The added control.'''
219        
220     if box:
221       box.add(ctrl)
222       
223     self._sync_edit(checkbox, ctrl)
224     checkbox.connect('toggled', self._sync_edit, ctrl)
225     return ctrl
226   
227     
228   # -----------------------------------------------------------------------
229   def _sync_edit(self, checkbox, edit):
230     edit.set_property('sensitive', checkbox.get_active())
231     
233       
234 # -----------------------------------------------------------------------
235 class HildonMainScreenLayout():
236     '''Provides a mechanism for creating a traditional multi-button button
237        selection, as made popular by Maemo 5's Media Player, Clock, Application
238        Manager and HIG.
239        
240        This does *not* require Hildon, however.
241     '''
243     # ---------------------------------------------------------------------
244     def __init__(self, container, offset = 0.5):
245       '''Create a new layout.
246       
247          @param container Container to add layout to. If unspecified,
248                 the application's main window will be used.
249          @param offset The vertical offset for the buttons. If unspecified,
250                 they will be centred. Ranges from 0.0 (top) to 1.0 (bottom).'''
251                 
252       self._container = container
253       alignment = gtk.Alignment(xalign=0.5, yalign=0.8, xscale=0.8)
254       self._box = gtk.HButtonBox()
255       alignment.add(self._box)
256       container.main_window.add(alignment)
257       self._box.set_property('layout-style', gtk.BUTTONBOX_SPREAD)
259       
260     # ---------------------------------------------------------------------
261     def add_button(self, title, subtitle = ''):
262       '''Add a button to the layout with the specified title. Upon clicking
263          the button, a method of the name 'do_title' will be invoked on the
264          main class.
265          
266          @param title Value of the button, and used to derive the callback method.
267          @param subtitle An optional subtitle containing more information.'''
269       if _have_hildon:         
270         button = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
271                                title = title, value = subtitle)
272       else:
273         button = gtk.Button(label = title)
275       button.set_property('width-request', 250)
276       button.connect('clicked', self._container.callback, title)
277       self._box.add(button)

Terms of Use    Privacy Policy    Contribution Guidelines    Feedback

Powered By GForge Collaborative Development Environment