~ubuntu-branches/ubuntu/maverick/awn-extras-applets/maverick

« back to all changes in this revision

Viewing changes to applets/maintained/yama/yama.py

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2010-08-29 14:29:52 UTC
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100829142952-rhvuetyms9bv5uu7
Tags: upstream-0.4.0+bzr1372
ImportĀ upstreamĀ versionĀ 0.4.0+bzr1372

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
 
# Copyright (C) 2009  onox <denkpadje@gmail.com>
 
2
# Copyright (C) 2009 - 2010  onox <denkpadje@gmail.com>
3
3
#
4
4
# This program is free software: you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
24
24
from urllib import unquote
25
25
 
26
26
import pygtk
27
 
pygtk.require('2.0')
 
27
pygtk.require("2.0")
28
28
import gtk
29
29
 
30
30
from awn.extras import awnlib, __version__
 
31
from desktopagnostic import fdo, vfs
31
32
 
32
33
try:
33
34
    import dbus
39
40
import gio
40
41
import glib
41
42
import gmenu
42
 
from xdg import BaseDirectory, DesktopEntry
 
43
from xdg import BaseDirectory
43
44
 
44
45
applet_name = "YAMA"
45
46
applet_description = "Main menu with places and recent documents"
47
48
# Applet's themed icon, also shown in the GTK About dialog
48
49
applet_logo = "start-here"
49
50
 
50
 
file_manager_apps = ("nautilus", "thunar", "xdg-open")
51
 
 
52
51
menu_editor_apps = ("alacarte", "gmenu-simple-editor")
53
52
 
54
53
# Describes the pattern used to try to decode URLs
55
54
url_pattern = re.compile("^[a-z]+://(?:[^@]+@)?([^/]+)/(.*)$")
56
55
 
57
 
# Pattern to extract the part of the path that doesn't end with %<a-Z>
58
 
exec_pattern = re.compile("^(.*?)\s+\%[a-zA-Z]$")
59
 
 
60
56
user_dir_pattern = re.compile("^XDG_([A-Z]+)_DIR=\"(.+)\"$")
61
57
 
62
58
# Delay in seconds before starting rebuilding the menu
246
242
            self.menu.foreach(gtk.Widget.destroy)
247
243
            self.build_menu()
248
244
 
249
 
    def start_subprocess_cb(self, widget, command, use_shell):
250
 
        try:
251
 
            subprocess.Popen(command, shell=use_shell)
252
 
        except OSError:
253
 
            pass
254
 
 
255
245
    def open_folder_cb(self, widget, path):
256
 
        for command in file_manager_apps:
 
246
        self.open_uri(path)
 
247
 
 
248
    def open_uri(self, uri):
 
249
        file = vfs.File.for_uri(uri)
 
250
 
 
251
        if file is not None and file.exists():
257
252
            try:
258
 
                subprocess.Popen([command, path])
259
 
                return
260
 
            except OSError:
261
 
                pass
262
 
        raise RuntimeError("No file manager found (%s) for %s" % (", ".join(file_manager_apps), path))
 
253
                file.launch()
 
254
            except glib.GError, e:
 
255
                print "Error when opening: %s" % e
 
256
        else:
 
257
            print "File at URI not found (%s)" % uri
263
258
 
264
259
    def create_places_submenu(self, parent_menu):
265
260
        item = self.append_menu_item(parent_menu, "Places", "folder", None)
270
265
        user_path = os.path.expanduser("~/")
271
266
 
272
267
        home_item = self.append_menu_item(menu, "Home Folder", "user-home", "Open your personal folder")
273
 
        home_item.connect("activate", self.open_folder_cb, user_path)
 
268
        home_item.connect("activate", self.open_folder_cb, "file://%s" % user_path)
274
269
        desktop_item = self.append_menu_item(menu, "Desktop", "user-desktop", "Open the contents of your desktop in a folder")
275
 
        desktop_item.connect("activate", self.open_folder_cb, os.path.join(user_path, "Desktop"))
 
270
        desktop_item.connect("activate", self.open_folder_cb, "file://%s" % os.path.join(user_path, "Desktop"))
