gtg team mailing list archive
-
gtg team
-
Mailing list archive
-
Message #03677
[Merge] lp:~izidor/gtg/bug1074140 into lp:gtg
Izidor Matušov has proposed merging lp:~izidor/gtg/bug1074140 into lp:gtg.
Requested reviews:
Gtg developers (gtg)
Related bugs:
Bug #1074140 in Getting Things GNOME!: "Notification area plugin can't be run on a distribution without appindicator"
https://bugs.launchpad.net/gtg/+bug/1074140
For more details, see:
https://code.launchpad.net/~izidor/gtg/bug1074140/+merge/132654
A patch to run notification area plugin even for systems without appindicator, e.g. Archlinux's XFCE4.
--
https://code.launchpad.net/~izidor/gtg/bug1074140/+merge/132654
Your team Gtg developers is requested to review the proposed merge of lp:~izidor/gtg/bug1074140 into lp:gtg.
=== removed directory 'GTG/plugins/notification_area/data'
=== removed directory 'GTG/plugins/notification_area/data/icons'
=== removed directory 'GTG/plugins/notification_area/data/icons/hicolor'
=== removed directory 'GTG/plugins/notification_area/data/icons/hicolor/22x22'
=== removed directory 'GTG/plugins/notification_area/data/icons/hicolor/22x22/apps'
=== modified file 'GTG/plugins/notification_area/notification_area.py'
--- GTG/plugins/notification_area/notification_area.py 2012-07-18 12:09:41 +0000
+++ GTG/plugins/notification_area/notification_area.py 2012-11-02 07:54:58 +0000
@@ -24,11 +24,109 @@
pass
from GTG import _
-from GTG import PLUGIN_DIR
from GTG.tools.borg import Borg
from GTG.tools.dates import Date
+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(TheIndicator, self).__init__()
+ if not hasattr(self, "_indicator"):
+ try:
+ self._indicator = appindicator.Indicator( \
+ "gtg",
+ "indicator-messages",
+ appindicator.CATEGORY_APPLICATION_STATUS)
+ except:
+ self._indicator = None
+
+ def get_indicator(self):
+ return self._indicator
+
+
+class IconIndicator:
+ """
+ A common interface to an app indicator and a status icon
+ """
+
+ NORMAL_ICON = "gtg"
+ ATTENTION_ICON = "gtg_need_attention"
+
+ def __init__(self):
+ self._indicator = TheIndicator().get_indicator()
+ self._icon = None
+ self._menu = None
+ self._attention = False
+
+ def activate(self, leftbtn_callback, menu):
+ """ Setup the icon / the indicator """
+
+ self._menu = menu
+
+ if self._indicator:
+ self._indicator.set_icon("gtg-panel")
+ self._indicator.set_attention_icon(self.ATTENTION_ICON)
+ self._indicator.set_menu(menu)
+ self._indicator.set_status(appindicator.STATUS_ACTIVE)
+ else:
+ self._icon = gtk.StatusIcon()
+ self._icon.set_from_icon_name(self.NORMAL_ICON)
+ self._icon.set_tooltip("Getting Things GNOME!")
+ self._icon.set_visible(True)
+ self._icon.connect('activate', leftbtn_callback)
+ self._icon.connect('popup-menu', self._on_icon_popup)
+
+ def deactivate(self):
+ """ Hide the icon """
+ if self._indicator:
+ self._indicator.set_status(appindicator.STATUS_PASSIVE)
+ else:
+ self._icon.set_visible(False)
+
+ def update_menu(self):
+ """ Force indicator to update menu """
+ if self._indicator:
+ self._indicator.set_menu(self._menu)
+
+ def set_attention(self, attention):
+ """ Show a special icon when the indicator needs attention """
+ # Change icon only when the attention change
+ if self._attention == attention:
+ return
+
+ if self._indicator:
+ if attention:
+ status = appindicator.STATUS_ATTENTION
+ else:
+ status = appindicator.STATUS_ACTIVE
+
+ self._indicator.set_status(status)
+ else:
+ if attention:
+ icon = self.ATTENTION_ICON
+ else:
+ icon = self.NORMAL_ICON
+
+ self._icon.set_from_icon_name(icon)
+
+ self._attention = attention
+
+ def _on_icon_popup(self, icon, button, timestamp):
+ """ Show the menu on right click on the icon """
+ if not self._indicator:
+ self._menu.popup(None, None, gtk.status_icon_position_menu,
+ button, timestamp, icon)
+
+
+
def _due_within(task, danger_zone):
"""
Determine if a task is the danger zone.
@@ -55,16 +153,10 @@
than time span (in days) defined by danger_zone.
"""
- STATUS = {'normal': appindicator.STATUS_ACTIVE,
- 'high': appindicator.STATUS_ATTENTION}
-
- ICON = {'normal': 'gtg-panel',
- 'high': 'gtg_need_attention'}
-
def __init__(self, danger_zone, indicator, tree, req):
self.__tree = tree
self.__req = req
- self.__indicator = indicator
+ self._indicator = indicator
self.danger_zone = danger_zone
# Setup list of tasks in danger zone
@@ -76,27 +168,13 @@
self.tasks_danger.append(tid)
# Set initial status
- self.__update_indicator(self.level())
-
- def level(self):
- """ Two states only: attention is either needed or not """
- return 'high' if len(self.tasks_danger)>0 else 'normal'
-
- def __update_indicator(self, new, old=None):
- """ Reset indicator status or update upon change in status """
- if old is None or not old == new:
- try:
- # This works if __indicator implements the appindicator api
- self.__indicator.set_status(self.STATUS[new])
- except AttributeError:
- # If we passed a status icon instead try this
- self.__indicator.set_from_icon_name(self.ICON[new])
- except:
- raise
+ self._update_indicator()
+
+ def _update_indicator(self):
+ """ Set the proper icon for the indicator """
+ self._indicator.set_attention(len(self.tasks_danger) > 0)
def update_on_task_modified(self, tid):
- # Store current attention level
- old_lev = self.level()
task = self.__req.get_task(tid)
if tid in self.tasks_danger:
if not _due_within(task, self.danger_zone):
@@ -104,19 +182,14 @@
else:
if _due_within(task, self.danger_zone):
self.tasks_danger.append(tid)
-
- # Update icon only if attention level has changed
- self.__update_indicator(self.level(), old_lev)
+
+ self._update_indicator()
def update_on_task_deleted(self, tid):
- # Store current attention level
- old_lev = self.level()
-
if tid in self.tasks_danger:
self.tasks_danger.remove(tid)
- # Update icon only if attention level has changed
- self.__update_indicator(self.level(), old_lev)
+ self._update_indicator()
class NotificationArea:
@@ -131,31 +204,9 @@
MAX_TITLE_LEN = 30
MAX_ITEMS = 10
- 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)
- except:
- self._indicator = None
-
- def get_indicator(self):
- return self._indicator
def __init__(self):
- self.__indicator = NotificationArea.TheIndicator().get_indicator()
+ self._indicator = IconIndicator()
self.__browser_handler = None
self.__liblarch_callbacks = []
@@ -203,10 +254,7 @@
def deactivate(self, plugin_api):
""" Set everything back to normal """
- if self.__indicator:
- self.__indicator.set_status(appindicator.STATUS_PASSIVE)
- else:
- self.status_icon.set_visible(False)
+ self._indicator.deactivate()
# Allow to close browser after deactivation
self.__set_browser_close_callback(None)
@@ -224,13 +272,13 @@
def __init_gtk(self):
browser = self.__view_manager.get_browser()
- self.__menu = gtk.Menu()
+ menu = gtk.Menu()
#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)
+ menu.append(menuItem)
#view in main window checkbox
view_browser_checkbox = gtk.CheckMenuItem(_("_View Main Window"))
@@ -239,48 +287,29 @@
self.__toggle_browser)
browser.connect('visibility-toggled', self.__on_browser_toggled,
view_browser_checkbox)
- self.__menu.append(view_browser_checkbox)
+ menu.append(view_browser_checkbox)
self.checkbox = view_browser_checkbox
#separator (it's intended to be after show_all)
# separator should be shown only when having tasks
self.__task_separator = gtk.SeparatorMenuItem()
- self.__menu.append(self.__task_separator)
- self.__menu_top_length = len(self.__menu)
+ menu.append(self.__task_separator)
+ menu_top_length = len(menu)
- self.__menu.append(gtk.SeparatorMenuItem())
+ menu.append(gtk.SeparatorMenuItem())
#quit item
menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
menuItem.connect('activate', self.__view_manager.close_browser)
- self.__menu.append(menuItem)
+ menu.append(menuItem)
- self.__menu.show_all()
+ menu.show_all()
self.__task_separator.hide()
self.__tasks_menu = SortedLimitedMenu(self.MAX_ITEMS,
- self.__menu, self.__menu_top_length)
-
- # Update the icon theme
- icon_theme = os.path.join('notification_area', 'data', 'icons')
- abs_theme_path = os.path.join(PLUGIN_DIR[0], icon_theme)
- theme = gtk.icon_theme_get_default()
- theme.append_search_path(abs_theme_path)
-
- if self.__indicator:
- self.__indicator.set_icon_theme_path(abs_theme_path)
- self.__indicator.set_icon("gtg-panel")
- self.__indicator.set_attention_icon("gtg_need_attention")
- self.__indicator.set_menu(self.__menu)
- self.__indicator.set_status(appindicator.STATUS_ACTIVE)
- else:
- self.status_icon = gtk.StatusIcon()
- self.status_icon.set_from_icon_name("gtg-panel")
- 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)
+ menu, menu_top_length)
+
+ self._indicator.activate(self.__toggle_browser, menu)
def __init_attention(self):
# Use two different viewtree for attention and menu
@@ -290,7 +319,7 @@
if self.preferences['danger_zone'] > 0:
self.__attention = _Attention( \
self.preferences['danger_zone'],
- self.__indicator if self.__indicator else self.status_icon,
+ self._indicator,
self.__tree_att,
self.__requester)
else:
@@ -340,8 +369,7 @@
menu_item.connect('activate', self.__open_task, tid)
self.__tasks_menu.add(tid, (task.get_due_date(), title), menu_item)
- if self.__indicator:
- self.__indicator.set_menu(self.__menu)
+ self._indicator.update_menu()
def __on_task_deleted_att(self, tid, path):
# Update icon on deletion
@@ -362,10 +390,6 @@
short_title = short_title.strip() + "..."
return short_title
- 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 preferences_load(self):
=== renamed file 'GTG/plugins/notification_area/data/icons/hicolor/22x22/apps/gtg_need_attention.png' => 'data/icons/hicolor/22x22/apps/gtg_need_attention.png'
=== renamed directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-dark' => 'data/icons/ubuntu-mono-dark'
=== renamed directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-light' => 'data/icons/ubuntu-mono-light'