1 # -*- coding: utf-8 -*-
3 UI Base Module for GtkBuilder
5 Based on SimpleGladeApp.py Copyright (C) 2004 Sandino Flores Moreno
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 class GtkBuilderWidget(object):
32 # Other code can set this to True if it wants us to try and
33 # replace GtkScrolledWindow widgets with Finger Scroll widgets
34 use_fingerscroll
= False
36 def __init__(self
, ui_folders
, textdomain
, **kwargs
):
38 Loads the UI file from the specified folder (with translations
39 from the textdomain) and initializes attributes.
42 List of folders with GtkBuilder .ui files in search order
45 The textdomain to be used for translating strings
48 Keyword arguments will be set as attributes to this window
50 for key
, value
in kwargs
.items():
51 setattr(self
, key
, value
)
53 self
.builder
= gtk
.Builder()
54 self
.builder
.set_translation_domain(textdomain
)
56 print >>sys
.stderr
, 'Creating new from file', self
.__class
__.__name
__
58 ui_file
= '%s.ui' % self
.__class
__.__name
__.lower()
60 # Search for the UI file in the UI folders, stop after first match
61 for ui_folder
in ui_folders
:
62 filename
= os
.path
.join(ui_folder
, ui_file
)
63 if os
.path
.exists(filename
):
64 self
.builder
.add_from_file(filename
)
67 self
.builder
.connect_signals(self
)
72 def _handle_scrolledwindow(self
, widget
):
73 """Helper for replacing gtk.ScrolledWindow with finger scroll
75 This function tries to replace a gtk.ScrolledWindow
76 widget with a finger scroll widget if available, reparenting
77 the child widget and trying to place the finger scroll
78 widget exactly where the ScrolledWindow was.
80 This function needs use_fingerscroll to be set to True,
81 otherwise it won't do anything."""
82 if not self
.use_fingerscroll
:
85 # Check if we have mokoui OR hildon before continuing
86 mokoui
, hildon
= None, None
89 except ImportError, ie
:
92 except ImportError, ie
:
94 if not hasattr(hildon
, 'PannableArea'):
95 # Probably using an older version of Hildon
98 parent
= widget
.get_parent()
99 child
= widget
.get_child()
102 def create_fingerscroll():
103 if mokoui
is not None:
104 scroll
= mokoui
.FingerScroll()
105 scroll
.set_property('mode', 0)
106 scroll
.set_property('spring-speed', 0)
107 scroll
.set_property('deceleration', .975)
109 scroll
= hildon
.PannableArea()
111 # The following call looks ugly, but see Gnome bug 591085
112 scroll
.set_name(gtk
.Buildable
.get_name(widget
))
116 def container_get_child_pos(container
, widget
):
117 for pos
, child
in enumerate(container
.get_children()):
122 if isinstance(parent
, gtk
.Paned
):
123 scroll
= create_fingerscroll()
124 child
.reparent(scroll
)
126 if parent
.get_child1() == widget
:
127 add_to_paned
= parent
.add1
129 add_to_paned
= parent
.add2
131 parent
.remove(widget
)
133 elif isinstance(parent
, gtk
.Box
):
134 scroll
= create_fingerscroll()
135 child
.reparent(scroll
)
137 position
= container_get_child_pos(parent
, widget
)
138 packing
= parent
.query_child_packing(widget
)
140 parent
.remove(widget
)
142 parent
.set_child_packing(scroll
, *packing
)
143 parent
.reorder_child(scroll
, position
)
144 elif isinstance(parent
, gtk
.Table
):
145 scroll
= create_fingerscroll()
146 child
.reparent(scroll
)
148 attachment
= parent
.child_get(widget
, 'left-attach', \
149 'right-attach', 'top-attach', 'bottom-attach', \
150 'x-options', 'y-options', 'x-padding', 'y-padding')
151 parent
.remove(widget
)
152 parent
.attach(scroll
, *attachment
)
154 if scroll
is not None:
155 if isinstance(child
, gtk
.TextView
):
156 child
.set_editable(False)
157 child
.set_cursor_visible(False)
158 child
.set_sensitive(False)
165 def set_attributes(self
):
167 Convert widget names to attributes of this object.
169 It means a widget named vbox-dialog in GtkBuilder
170 is refered using self.vbox_dialog in the code.
172 for widget
in self
.builder
.get_objects():
173 # Just to be safe - every widget from the builder is buildable
174 if not isinstance(widget
, gtk
.Buildable
):
177 if isinstance(widget
, gtk
.ScrolledWindow
):
178 widget
= self
._handle
_scrolledwindow
(widget
)
180 # The following call looks ugly, but see Gnome bug 591085
181 widget_name
= gtk
.Buildable
.get_name(widget
)
183 widget_api_name
= '_'.join(re
.findall(tokenize
.Name
, widget_name
))
184 if hasattr(self
, widget_api_name
):
185 raise AttributeError("instance %s already has an attribute %s" % (self
,widget_api_name
))
187 setattr(self
, widget_api_name
, widget
)
190 def main_window(self
):
191 """Returns the main window of this GtkBuilderWidget"""
192 return getattr(self
, self
.__class
__.__name
__)
196 Method called when the user interface is loaded and ready to be used.
197 At this moment, the widgets are loaded and can be refered as self.widget_name
203 Starts the main loop of processing events.
204 The default implementation calls gtk.main()
206 Useful for applications that needs a non gtk main loop.
207 For example, applications based on gstreamer needs to override
208 this method with gst.main()
210 Do not directly call this method in your programs.
211 Use the method run() instead.
217 Quit processing events.
218 The default implementation calls gtk.main_quit()
220 Useful for applications that needs a non gtk main loop.
221 For example, applications based on gstreamer needs to override
222 this method with gst.main_quit()
228 Starts the main loop of processing events checking for Control-C.
230 The default implementation checks wheter a Control-C is pressed,
231 then calls on_keyboard_interrupt().
233 Use this method for starting programs.
237 except KeyboardInterrupt:
238 self
.on_keyboard_interrupt()
240 def on_keyboard_interrupt(self
):
242 This method is called by the default implementation of run()
243 after a program is finished by pressing Control-C.