Merge lp:~laudeci/unity-launcher-editor/dev into lp:unity-launcher-editor
- dev
- Merge into unity-launcher-editor
Proposed by
Laudeci Oliveira
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 54 | ||||||||||||||||
Proposed branch: | lp:~laudeci/unity-launcher-editor/dev | ||||||||||||||||
Merge into: | lp:unity-launcher-editor | ||||||||||||||||
Diff against target: |
1776 lines (+815/-501) 13 files modified
distribute_setup.py (+3/-3) unitylaunchereditor/appgui.py (+7/-24) unitylaunchereditor/data/application.glade (+51/-234) unitylaunchereditor/desktop.py (+1/-1) unitylaunchereditor/groupsdialog.py (+157/-32) unitylaunchereditor/locale/unity-launcher-editor.pot (+79/-0) unitylaunchereditor/mainwindow.py (+135/-187) unitylaunchereditor/newlauncher.py (+23/-19) unitylaunchereditor/translation.py (+28/-0) unitylaunchereditor/utils.py (+1/-1) unitylaunchereditor/widgets/__init__.py (+1/-0) unitylaunchereditor/widgets/grouptree.py (+133/-0) unitylaunchereditor/widgets/launcherview.py (+196/-0) |
||||||||||||||||
To merge this branch: | bzr merge lp:~laudeci/unity-launcher-editor/dev | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laudeci Oliveira | Approve | ||
Ursula Junque | Pending | ||
Review via email:
|
Commit message
Description of the change
Modularization and code internationaliz
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Laudeci Oliveira (laudeci) : | # |
review:
Approve
- 53. By Ursula Junque
-
Merging Pretto's branch
- 54. By Ursula Junque
-
merging laudeci-dev
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'distribute_setup.py' |
2 | --- distribute_setup.py 2011-05-13 14:49:09 +0000 |
3 | +++ distribute_setup.py 2011-05-21 20:12:30 +0000 |
4 | @@ -144,7 +144,7 @@ |
5 | except ImportError: |
6 | return _do_download(version, download_base, to_dir, download_delay) |
7 | try: |
8 | - pkg_resources.require("distribute>="+version) |
9 | + pkg_resources.require("distribute>=" + version) |
10 | return |
11 | except pkg_resources.VersionConflict: |
12 | e = sys.exc_info()[1] |
13 | @@ -351,7 +351,7 @@ |
14 | def _under_prefix(location): |
15 | if 'install' not in sys.argv: |
16 | return True |
17 | - args = sys.argv[sys.argv.index('install')+1:] |
18 | + args = sys.argv[sys.argv.index('install') + 1:] |
19 | for index, arg in enumerate(args): |
20 | for option in ('--root', '--prefix'): |
21 | if arg.startswith('%s=' % option): |
22 | @@ -359,7 +359,7 @@ |
23 | return location.startswith(top_dir) |
24 | elif arg == option: |
25 | if len(args) > index: |
26 | - top_dir = args[index+1] |
27 | + top_dir = args[index + 1] |
28 | return location.startswith(top_dir) |
29 | if arg == '--user' and USER_SITE is not None: |
30 | return location.startswith(USER_SITE) |
31 | |
32 | === modified file 'unitylaunchereditor/appgui.py' |
33 | --- unitylaunchereditor/appgui.py 2011-05-13 18:18:55 +0000 |
34 | +++ unitylaunchereditor/appgui.py 2011-05-21 20:12:30 +0000 |
35 | @@ -18,9 +18,11 @@ |
36 | def save_unity_list(self, menu_items): |
37 | try: |
38 | print str(menu_items) |
39 | - self.gsettings.set_strv('favorites',menu_items) |
40 | - except GError,e: |
41 | - print e |
42 | + self.gsettings.set_strv('favorites', menu_items) |
43 | + self.get_unity_list() |
44 | + return True |
45 | + except GError, e: |
46 | + return False |
47 | #return_code = os.system('unity --reset') #subprocess.call(['unity','--reset']) |
48 | #if return_code != 0: |
49 | # print "Settings fail to transition to new unity compiz favorites" |
50 | @@ -28,27 +30,8 @@ |
51 | def get_unity_list(self): |
52 | """ Create a list of items from unity's Launcher Panel.""" |
53 | unity = self.gsettings.get_value('favorites') |
54 | - store = self.main_window.listview_launcher.get_model() |
55 | - store.clear() |
56 | - print unity |
57 | - for menu_item in unity: |
58 | - desktop_parser = DesktopParser(menu_item) |
59 | - desktop_parser.update_keys() |
60 | - sname = desktop_parser.get('Name') |
61 | - icon = desktop_parser.get('Icon') |
62 | - if sname is None: |
63 | - sname = desktop_parser.get('Name', 'en') |
64 | - if icon is None: |
65 | - pix = None |
66 | - else: |
67 | - pix = get_icon(icon) |
68 | - store.append((pix, '%s' % sname, desktop_parser, menu_item)) |
69 | - print sname, menu_item |
70 | |
71 | - self.main_window.listview_launcher.set_model(store) |
72 | - self.main_window.listview_launcher.connect('cursor-changed', |
73 | - self.main_window.listview_launcher_row_change) |
74 | - #make first row active |
75 | - self.main_window.listview_launcher.set_cursor((0,)) |
76 | + self.main_window.load_launcher_from_list(unity) |
77 | + |
78 | |
79 | |
80 | |
81 | === modified file 'unitylaunchereditor/data/application.glade' |
82 | --- unitylaunchereditor/data/application.glade 2011-05-12 18:36:05 +0000 |
83 | +++ unitylaunchereditor/data/application.glade 2011-05-21 20:12:30 +0000 |
84 | @@ -159,203 +159,6 @@ |
85 | </packing> |
86 | </child> |
87 | </object> |
88 | - <object class="GtkFrame" id="frame4"> |
89 | - <property name="visible">True</property> |
90 | - <property name="can_focus">False</property> |
91 | - <property name="border_width">4</property> |
92 | - <property name="label_xalign">0</property> |
93 | - <property name="label_yalign">0</property> |
94 | - <property name="shadow_type">none</property> |
95 | - <child> |
96 | - <object class="GtkAlignment" id="alignment5"> |
97 | - <property name="visible">True</property> |
98 | - <property name="can_focus">False</property> |
99 | - <property name="left_padding">12</property> |
100 | - <child> |
101 | - <object class="GtkTable" id="table1"> |
102 | - <property name="visible">True</property> |
103 | - <property name="can_focus">False</property> |
104 | - <property name="border_width">5</property> |
105 | - <property name="n_rows">4</property> |
106 | - <property name="n_columns">2</property> |
107 | - <property name="column_spacing">5</property> |
108 | - <property name="row_spacing">5</property> |
109 | - <child> |
110 | - <object class="GtkEventBox" id="eventbox7"> |
111 | - <property name="visible">True</property> |
112 | - <property name="can_focus">False</property> |
113 | - <child> |
114 | - <object class="GtkLabel" id="label9"> |
115 | - <property name="visible">True</property> |
116 | - <property name="can_focus">False</property> |
117 | - <property name="xalign">0</property> |
118 | - <property name="yalign">0</property> |
119 | - <property name="label" translatable="yes">Target Environment:</property> |
120 | - </object> |
121 | - </child> |
122 | - </object> |
123 | - <packing> |
124 | - <property name="top_attach">3</property> |
125 | - <property name="bottom_attach">4</property> |
126 | - <property name="x_options">GTK_FILL</property> |
127 | - <property name="y_options">GTK_FILL</property> |
128 | - </packing> |
129 | - </child> |
130 | - <child> |
131 | - <object class="GtkComboBox" id="cmbTarget"> |
132 | - <property name="visible">True</property> |
133 | - <property name="can_focus">False</property> |
134 | - <property name="model">lstTarget</property> |
135 | - </object> |
136 | - <packing> |
137 | - <property name="left_attach">1</property> |
138 | - <property name="right_attach">2</property> |
139 | - <property name="top_attach">3</property> |
140 | - <property name="bottom_attach">4</property> |
141 | - </packing> |
142 | - </child> |
143 | - <child> |
144 | - <object class="GtkEventBox" id="eventbox6"> |
145 | - <property name="visible">True</property> |
146 | - <property name="can_focus">False</property> |
147 | - <child> |
148 | - <object class="GtkLabel" id="label8"> |
149 | - <property name="visible">True</property> |
150 | - <property name="can_focus">False</property> |
151 | - <property name="xalign">0</property> |
152 | - <property name="label" translatable="yes">Command:</property> |
153 | - </object> |
154 | - </child> |
155 | - </object> |
156 | - <packing> |
157 | - <property name="top_attach">2</property> |
158 | - <property name="bottom_attach">3</property> |
159 | - <property name="x_options">GTK_FILL</property> |
160 | - <property name="y_options">GTK_FILL</property> |
161 | - </packing> |
162 | - </child> |
163 | - <child> |
164 | - <object class="GtkHBox" id="hbox4"> |
165 | - <property name="visible">True</property> |
166 | - <property name="can_focus">False</property> |
167 | - <child> |
168 | - <object class="GtkEntry" id="txtGCommand"> |
169 | - <property name="visible">True</property> |
170 | - <property name="can_focus">True</property> |
171 | - <property name="invisible_char">•</property> |
172 | - <property name="invisible_char_set">True</property> |
173 | - <property name="primary_icon_activatable">False</property> |
174 | - <property name="secondary_icon_activatable">False</property> |
175 | - <property name="primary_icon_sensitive">True</property> |
176 | - <property name="secondary_icon_sensitive">True</property> |
177 | - </object> |
178 | - <packing> |
179 | - <property name="expand">True</property> |
180 | - <property name="fill">True</property> |
181 | - <property name="position">0</property> |
182 | - </packing> |
183 | - </child> |
184 | - <child> |
185 | - <object class="GtkButton" id="cmdGRun"> |
186 | - <property name="label" translatable="yes">...</property> |
187 | - <property name="visible">True</property> |
188 | - <property name="can_focus">True</property> |
189 | - <property name="receives_default">True</property> |
190 | - <property name="use_action_appearance">False</property> |
191 | - </object> |
192 | - <packing> |
193 | - <property name="expand">False</property> |
194 | - <property name="fill">True</property> |
195 | - <property name="position">1</property> |
196 | - </packing> |
197 | - </child> |
198 | - </object> |
199 | - <packing> |
200 | - <property name="left_attach">1</property> |
201 | - <property name="right_attach">2</property> |
202 | - <property name="top_attach">2</property> |
203 | - <property name="bottom_attach">3</property> |
204 | - </packing> |
205 | - </child> |
206 | - <child> |
207 | - <object class="GtkEventBox" id="eventbox5"> |
208 | - <property name="visible">True</property> |
209 | - <property name="can_focus">False</property> |
210 | - <child> |
211 | - <object class="GtkLabel" id="label3"> |
212 | - <property name="visible">True</property> |
213 | - <property name="can_focus">False</property> |
214 | - <property name="xalign">0</property> |
215 | - <property name="label" translatable="yes">Command Name:</property> |
216 | - </object> |
217 | - </child> |
218 | - </object> |
219 | - <packing> |
220 | - <property name="top_attach">1</property> |
221 | - <property name="bottom_attach">2</property> |
222 | - <property name="x_options">GTK_FILL</property> |
223 | - <property name="y_options"></property> |
224 | - </packing> |
225 | - </child> |
226 | - <child> |
227 | - <object class="GtkEventBox" id="eventbox8"> |
228 | - <property name="visible">True</property> |
229 | - <property name="can_focus">False</property> |
230 | - <child> |
231 | - <object class="GtkLabel" id="label10"> |
232 | - <property name="visible">True</property> |
233 | - <property name="can_focus">False</property> |
234 | - <property name="xalign">0</property> |
235 | - <property name="label" translatable="yes">Group Name:</property> |
236 | - </object> |
237 | - </child> |
238 | - </object> |
239 | - <packing> |
240 | - <property name="x_options">GTK_FILL</property> |
241 | - <property name="y_options"></property> |
242 | - </packing> |
243 | - </child> |
244 | - <child> |
245 | - <object class="GtkEntry" id="txtGName"> |
246 | - <property name="visible">True</property> |
247 | - <property name="can_focus">True</property> |
248 | - <property name="invisible_char">•</property> |
249 | - <property name="invisible_char_set">True</property> |
250 | - <property name="primary_icon_activatable">False</property> |
251 | - <property name="secondary_icon_activatable">False</property> |
252 | - <property name="primary_icon_sensitive">True</property> |
253 | - <property name="secondary_icon_sensitive">True</property> |
254 | - </object> |
255 | - <packing> |
256 | - <property name="left_attach">1</property> |
257 | - <property name="right_attach">2</property> |
258 | - <property name="top_attach">1</property> |
259 | - <property name="bottom_attach">2</property> |
260 | - <property name="y_options"></property> |
261 | - </packing> |
262 | - </child> |
263 | - <child> |
264 | - <object class="GtkEntry" id="txtGGroup"> |
265 | - <property name="visible">True</property> |
266 | - <property name="can_focus">True</property> |
267 | - <property name="invisible_char">•</property> |
268 | - <property name="invisible_char_set">True</property> |
269 | - <property name="primary_icon_activatable">False</property> |
270 | - <property name="secondary_icon_activatable">False</property> |
271 | - <property name="primary_icon_sensitive">True</property> |
272 | - <property name="secondary_icon_sensitive">True</property> |
273 | - </object> |
274 | - <packing> |
275 | - <property name="left_attach">1</property> |
276 | - <property name="right_attach">2</property> |
277 | - <property name="y_options"></property> |
278 | - </packing> |
279 | - </child> |
280 | - </object> |
281 | - </child> |
282 | - </object> |
283 | - </child> |
284 | - </object> |
285 | <object class="GtkListStore" id="liststore1"/> |
286 | <object class="GtkListStore" id="lstTarget"> |
287 | <columns> |
288 | @@ -398,19 +201,14 @@ |
289 | </packing> |
290 | </child> |
291 | <child> |
292 | - <object class="GtkScrolledWindow" id="scrolledwindow1"> |
293 | + <object class="GtkScrolledWindow" id="list_container"> |
294 | <property name="visible">True</property> |
295 | <property name="can_focus">True</property> |
296 | <property name="hscrollbar_policy">never</property> |
297 | <property name="vscrollbar_policy">automatic</property> |
298 | <property name="shadow_type">in</property> |
299 | <child> |
300 | - <object class="GtkTreeView" id="ListViewLauncher"> |
301 | - <property name="visible">True</property> |
302 | - <property name="can_focus">True</property> |
303 | - <property name="headers_visible">False</property> |
304 | - <property name="reorderable">True</property> |
305 | - </object> |
306 | + <placeholder/> |
307 | </child> |
308 | </object> |
309 | <packing> |
310 | @@ -420,35 +218,57 @@ |
311 | </packing> |
312 | </child> |
313 | <child> |
314 | - <object class="GtkButton" id="cmdAdd"> |
315 | - <property name="label">gtk-add</property> |
316 | + <object class="GtkHButtonBox" id="hbuttonbox2"> |
317 | <property name="visible">True</property> |
318 | - <property name="can_focus">True</property> |
319 | - <property name="receives_default">True</property> |
320 | - <property name="use_action_appearance">False</property> |
321 | - <property name="use_stock">True</property> |
322 | + <property name="can_focus">False</property> |
323 | + <property name="layout_style">end</property> |
324 | + <child> |
325 | + <object class="GtkButton" id="cmdAdd"> |
326 | + <property name="visible">True</property> |
327 | + <property name="can_focus">True</property> |
328 | + <property name="receives_default">True</property> |
329 | + <property name="use_action_appearance">False</property> |
330 | + <child> |
331 | + <object class="GtkImage" id="image1"> |
332 | + <property name="visible">True</property> |
333 | + <property name="can_focus">False</property> |
334 | + <property name="stock">gtk-add</property> |
335 | + </object> |
336 | + </child> |
337 | + </object> |
338 | + <packing> |
339 | + <property name="expand">False</property> |
340 | + <property name="fill">False</property> |
341 | + <property name="position">0</property> |
342 | + </packing> |
343 | + </child> |
344 | + <child> |
345 | + <object class="GtkButton" id="cmdRemove"> |
346 | + <property name="visible">True</property> |
347 | + <property name="can_focus">True</property> |
348 | + <property name="receives_default">True</property> |
349 | + <property name="use_action_appearance">False</property> |
350 | + <child> |
351 | + <object class="GtkImage" id="image2"> |
352 | + <property name="visible">True</property> |
353 | + <property name="can_focus">False</property> |
354 | + <property name="stock">gtk-remove</property> |
355 | + </object> |
356 | + </child> |
357 | + </object> |
358 | + <packing> |
359 | + <property name="expand">False</property> |
360 | + <property name="fill">False</property> |
361 | + <property name="position">1</property> |
362 | + </packing> |
363 | + </child> |
364 | </object> |
365 | <packing> |
366 | <property name="expand">False</property> |
367 | - <property name="fill">False</property> |
368 | + <property name="fill">True</property> |
369 | <property name="position">2</property> |
370 | </packing> |
371 | </child> |
372 | - <child> |
373 | - <object class="GtkButton" id="cmdRemove"> |
374 | - <property name="label">gtk-remove</property> |
375 | - <property name="visible">True</property> |
376 | - <property name="can_focus">True</property> |
377 | - <property name="receives_default">True</property> |
378 | - <property name="use_action_appearance">False</property> |
379 | - <property name="use_stock">True</property> |
380 | - </object> |
381 | - <packing> |
382 | - <property name="expand">False</property> |
383 | - <property name="fill">False</property> |
384 | - <property name="position">3</property> |
385 | - </packing> |
386 | - </child> |
387 | </object> |
388 | <packing> |
389 | <property name="resize">False</property> |
390 | @@ -784,7 +604,9 @@ |
391 | <object class="GtkAlignment" id="alignment3"> |
392 | <property name="visible">True</property> |
393 | <property name="can_focus">False</property> |
394 | - <property name="left_padding">12</property> |
395 | + <property name="bottom_padding">9</property> |
396 | + <property name="left_padding">6</property> |
397 | + <property name="right_padding">9</property> |
398 | <child> |
399 | <object class="GtkVBox" id="vbox4"> |
400 | <property name="visible">True</property> |
401 | @@ -845,18 +667,13 @@ |
402 | </packing> |
403 | </child> |
404 | <child> |
405 | - <object class="GtkScrolledWindow" id="scrolledwindow2"> |
406 | + <object class="GtkScrolledWindow" id="group_container"> |
407 | <property name="visible">True</property> |
408 | <property name="can_focus">True</property> |
409 | <property name="hscrollbar_policy">automatic</property> |
410 | <property name="vscrollbar_policy">automatic</property> |
411 | <child> |
412 | - <object class="GtkTreeView" id="tvwGroups"> |
413 | - <property name="visible">True</property> |
414 | - <property name="can_focus">True</property> |
415 | - <property name="model">liststore1</property> |
416 | - <property name="headers_visible">False</property> |
417 | - </object> |
418 | + <placeholder/> |
419 | </child> |
420 | </object> |
421 | <packing> |
422 | |
423 | === modified file 'unitylaunchereditor/desktop.py' |
424 | --- unitylaunchereditor/desktop.py 2011-05-13 18:18:55 +0000 |
425 | +++ unitylaunchereditor/desktop.py 2011-05-21 20:12:30 +0000 |
426 | @@ -54,7 +54,7 @@ |
427 | self.add_section(keyname) |
428 | self.keys_menu.append(keyname) |
429 | |
430 | - def remove_section(self,keyname): |
431 | + def remove_sections(self, keyname): |
432 | self.remove_section(keyname) |
433 | self.keys_menu.append(keyname) |
434 | |
435 | |
436 | === modified file 'unitylaunchereditor/groupsdialog.py' |
437 | --- unitylaunchereditor/groupsdialog.py 2011-05-10 02:13:09 +0000 |
438 | +++ unitylaunchereditor/groupsdialog.py 2011-05-21 20:12:30 +0000 |
439 | @@ -1,3 +1,8 @@ |
440 | +# -*- coding: utf-8 -*- |
441 | +##################################################################### |
442 | +# Laudeci Oliveira <laudeci@ubuntu.com> |
443 | +# Ursula Junque <ursinha@ubuntu.com> |
444 | +# |
445 | # Copyright 2011 unity-launcher-editor-dev. |
446 | # |
447 | # This program is free software; you can redistribute it and/or modify |
448 | @@ -14,42 +19,157 @@ |
449 | import gtk |
450 | from gobject import TYPE_STRING |
451 | from utils import FileChooser |
452 | -from os.path import exists, expanduser, isfile, join |
453 | - |
454 | +from translation import _ |
455 | |
456 | class GroupsDialog(gtk.Dialog): |
457 | """XXX: add docs.""" |
458 | |
459 | - def __init__(self, title='Add Group...'): |
460 | + def __init__(self, title=_('Add Group...'), parent=None): |
461 | super(GroupsDialog, self).__init__(title, |
462 | - None, (gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | |
463 | + None, (gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | |
464 | gtk.DIALOG_NO_SEPARATOR), |
465 | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) |
466 | - |
467 | - glade_file = "application.glade" |
468 | - self.builder = gtk.Builder() |
469 | - |
470 | - glade_path = join("data", glade_file) |
471 | - if not exists(glade_path): |
472 | - raise Exception( |
473 | - "Critical: couldn't find glade file: %s" % glade_path) |
474 | - self.builder.add_from_file(glade_path) |
475 | - self.add_group_panel = self.builder.get_object('frame4') |
476 | - |
477 | + |
478 | + |
479 | + self.set_resizable(False) |
480 | + |
481 | + if parent: |
482 | + self.set_transient_for(parent) |
483 | + |
484 | + self.add_group_panel = self.create_widgets() |
485 | + self.vbox.pack_start(self.add_group_panel, True, True, 0) |
486 | + self.vbox.show_all() |
487 | + |
488 | self.ok_button = self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) |
489 | self.ok_button.grab_default() |
490 | self.ok_button.set_sensitive(False) |
491 | self.set_alternative_button_order( |
492 | [gtk.RESPONSE_CANCEL, gtk.RESPONSE_OK]) |
493 | + |
494 | + self.txtName.connect('changed', self.on_change) |
495 | + self.txtCommand.connect('changed', self.on_change) |
496 | + self.cmdGRun.connect('clicked', self.open_executable) |
497 | |
498 | - self.txtGroup =self.builder.get_object('txtGGroup') |
499 | - self.txtName = self.builder.get_object('txtGName') |
500 | + def create_widgets(self): |
501 | + ''' |
502 | + this will create input widgets for our dialog |
503 | + without depending on glade for that and |
504 | + solving the file not found error report. |
505 | + ''' |
506 | + |
507 | + frame4 = gtk.Frame() |
508 | + frame4.set_shadow_type(gtk.SHADOW_NONE) |
509 | + |
510 | + align = gtk.Alignment() |
511 | + align.set_padding(0, 0, 12, 0) |
512 | + |
513 | + table = gtk.Table(rows=4, columns=2, homogeneous=False) |
514 | + table.set_col_spacings(5) |
515 | + table.set_row_spacings(5) |
516 | + |
517 | + label8 = gtk.Label(_('Group Name:')) |
518 | + label8.set_alignment(0, 0.5) |
519 | + eventbox8 = gtk.EventBox() |
520 | + eventbox8.add(label8) |
521 | + |
522 | + table.attach(eventbox8, |
523 | + left_attach=0, |
524 | + right_attach=1, |
525 | + top_attach=0, |
526 | + bottom_attach=1, |
527 | + xoptions=gtk.FILL, |
528 | + yoptions=gtk.FILL, |
529 | + xpadding=0, |
530 | + ypadding=0) |
531 | + |
532 | + |
533 | + label5 = gtk.Label(_('Command Name:')) |
534 | + label5.set_alignment(0, 0.5) |
535 | + eventbox5 = gtk.EventBox() |
536 | + eventbox5.add(label5) |
537 | + table.attach(eventbox5, |
538 | + left_attach=0, |
539 | + right_attach=1, |
540 | + top_attach=1, |
541 | + bottom_attach=2, |
542 | + xoptions=gtk.FILL, |
543 | + yoptions=gtk.FILL, |
544 | + xpadding=0, |
545 | + ypadding=0) |
546 | + |
547 | + |
548 | + label6 = gtk.Label(_('Command:')) |
549 | + label6.set_alignment(0, 0.5) |
550 | + eventbox6 = gtk.EventBox() |
551 | + eventbox6.add(label6) |
552 | + table.attach(eventbox6, |
553 | + left_attach=0, |
554 | + right_attach=1, |
555 | + top_attach=2, |
556 | + bottom_attach=3, |
557 | + xoptions=gtk.FILL, |
558 | + yoptions=gtk.FILL, |
559 | + xpadding=0, |
560 | + ypadding=0) |
561 | + |
562 | + label7 = gtk.Label(_('Target Environment:')) |
563 | + label7.set_alignment(0, 0.5) |
564 | + eventbox7 = gtk.EventBox() |
565 | + eventbox7.add(label7) |
566 | + table.attach(eventbox7, |
567 | + left_attach=0, |
568 | + right_attach=1, |
569 | + top_attach=3, |
570 | + bottom_attach=4, |
571 | + xoptions=gtk.FILL, |
572 | + yoptions=gtk.FILL, |
573 | + xpadding=0, |
574 | + ypadding=0) |
575 | + |
576 | + self.txtGroup = gtk.Entry() |
577 | + table.attach(self.txtGroup, |
578 | + left_attach=1, |
579 | + right_attach=2, |
580 | + top_attach=0, |
581 | + bottom_attach=1, |
582 | + xoptions=gtk.FILL, |
583 | + yoptions=gtk.FILL, |
584 | + xpadding=0, |
585 | + ypadding=0) |
586 | + |
587 | + self.txtName = gtk.Entry() |
588 | self.txtName.set_name('Name') |
589 | - self.txtCommand = self.builder.get_object('txtGCommand') |
590 | + table.attach(self.txtName, |
591 | + left_attach=1, |
592 | + right_attach=2, |
593 | + top_attach=1, |
594 | + bottom_attach=2, |
595 | + xoptions=gtk.EXPAND | gtk.FILL, |
596 | + #yoptions=gtk.None, |
597 | + xpadding=0, |
598 | + ypadding=0) |
599 | + |
600 | + hbox4 = gtk.HBox() |
601 | + self.txtCommand = gtk.Entry() |
602 | self.txtCommand.set_name('Exec') |
603 | - self.cmbTargetEnvironment = self.builder.get_object('cmbTarget') |
604 | + self.cmdGRun = gtk.Button('...') |
605 | + |
606 | + hbox4.pack_start(self.txtCommand, expand=True, fill=True, padding=0) |
607 | + hbox4.pack_start(self.cmdGRun, expand=False, fill=True, padding=0) |
608 | + |
609 | + table.attach(hbox4, |
610 | + left_attach=1, |
611 | + right_attach=2, |
612 | + top_attach=2, |
613 | + bottom_attach=3, |
614 | + xoptions=gtk.EXPAND | gtk.FILL, |
615 | + yoptions=gtk.EXPAND | gtk.FILL, |
616 | + xpadding=0, |
617 | + ypadding=0) |
618 | + |
619 | + self.cmbTargetEnvironment = gtk.ComboBox() |
620 | self.cmbTargetEnvironment.set_name('TargetEnvironment') |
621 | - |
622 | + |
623 | self.combo_model = gtk.ListStore(TYPE_STRING) |
624 | for target_key in ['Unity', 'Message Menu', 'Unity;Message Menu']: |
625 | self.combo_model.append([target_key]) |
626 | @@ -60,14 +180,22 @@ |
627 | self.cmbTargetEnvironment.add_attribute(celltitle, 'text', 0) |
628 | self.cmbTargetEnvironment.set_model(self.combo_model) |
629 | self.cmbTargetEnvironment.set_active(0) |
630 | - |
631 | - self.txtName.connect('changed', self.on_change) |
632 | - self.txtCommand.connect('changed', self.on_change) |
633 | - self.builder.get_object('cmdGRun').connect( |
634 | - 'clicked', self.open_executable) |
635 | - |
636 | - self.vbox.pack_start(self.add_group_panel, True, True, 0) |
637 | - |
638 | + |
639 | + table.attach(self.cmbTargetEnvironment, |
640 | + left_attach=1, |
641 | + right_attach=2, |
642 | + top_attach=3, |
643 | + bottom_attach=4, |
644 | + xoptions=gtk.EXPAND | gtk.FILL, |
645 | + yoptions=gtk.EXPAND | gtk.FILL, |
646 | + xpadding=0, |
647 | + ypadding=0) |
648 | + |
649 | + align.add(table) |
650 | + frame4.add(align) |
651 | + |
652 | + return frame4 |
653 | + |
654 | def populate(self, values): |
655 | try: |
656 | self.txtGroup.set_text(values['GroupName']) |
657 | @@ -94,6 +222,7 @@ |
658 | 'TargetEnvironment': ( |
659 | self.cmbTargetEnvironment.get_active_text()), |
660 | } |
661 | + print obj |
662 | if destroy: |
663 | self.destroy() |
664 | if resp == gtk.RESPONSE_OK: |
665 | @@ -114,7 +243,3 @@ |
666 | if response: |
667 | self.txtCommand.set_text(filename) |
668 | |
669 | - |
670 | -if __name__ == "__main__": |
671 | - dialog = GroupsDialog() |
672 | - result, group = dialog.run() |
673 | |
674 | === added directory 'unitylaunchereditor/locale' |
675 | === added directory 'unitylaunchereditor/locale/en' |
676 | === added file 'unitylaunchereditor/locale/unity-launcher-editor.pot' |
677 | --- unitylaunchereditor/locale/unity-launcher-editor.pot 1970-01-01 00:00:00 +0000 |
678 | +++ unitylaunchereditor/locale/unity-launcher-editor.pot 2011-05-21 20:12:30 +0000 |
679 | @@ -0,0 +1,79 @@ |
680 | +# SOME DESCRIPTIVE TITLE. |
681 | +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
682 | +# This file is distributed under the same license as the PACKAGE package. |
683 | +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
684 | +# |
685 | +#, fuzzy |
686 | +msgid "" |
687 | +msgstr "" |
688 | +"Project-Id-Version: PACKAGE VERSION\n" |
689 | +"Report-Msgid-Bugs-To: \n" |
690 | +"POT-Creation-Date: 2011-05-15 00:23-0300\n" |
691 | +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
692 | +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
693 | +"Language-Team: LANGUAGE <LL@li.org>\n" |
694 | +"Language: \n" |
695 | +"MIME-Version: 1.0\n" |
696 | +"Content-Type: text/plain; charset=CHARSET\n" |
697 | +"Content-Transfer-Encoding: 8bit\n" |
698 | + |
699 | +#: groupsdialog.py:29 |
700 | +msgid "Add Group..." |
701 | +msgstr "" |
702 | + |
703 | +#: groupsdialog.py:41 mainwindow.py:48 |
704 | +#, python-format |
705 | +msgid "Critical: couldn't find glade file: %s" |
706 | +msgstr "" |
707 | + |
708 | +#: mainwindow.py:141 |
709 | +msgid "Save" |
710 | +msgstr "" |
711 | + |
712 | +#: mainwindow.py:142 |
713 | +msgid "Save changes" |
714 | +msgstr "" |
715 | + |
716 | +#: mainwindow.py:143 |
717 | +msgid "Do you want to save your changes?" |
718 | +msgstr "" |
719 | + |
720 | +#: mainwindow.py:226 mainwindow.py:276 mainwindow.py:287 |
721 | +msgid "Remove" |
722 | +msgstr "" |
723 | + |
724 | +#: mainwindow.py:227 |
725 | +msgid "Remove Group" |
726 | +msgstr "" |
727 | + |
728 | +#: mainwindow.py:228 |
729 | +msgid "You are about to remove a Quick List Group, are you sure?" |
730 | +msgstr "" |
731 | + |
732 | +#: mainwindow.py:277 mainwindow.py:288 |
733 | +msgid "Remove Launcher" |
734 | +msgstr "" |
735 | + |
736 | +#: mainwindow.py:278 |
737 | +msgid "You are about to remove a Launcher item, are you sure?" |
738 | +msgstr "" |
739 | + |
740 | +#: mainwindow.py:289 |
741 | +msgid "No launcher selected" |
742 | +msgstr "" |
743 | + |
744 | +#: mainwindow.py:298 |
745 | +msgid "Add Launcher" |
746 | +msgstr "" |
747 | + |
748 | +#: mainwindow.py:299 |
749 | +msgid "Add a new launcher..." |
750 | +msgstr "" |
751 | + |
752 | +#: mainwindow.py:300 |
753 | +msgid "Type a launcher name to create a new launcher." |
754 | +msgstr "" |
755 | + |
756 | +#: mainwindow.py:302 |
757 | +msgid "Name:" |
758 | +msgstr "" |
759 | |
760 | === modified file 'unitylaunchereditor/mainwindow.py' |
761 | --- unitylaunchereditor/mainwindow.py 2011-05-13 18:18:55 +0000 |
762 | +++ unitylaunchereditor/mainwindow.py 2011-05-21 20:12:30 +0000 |
763 | @@ -21,15 +21,12 @@ |
764 | import gobject |
765 | from pkg_resources import resource_filename |
766 | from desktop import DesktopParser |
767 | -from os.path import basename, dirname, exists, expanduser, join |
768 | +from os.path import basename, exists, expanduser, join |
769 | from utils import DialogType, FileChooser, get_icon, MessageBox, nullstring |
770 | from groupsdialog import GroupsDialog |
771 | - |
772 | -# Constants for column mapping |
773 | -(COLUMN_ICON, |
774 | - COLUMN_NAME, |
775 | - COLUMN_DESKTOP, |
776 | - COLUMN_PATH) = range(4) |
777 | +from widgets.launcherview import LauncherView |
778 | +from widgets.grouptree import GroupTree |
779 | +from translation import _ |
780 | |
781 | #constantes for toolbar buttons |
782 | (TOOLBUTTON_ADD, |
783 | @@ -40,51 +37,31 @@ |
784 | |
785 | builder = gtk.Builder() |
786 | |
787 | - def __init__(self, controller = None, glade_file="application.glade"): |
788 | + def __init__(self, controller=None, glade_file="application.glade"): |
789 | self.controller = controller |
790 | glade_path = resource_filename(__name__, join("data", glade_file)) |
791 | try: |
792 | self.builder.add_from_file(glade_path) |
793 | except gobject.GError: |
794 | if not exists(glade_path): |
795 | - print "Critical: couldn't find glade file: %s" % glade_path |
796 | + print _("Critical: couldn't find glade file: %s") % glade_path |
797 | raise |
798 | except Exception, exc: |
799 | - print "Something else went wrong: %s" % exc |
800 | + print ("Something else went wrong: %s") % exc |
801 | raise |
802 | |
803 | window_name = "window1" |
804 | self.window = self.builder.get_object(window_name) |
805 | |
806 | # launcher Objects |
807 | - self.listview_launcher = self.builder.get_object('ListViewLauncher') |
808 | - self.LauncherModel = gtk.ListStore(Pixbuf, gobject.TYPE_STRING, |
809 | - gobject.TYPE_PYOBJECT, gobject.TYPE_STRING) |
810 | - render_pixbuf = gtk.CellRendererPixbuf() |
811 | - render_text = gtk.CellRendererText() |
812 | - col = gtk.TreeViewColumn() |
813 | - col.pack_start(render_pixbuf, expand=False) |
814 | - col.add_attribute(render_pixbuf, 'pixbuf', COLUMN_ICON) |
815 | - col.pack_start(render_text, expand=True) |
816 | - col.add_attribute(render_text, 'text', COLUMN_NAME) |
817 | - self.listview_launcher.append_column(col) |
818 | - self.listview_launcher.set_model(self.LauncherModel) |
819 | - |
820 | + self.list_container = self.builder.get_object('list_container') |
821 | + self.listview_launcher = LauncherView() |
822 | + self.list_container.add_with_viewport(self.listview_launcher) |
823 | # groups objects |
824 | - self.tvwGroups = self.builder.get_object('tvwGroups') |
825 | - self.GroupsModel = gtk.TreeStore(gobject.TYPE_STRING, |
826 | - gobject.TYPE_STRING) |
827 | - col = gtk.TreeViewColumn('Quicklist Groups', |
828 | - gtk.CellRendererText(), text=0) |
829 | - self.tvwGroups.append_column(col) |
830 | - |
831 | - cell_renderer = gtk.CellRendererText(); |
832 | - #cell_renderer.set_property('editable', True); |
833 | - col = gtk.TreeViewColumn('', cell_renderer, text=1); |
834 | - self.tvwGroups.append_column(col) |
835 | - |
836 | - self.tvwGroups.set_model(self.GroupsModel) |
837 | - |
838 | + self.group_container = self.builder.get_object('group_container') |
839 | + self.tvwGroups = GroupTree() |
840 | + self.group_container.add_with_viewport(self.tvwGroups) |
841 | + |
842 | # info Widgets |
843 | self.imgIcon = self.builder.get_object('imgIcon') |
844 | self.txtName = self.builder.get_object('txtName') |
845 | @@ -127,7 +104,7 @@ |
846 | self.txtCommand.connect('focus-out-event', self.on_txt_focus_out) |
847 | |
848 | #list group signals |
849 | - self.tvwGroups.connect('cursor-changed', self.tvwgroups_row_change) |
850 | + self.tvwGroups.connect('selection-changed', self.on_tvwgroups_row_change) |
851 | |
852 | #group signals |
853 | self.builder.get_object('btnAdd').connect('clicked', self.add_remove_group, TOOLBUTTON_ADD) |
854 | @@ -141,44 +118,63 @@ |
855 | file_name = basename(str_path) |
856 | str_path = '%s/.local/share/applications/%s' % (expanduser('~'), |
857 | file_name) |
858 | - |
859 | - #if not '/home' in str_path: |
860 | - # str_path='%s.local/share/applications/%s' % (expanduser('~'),str_path) |
861 | - # #str_path='%s/Desktop/applications/%s' % (expanduser('~'),str_path) |
862 | - #else: |
863 | - # file_name= basename(str_path) |
864 | - # str_path='%s/Desktop/applications/%s' % (expanduser('~'),file_name) |
865 | return str_path |
866 | |
867 | + def load_launcher_from_list(self, unity_items): |
868 | + self.listview_launcher.clear_list(); |
869 | + for menu_item in unity_items: |
870 | + self.listview_launcher.add_row(menu_item) |
871 | + |
872 | + self.listview_launcher.connect('selection-changed', self.listview_launcher_row_change) |
873 | + #make first row active |
874 | + self.listview_launcher.set_cursor((0,)) |
875 | + |
876 | def save_launchers(self, widget): |
877 | - dialog = MessageBox( self.window, |
878 | - window_title='Save' , |
879 | - action_text='Save changes', |
880 | - message='Do you want to save your changes?', |
881 | + dialog = MessageBox(self.window, |
882 | + window_title=_('Save'), |
883 | + action_text=_('Save changes'), |
884 | + message=_('Do you want to save your changes?'), |
885 | dlg_type=DialogType.DIALOG_CONFIRMATION, |
886 | label_text=None |
887 | ) |
888 | result, text = dialog.run() |
889 | if result: |
890 | - for n in self.LauncherModel: |
891 | - obj = n[COLUMN_DESKTOP] |
892 | - fli = open(self.normalize_path( n[COLUMN_PATH]),'w') |
893 | + launchers = [] |
894 | + for row in self.listview_launcher.get_rows(): |
895 | + file_path = self.normalize_path(row["path"]) |
896 | + fli = open(file_path, 'w') |
897 | + |
898 | + obj = row["obj"] |
899 | obj.write(fli) |
900 | fli.close() |
901 | - launchers = [] |
902 | - for launcher in self.LauncherModel: |
903 | - launchers.append(self.normalize_path(launcher[COLUMN_PATH])) |
904 | - if self.controller: |
905 | - self.controller.save_unity_list(launchers) |
906 | + launchers.append(file_path) |
907 | + |
908 | + if self.controller: |
909 | + self.controller.save_unity_list(launchers) |
910 | + MessageBox(self.window, |
911 | + window_title=_('Information'), |
912 | + action_text=_('Changes saved'), |
913 | + message=_('Your changes were successfuly saved.\n\n To apply the changes to your launcher you will need to <b>logout</b> and login again.'), |
914 | + dlg_type=DialogType.DIALOG_MESSAGE, |
915 | + label_text=None |
916 | + ).run() |
917 | + else: |
918 | + MessageBox(self.window, |
919 | + window_title=_('Error'), |
920 | + action_text=_('Changes not saved'), |
921 | + message=_("There's a problem with your application, \n controller not found."), |
922 | + dlg_type=DialogType.DIALOG_MESSAGE, |
923 | + label_text=None |
924 | + ).run() |
925 | + |
926 | |
927 | def chk_toggle(self, widget): |
928 | # only run when gaving the focus |
929 | # this will prevent execution when setting the value by code. |
930 | |
931 | if widget.is_focus(): |
932 | + objDesktop = self.listview_launcher.get_selected_desktop() |
933 | value = widget.get_active() |
934 | - model, tree_iter = self.get_selected_launcher_row() |
935 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
936 | option = widget.get_name() |
937 | objDesktop.set(option, value) |
938 | |
939 | @@ -194,39 +190,36 @@ |
940 | value = widget.get_text() |
941 | |
942 | if ilength > 0: |
943 | - model, tree_iter = self.get_selected_launcher_row() |
944 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
945 | + objDesktop = self.listview_launcher.get_selected_desktop() |
946 | option = widget.get_name() |
947 | - if option == 'Name': |
948 | - model[tree_iter][COLUMN_NAME] = value |
949 | objDesktop.set(option, value) |
950 | + if option == 'Name' or option == 'Comment': |
951 | + sname = objDesktop.get('Name') |
952 | + desc = objDesktop.get('Comment') |
953 | + self.listview_launcher.set_value('<b>%s</b>\n%s' % (sname, desc), self.listview_launcher.COLUMN_NAME) |
954 | |
955 | def add_remove_group(self, widget, operation): |
956 | - model, tree_iter = self.get_selected_launcher_row() |
957 | - if not model: |
958 | - return |
959 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
960 | - |
961 | + |
962 | + objDesktop = self.listview_launcher.get_selected_desktop() |
963 | + |
964 | if operation == TOOLBUTTON_ADD: |
965 | #TODO : update ayatana entry |
966 | - dialog = GroupsDialog() |
967 | + |
968 | + dialog = GroupsDialog(parent=self.window) |
969 | result, group = dialog.run() |
970 | if result: |
971 | - gModel = self.tvwGroups.get_model() |
972 | - root = gModel.append(None, (group['GroupName'], '')) |
973 | + root = self.tvwGroups.add_root(group['GroupName']) |
974 | |
975 | shortcut_group_name = "%s Shortcut Group" % group['GroupName'] |
976 | - |
977 | - gModel.append(root, ('Name', group['Name'])) |
978 | - gModel.append(root, ('Exec', group['Exec'])) |
979 | - gModel.append(root, ('TargetEnvironment', |
980 | - group['TargetEnvironment'])) |
981 | + self.tvwGroups.add_root_row(root, 'Name', group['Name']) |
982 | + self.tvwGroups.add_root_row(root, 'Exec', group['Exec']) |
983 | + self.tvwGroups.add_root_row(root, 'TargetEnvironment', group['TargetEnvironment']) |
984 | |
985 | items = objDesktop.get('X-Ayatana-Desktop-Shortcuts') |
986 | if items is None: |
987 | items = [] |
988 | else: |
989 | - items =[n for n in items if n != ''] |
990 | + items = [n for n in items if n != ''] |
991 | items.append(group['GroupName']) |
992 | objDesktop.set('X-Ayatana-Desktop-Shortcuts', items) |
993 | |
994 | @@ -234,106 +227,76 @@ |
995 | objDesktop.set('Name', group['Name'] , None, shortcut_group_name) |
996 | objDesktop.set('Exec', group['Exec'] , None, shortcut_group_name) |
997 | objDesktop.set('TargetEnvironment', group['TargetEnvironment'] , None, shortcut_group_name) |
998 | + self.tvwGroups.expand(root, True) |
999 | |
1000 | |
1001 | |
1002 | elif operation == TOOLBUTTON_REMOVE: |
1003 | dialog = MessageBox(self.window, |
1004 | - window_title='Remove' , |
1005 | - action_text='Remove Group', |
1006 | - message='You are about to remove a Quick List Group, are you sure?', |
1007 | + window_title=_('Remove') , |
1008 | + action_text=_('Remove Group'), |
1009 | + message=_('You are about to remove a Quick List Group, are you sure?'), |
1010 | dlg_type=DialogType.DIALOG_CONFIRMATION, |
1011 | label_text=None |
1012 | ) |
1013 | result = dialog.run() |
1014 | |
1015 | if result[0]: |
1016 | - selection = self.tvwGroups.get_selection() |
1017 | - gModel, titer = selection.get_selected() |
1018 | - root_iter = gModel.iter_parent(titer) |
1019 | - |
1020 | - if not root_iter: |
1021 | - root_iter = titer |
1022 | - |
1023 | - shortcut_group_name = "%s Shortcut Group" % gModel.get_value(titer, 0) |
1024 | - gModel.remove(root_iter) |
1025 | + root_iter = self.tvwGroups.get_selected_root() |
1026 | + group = self.tvwGroups.get_root_text() |
1027 | + shortcut_group_name = "%s Shortcut Group" % group |
1028 | + |
1029 | + self.tvwGroups.remove_root(root_iter) |
1030 | + |
1031 | items = objDesktop.get('X-Ayatana-Desktop-Shortcuts') |
1032 | - items.remove(shortcut_group_name) |
1033 | + items.remove(group) |
1034 | + groups = [x for x in items if x != ''] |
1035 | objDesktop.remove_section(shortcut_group_name) |
1036 | - objDesktop.set('X-Ayatana-Desktop-Shortcuts',items) |
1037 | + objDesktop.set('X-Ayatana-Desktop-Shortcuts', groups) |
1038 | |
1039 | elif operation == TOOLBUTTON_EDIT: |
1040 | - selection = self.tvwGroups.get_selection() |
1041 | - gModel, titer = selection.get_selected() |
1042 | - |
1043 | - root_iter = gModel.iter_parent(titer) |
1044 | - |
1045 | - if not root_iter: |
1046 | - root_iter = titer |
1047 | - count = gModel.iter_n_children(root_iter) |
1048 | - |
1049 | - shortcut_group_name = "%s Shortcut Group" % gModel.get_value(root_iter, 0) |
1050 | - |
1051 | - items = {'GroupName': gModel.get_value(root_iter, 0)} |
1052 | - |
1053 | - for n in range(count): |
1054 | - it = gModel.iter_nth_child(root_iter, n) |
1055 | - items[ gModel.get_value(it, 0)]= gModel.get_value(it, 1) |
1056 | - dialog = GroupsDialog() |
1057 | + root_iter = self.tvwGroups.get_selected_root() |
1058 | + |
1059 | + root_text = self.tvwGroups.get_root_text() |
1060 | + |
1061 | + shortcut_group_name = "%s Shortcut Group" % root_text |
1062 | + |
1063 | + items = self.tvwGroups.get_children_values(root_iter) |
1064 | + |
1065 | + dialog = GroupsDialog(parent=self.window) |
1066 | dialog.populate(items) |
1067 | result, group = dialog.run() |
1068 | - |
1069 | + print self.builder |
1070 | if result: |
1071 | - #gModel.set(root_iter,0,group['Name']) |
1072 | - it = gModel.iter_nth_child(root_iter, 0) |
1073 | - gModel.set(it,1,group['Name']) |
1074 | - it = gModel.iter_nth_child(root_iter, 1) |
1075 | - gModel.set(it,1,group['Exec']) |
1076 | - it = gModel.iter_nth_child(root_iter, 2) |
1077 | - gModel.set(it,1,group['TargetEnvironment']) |
1078 | + self.tvwGroups.set_child_value(root_iter, 0, group['Name']) |
1079 | + self.tvwGroups.set_child_value(root_iter, 1, group['Exec']) |
1080 | + self.tvwGroups.set_child_value(root_iter, 2, group['TargetEnvironment']) |
1081 | |
1082 | objDesktop.set('Name', group['Name'] , None, shortcut_group_name) |
1083 | objDesktop.set('Exec', group['Exec'] , None, shortcut_group_name) |
1084 | - objDesktop.set('TargetEnvironment', group['TargetEnvironment'] , None,shortcut_group_name) |
1085 | + objDesktop.set('TargetEnvironment', group['TargetEnvironment'] , None, shortcut_group_name) |
1086 | |
1087 | |
1088 | |
1089 | def remove_from_launcher(self, widget): |
1090 | """Signal handler for button to remoce an item from the Launcher List""" |
1091 | |
1092 | - model, tree_iter = self.get_selected_launcher_row() |
1093 | - if tree_iter: |
1094 | + if self.listview_launcher.is_selected: |
1095 | dialog = MessageBox(self.window, |
1096 | - window_title='Remove' , |
1097 | - action_text='Remove Launcher', |
1098 | - message='You are about to remove a Launcher item, are you sure?', |
1099 | + window_title=_('Remove') , |
1100 | + action_text=_('Remove Launcher'), |
1101 | + message=_('You are about to remove a Launcher item, are you sure?'), |
1102 | dlg_type=DialogType.DIALOG_CONFIRMATION, |
1103 | label_text=None |
1104 | ) |
1105 | result, text = dialog.run() |
1106 | if result: |
1107 | - #get the current index on the list |
1108 | - indx = model.get_path(tree_iter)[0] |
1109 | - model.remove(tree_iter) |
1110 | - # try to select the previous item in the list |
1111 | - #or the next if the list still having data |
1112 | - icount = len(model) |
1113 | - print indx, icount |
1114 | - |
1115 | - if indx == icount and icount > 0: |
1116 | - print 'indx-1' |
1117 | - self.listview_launcher.set_cursor((indx - 1,)) |
1118 | - elif indx < icount and icount > 0: |
1119 | - print 'indx' |
1120 | - self.listview_launcher.set_cursor((indx,)) |
1121 | - else: |
1122 | - print 'indx+1' |
1123 | - self.listview_launcher.set_cursor((indx + 1,)) |
1124 | + self.listview_launcher.remove_current_row() |
1125 | |
1126 | else: |
1127 | - MessageBox(self.window,window_title='Remove' , |
1128 | - action_text='Remove Launcher', |
1129 | - message='No launcher selected', |
1130 | + MessageBox(self.window, window_title=_('Remove') , |
1131 | + action_text=_('Remove Launcher'), |
1132 | + message=_('No launcher selected'), |
1133 | dlg_type=DialogType.DIALOG_CONFIRMATION, |
1134 | label_text=None |
1135 | ).run() |
1136 | @@ -342,33 +305,31 @@ |
1137 | """Signal handler for button to add a new item into the Launcher List""" |
1138 | |
1139 | dialog = MessageBox(self.window, |
1140 | - window_title='Add Launcher' , |
1141 | - action_text='Add a new launcher...' , |
1142 | - message='Type a launcher name to create a new launcher.', |
1143 | + window_title=_('Add Launcher') , |
1144 | + action_text=_('Add a new launcher...') , |
1145 | + message=_('Type a launcher name to create a new launcher.'), |
1146 | dlg_type=DialogType.DIALOG_INPUT, |
1147 | - label_text='Name:' |
1148 | + label_text=_('Name:') |
1149 | ) |
1150 | |
1151 | result, text = dialog.run() |
1152 | - print result, text |
1153 | + |
1154 | if result and len(text) > 0: |
1155 | desktop_parser = DesktopParser() |
1156 | desktop_parser.set('Name', text) |
1157 | desktop_parser.set('Terminal', False) |
1158 | - path = join(expanduser('~/.local/share/applications/'), |
1159 | + desktop_parser.set('Icon', 'wft') |
1160 | + path_name = join(expanduser('~/.local/share/applications/'), |
1161 | '%s.desktop' % text) |
1162 | - tree_iter = self.LauncherModel.append((get_icon('wft'), text, desktop_parser, |
1163 | - path)) |
1164 | - #selects the inserted row |
1165 | - self.listview_launcher.set_cursor(self.LauncherModel.get_path(tree_iter)) |
1166 | + row_iter = self.listview_launcher.add_row(path_name, True, desktop_parser) |
1167 | + return row_iter |
1168 | |
1169 | def open_executable(self, widget): |
1170 | dialog = FileChooser() |
1171 | response, filename = dialog.run() |
1172 | if response: |
1173 | self.txtCommand.set_text(filename) |
1174 | - model, tree_iter = self.get_selected_launcher_row() |
1175 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
1176 | + objDesktop = self.listview_launcher.get_selected_desktop() |
1177 | objDesktop.set(self.txtCommand.get_name(), filename) |
1178 | |
1179 | |
1180 | @@ -395,62 +356,49 @@ |
1181 | self.imgIcon.set_from_pixbuf(pixbuf) |
1182 | # TODO: add code to write changes here |
1183 | # the best way is to put an apply button? |
1184 | - model, tree_iter = self.get_selected_launcher_row() |
1185 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
1186 | - model[tree_iter][COLUMN_ICON] = pixbuf |
1187 | + objDesktop = self.listview_launcher.get_selected_desktop() |
1188 | objDesktop.set('Icon', filename) |
1189 | - |
1190 | - def get_selected_launcher_row(self): |
1191 | - selection = self.listview_launcher.get_selection() |
1192 | - return selection.get_selected() |
1193 | + self.listview_launcher.set_value(pixbuf, self.listview_launcher.COLUMN_ICON) |
1194 | |
1195 | - def listview_launcher_row_change(self, data=None): |
1196 | + def listview_launcher_row_change(self, widget, model, row_iter, objDesktop): |
1197 | |
1198 | #disable groups toobar buttons |
1199 | self.btnEdit.set_sensitive(False) |
1200 | self.btnRemove.set_sensitive(False) |
1201 | |
1202 | - model, tree_iter = self.get_selected_launcher_row() |
1203 | - |
1204 | - objDesktop = model[tree_iter][COLUMN_DESKTOP] |
1205 | - |
1206 | # show properties |
1207 | - self.imgIcon.set_from_pixbuf(model[tree_iter][COLUMN_ICON]) |
1208 | + self.imgIcon.set_from_pixbuf(widget.get_selected_icon()) |
1209 | |
1210 | self.txtName.set_text(nullstring(objDesktop.get('Name'))) |
1211 | self.txtComment.get_buffer().set_text( |
1212 | nullstring(objDesktop.get('Comment'))) |
1213 | self.txtCommand.set_text(nullstring(objDesktop.get('Exec'))) |
1214 | - self.chkTerminal.set_active(objDesktop.get('Terminal')) |
1215 | + |
1216 | + checked = objDesktop.get('Terminal') |
1217 | + if not checked: |
1218 | + checked = False |
1219 | + |
1220 | + self.chkTerminal.set_active(checked) |
1221 | |
1222 | items = objDesktop.get('X-Ayatana-Desktop-Shortcuts') |
1223 | |
1224 | - gModel = self.tvwGroups.get_model() |
1225 | - gModel.clear() |
1226 | + self.tvwGroups.clear() |
1227 | |
1228 | if items: |
1229 | - if isinstance(items,str): |
1230 | - items=[items] |
1231 | + if isinstance(items, str): |
1232 | + items = [items] |
1233 | |
1234 | for group in items: |
1235 | if group != '': |
1236 | - root = gModel.append(None, (group, '')) |
1237 | + root = self.tvwGroups.add_root(group) |
1238 | for key in ('Name', 'Exec', 'TargetEnvironment'): |
1239 | - opt = objDesktop.get(key, "%s Shortcut Group" % group) |
1240 | - if opt: |
1241 | - gModel.append(root, (key, opt)) |
1242 | + value = objDesktop.get(key, "%s Shortcut Group" % group) |
1243 | + if value: |
1244 | + self.tvwGroups.add_root_row(root, key, value) |
1245 | + self.tvwGroups.expand_all() |
1246 | + |
1247 | |
1248 | - def tvwgroups_row_change(self, data=None): |
1249 | - selection = self.tvwGroups.get_selection() |
1250 | - gModel, titer = selection.get_selected() |
1251 | - |
1252 | - if not gModel or not titer: |
1253 | - return |
1254 | - |
1255 | - root_iter = gModel.iter_parent(titer) |
1256 | - |
1257 | - if not root_iter: |
1258 | - root_iter = titer |
1259 | + def on_tvwgroups_row_change(self, widget, root_iter): |
1260 | if root_iter: |
1261 | self.btnEdit.set_sensitive(True) |
1262 | self.btnRemove.set_sensitive(True) |
1263 | |
1264 | === modified file 'unitylaunchereditor/newlauncher.py' |
1265 | --- unitylaunchereditor/newlauncher.py 2011-05-12 20:23:39 +0000 |
1266 | +++ unitylaunchereditor/newlauncher.py 2011-05-21 20:12:30 +0000 |
1267 | @@ -22,26 +22,28 @@ |
1268 | from desktop import DesktopParser |
1269 | from os.path import exists, expanduser, isdir, isfile, join |
1270 | from xdg import BaseDirectory |
1271 | +from pkg_resources import resource_filename |
1272 | from utils import DialogType, FileChooser, get_icon, MessageBox, nullstring |
1273 | # Constants for column mapping |
1274 | (COLUMN_ICON, |
1275 | COLUMN_NAME, |
1276 | COLUMN_DESKTOP, |
1277 | COLUMN_PATH, |
1278 | - COLUMN_COMMENT) = range(5) |
1279 | + COLUMN_COMMENT, |
1280 | + COLUMN_SORT) = range(6) |
1281 | |
1282 | class AddLauncherDialog(gtk.Dialog): |
1283 | """XXX: add docs.""" |
1284 | def __init__(self, title='Add Launcher...'): |
1285 | super(AddLauncherDialog, self).__init__(title, |
1286 | - None, (gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | |
1287 | + None, (gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | |
1288 | gtk.DIALOG_NO_SEPARATOR), |
1289 | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) |
1290 | |
1291 | glade_file = "application.glade" |
1292 | self.builder = gtk.Builder() |
1293 | - |
1294 | - glade_path = join(expanduser("~/Desktop/unity-launcher-editor/data"), glade_file) |
1295 | + glade_path = resource_filename(__name__, join("data", glade_file)) |
1296 | + #glade_path = join(expanduser("~/Desktop/unity-launcher-editor/data"), glade_file) |
1297 | if not exists(glade_path): |
1298 | raise Exception("Critical: couldn't find glade file: %s" % glade_path) |
1299 | self.builder.add_from_file(glade_path) |
1300 | @@ -53,12 +55,12 @@ |
1301 | self.set_alternative_button_order( |
1302 | [gtk.RESPONSE_CANCEL, gtk.RESPONSE_OK]) |
1303 | |
1304 | - self.lvwAddLaunchers =self.builder.get_object('lvwAddLaunchers') |
1305 | - self.txtSearch = self.builder.get_object('entry2') |
1306 | - self.txtSearch.connect("icon-press", lambda x,y,z : self.filter.refilter()) |
1307 | + self.lvwAddLaunchers = self.builder.get_object('lvwAddLaunchers') |
1308 | + self.txtSearch = self.builder.get_object('entry2') |
1309 | + self.txtSearch.connect("icon-press", lambda x, y, z : self.filter.refilter()) |
1310 | |
1311 | self.listmodel = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, |
1312 | - gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING) |
1313 | + gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) |
1314 | |
1315 | self.filter = self.listmodel.filter_new() |
1316 | self.filter.set_visible_func(self.match_type) |
1317 | @@ -68,7 +70,6 @@ |
1318 | |
1319 | col = gtk.TreeViewColumn() |
1320 | |
1321 | - col.set_sort_column_id(COLUMN_NAME) |
1322 | col.pack_start(render_pixbuf, expand=False) |
1323 | col.add_attribute(render_pixbuf, 'pixbuf', COLUMN_ICON) |
1324 | col.pack_start(render_text, expand=True) |
1325 | @@ -82,9 +83,9 @@ |
1326 | self.lvwAddLaunchers.append_column(col) |
1327 | self.lvwAddLaunchers.set_model(self.sorter) |
1328 | #self.lvwAddLaunchers.set_search_entry(self.txtSearch); |
1329 | - apps_list=[] |
1330 | + apps_list = [] |
1331 | for n in ['/usr/share/']:#BaseDirectory.xdg_data_dirs: |
1332 | - desktop_dir = '%sapplications' %n |
1333 | + desktop_dir = '%sapplications' % n |
1334 | |
1335 | for launcher_location in glob.glob('%s/*.desktop' % desktop_dir): |
1336 | # blacklist ubiquity as will have two ubiquity in the netbook live session then |
1337 | @@ -92,12 +93,14 @@ |
1338 | apps_list.append(launcher_location) #= self.register_new_app(launcher_location, apps_list) |
1339 | apps_list.sort() |
1340 | self.populate(apps_list) |
1341 | + self.listmodel.set_sort_column_id(COLUMN_SORT,gtk.SORT_ASCENDING) |
1342 | self.vbox.pack_start(self.add_panel, True, True, 0) |
1343 | + |
1344 | |
1345 | def match_type(self, model, iter): |
1346 | value = model.get_value(iter, COLUMN_DESKTOP) |
1347 | |
1348 | - if self.txtSearch.get_text_length()==0: |
1349 | + if self.txtSearch.get_text_length() == 0: |
1350 | return True |
1351 | if self.txtSearch.get_text().lower() in value.get("Name").lower(): |
1352 | return True |
1353 | @@ -105,7 +108,7 @@ |
1354 | return False |
1355 | |
1356 | def populate(self, values): |
1357 | - var=[] |
1358 | + var = [] |
1359 | for menu_item in values: |
1360 | print menu_item |
1361 | desktop_parser = DesktopParser(menu_item) |
1362 | @@ -116,15 +119,16 @@ |
1363 | if sname is None: |
1364 | sname = desktop_parser.get('Name', 'en') |
1365 | if icon is None: |
1366 | - pix = get_icon('image-missing',32) |
1367 | + pix = get_icon('image-missing', 16) |
1368 | else: |
1369 | - pix = get_icon(icon,32) |
1370 | - var.append(('%s' % sname,pix,desktop_parser, menu_item, comm)) |
1371 | + pix = get_icon(icon, 16) |
1372 | + var.append(('%s' % sname, pix, desktop_parser, menu_item, comm,sname.upper())) |
1373 | |
1374 | #self.listmodel.append((pix, '%s' % sname, desktop_parser, menu_item)) |
1375 | - var.sort() |
1376 | - for sname, pix, desktop_parser, menu_item, comm in var: |
1377 | - self.listmodel.append((pix, '%s' % sname, desktop_parser, menu_item, comm)) |
1378 | + #var.sort() |
1379 | + |
1380 | + for sname, pix, desktop_parser, menu_item, comm, ssort in var: |
1381 | + self.listmodel.append((pix, '%s' % sname, desktop_parser, menu_item, comm,ssort.upper())) |
1382 | #self.main_window.listview_launcher.set_model(store) |
1383 | |
1384 | def get_desktop_dir(self): |
1385 | |
1386 | === added file 'unitylaunchereditor/translation.py' |
1387 | --- unitylaunchereditor/translation.py 1970-01-01 00:00:00 +0000 |
1388 | +++ unitylaunchereditor/translation.py 2011-05-21 20:12:30 +0000 |
1389 | @@ -0,0 +1,28 @@ |
1390 | +# -*- coding: utf-8 -*- |
1391 | +##################################################################### |
1392 | +# Laudeci Oliveira <laudeci@ubuntu.com> |
1393 | +# Ursula Junque <ursinha@ubuntu.com> |
1394 | +# |
1395 | +# Copyright 2011 unity-launcher-editor-dev. |
1396 | +# |
1397 | +# This program is free software; you can redistribute it and/or modify |
1398 | +# it under the terms of the GNU General Public License as published |
1399 | +# by the Free Software Foundation; version 3 only. |
1400 | +# |
1401 | +# This program is distributed in the hope that it will be useful, |
1402 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1403 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1404 | +# GNU General Public License for more details. |
1405 | +# |
1406 | +##################################################################### |
1407 | + |
1408 | +APP = 'unity-launcher-editor' |
1409 | +DIR = 'locale' |
1410 | + |
1411 | +import locale |
1412 | +import gettext |
1413 | + |
1414 | +locale.setlocale(locale.LC_ALL, '') |
1415 | +gettext.bindtextdomain(APP, DIR) |
1416 | +gettext.textdomain(APP) |
1417 | +_ = gettext.gettext |
1418 | |
1419 | === modified file 'unitylaunchereditor/utils.py' |
1420 | --- unitylaunchereditor/utils.py 2011-05-13 18:18:55 +0000 |
1421 | +++ unitylaunchereditor/utils.py 2011-05-21 20:12:30 +0000 |
1422 | @@ -88,7 +88,7 @@ |
1423 | return False, None |
1424 | |
1425 | class MessageBox(gtk.MessageDialog): |
1426 | - def __init__(self,parent, |
1427 | + def __init__(self, parent, |
1428 | window_title, |
1429 | action_text, |
1430 | message, |
1431 | |
1432 | === added directory 'unitylaunchereditor/widgets' |
1433 | === added file 'unitylaunchereditor/widgets/__init__.py' |
1434 | --- unitylaunchereditor/widgets/__init__.py 1970-01-01 00:00:00 +0000 |
1435 | +++ unitylaunchereditor/widgets/__init__.py 2011-05-21 20:12:30 +0000 |
1436 | @@ -0,0 +1,1 @@ |
1437 | + |
1438 | |
1439 | === added file 'unitylaunchereditor/widgets/grouptree.py' |
1440 | --- unitylaunchereditor/widgets/grouptree.py 1970-01-01 00:00:00 +0000 |
1441 | +++ unitylaunchereditor/widgets/grouptree.py 2011-05-21 20:12:30 +0000 |
1442 | @@ -0,0 +1,133 @@ |
1443 | +# -*- coding: utf-8 -*- |
1444 | +##################################################################### |
1445 | +# Laudeci Oliveira <laudeci@ubuntu.com> |
1446 | +# Ursula Junque <ursinha@ubuntu.com> |
1447 | +# |
1448 | +# Copyright 2011 unity-launcher-editor-dev. |
1449 | +# |
1450 | +# This program is free software; you can redistribute it and/or modify |
1451 | +# it under the terms of the GNU General Public License as published |
1452 | +# by the Free Software Foundation; version 3 only. |
1453 | +# |
1454 | +# This program is distributed in the hope that it will be useful, |
1455 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1456 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1457 | +# GNU General Public License for more details. |
1458 | +# |
1459 | +##################################################################### |
1460 | + |
1461 | +import gtk |
1462 | +from gtk.gdk import Pixbuf |
1463 | +import gobject |
1464 | +import pango |
1465 | +from re import sub |
1466 | + |
1467 | +class GroupTree(gtk.TreeView): |
1468 | + |
1469 | + __gsignals__ = { |
1470 | + "selection-changed" : (gobject.SIGNAL_RUN_LAST, |
1471 | + gobject.TYPE_NONE, |
1472 | + (gobject.TYPE_PYOBJECT,)), |
1473 | + |
1474 | + } |
1475 | + |
1476 | + def __init__(self): |
1477 | + super(GroupTree, self).__init__() |
1478 | + self.set_headers_visible(False) |
1479 | + self._setup_columns() |
1480 | + self._setup_model() |
1481 | + |
1482 | + self.connect('cursor-changed', self._on_row_change) |
1483 | + |
1484 | + |
1485 | + |
1486 | + def _setup_columns(self): |
1487 | + |
1488 | + render = gtk.CellRendererText() |
1489 | + |
1490 | + column = gtk.TreeViewColumn() |
1491 | + column.pack_start(render, expand=True) |
1492 | + column.add_attribute(render, 'markup', 0) |
1493 | + self.append_column(column) |
1494 | + |
1495 | + cell_renderer = gtk.CellRendererText(); |
1496 | + col = gtk.TreeViewColumn('', cell_renderer, text=1); |
1497 | + self.append_column(col) |
1498 | + |
1499 | + def _setup_model(self): |
1500 | + model = gtk.TreeStore(gobject.TYPE_STRING, |
1501 | + gobject.TYPE_STRING) |
1502 | + |
1503 | + old_model = self.get_model() |
1504 | + |
1505 | + if old_model: |
1506 | + del old_model |
1507 | + self.set_model(model) |
1508 | + |
1509 | + def get_selected_root(self): |
1510 | + selection = self.get_selection() |
1511 | + gModel, titer = selection.get_selected() |
1512 | + root_iter = gModel.iter_parent(titer) |
1513 | + |
1514 | + if not root_iter: |
1515 | + root_iter = titer |
1516 | + |
1517 | + return root_iter |
1518 | + |
1519 | + def get_children_values(self, root_iter): |
1520 | + model = self.get_model() |
1521 | + items = {'GroupName': self.get_root_text()} |
1522 | + items_count = model.iter_n_children(root_iter) |
1523 | + |
1524 | + for indx in range(items_count): |
1525 | + it = model.iter_nth_child(root_iter, indx) |
1526 | + items[ model.get_value(it, 0)] = model.get_value(it, 1) |
1527 | + return items |
1528 | + def expand(self, root_iter, select=False): |
1529 | + model = self.get_model() |
1530 | + path = model.get_path(root_iter) |
1531 | + self.expand_row(path, False) |
1532 | + if select: |
1533 | + self.set_cursor(path) |
1534 | + |
1535 | + def set_child_value(self, root_iter, indx, value): |
1536 | + model = self.get_model() |
1537 | + |
1538 | + it = model.iter_nth_child(root_iter, indx) |
1539 | + model.set(it, 1, value) |
1540 | + |
1541 | + def get_root_text(self): |
1542 | + root_iter = self.get_selected_root() |
1543 | + text = self.get_model().get_value(root_iter, 0) |
1544 | + text = sub('<.*?>', '', text) |
1545 | + return text |
1546 | + |
1547 | + def _on_row_change(self, data=None): |
1548 | + try: |
1549 | + root_iter = self.get_selected_root() |
1550 | + except: |
1551 | + root_iter = None |
1552 | + |
1553 | + self.emit("selection-changed", root_iter) |
1554 | + |
1555 | + def add_root_row(self, root, column, value): |
1556 | + model = self.get_model() |
1557 | + |
1558 | + new_row = model.append(root, (column, value)) |
1559 | + |
1560 | + return new_row |
1561 | + |
1562 | + def add_root(self, group_name): |
1563 | + model = self.get_model() |
1564 | + |
1565 | + new_root = model.append(None, ("<b>%s</b>" % group_name, '')) |
1566 | + |
1567 | + return new_root |
1568 | + |
1569 | + def clear(self): |
1570 | + self.get_model().clear() |
1571 | + |
1572 | + def remove_root(self, root): |
1573 | + model = self.get_model() |
1574 | + model.remove(root) |
1575 | + |
1576 | |
1577 | === added file 'unitylaunchereditor/widgets/launcherview.py' |
1578 | --- unitylaunchereditor/widgets/launcherview.py 1970-01-01 00:00:00 +0000 |
1579 | +++ unitylaunchereditor/widgets/launcherview.py 2011-05-21 20:12:30 +0000 |
1580 | @@ -0,0 +1,196 @@ |
1581 | +# -*- coding: utf-8 -*- |
1582 | +##################################################################### |
1583 | +# Laudeci Oliveira <laudeci@ubuntu.com> |
1584 | +# Ursula Junque <ursinha@ubuntu.com> |
1585 | +# |
1586 | +# Copyright 2011 unity-launcher-editor-dev. |
1587 | +# |
1588 | +# This program is free software; you can redistribute it and/or modify |
1589 | +# it under the terms of the GNU General Public License as published |
1590 | +# by the Free Software Foundation; version 3 only. |
1591 | +# |
1592 | +# This program is distributed in the hope that it will be useful, |
1593 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1594 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1595 | +# GNU General Public License for more details. |
1596 | +# |
1597 | +##################################################################### |
1598 | + |
1599 | +import gtk |
1600 | +from gtk.gdk import Pixbuf |
1601 | +import gobject |
1602 | +import pango |
1603 | + |
1604 | +from desktop import DesktopParser |
1605 | +from utils import get_icon |
1606 | + |
1607 | +class LauncherView(gtk.TreeView): |
1608 | + __gsignals__ = { |
1609 | + "selection-changed" : (gobject.SIGNAL_RUN_LAST, |
1610 | + gobject.TYPE_NONE, |
1611 | + (gobject.TYPE_PYOBJECT, |
1612 | + gobject.TYPE_PYOBJECT, |
1613 | + gobject.TYPE_PYOBJECT),), |
1614 | + |
1615 | + } |
1616 | + # Constants for column mapping |
1617 | + (COLUMN_ICON, COLUMN_NAME, COLUMN_DESKTOP, COLUMN_PATH) = range(4) |
1618 | + |
1619 | + def __init__(self): |
1620 | + super(LauncherView, self).__init__() |
1621 | + self.set_headers_visible(False) |
1622 | + self.set_reorderable(True) |
1623 | + #self.set_rules_hint(True) |
1624 | + self.get_selection().set_mode(gtk.SELECTION_SINGLE) |
1625 | + |
1626 | + self._setup_columns() |
1627 | + self._setup_model() |
1628 | + |
1629 | + # assign the tooltip |
1630 | + self.set_has_tooltip(True) |
1631 | + self.connect("query-tooltip", self._ViewTooltip) |
1632 | + #self.set_events(gtk.gdk.POINTER_MOTION_MASK) |
1633 | + |
1634 | + self.connect('cursor-changed', self._on_row_change) |
1635 | + |
1636 | + def _setup_columns(self): |
1637 | + #this renderer will show application icon |
1638 | + render_pixbuf = gtk.CellRendererPixbuf() |
1639 | + |
1640 | + #this will show application text |
1641 | + #using 2 lines, one for application name and other for description |
1642 | + #or command |
1643 | + render_text = gtk.CellRendererText() |
1644 | + render_text.set_property("ellipsize", pango.ELLIPSIZE_END) |
1645 | + |
1646 | + |
1647 | + column = gtk.TreeViewColumn() |
1648 | + column.pack_start(render_pixbuf, expand=False) |
1649 | + column.add_attribute(render_pixbuf, 'pixbuf', self.COLUMN_ICON) |
1650 | + column.pack_start(render_text, expand=True) |
1651 | + column.add_attribute(render_text, 'markup', self.COLUMN_NAME) |
1652 | + self.append_column(column) |
1653 | + |
1654 | + def _setup_model(self): |
1655 | + model = gtk.ListStore(Pixbuf, |
1656 | + gobject.TYPE_STRING, |
1657 | + gobject.TYPE_PYOBJECT, |
1658 | + gobject.TYPE_STRING) |
1659 | + |
1660 | + old_model = self.get_model() |
1661 | + |
1662 | + if old_model: |
1663 | + del old_model |
1664 | + self.set_model(model) |
1665 | + |
1666 | + def _ViewTooltip(self, widget, x, y, keyboard_mode, tooltip): |
1667 | + try: |
1668 | + (path, col, x, y) = widget.get_path_at_pos(int(x), int(y)) |
1669 | + it = widget.get_model().get_iter(path) |
1670 | + value = widget.get_model().get_value(it, self.COLUMN_NAME) |
1671 | + value += "\n%s" % widget.get_model().get_value(it, self.COLUMN_PATH) |
1672 | + pix = widget.get_model().get_value(it, self.COLUMN_ICON) |
1673 | + tooltip.set_icon(pix) |
1674 | + tooltip.set_markup(value) |
1675 | + except Exception, e: |
1676 | + tooltip.set_text(str(e)) |
1677 | + |
1678 | + |
1679 | + return True |
1680 | + |
1681 | + def _on_row_change(self, data=None): |
1682 | + |
1683 | + selection = self.get_selection() |
1684 | + model, row_iter = selection.get_selected() |
1685 | + |
1686 | + objDesktop = model[row_iter][self.COLUMN_DESKTOP] |
1687 | + self.emit("selection-changed", model, row_iter, objDesktop) |
1688 | + |
1689 | + def clear_list(self): |
1690 | + model = self.get_model() |
1691 | + if model: |
1692 | + model.clear() |
1693 | + def get_selected_row(self): |
1694 | + selection = self.get_selection() |
1695 | + return selection.get_selected() |
1696 | + |
1697 | + def get_rows(self): |
1698 | + desktops = [] |
1699 | + for row_iter in self.get_model(): |
1700 | + desktops.append({ |
1701 | + "icon": row_iter[self.COLUMN_ICON], |
1702 | + "path": row_iter[self.COLUMN_PATH], |
1703 | + "obj": row_iter[self.COLUMN_DESKTOP] |
1704 | + }) |
1705 | + |
1706 | + return desktops |
1707 | + |
1708 | + def get_selected_desktop(self): |
1709 | + selection = self.get_selection() |
1710 | + model, row_iter = selection.get_selected() |
1711 | + |
1712 | + return model[row_iter][self.COLUMN_DESKTOP] |
1713 | + |
1714 | + def get_selected_icon(self): |
1715 | + selection = self.get_selection() |
1716 | + model, row_iter = selection.get_selected() |
1717 | + |
1718 | + return model[row_iter][self.COLUMN_ICON] |
1719 | + |
1720 | + def set_value(self, value, column): |
1721 | + selection = self.get_selection() |
1722 | + model, row_iter = selection.get_selected() |
1723 | + |
1724 | + model[row_iter][column] = value |
1725 | + |
1726 | + @property |
1727 | + def is_selected(self): |
1728 | + selection = self.get_selection() |
1729 | + model, row_iter = selection.get_selected() |
1730 | + |
1731 | + return (not row_iter is None) |
1732 | + |
1733 | + def remove_current_row(self): |
1734 | + selection = self.get_selection() |
1735 | + model, row_iter = selection.get_selected() |
1736 | + |
1737 | + indx = model.get_path(row_iter)[0] |
1738 | + model.remove(row_iter) |
1739 | + |
1740 | + icount = len(model) |
1741 | + |
1742 | + if indx == icount and icount > 0: |
1743 | + self.set_cursor((indx - 1,)) |
1744 | + elif indx < icount and icount > 0: |
1745 | + self.set_cursor((indx,)) |
1746 | + else: |
1747 | + self.set_cursor((indx + 1,)) |
1748 | + |
1749 | + def set_selected_iter(self, row): |
1750 | + self.set_cursor(self.get_model().get_path(row)) |
1751 | + |
1752 | + def add_row(self, path_name, selected=False, desktop_parser=None): |
1753 | + if not desktop_parser: |
1754 | + desktop_parser = DesktopParser(path_name) |
1755 | + desktop_parser.update_keys() |
1756 | + |
1757 | + sname = desktop_parser.get('Name') |
1758 | + icon = desktop_parser.get('Icon') |
1759 | + desc = desktop_parser.get('Comment') |
1760 | + if sname is None: |
1761 | + sname = desktop_parser.get('Name', 'en') |
1762 | + if icon is None: |
1763 | + pix = None |
1764 | + else: |
1765 | + pix = get_icon(icon) |
1766 | + |
1767 | + model = self.get_model() |
1768 | + new_iter = model.append((pix, '<b>%s</b>\n%s' % (sname, desc), desktop_parser, path_name)) |
1769 | + |
1770 | + if selected: |
1771 | + self.set_cursor(self.get_model().get_path(new_iter)) |
1772 | + |
1773 | + return new_iter |
1774 | + |
1775 | +if __name__ == "__main__": |
1776 | + x = LauncherView() |