def activate(self, plugin_api):
     self.__plugin_api = plugin_api
     self.__view_manager = plugin_api.get_view_manager()
     self.__requester = plugin_api.get_requester()
     #Tasks_in_menu will hold the menu_items in the menu, to quickly access
     #them given the task id. Contains tuple of this format: (title, key,
     # gtk.MenuItem)
     self.__tasks_in_menu = SortedDict(key_position = 1, sort_position = 0)
     self.__init_gtk()
     self.__connect_to_tree()
     #Load the preferences
     self.preference_dialog_init()
     self.preferences_load()
     self.preferences_apply(True)
class NotificationArea:
    '''
    Plugin that display a notification area widget or an indicator
    to quickly access tasks.
    '''


    DEFAULT_PREFERENCES = {"start_minimized": False}
    PLUGIN_NAME = "notification_area"
    MAX_TITLE_LEN = 30

    class TheIndicator(Borg):
        """
        Application indicator can be instantiated only once. The
        plugin api, when toggling the activation state of a plugin,
        instantiates different objects from the plugin class. Therefore,
        we need to keep a reference to the indicator object. This class
        does that.
        """
        def __init__(self):
            super(NotificationArea.TheIndicator, self).__init__()
            if not hasattr(self, "_indicator"):
                try:
                    self._indicator = appindicator.Indicator( \
                                  "gtg",
                                  "indicator-messages",
                                   appindicator.CATEGORY_APPLICATION_STATUS)
                    self._indicator.set_icon("gtg")
                except:
                    self._indicator = None

        def get_indicator(self):
            return self._indicator

    def __init__(self):
        self.__indicator = NotificationArea.TheIndicator().get_indicator()
        print "INDI", self.__indicator

    def activate(self, plugin_api):
        self.__plugin_api = plugin_api
        self.__view_manager = plugin_api.get_view_manager()
        self.__requester = plugin_api.get_requester()
        #Tasks_in_menu will hold the menu_items in the menu, to quickly access
        #them given the task id. Contains tuple of this format: (title, key,
        # gtk.MenuItem)
        self.__tasks_in_menu = SortedDict(key_position = 1, sort_position = 0)
        self.__init_gtk()
        self.__connect_to_tree()
        #Load the preferences
        self.preference_dialog_init()
        self.preferences_load()
        self.preferences_apply(True)

    def deactivate(self, plugin_api):
        if self.__indicator:
            self.__indicator.set_status(appindicator.STATUS_PASSIVE)
        else:
            self.__status_icon.set_visible(False)

