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()
110 scroll
.set_name(widget
.get_name())
113 def container_get_child_pos(container
, widget
):
114 for pos
, child
in enumerate(container
.get_children()):
119 if isinstance(parent
, gtk
.Paned
):
120 scroll
= create_fingerscroll()
121 child
.reparent(scroll
)
123 if parent
.get_child1() == widget
:
124 add_to_paned
= parent
.add1
126 add_to_paned
= parent
.add2
128 parent
.remove(widget
)
130 elif isinstance(parent
, gtk
.Box
):
131 scroll
= create_fingerscroll()
132 child
.reparent(scroll
)
134 position
= container_get_child_pos(parent
, widget
)
135 packing
= parent
.query_child_packing(widget
)
137 parent
.remove(widget
)
139 parent
.set_child_packing(scroll
, *packing
)
140 parent
.reorder_child(scroll
, position
)
141 elif isinstance(parent
, gtk
.Table
):
142 scroll
= create_fingerscroll()
143 child
.reparent(scroll
)
145 attachment
= parent
.child_get(widget
, 'left-attach', \
146 'right-attach', 'top-attach', 'bottom-attach', \
147 'x-options', 'y-options', 'x-padding', 'y-padding')
148 parent
.remove(widget
)
149 parent
.attach(scroll
, *attachment
)
151 if scroll
is not None:
152 if isinstance(child
, gtk
.TextView
):
153 child
.set_editable(False)
154 child
.set_cursor_visible(False)
155 child
.set_sensitive(False)
162 def set_attributes(self
):
164 Convert widget names to attributes of this object.
166 It means a widget named vbox-dialog in GtkBuilder
167 is refered using self.vbox_dialog in the code.
169 for widget
in self
.builder
.get_objects():
170 if not hasattr(widget
, 'get_name'):
173 if isinstance(widget
, gtk
.ScrolledWindow
):
174 widget
= self
._handle
_scrolledwindow
(widget
)
176 widget_name
= widget
.get_name()
177 widget_api_name
= '_'.join(re
.findall(tokenize
.Name
, widget_name
))
178 widget
.set_name(widget_api_name
)
179 if hasattr(self
, widget_api_name
):
180 raise AttributeError("instance %s already has an attribute %s" % (self
,widget_api_name
))
182 setattr(self
, widget_api_name
, widget
)
185 def main_window(self
):
186 """Returns the main window of this GtkBuilderWidget"""
187 return getattr(self
, self
.__class
__.__name
__)
191 Method called when the user interface is loaded and ready to be used.
192 At this moment, the widgets are loaded and can be refered as self.widget_name
198 Starts the main loop of processing events.
199 The default implementation calls gtk.main()
201 Useful for applications that needs a non gtk main loop.
202 For example, applications based on gstreamer needs to override
203 this method with gst.main()
205 Do not directly call this method in your programs.
206 Use the method run() instead.
212 Quit processing events.
213 The default implementation calls gtk.main_quit()
215 Useful for applications that needs a non gtk main loop.
216 For example, applications based on gstreamer needs to override
217 this method with gst.main_quit()
223 Starts the main loop of processing events checking for Control-C.
225 The default implementation checks wheter a Control-C is pressed,
226 then calls on_keyboard_interrupt().
228 Use this method for starting programs.
232 except KeyboardInterrupt:
233 self
.on_keyboard_interrupt()
235 def on_keyboard_interrupt(self
):
237 This method is called by the default implementation of run()
238 after a program is finished by pressing Control-C.