276
271
 
277
272
        """ Bookmarks """
278
273
        self.places_menu = menu
314
309
        self.__mounts_index = len(self.places_menu) - len(self.volume_items) - len(self.bookmarks_items)
315
310
        self.mount_items = []
316
311
        self.append_mounts()
317
 
        # TODO if added is False and no mounts, then their are two separators
 
312
        # TODO if added is False and no mounts, then there are two separators
318
313
 
319
314
        # Connect signals after having initialized volumes and mounts
320
315
        for signal in ("volume-added", "volume-changed", "volume-removed", "mount-added", "mount-changed", "mount-removed"):
323
318
        ncs_exists = os.path.exists(commands.getoutput("which nautilus-connect-server"))
324
319
        if ncs_exists:
325
320
            connect_item = self.append_menu_item(menu, "Connect to Server...", "applications-internet", "Connect to a remote computer or shared disk")
326
 
            connect_item.connect("activate", self.start_subprocess_cb, "nautilus-connect-server", False)
 
321
            connect_item.connect("activate", lambda w: subprocess.Popen("nautilus-connect-server"))
327
322
        added |= ncs_exists
328
323
 
329
324
        if added:
347
342
        set_sensitivity_recent_menu()
348
343
 
349
344
        def open_recent_document(widget):
350
 
            self.start_subprocess_cb(None, "xdg-open %s" % widget.get_current_uri(), True)
 
345
            self.open_uri(widget.get_current_uri())
351
346
        chooser_menu.connect("item-activated", open_recent_document)
352
347
 
353
348
        chooser_menu.append(gtk.SeparatorMenuItem())
388
383
                        else:
389
384
                            basename = glib.filename_display_basename(url_name[0])
390
385
                            url_name.append(unquote(str(basename)))
391
 
                    url, name = (url_name[0], url_name[1])
 
386
                    uri, name = (url_name[0], url_name[1])
392
387
 
393
 
                    if url.startswith("file://"):
394
 
                        if url in user_dirs:
395
 
                            icon = self.get_first_existing_icon([user_dirs[url], "folder"])
 
388
                    if uri.startswith("file://"):
 
389
                        if not vfs.File.for_uri(uri).exists():
 
390
                            continue
 
391
                        if uri in user_dirs:
 
392
                            icon = self.get_first_existing_icon([user_dirs[uri], "folder"])
396
393
                        else:
397
394
                            icon = "folder"
398
 
                        display_url = url[7:]
 
395
                        display_uri = uri[7:]
399
396
                    else:
400
397
                        icon = "folder-remote"
401
 
                        display_url = url
 
398
                        display_uri = uri
 
399
                    display_uri = unquote(display_uri)
402
400
 
403
 
                    item = self.create_menu_item(name, icon, "Open '%s'" % display_url)
 
401
                    item = self.create_menu_item(name, icon, "Open '%s'" % display_uri)
404
402
                    self.places_menu.insert(item, index)
405
 
                    item.connect("activate", self.open_folder_cb, url)
 
403
                    item.connect("activate", self.open_folder_cb, uri)
406
404
                    index += 1
407
405
                    self.bookmarks_items.append(item)
408
406
 
450
448
            self.volume_items.append(item)
451
449
 
452
450
            if mount is not None:
453
 
                url = mount.get_root().get_uri()
454
 
                item.connect("activate", self.open_folder_cb, url)
 
451
                uri = mount.get_root().get_uri()
 
452
                item.connect("activate", self.open_folder_cb, uri)
455
453
            else:
456
454
                def mount_volume(widget, vol):
457
455
                    def mount_result(vol2, result):
458
 
                        if volume.mount_finish(result):
459
 
                            url = volume.get_mount().get_root().get_uri()
460
 
                            self.open_folder_cb(None, url)
461
 
                    volume.mount(gio.MountOperation(), mount_result)
 
456
                        try:
 
457
                            if vol2.mount_finish(result):
 
458
                                uri = vol2.get_mount().get_root().get_uri()
 
459
                                self.open_uri(uri)
 
460
                        except glib.GError, e:
 
