1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import glob, gtk
16 import xml.dom.minidom
17 from xml.dom.minidom import Node
18 import os
19 import gettext
20 import screenlets
21
22 gettext.textdomain('screenlets')
23 gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX + '/share/locale')
24
26 return gettext.gettext(s)
27
29 """Convenience function to create a menuitem, connect
30 a callback, and add the menuitem to menu."""
31 if label == "-":
32 item = gtk.SeparatorMenuItem()
33 else:
34 item = gtk.MenuItem(label)
35 return add_menuitem_with_item(menu, item, callback, cb_data)
36
42
44 """Convenience function to add submenuitems to a right-click menu through a list.
45
46 images is an optional list of filenames to be used as an image in each menuitem.
47 Each item in the list should either be a string or None. (If an item is None, gtk's
48 no-image icon will be used.)
49
50 If callback is not None, each menuitem will be connected to callback with it's
51 label as callback data. If prefix exists, prefix will be prefixed to the label's
52 name in the callback data.
53
54 Returns the new submenu."""
55 root_item = gtk.MenuItem(label)
56 root_menu.append(root_item)
57 root_item.show()
58
59 menu = gtk.Menu()
60 root_item.set_submenu(menu)
61
62 i = 0
63 for name in lst:
64
65 if images is not None:
66 item = ImageMenuItem(label=name)
67
68 if images[i] is not None:
69 pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(images[i], *image_size)
70 item.set_image_from_pixbuf(pixbuf)
71
72 else:
73 item.set_image_from_file('')
74
75 else:
76 item = gtk.MenuItem(name)
77 if callback is not None:
78 if prefix is not None:
79 item.connect("activate", callback, prefix+name)
80 else:
81 item.connect("activate", callback, name)
82 item.show()
83 menu.append(item)
84 i += 1
85
86 return menu
87
89 """Convenience function to add a menuitem to a menu
90 and connect a callback."""
91 if callback:
92 if cb_data:
93 item.connect("activate", callback, cb_data)
94 else:
95 item.connect("activate", callback)
96 menu.append(item)
97 item.show()
98 return item
99
101 """Creates a menu from an XML-file and returns None if something went wrong"""
102 doc = None
103 try:
104 doc = xml.dom.minidom.parse(filename)
105 except Exception, e:
106 print "XML-Error: %s" % str(e)
107 return None
108 return create_menu_from_xml(doc.firstChild, callback)
109
111 """Create a gtk.Menu by an XML-Node"""
112 menu = gtk.Menu()
113 for node in node.childNodes:
114
115 type = node.nodeType
116 if type == Node.ELEMENT_NODE:
117 label = node.getAttribute("label")
118 id = node.getAttribute("id")
119 item = None
120 is_check = False
121
122 if node.nodeName == "item":
123 item = gtk.MenuItem(label)
124
125 elif node.nodeName == "checkitem":
126 item = gtk.CheckMenuItem(label)
127 is_check = True
128 if node.hasAttribute("checked"):
129 item.set_active(True)
130
131 elif node.nodeName == "imageitem":
132 icon = node.getAttribute("icon")
133 item = imageitem_from_name(icon, label, icon_size)
134
135 elif node.nodeName == "separator":
136 item = gtk.SeparatorMenuItem()
137
138 elif node.nodeName == "appdir":
139
140 path = node.getAttribute("path")
141 appmenu = ApplicationMenu(path)
142 cats = node.getAttribute("cats").split(",")
143 for cat in cats:
144 item = gtk.MenuItem(cat)
145
146 submenu = appmenu.get_menu_for_category(cat, callback)
147 item.set_submenu(submenu)
148 item.show()
149 menu.append(item)
150 item = None
151
152 elif node.nodeName == "scandir":
153
154 dir = node.getAttribute("directory")
155
156 dir = dir.replace('$HOME', os.environ['HOME'])
157
158 idprfx = node.getAttribute("id_prefix")
159 idsufx = node.getAttribute("id_suffix")
160 srch = node.getAttribute("search").split(',')
161 repl = node.getAttribute("replace").split(',')
162 skp = node.getAttribute("skip").split(',')
163
164 flt = node.getAttribute("filter")
165 if flt=='':
166 flt='*'
167
168
169 fill_menu_from_directory(dir, menu, callback, filter=flt,
170 id_prefix=idprfx, id_suffix=idsufx, search=srch,
171 replace=repl, skip=skp)
172
173 if item:
174 if node.hasChildNodes():
175
176 submenu = create_menu_from_xml(node,
177 callback, icon_size)
178 item.set_submenu(submenu)
179 item.show()
180 if id:
181 item.connect("activate", callback, id)
182 menu.append(item)
183 return menu
184
187 """Create MenuItems from a directory.
188 TODO: use regular expressions"""
189
190 lst = glob.glob(dirname + "/" + filter)
191
192 lst.sort()
193 dlen = len(dirname) + 1
194
195 for filename in lst:
196
197 fname = filename[dlen:]
198
199 if skip.count(fname)<1:
200
201
202 l = len(search)
203 if l>0 and l == len(replace):
204 for i in xrange(l):
205 fname = fname.replace(search[i], replace[i])
206
207 id = id_prefix + fname + id_suffix
208
209
210 item = gtk.MenuItem(fname)
211 item.connect("activate", callback, id)
212 item.show()
213 menu.append(item)
214
216 """Creates a new gtk.ImageMenuItem from a given icon/filename.
217 If an absolute path is not given, the function checks for the name
218 of the icon within the current gtk-theme."""
219 item = gtk.ImageMenuItem(label)
220 image = gtk.Image()
221 if filename and filename[0]=='/':
222
223 try:
224 image.set_from_file(filename)
225 pb = image.get_pixbuf()
226
227 if pb.get_width() > icon_size :
228 pb2 = pb.scale_simple(
229 icon_size, icon_size,
230 gtk.gdk.INTERP_HYPER)
231 image.set_from_pixbuf(pb2)
232 else:
233 image.set_from_pixbuf(pb)
234 except:
235 print "Error while creating image from file: %s" % filename
236 return None
237 else:
238 image.set_from_icon_name(filename, 3)
239 if image:
240 item.set_image(image)
241 return item
242
244 """Read ".desktop"-file into a dict
245 NOTE: Should use utils.IniReader ..."""
246 list = {}
247 f=None
248 try:
249 f = open (filename, "r")
250 except:
251 print "Error: file %s not found." % filename
252 if f:
253 lines = f.readlines()
254 for line in lines:
255 if line[0] != "#" and line !="\n" and line[0] != "[":
256 ll = line.split('=', 1)
257 if len(ll) > 1:
258 list[ll[0]] = ll[1].replace("\n", "")
259 return list
260
261
262
263
264
266 """A utility-class to simplify the creation of gtk.Menus from directories with
267 desktop-files. Reads all files in one or multiple directories into its internal list
268 and offers an easy way to create entire categories as complete gtk.Menu
269 with gtk.ImageMenuItems. """
270
271
272 __path = ""
273
274 __applications = []
275
281
283 """read all desktop-files in a directory into the internal list
284 and sort them into the available categories"""
285 dirlst = glob.glob(path + '/*')
286
287 namelen = len(path)
288 for file in dirlst:
289 if file[-8:]=='.desktop':
290 fname = file[namelen:]
291
292 df = read_desktop_file(file)
293 name = ""
294 icon = ""
295 cmd = ""
296 try:
297 name = df['Name']
298 icon = df['Icon']
299 cmd = df['Exec']
300 cats = df['Categories'].split(';')
301
302
303 self.__applications.append(df)
304 except Exception, ex:
305 print "Exception: %s" % str(ex)
306 print "An error occured with desktop-file: %s" % file
307
309 """returns a gtk.Menu with all apps in the given category"""
310
311 applist = []
312 for app in self.__applications:
313 try:
314 if (';'+app['Categories']).count(';'+cat_name+';') > 0:
315 applist.append(app)
316 except:
317 pass
318
319
320 for app in applist:
321 if applist.count(app) > 1:
322 applist.remove(app)
323
324 applist.sort()
325
326 menu = gtk.Menu()
327 for app in applist:
328 item = imageitem_from_name(app['Icon'], app['Name'], 24)
329 if item:
330 item.connect("activate", callback, "exec:" + app['Exec'])
331 item.show()
332 menu.append(item)
333
334 return menu
335
356
357
359 """A menuitem with a custom image and label.
360 To set the image to a non-stock image, just
361 create the menuitem without an image and then
362 set the image with the appropriate method."""
363
365 """stock: a stock image or 'none'.
366 label: text to set as the label or None."""
367
368 super(ImageMenuItem, self).__init__(stock)
369
370
371 self.label = self.get_child()
372 self.image = self.get_image()
373
374
375 if label is not None:
376 self.set_label(label)
377
379 """Set the image from file."""
380 self.image.set_from_file(filename)
381
383 """Set the image from a pixbuf."""
384 self.image.set_from_pixbuf(pixbuf)
385
387 """Set the image from a stock image."""
388 self.image.set_from_stock(name, gtk.ICON_SIZE_MENU)
389
393
395 """Resize the menuitem's image."""
396 self.image.set_size_request(width, height)
397