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
21 gettext.textdomain('screenlets')
22 gettext.bindtextdomain('screenlets', '/usr/share/locale')
23
25 return gettext.gettext(s)
26
28 """Convenience function to create a menuitem, connect
29 a callback, and add the menuitem to menu."""
30 if label == "-":
31 item = gtk.SeparatorMenuItem()
32 else:
33 item = gtk.MenuItem(label)
34 return add_menuitem_with_item(menu, item, callback, cb_data)
35
37 """Convenience function to create an ImageMenuItem, connect
38 a callback, and add the menuitem to menu."""
39 item = ImageMenuItem(stock, label)
40 return add_menuitem_with_item(menu, item, callback, cb_data)
41
43 """Convenience function to add a menuitem to a menu
44 and connect a callback."""
45 if callback:
46 if cb_data:
47 item.connect("activate", callback, cb_data)
48 else:
49 item.connect("activate", callback)
50 menu.append(item)
51 item.show()
52 return item
53
55 """Creates a menu from an XML-file and returns None if something went wrong"""
56 doc = None
57 try:
58 doc = xml.dom.minidom.parse(filename)
59 except Exception, e:
60 print _("XML-Error: %s") % str(e)
61 return None
62 return create_menu_from_xml(doc.firstChild, callback)
63
65 """Create a gtk.Menu by an XML-Node"""
66 menu = gtk.Menu()
67 for node in node.childNodes:
68
69 type = node.nodeType
70 if type == Node.ELEMENT_NODE:
71 label = node.getAttribute("label")
72 id = node.getAttribute("id")
73 item = None
74 is_check = False
75
76 if node.nodeName == "item":
77 item = gtk.MenuItem(label)
78
79 elif node.nodeName == "checkitem":
80 item = gtk.CheckMenuItem(label)
81 is_check = True
82 if node.hasAttribute("checked"):
83 item.set_active(True)
84
85 elif node.nodeName == "imageitem":
86 icon = node.getAttribute("icon")
87 item = imageitem_from_name(icon, label, icon_size)
88
89 elif node.nodeName == "separator":
90 item = gtk.SeparatorMenuItem()
91
92 elif node.nodeName == "appdir":
93
94 path = node.getAttribute("path")
95 appmenu = ApplicationMenu(path)
96 cats = node.getAttribute("cats").split(",")
97 for cat in cats:
98 item = gtk.MenuItem(cat)
99
100 submenu = appmenu.get_menu_for_category(cat, callback)
101 item.set_submenu(submenu)
102 item.show()
103 menu.append(item)
104 item = None
105
106 elif node.nodeName == "scandir":
107
108 dir = node.getAttribute("directory")
109
110 dir = dir.replace('$HOME', os.environ['HOME'])
111
112 idprfx = node.getAttribute("id_prefix")
113 idsufx = node.getAttribute("id_suffix")
114 srch = node.getAttribute("search").split(',')
115 repl = node.getAttribute("replace").split(',')
116 skp = node.getAttribute("skip").split(',')
117
118 flt = node.getAttribute("filter")
119 if flt=='':
120 flt='*'
121
122
123 fill_menu_from_directory(dir, menu, callback, filter=flt,
124 id_prefix=idprfx, id_suffix=idsufx, search=srch,
125 replace=repl, skip=skp)
126
127 if item:
128 if node.hasChildNodes():
129
130 submenu = create_menu_from_xml(node,
131 callback, icon_size)
132 item.set_submenu(submenu)
133 item.show()
134 if id:
135 item.connect("activate", callback, id)
136 menu.append(item)
137 return menu
138
141 """Create MenuItems from a directory.
142 TODO: use regular expressions"""
143
144 lst = glob.glob(dirname + "/" + filter)
145
146 lst.sort()
147 dlen = len(dirname) + 1
148
149 for filename in lst:
150
151 fname = filename[dlen:]
152
153 if skip.count(fname)<1:
154
155
156 l = len(search)
157 if l>0 and l == len(replace):
158 for i in xrange(l):
159 fname = fname.replace(search[i], replace[i])
160
161 id = id_prefix + fname + id_suffix
162
163
164 item = gtk.MenuItem(fname)
165 item.connect("activate", callback, id)
166 item.show()
167 menu.append(item)
168
170 """Creates a new gtk.ImageMenuItem from a given icon/filename.
171 If an absolute path is not given, the function checks for the name
172 of the icon within the current gtk-theme."""
173 item = gtk.ImageMenuItem(label)
174 image = gtk.Image()
175 if filename and filename[0]=='/':
176
177 try:
178 image.set_from_file(filename)
179 pb = image.get_pixbuf()
180
181 if pb.get_width() > icon_size :
182 pb2 = pb.scale_simple(
183 icon_size, icon_size,
184 gtk.gdk.INTERP_HYPER)
185 image.set_from_pixbuf(pb2)
186 else:
187 image.set_from_pixbuf(pb)
188 except:
189 print _("Error while creating image from file: %s") % filename
190 return None
191 else:
192 image.set_from_icon_name(filename, 3)
193 if image:
194 item.set_image(image)
195 return item
196
198 """Read ".desktop"-file into a dict
199 NOTE: Should use utils.IniReader ..."""
200 list = {}
201 f=None
202 try:
203 f = open (filename, "r")
204 except:
205 print _("Error: file %s not found.") % filename
206 if f:
207 lines = f.readlines()
208 for line in lines:
209 if line[0] != "#" and line !="\n" and line[0] != "[":
210 ll = line.split('=', 1)
211 if len(ll) > 1:
212 list[ll[0]] = ll[1].replace("\n", "")
213 return list
214
215
216
217
218
220 """A utility-class to simplify the creation of gtk.Menus from directories with
221 desktop-files. Reads all files in one or multiple directories into its internal list
222 and offers an easy way to create entire categories as complete gtk.Menu
223 with gtk.ImageMenuItems. """
224
225
226 __path = ""
227
228 __applications = []
229
235
237 """read all desktop-files in a directory into the internal list
238 and sort them into the available categories"""
239 dirlst = glob.glob(path + '/*')
240
241 namelen = len(path)
242 for file in dirlst:
243 if file[-8:]=='.desktop':
244 fname = file[namelen:]
245
246 df = read_desktop_file(file)
247 name = ""
248 icon = ""
249 cmd = ""
250 try:
251 name = df['Name']
252 icon = df['Icon']
253 cmd = df['Exec']
254 cats = df['Categories'].split(';')
255
256
257 self.__applications.append(df)
258 except Exception, ex:
259 print _("Exception: %s") % str(ex)
260 print _("An error occured with desktop-file: %s") % file
261
263 """returns a gtk.Menu with all apps in the given category"""
264
265 applist = []
266 for app in self.__applications:
267 try:
268 if (';'+app['Categories']).count(';'+cat_name+';') > 0:
269 applist.append(app)
270 except:
271 pass
272
273
274 for app in applist:
275 if applist.count(app) > 1:
276 applist.remove(app)
277
278 applist.sort()
279
280 menu = gtk.Menu()
281 for app in applist:
282 item = imageitem_from_name(app['Icon'], app['Name'], 24)
283 if item:
284 item.connect("activate", callback, "exec:" + app['Exec'])
285 item.show()
286 menu.append(item)
287
288 return menu
289
309
310
312 """A menuitem with a custom image and label.
313 To set the image to a non-stock image, just
314 create the menuitem without an image and then
315 set the image with the appropriate method."""
316
318 """stock: a stock image or 'none'.
319 label: text to set as the label or None."""
320
321 super(ImageMenuItem, self).__init__(stock)
322
323
324 children = self.get_children()
325 self.label = children[0]
326 self.image = children[1]
327
328
329 if label is not None:
330 self.set_label(label)
331
333 """Set the image from file."""
334 self.image.set_from_file(filename)
335
337 """Set the image from a pixbuf."""
338 self.image.set_from_pixbuf(pixbuf)
339
341 """Set the image from a stock image."""
342 self.image.set_from_stock(name, gtk.ICON_SIZE_MENU)
343
345 """Set the label's text."""
346 self.label.set_text(text)
347
349 """Resize the menuitem's image."""
350 self.image.set_size_request(width, height)
351