Merge lp:~keirangtp/cardapio/settings-helper into lp:cardapio
- settings-helper
- Merge into cardapio
Proposed by
Paweł Bara
Status: | Merged |
---|---|
Merged at revision: | 533 |
Proposed branch: | lp:~keirangtp/cardapio/settings-helper |
Merge into: | lp:cardapio |
Diff against target: |
748 lines (+335/-258) 5 files modified
src/cardapio (+0/-9) src/cardapio.py (+30/-195) src/docky/DockySettingsHelper.py (+0/-44) src/docky/cardapio_helper.py (+91/-10) src/misc.py (+214/-0) |
To merge this branch: | bzr merge lp:~keirangtp/cardapio/settings-helper |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thiago Teixeira | Approve | ||
Review via email: mp+41638@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Paweł Bara (keirangtp) wrote : | # |
Revision history for this message
Thiago Teixeira (tvst) wrote : | # |
I'll take a loot at this tonight.
Revision history for this message
Thiago Teixeira (tvst) wrote : | # |
Ok, at first sight this looks good. I will test it in a little bit and get back to you.
One thing that seemed strange, though, is that you removed the line
self.safe_
Why did you do this?
Revision history for this message
Thiago Teixeira (tvst) wrote : | # |
Oh, apparently that line is not longer used inside any plugin (it was used before when getting the max number of items for search results, but now we pass it as a parameter).
Ok, then :)
Revision history for this message
Thiago Teixeira (tvst) wrote : | # |
So I don't know if you noticed but this is already on the PPA :)
Also, good job with the getter/setter approach to replacing the settings dict. This way there's almost no change to the code required :)
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/cardapio' |
2 | --- src/cardapio 2010-11-21 22:19:26 +0000 |
3 | +++ src/cardapio 2010-11-23 18:22:35 +0000 |
4 | @@ -84,15 +84,6 @@ |
5 | show_hide = bus.get_object(Cardapio.bus_name_str, Cardapio.bus_obj_str).get_dbus_method('show_hide') |
6 | show_hide() |
7 | |
8 | - elif sys.argv[1] == 'docky-install': |
9 | - |
10 | - from docky.DockySettingsHelper import install_cardapio_launcher |
11 | - install_cardapio_launcher() |
12 | - |
13 | - elif sys.argv[1] == 'docky-uninstall': |
14 | - |
15 | - from docky.DockySettingsHelper import remove_cardapio_launcher |
16 | - remove_cardapio_launcher() |
17 | |
18 | elif sys.argv[1] == 'docky-open': |
19 | |
20 | |
21 | === modified file 'src/cardapio.py' |
22 | --- src/cardapio.py 2010-11-21 22:35:56 +0000 |
23 | +++ src/cardapio.py 2010-11-23 18:22:35 +0000 |
24 | @@ -22,9 +22,9 @@ |
25 | # TODO: add "most recent" and "most frequent" with a zeitgeist plugin |
26 | # plus other TODO's elsewhere in the code... |
27 | |
28 | -from misc import * |
29 | - |
30 | try: |
31 | + from misc import * |
32 | + |
33 | import gc |
34 | import os |
35 | import re |
36 | @@ -39,6 +39,7 @@ |
37 | import logging |
38 | import platform |
39 | import keybinder |
40 | + import traceback |
41 | import subprocess |
42 | import dbus, dbus.service |
43 | |
44 | @@ -183,8 +184,19 @@ |
45 | |
46 | self.home_folder_path = os.path.abspath(os.path.expanduser('~')) |
47 | |
48 | - self.read_config_file() |
49 | - |
50 | + logging.info('Loading settings...') |
51 | + try: |
52 | + self.settings = SettingsHelper(self.config_folder_path) |
53 | + except Exception, ex: |
54 | + msg = 'unable to read settings: ' + str(ex) |
55 | + |
56 | + logging.error(msg) |
57 | + fatal_error('Settings error', msg) |
58 | + traceback.print_exc() |
59 | + |
60 | + sys.exit(1) |
61 | + logging.info(' ...done loading!') |
62 | + |
63 | self.panel_applet = panel_applet |
64 | self.panel_button = panel_button |
65 | self.last_visibility_toggle = 0 |
66 | @@ -216,8 +228,6 @@ |
67 | self.bookmark_monitor = None |
68 | self.volume_monitor = None |
69 | |
70 | - self.icon_extension_types = re.compile('.*\.(png|xpm|svg)$') |
71 | - |
72 | self.sys_tree = gmenu.lookup_tree('gnomecc.menu') |
73 | self.have_control_center = (self.sys_tree.root is not None) |
74 | |
75 | @@ -254,10 +264,6 @@ |
76 | if show == Cardapio.SHOW_NEAR_MOUSE: self.show_hide_near_mouse() |
77 | elif show == Cardapio.SHOW_CENTERED : self.show() |
78 | |
79 | - # this is useful so that the user can edit the config file on first-run |
80 | - # without need to quit cardapio first: |
81 | - self.save_config_file() |
82 | - |
83 | if gnome_program_init is not None: |
84 | gnome_program_init('', self.version) # Prints a warning to the screen. Ignore it. |
85 | client = gnome_ui_master_client() |
86 | @@ -279,14 +285,18 @@ |
87 | Saves the current state and quits |
88 | """ |
89 | |
90 | - self.save_config_file() |
91 | + try: |
92 | + self.settings.save() |
93 | + except Exception, ex: |
94 | + logging.error('error while saving settings: %s' % ex) |
95 | self.quit() |
96 | |
97 | |
98 | - def quit(self): |
99 | - """ |
100 | - Quits without saving the current state |
101 | - """ |
102 | + def quit(self, *dummy): |
103 | + """ |
104 | + Quits without saving the current state. |
105 | + """ |
106 | + |
107 | logging.info('Exiting...') |
108 | gtk.main_quit() |
109 | |
110 | @@ -563,179 +573,6 @@ |
111 | self.quit() |
112 | |
113 | |
114 | - def get_config_file(self, mode): |
115 | - """ |
116 | - Returns a file handler to Cardapio's config file. |
117 | - """ |
118 | - |
119 | - old_config_file_path = os.path.join(self.config_folder_path, 'config.ini') |
120 | - config_file_path = os.path.join(self.config_folder_path, 'config.json') |
121 | - |
122 | - if not os.path.exists(config_file_path): |
123 | - |
124 | - if os.path.exists(old_config_file_path): |
125 | - os.rename(old_config_file_path, config_file_path) |
126 | - os.remove(os.path.join(self.config_folder_path, 'cardapio.log')) |
127 | - else: |
128 | - open(config_file_path, 'w+') |
129 | - |
130 | - elif not os.path.isfile(config_file_path): |
131 | - logging.error('Error! Cannot create file "%s" because a folder with that name already exists!' % config_file_path) |
132 | - self.quit() |
133 | - |
134 | - try: |
135 | - config_file = open(config_file_path, mode) |
136 | - |
137 | - except Exception, exception: |
138 | - logging.error('Could not read config file "%s":' % config_file_path) |
139 | - logging.error(exception) |
140 | - config_file = None |
141 | - |
142 | - return config_file |
143 | - |
144 | - |
145 | - def read_config_file(self): |
146 | - """ |
147 | - Reads Cardapio's config file and builds the self.settings dict |
148 | - """ |
149 | - |
150 | - config_file = self.get_config_file('r') |
151 | - |
152 | - self.settings = {} |
153 | - s = {} |
154 | - |
155 | - try: |
156 | - s = json.load(config_file) |
157 | - |
158 | - except Exception, exception: |
159 | - logging.error('Could not read config file:') |
160 | - logging.error(exception) |
161 | - |
162 | - finally: |
163 | - config_file.close() |
164 | - |
165 | - default_side_pane_items = [] |
166 | - path = which('software-center') |
167 | - if path is not None: |
168 | - default_side_pane_items.append( |
169 | - { |
170 | - 'name' : _('Ubuntu Software Center'), |
171 | - 'icon name' : 'softwarecenter', |
172 | - 'tooltip' : _('Lets you choose from thousands of free applications available for Ubuntu'), |
173 | - 'type' : 'raw', |
174 | - 'command' : 'software-center', |
175 | - }) |
176 | - |
177 | - default_side_pane_items.append( |
178 | - { |
179 | - 'name' : _('Help and Support'), |
180 | - 'icon name' : 'help-contents', |
181 | - 'tooltip' : _('Get help with %(distro_name)s') % {'distro_name':Cardapio.distro_name}, |
182 | - 'type' : 'raw', |
183 | - 'command' : 'gnome-help', |
184 | - }) |
185 | - |
186 | - self.read_config_option(s, 'window size' , None ) # format: [px, px] |
187 | - self.read_config_option(s, 'mini mode' , False ) # bool |
188 | - self.read_config_option(s, 'splitter position' , 0 ) # int, position in pixels |
189 | - self.read_config_option(s, 'show session buttons' , False ) # bool |
190 | - self.read_config_option(s, 'keep search results' , False ) # bool |
191 | - self.read_config_option(s, 'open on hover' , False ) # bool |
192 | - self.read_config_option(s, 'open categories on hover' , False ) # bool |
193 | - self.read_config_option(s, 'min search string length' , 3 ) # int, number of characters |
194 | - self.read_config_option(s, 'menu rebuild delay' , 3 , force_update_from_version = [0,9,96]) # seconds |
195 | - self.read_config_option(s, 'search results limit' , 5 ) # int, number of results |
196 | - self.read_config_option(s, 'long search results limit' , 15 ) # int, number of results |
197 | - self.read_config_option(s, 'local search update delay' , 100 , force_update_from_version = [0,9,96]) # msec |
198 | - self.read_config_option(s, 'remote search update delay' , 250 , force_update_from_version = [0,9,96]) # msec |
199 | - self.read_config_option(s, 'local search timeout' , 3000 ) # msec |
200 | - self.read_config_option(s, 'remote search timeout' , 5000 ) # msec |
201 | - self.read_config_option(s, 'autohide delay' , 250 ) # msec |
202 | - self.read_config_option(s, 'keybinding' , '<Super>space' ) # the user should use gtk.accelerator_parse('<Super>space') to see if the string is correct! |
203 | - self.read_config_option(s, 'applet label' , _('Menu') ) # string |
204 | - self.read_config_option(s, 'applet icon' , 'start-here' , override_empty_str = True) # string (either a path to the icon, or an icon name) |
205 | - self.read_config_option(s, 'pinned items' , [] ) |
206 | - self.read_config_option(s, 'side pane items' , default_side_pane_items ) |
207 | - self.read_config_option(s, 'active plugins' , ['pinned', 'places', 'applications', 'tracker', 'google', 'command_launcher']) |
208 | - self.read_config_option(s, 'plugin settings' , {} ) |
209 | - |
210 | - # these are a bit of a hack: |
211 | - self.read_config_option(s, 'handler for ftp paths' , r"nautilus '%s'" ) # a command line using %s |
212 | - self.read_config_option(s, 'handler for sftp paths' , r"nautilus '%s'" ) # a command line using %s |
213 | - self.read_config_option(s, 'handler for smb paths' , r"nautilus '%s'" ) # a command line using %s |
214 | - # (see https://bugs.launchpad.net/bugs/593141) |
215 | - |
216 | - self.settings['cardapio version'] = self.version |
217 | - |
218 | - |
219 | - # clean up the config file whenever options are changed between versions |
220 | - |
221 | - # 'side pane' used to be called 'system pane' |
222 | - if 'system pane' in self.settings: |
223 | - self.settings['side pane'] = self.settings['system pane'] |
224 | - self.settings.pop('system pane') |
225 | - |
226 | - # 'None' used to be the 'applications' plugin |
227 | - if None in self.settings['active plugins']: |
228 | - i = self.settings['active plugins'].index(None) |
229 | - self.settings['active plugins'][i] = 'applications' |
230 | - |
231 | - # make sure required plugins are in the plugin list |
232 | - for required_plugin in self.required_plugins: |
233 | - |
234 | - if required_plugin not in self.settings['active plugins']: |
235 | - self.settings['active plugins'] = [required_plugin] + self.settings['active plugins'] |
236 | - |
237 | - # make sure plugins only appear once in the plugin list |
238 | - for plugin_name in self.settings['active plugins']: |
239 | - |
240 | - while len([basename for basename in self.settings['active plugins'] if basename == plugin_name]) > 1: |
241 | - self.settings['active plugins'].remove(plugin_name) |
242 | - |
243 | - |
244 | - def read_config_option(self, user_settings, key, val, override_empty_str = False, force_update_from_version = None): |
245 | - """ |
246 | - Reads the config option 'key' from a the 'user_settings' dict, using |
247 | - 'val' as a fallback. |
248 | - """ |
249 | - |
250 | - if key in user_settings: |
251 | - if override_empty_str and len(user_settings[key]) == 0: |
252 | - self.settings[key] = val |
253 | - else: |
254 | - self.settings[key] = user_settings[key] |
255 | - else: |
256 | - self.settings[key] = val |
257 | - |
258 | - if force_update_from_version is not None: |
259 | - |
260 | - if 'cardapio version' in user_settings: |
261 | - settings_version = [int(i) for i in user_settings['cardapio version'].split('.')] |
262 | - |
263 | - else: |
264 | - settings_version = 0 |
265 | - |
266 | - if settings_version <= force_update_from_version: |
267 | - |
268 | - self.settings[key] = val |
269 | - |
270 | - |
271 | - def save_config_file(self): |
272 | - """ |
273 | - Saves the self.settings dict into the config file |
274 | - """ |
275 | - |
276 | - config_file = self.get_config_file('w') |
277 | - |
278 | - if config_file is None: |
279 | - logging.error('Could not load config file for saving settings') |
280 | - return |
281 | - |
282 | - logging.info('Saving config file...') |
283 | - json.dump(self.settings, config_file, sort_keys = True, indent = 4) |
284 | - logging.info(' ...done!') |
285 | - |
286 | - |
287 | def setup_base_ui(self): |
288 | """ |
289 | Reads the GTK Builder interface file and sets up some UI details |
290 | @@ -871,7 +708,6 @@ |
291 | """ |
292 | |
293 | self.safe_cardapio_proxy = Cardapio.SafeCardapioProxy() |
294 | - self.safe_cardapio_proxy.settings = self.settings |
295 | self.safe_cardapio_proxy.write_to_log = self.plugin_write_to_log |
296 | self.safe_cardapio_proxy.handle_search_result = self.plugin_handle_search_result |
297 | self.safe_cardapio_proxy.handle_search_error = self.plugin_handle_search_error |
298 | @@ -1254,7 +1090,11 @@ |
299 | """ |
300 | |
301 | self.options_dialog.hide() |
302 | - self.save_config_file() |
303 | + try: |
304 | + self.settings.save() |
305 | + except Exception, ex: |
306 | + logging.error('error while saving settings: %s' % ex) |
307 | + |
308 | return True |
309 | |
310 | |
311 | @@ -4271,9 +4111,6 @@ |
312 | The constructor is given a single parameter, which is an object used to |
313 | communicate with Cardapio. This object has the following members: |
314 | |
315 | - - settings - this is a dict containing the same things that you will |
316 | - find in the config.json |
317 | - |
318 | - write_to_log - this is a function that lets you write to Cardapio's |
319 | log file, like this: write_to_log(self, 'hi there') |
320 | |
321 | @@ -4290,8 +4127,6 @@ |
322 | internal databases, though, so this is not always applicable. This |
323 | is used, for example, with the software_center plugin. (see |
324 | on_reload_permission_granted below for more info) |
325 | - |
326 | - Note: DO NOT WRITE ANYTHING IN THE settings DICT!! |
327 | """ |
328 | pass |
329 | |
330 | |
331 | === modified file 'src/docky/DockySettingsHelper.py' |
332 | --- src/docky/DockySettingsHelper.py 2010-11-21 22:11:55 +0000 |
333 | +++ src/docky/DockySettingsHelper.py 2010-11-23 18:22:35 +0000 |
334 | @@ -1,6 +1,5 @@ |
335 | import gconf |
336 | import gtk |
337 | -from misc import which |
338 | |
339 | class DockySettingsHelper: |
340 | """ |
341 | @@ -157,49 +156,6 @@ |
342 | force_anchor_right = True |
343 | |
344 | return x, y, force_anchor_right, force_anchor_bottom |
345 | - |
346 | - |
347 | -def install_cardapio_launcher(): |
348 | - """ |
349 | - Sets Docky up so that Cardapio is launched whenever the dock icon is clicked. |
350 | - """ |
351 | - gconf_client = gconf.client_get_default() |
352 | - new_command = which('cardapio') + ' docky-open' |
353 | - |
354 | - current_command = gconf_client.get_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/DockyItemCommand') |
355 | - if current_command == new_command: return |
356 | - |
357 | - if current_command is not None: |
358 | - if 'cardapio' not in current_command: |
359 | - gconf_client.set_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/OldDockyItemCommand', current_command) |
360 | - else: |
361 | - gconf_client.set_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/OldDockyItemCommand', '') |
362 | - |
363 | - try: |
364 | - gconf_client.set_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/DockyItemCommand', new_command) |
365 | - except: |
366 | - pass |
367 | - |
368 | - |
369 | -def remove_cardapio_launcher(): |
370 | - """ |
371 | - Resets Docky to its initial state, before Cardapio ever loaded. |
372 | - """ |
373 | - gconf_client = gconf.client_get_default() |
374 | - |
375 | - current_command = gconf_client.get_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/DockyItemCommand') |
376 | - if current_command != which('cardapio') + ' docky-open': return |
377 | - |
378 | - old_command = gconf_client.get_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/OldDockyItemCommand') |
379 | - if old_command is not None and old_command != '': |
380 | - gconf_client.set_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/DockyItemCommand', old_command) |
381 | - else: |
382 | - gconf_client.set_string(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/DockyItemCommand', '') |
383 | - |
384 | - try: |
385 | - gconf_client.unset(DockySettingsHelper.docky_gconf_root + '/Items/DockyItem/OldDockyItemCommand') |
386 | - except: |
387 | - pass |
388 | |
389 | |
390 | class MainDockError(Exception): |
391 | |
392 | === modified file 'src/docky/cardapio_helper.py' |
393 | --- src/docky/cardapio_helper.py 2010-11-22 10:25:42 +0000 |
394 | +++ src/docky/cardapio_helper.py 2010-11-23 18:22:35 +0000 |
395 | @@ -17,27 +17,108 @@ |
396 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
397 | # |
398 | |
399 | -from sys import exit |
400 | -import gobject |
401 | -import os |
402 | -import subprocess |
403 | - |
404 | try: |
405 | + from dockmanager.dockmanager import DockManagerSink |
406 | + |
407 | + from sys import exit |
408 | from signal import signal, SIGTERM |
409 | + |
410 | + import atexit |
411 | + import gobject |
412 | + import subprocess |
413 | + import os |
414 | + import gconf |
415 | except ImportError, e: |
416 | exit() |
417 | |
418 | + |
419 | +# note - this is duplicated in misc.py |
420 | +def which(filename): |
421 | + """ |
422 | + Searches the folders in the OS's PATH variable, looking for a file called |
423 | + "filename". If found, returns the full path. Otherwise, returns None. |
424 | + """ |
425 | + |
426 | + for path in os.environ["PATH"].split(os.pathsep): |
427 | + if os.access(os.path.join(path, filename), os.X_OK): |
428 | + return "%s/%s" % (path, filename) |
429 | + return None |
430 | + |
431 | + |
432 | +docky_item_gconf_root = '/apps/docky-2/Docky/Items/DockyItem' |
433 | + |
434 | + |
435 | +def install_cardapio_launcher(): |
436 | + """ |
437 | + Sets Docky up so that Cardapio is launched whenever the dock icon is clicked. |
438 | + """ |
439 | + |
440 | + gconf_client = gconf.client_get_default() |
441 | + |
442 | + new_command = which('cardapio') + ' docky-open' |
443 | + |
444 | + current_command = gconf_client.get_string(docky_item_gconf_root + '/DockyItemCommand') |
445 | + if current_command == new_command: |
446 | + return |
447 | + |
448 | + if current_command is not None and current_command != '': |
449 | + if 'cardapio' not in current_command: |
450 | + gconf_client.set_string(docky_item_gconf_root + '/OldDockyItemCommand', current_command) |
451 | + |
452 | + try: |
453 | + gconf_client.set_string(docky_item_gconf_root + '/DockyItemCommand', new_command) |
454 | + except: |
455 | + pass |
456 | + |
457 | + |
458 | +def remove_cardapio_launcher(): |
459 | + """ |
460 | + Resets Docky to its initial state, before Cardapio ever loaded. |
461 | + """ |
462 | + |
463 | + gconf_client = gconf.client_get_default() |
464 | + |
465 | + current_command = gconf_client.get_string(docky_item_gconf_root + '/DockyItemCommand') |
466 | + if current_command != which('cardapio') + ' docky-open': |
467 | + return |
468 | + |
469 | + old_command = gconf_client.get_string(docky_item_gconf_root + '/OldDockyItemCommand') |
470 | + if old_command is not None and old_command != '': |
471 | + gconf_client.set_string(docky_item_gconf_root + '/DockyItemCommand', old_command) |
472 | + else: |
473 | + gconf_client.set_string(docky_item_gconf_root + '/DockyItemCommand', '') |
474 | + |
475 | + try: |
476 | + gconf_client.unset(docky_item_gconf_root + '/OldDockyItemCommand') |
477 | + except: |
478 | + pass |
479 | + |
480 | + |
481 | +class CardapioSink(DockManagerSink): |
482 | + """ |
483 | + This is not attaching any helpers - just waiting for the signal |
484 | + to close. |
485 | + """ |
486 | + |
487 | + def item_path_found(self, pathtoitem, item): |
488 | + pass |
489 | + |
490 | + |
491 | +cardapio_sink = CardapioSink() |
492 | + |
493 | + |
494 | def cleanup(): |
495 | - subprocess.Popen('cardapio docky-uninstall', shell = True) |
496 | + remove_cardapio_launcher() |
497 | + cardapio_sink.dispose() |
498 | + |
499 | |
500 | if __name__ == "__main__": |
501 | - subprocess.Popen('cardapio docky-install', shell = True) |
502 | - subprocess.Popen('cardapio hidden', shell = True) |
503 | + install_cardapio_launcher() |
504 | + subprocess.Popen('cardapio hidden', shell=True) |
505 | |
506 | mainloop = gobject.MainLoop(is_running=True) |
507 | |
508 | atexit.register (cleanup) |
509 | signal(SIGTERM, lambda signum, stack_frame: exit(0)) |
510 | |
511 | - mainloop.run() |
512 | - |
513 | + mainloop.run() |
514 | \ No newline at end of file |
515 | |
516 | === modified file 'src/misc.py' |
517 | --- src/misc.py 2010-11-17 13:20:29 +0000 |
518 | +++ src/misc.py 2010-11-23 18:22:35 +0000 |
519 | @@ -16,10 +16,15 @@ |
520 | # |
521 | |
522 | try: |
523 | + |
524 | + import cardapio |
525 | + |
526 | import re |
527 | import os |
528 | import gtk |
529 | + import json |
530 | import gio |
531 | + import sys |
532 | import logging |
533 | import commands |
534 | from xdg import BaseDirectory |
535 | @@ -234,3 +239,212 @@ |
536 | self._listener() |
537 | |
538 | |
539 | +class SettingsHelper: |
540 | + |
541 | + def __init__(self, config_folder_path): |
542 | + """ |
543 | + Reads Cardapio's config file and builds the settings dictionary. |
544 | + """ |
545 | + |
546 | + self.config_folder_path = config_folder_path |
547 | + |
548 | + self.settings = {} |
549 | + s = {} |
550 | + |
551 | + with self.get_config_file('r') as config_file: |
552 | + # if the file is empty, we assume it's the first run and |
553 | + # we'll fill it while saving the settings for the first time |
554 | + if(os.path.getsize(config_file.name) > 0): |
555 | + s = json.load(config_file) |
556 | + |
557 | + default_side_pane_items = [] |
558 | + path = which('software-center') |
559 | + if path is not None: |
560 | + default_side_pane_items.append( |
561 | + { |
562 | + 'name' : _('Ubuntu Software Center'), |
563 | + 'icon name' : 'softwarecenter', |
564 | + 'tooltip' : _('Lets you choose from thousands of free applications available for Ubuntu'), |
565 | + 'type' : 'raw', |
566 | + 'command' : 'software-center', |
567 | + }) |
568 | + |
569 | + default_side_pane_items.append( |
570 | + { |
571 | + 'name' : _('Help and Support'), |
572 | + 'icon name' : 'help-contents', |
573 | + 'tooltip' : _('Get help with %(distro_name)s') % { 'distro_name': cardapio.Cardapio.distro_name }, |
574 | + 'type' : 'raw', |
575 | + 'command' : 'gnome-help', |
576 | + }) |
577 | + |
578 | + self.read_config_option(s, 'window size' , None ) # format: [px, px] |
579 | + self.read_config_option(s, 'mini mode' , False ) # bool |
580 | + self.read_config_option(s, 'splitter position' , 0 ) # int, position in pixels |
581 | + self.read_config_option(s, 'show session buttons' , False ) # bool |
582 | + self.read_config_option(s, 'keep search results' , False ) # bool |
583 | + self.read_config_option(s, 'open on hover' , False ) # bool |
584 | + self.read_config_option(s, 'open categories on hover' , False ) # bool |
585 | + self.read_config_option(s, 'min search string length' , 3 ) # int, number of characters |
586 | + self.read_config_option(s, 'menu rebuild delay' , 3 , force_update_from_version = [0,9,96]) # seconds |
587 | + self.read_config_option(s, 'search results limit' , 5 ) # int, number of results |
588 | + self.read_config_option(s, 'long search results limit' , 15 ) # int, number of results |
589 | + self.read_config_option(s, 'local search update delay' , 100 , force_update_from_version = [0,9,96]) # msec |
590 | + self.read_config_option(s, 'remote search update delay' , 250 , force_update_from_version = [0,9,96]) # msec |
591 | + self.read_config_option(s, 'local search timeout' , 3000 ) # msec |
592 | + self.read_config_option(s, 'remote search timeout' , 5000 ) # msec |
593 | + self.read_config_option(s, 'autohide delay' , 250 ) # msec |
594 | + self.read_config_option(s, 'keybinding' , '<Super>space' ) # the user should use gtk.accelerator_parse('<Super>space') to see if the string is correct! |
595 | + self.read_config_option(s, 'applet label' , _('Menu') ) # string |
596 | + self.read_config_option(s, 'applet icon' , 'start-here' , override_empty_str = True) # string (either a path to the icon, or an icon name) |
597 | + self.read_config_option(s, 'pinned items' , [] ) |
598 | + self.read_config_option(s, 'side pane items' , default_side_pane_items ) |
599 | + self.read_config_option(s, 'active plugins' , ['pinned', 'places', 'applications', 'tracker', 'google', 'command_launcher']) |
600 | + self.read_config_option(s, 'plugin settings' , {} ) |
601 | + |
602 | + # these are a bit of a hack: |
603 | + self.read_config_option(s, 'handler for ftp paths' , r"nautilus '%s'" ) # a command line using %s |
604 | + self.read_config_option(s, 'handler for sftp paths' , r"nautilus '%s'" ) # a command line using %s |
605 | + self.read_config_option(s, 'handler for smb paths' , r"nautilus '%s'" ) # a command line using %s |
606 | + # see https://bugs.launchpad.net/bugs/593141 |
607 | + |
608 | + self.settings['cardapio version'] = cardapio.Cardapio.version |
609 | + |
610 | + # clean up the config file whenever options are changed between versions |
611 | + |
612 | + # 'side pane' used to be called 'system pane' |
613 | + if 'system pane' in self.settings: |
614 | + self.settings['side pane'] = self.settings['system pane'] |
615 | + self.settings.pop('system pane') |
616 | + |
617 | + # 'None' used to be the 'applications' plugin |
618 | + if None in self.settings['active plugins']: |
619 | + i = self.settings['active plugins'].index(None) |
620 | + self.settings['active plugins'][i] = 'applications' |
621 | + |
622 | + # make sure required plugins are in the plugin list |
623 | + for required_plugin in cardapio.Cardapio.required_plugins: |
624 | + if required_plugin not in self.settings['active plugins']: |
625 | + self.settings['active plugins'] = [required_plugin] + self.settings['active plugins'] |
626 | + |
627 | + # make sure plugins only appear once in the plugin list |
628 | + for plugin_name in self.settings['active plugins']: |
629 | + while len([basename for basename in self.settings['active plugins'] if basename == plugin_name]) > 1: |
630 | + self.settings['active plugins'].remove(plugin_name) |
631 | + |
632 | + # this saves the loaded config file (useful on the first run) |
633 | + self.save() |
634 | + |
635 | + |
636 | + def assert_config_file_exists(self): |
637 | + """ |
638 | + If this doesn't throw any exceptions, after the invocation the caller |
639 | + might be sure that the config file "config.json" exists at and can be |
640 | + used further. |
641 | + |
642 | + The method returns a file path to the config file. |
643 | + |
644 | + It might raise FatalSettingsError if "config.json" exists but is |
645 | + a directory. |
646 | + """ |
647 | + |
648 | + old_config_file_path = os.path.join(self.config_folder_path, 'config.ini') |
649 | + config_file_path = os.path.join(self.config_folder_path, 'config.json') |
650 | + |
651 | + if not os.path.exists(config_file_path): |
652 | + |
653 | + # maybe it's not there because we're migrating from version |
654 | + # that's using the old file extension (".ini")? |
655 | + if os.path.exists(old_config_file_path): |
656 | + # change the extension |
657 | + os.rename(old_config_file_path, config_file_path) |
658 | + # also, let's remove the old log file while we're at it... |
659 | + os.remove(os.path.join(self.config_folder_path, 'cardapio.log')) |
660 | + else: |
661 | + # create and close an empty file |
662 | + with open(config_file_path, 'w+') as new_file: |
663 | + pass |
664 | + |
665 | + elif not os.path.isfile(config_file_path): |
666 | + raise FatalSettingsError('cannot create file "%s" because a folder with that name already exists!' % config_file_path) |
667 | + |
668 | + return config_file_path |
669 | + |
670 | + |
671 | + def get_config_file(self, mode): |
672 | + """ |
673 | + Returns a file handler to Cardapio's config file. The caller is |
674 | + responsible for closing the file. |
675 | + """ |
676 | + |
677 | + return open(self.assert_config_file_exists(), mode) |
678 | + |
679 | + |
680 | + def save(self): |
681 | + """ |
682 | + Saves this settings object to a config file. |
683 | + """ |
684 | + |
685 | + with self.get_config_file('w') as config_file: |
686 | + logging.info('Saving config file...') |
687 | + json.dump(self.settings, config_file, sort_keys = True, indent = 4) |
688 | + logging.info(' ...done!') |
689 | + |
690 | + |
691 | + def read_config_option(self, user_settings, key, val, override_empty_str = False, force_update_from_version = None): |
692 | + """ |
693 | + Sets on itself the config option 'key' from the 'user_settings' |
694 | + dictionary using 'val' as a fallback value. |
695 | + |
696 | + Will override found but empty settings when the override_empty_str flag |
697 | + is set to true. |
698 | + |
699 | + Will update the setting 'key' to the 'val' value if user is migrating |
700 | + from version force_update_from_version. |
701 | + """ |
702 | + |
703 | + if key in user_settings: |
704 | + |
705 | + if override_empty_str and len(user_settings[key]) == 0: |
706 | + self.settings[key] = val |
707 | + else: |
708 | + self.settings[key] = user_settings[key] |
709 | + |
710 | + else: |
711 | + |
712 | + self.settings[key] = val |
713 | + |
714 | + if force_update_from_version is not None: |
715 | + |
716 | + if 'cardapio version' in user_settings: |
717 | + settings_version = [int(i) for i in user_settings['cardapio version'].split('.')] |
718 | + else: |
719 | + settings_version = 0 |
720 | + |
721 | + if settings_version <= force_update_from_version: |
722 | + self.settings[key] = val |
723 | + |
724 | + |
725 | + def __getitem__(self, name): |
726 | + """ |
727 | + Returns the value of the setting named 'name'. |
728 | + """ |
729 | + |
730 | + return self.settings[name]; |
731 | + |
732 | + |
733 | + def __setitem__(self, name, value): |
734 | + """ |
735 | + Sets the value of the setting named 'name' to 'value'. |
736 | + """ |
737 | + |
738 | + self.settings[name] = value; |
739 | + |
740 | + |
741 | + |
742 | +class FatalSettingsError(Exception): |
743 | + """ |
744 | + Indicates unrecoverable SettingsHelper error. |
745 | + """ |
746 | + |
747 | + pass |
748 | \ No newline at end of file |
summary of settings changes:
- refactored Settings to a helper which looks like a dictionary
- redone the whole concept of raising errors from settings code and the handling of those errors in main Cardapio's code
summary of Docky related changes:
- better check of empty 'DockyItemCommand' setting
- added and empty DockManagerSink for Cardapio; it let's you run the helper from any environment and it will always close cleanly when Docky's closing
- moved installing and uninstalling the launcher from DockySettingsHelper and cardapio to cardapio_helper
Please note that even though I've done some changes to the helper's code, it's not removing the anchor icon's tooltip as we discussed. Docky's caches this setting when it starts so when we change it, it's too late. We could make it work after a restart of Docky but we would have to abandon the whole "remember the old setting" concept then.
Still, I think that removing this tooltip is a vital part of current helper's functionality so we should at least add a comment to the "advertisements" and informations on project's site saying something like:
Please note that you can remove the tooltip of Docky's anchor icon which will otherwise in many cases overlap Cardapio's window. To do that run: "gconftool -s /apps/docky- 2/Docky/ Items/DockyItem /HoverText -t string ''" from command line and restart Docky.