## Helper methods ##############################################################

    def __init_gtk(self):
        self.__menu = gtk.Menu()
        #view in main window checkbox
        view_browser_checkbox = gtk.CheckMenuItem(_("_View Main Window"))
        view_browser_checkbox.set_active(self.__view_manager.get_browser( \
                                                            ).is_shown())
        self.__signal_handler = view_browser_checkbox.connect('activate',
                                                       self.__toggle_browser)
        self.__view_manager.get_browser().connect('visibility-toggled',
                                                self.__on_browser_toggled,
                                                view_browser_checkbox)
        self.__menu.append(view_browser_checkbox)
        #add "new task"
        menuItem = gtk.ImageMenuItem(gtk.STOCK_ADD)
        menuItem.get_children()[0].set_label(_('Add _New Task'))
        menuItem.connect('activate', self.__open_task)
        self.__menu.append(menuItem)
        #quit item
        menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        menuItem.connect('activate', self.__view_manager.close_browser)
        self.__menu.append(menuItem)
        self.__menu.show_all()
        #separator (it's intended to be after show_all)
        self.__task_separator = gtk.SeparatorMenuItem()
        self.__task_separator.show()
        self.__menu.append(self.__task_separator)
        self.__menu_top_length = len(self.__menu)
        if self.__indicator:
            self.__indicator.set_menu(self.__menu)
            self.__indicator.set_status(appindicator.STATUS_ACTIVE)
        else:
            print "ELSE?"
            icon = gtk.gdk.pixbuf_new_from_file_at_size(DATA_DIR + \
                                "/icons/hicolor/16x16/apps/gtg.png", 16, 16)
            self.status_icon = gtk.status_icon_new_from_pixbuf(icon)
            self.status_icon.set_tooltip("Getting Things Gnome!")
            self.status_icon.set_visible(True)
            self.status_icon.connect('activate', self.__toggle_browser)
            self.status_icon.connect('popup-menu', \
                                     self.__on_icon_popup, \
                                     self.__menu)

    def __toggle_browser(self, sender = None, data = None):
        if self.__plugin_api.get_ui().is_shown():
            self.__plugin_api.get_view_manager().hide_browser()
        else:
            self.__plugin_api.get_view_manager().show_browser()

    def __on_browser_toggled(self, sender, checkbox):
        checkbox.disconnect(self.__signal_handler)
        checkbox.set_active(self.__view_manager.get_browser().is_shown())
        self.__signal_handler = checkbox.connect('activate',
                                               self.__toggle_browser)

    def __open_task(self, widget, tid = None):
        """
        Opens a task in the TaskEditor, if it's not currently opened.
        If tid is None, it creates a new task and opens it
        """
        if tid == None:
            tid = self.__requester.new_task().get_id()
        self.__view_manager.open_task(tid)

    def __connect_to_tree(self):
        self.__tree = self.__requester.get_tasks_tree()
        self.__tree.apply_filter('workview')
        self.__tree.connect("node-added-inview", self.__on_task_added)
        self.__tree.connect("node-deleted-inview", self.__on_task_deleted)
        self.__tree.connect("node-modified-inview", self.__on_task_added)

        #Flushing all tasks, as the plugin may have been started after GTG
        def visit_tree(tree, nodes, fun):
            for node in nodes:
                tid = node.get_id()
                if tree.is_displayed(tid):
                    fun(tid)
                    if node.has_child():
                        children = [node.get_child(c) \
                                    for c in node.get_children()]
                        visit_tree(tree, children, fun)
        virtual_root = self.__tree.get_root()
        visit_tree(self.__tree,
                   [virtual_root.get_child(c) \
                            for c in virtual_root.get_children()],
                   lambda t: self.__on_task_added(None, t, None))

    def __on_task_added(self, sender, tid, something):
        self.__task_separator.show()
        task = self.__requester.get_task(tid)
        #ellipsis of the title
        title = self.__create_short_title(task.get_title())
        try:
            #if it's already in the menu, remove it (to reinsert in a sorted
            # way)
            menu_item = self.__tasks_in_menu.pop_by_key(tid)[2]
            self.__menu.remove(menu_item)
        except:
            pass
        #creating the menu item
        menu_item = gtk.MenuItem(title,False)
        menu_item.connect('activate', self.__open_task, tid)
        menu_item.show()
        position = self.__tasks_in_menu.sorted_insert((title, tid, menu_item))
        self.__menu.insert(menu_item, position + self.__menu_top_length)
        if self.__indicator:
            self.__indicator.set_menu(self.__menu)

    def __create_short_title(self, title):
        # Underscores must be escaped to avoid to be ignored (or, optionally,
        # treated like accelerators ~~ Invernizzi
        title =title.replace("_", "__")
        short_title = title[0 : self.MAX_TITLE_LEN]
        if len(title) > self.MAX_TITLE_LEN:
            short_title = short_title.strip() + "..."
        return short_title

    def __on_task_deleted(self, sender, tid, something):
        try:
            menu_item = self.__tasks_in_menu.pop_by_key(tid)[2]
            self.__menu.remove(menu_item)
        except:
            return
        #if the dynamic menu is empty, remove the separator
        if not self.__tasks_in_menu:
            self.__task_separator.hide()

    def __on_icon_popup(self, icon, button, timestamp, menu=None):
        if not self.__indicator:
            menu.popup(None, None, gtk.status_icon_position_menu, \
                       button, timestamp, icon)

### Preferences methods #######################################################

    def is_configurable(self):
        """A configurable plugin should have this method and return True"""
        return True

    def configure_dialog(self, manager_dialog):
        self.preference_dialog_init()
        self.preferences_load()
        self.chbox_minimized.set_active(self.preferences["start_minimized"])
        self.preferences_dialog.show_all()
        self.preferences_dialog.set_transient_for(manager_dialog)

    def on_preferences_cancel(self, widget = None, data = None):
        self.preferences_dialog.hide()
        return True

    def on_preferences_ok(self, widget = None, data = None):
        self.preferences["start_minimized"] = self.chbox_minimized.get_active()
        self.preferences_apply(False)
        self.preferences_store()
        self.preferences_dialog.hide()

    def preferences_load(self):
        data = self.__plugin_api.load_configuration_object(self.PLUGIN_NAME,
                                                         "preferences")
        if not data or isinstance(data, dict):
            self.preferences = self.DEFAULT_PREFERENCES
        else:
            self.preferences = data

    def preferences_store(self):
        self.__plugin_api.save_configuration_object(self.PLUGIN_NAME,
                                                  "preferences",
                                                  self.preferences)

    def preferences_apply(self, first_start):
        if self.preferences["start_minimized"]:
            self.__view_manager.start_browser_hidden()

    def preference_dialog_init(self):
        self.builder = gtk.Builder()
        self.builder.add_from_file(os.path.join(
                    os.path.dirname(os.path.abspath(__file__)),
                    "notification_area.ui"))
        self.preferences_dialog = self.builder.get_object("preferences_dialog")
        self.chbox_minimized = self.builder.get_object("pref_chbox_minimized")
        SIGNAL_CONNECTIONS_DIC = {
            "on_preferences_dialog_delete_event":
                self.on_preferences_cancel,
            "on_btn_preferences_cancel_clicked":
                self.on_preferences_cancel,
            "on_btn_preferences_ok_clicked":
                self.on_preferences_ok
        }
        self.builder.connect_signals(SIGNAL_CONNECTIONS_DIC)