461
                            error_dialog = self.UnableToMountErrorDialog(self.applet, vol2.get_name(), e)
 
462
                            error_dialog.show_all()
 
463
                    vol.mount(gio.MountOperation(), mount_result)
462
464
                item.connect("activate", mount_volume, volume)
463
465
 
464
466
    def append_mounts(self):
478
480
                index += 1
479
481
                self.mount_items.append(item)
480
482
 
481
 
                url = mount.get_root().get_uri()
482
 
                item.connect("activate", self.open_folder_cb, url)
 
483
                uri = mount.get_root().get_uri()
 
484
                item.connect("activate", self.open_folder_cb, uri)
483
485
 
484
486
    def create_menu_item(self, label, icon_name, comment):
485
487
        item = gtk.ImageMenuItem(label)
497
499
        return item
498
500
 
499
501
    def launch_app(self, widget, desktop_path):
500
 
        if os.path.exists(desktop_path):
501
 
            path = DesktopEntry.DesktopEntry(desktop_path).getExec()
502
 
 
503
 
            # Strip last part of path if it contains %<a-Z>
504
 
            match = exec_pattern.match(path)
505
 
            if match is not None:
506
 
                path = match.group(1)
507
 
 
508
 
            self.start_subprocess_cb(None, path, True)
 
502
        file = vfs.File.for_path(desktop_path)
 
503
 
 
504
        if file is not None and file.exists():
 
505
            entry = fdo.DesktopEntry.for_file(file)
 
506
 
 
507
            if entry.key_exists("Exec"):
 
508
                try:
 
509
                    entry.launch(0, None)
 
510
                except glib.GError, e:
 
511
                    print "Error when launching: %s" % e
 
512
        else:
 
513
            print "File not found (%s)" % desktop_path
509
514
 
510
515
    def append_directory(self, tree, menu, index=None, item_list=None):
511
516
        for node in tree.contents:
540
545
    def append_awn_desktop(self, menu, desktop_name):
541
546
        for dir in BaseDirectory.xdg_data_dirs:
542
547
            path = os.path.join(dir, "applications", desktop_name + ".desktop")
543
 
            if os.path.isfile(path):
544
 
                desktop_entry = DesktopEntry.DesktopEntry(path)
545
 
                item = self.append_menu_item(menu, desktop_entry.getName(), desktop_entry.getIcon(), desktop_entry.getComment())
546
 
                item.connect("activate", self.launch_app, desktop_entry.getFileName())
 
548
            file = vfs.File.for_path(path)
 
549
 
 
550
            if file is not None and file.exists():
 
551
                entry = fdo.DesktopEntry.for_file(file)
 
552
 
 
553
                item = self.append_menu_item(menu, entry.get_name(), entry.get_icon(), entry.get_string("Comment"))
 
554
                item.connect("activate", self.launch_app, file.props.path)
547
555
                return True
548
556
        return False
549
557
 
596
604
            clear_button.connect("clicked", clear_and_hide)
597
605
            self.action_area.add(clear_button)
598
606
 
 
607
    class UnableToMountErrorDialog(awnlib.Dialogs.BaseDialog, gtk.MessageDialog):
 
608
 
 
609
        def __init__(self, parent, volume_name, error):
 
610
            gtk.MessageDialog.__init__(self, type=gtk.MESSAGE_ERROR, message_format="Unable to mount %s" % volume_name, buttons=gtk.BUTTONS_OK)
 
611
            awnlib.Dialogs.BaseDialog.__init__(self, parent)
 
612
 
 
613
            self.set_skip_taskbar_hint(True)
 
614
 
 
615
            self.format_secondary_markup(str(error))
 
616
 
599
617
 
600
618
if __name__ == "__main__":
601
619
    awnlib.init_start(YamaApplet, {"name": applet_name,
604
622
        "description": applet_description,
605
623
        "theme": applet_logo,
606
624
        "author": "onox",
607
 
        "copyright-year": 2009,
 
625
        "copyright-year": "2009 - 2010",
608
626
        "authors": ["onox <denkpadje@gmail.com>"]},
609
627
        ["no-tooltip"])