gtg team mailing list archive
-
gtg team
-
Mailing list archive
-
Message #03541
[Merge] lp:~antonio-roquentin/gtg/notification_colored_icon into lp:gtg
Antonio Roquentin has proposed merging lp:~antonio-roquentin/gtg/notification_colored_icon into lp:gtg.
Requested reviews:
Gtg developers (gtg)
Related bugs:
Bug #1001012 in Getting Things GNOME!: "Notification area icon should change color when there are urgent tasks"
https://bugs.launchpad.net/gtg/+bug/1001012
For more details, see:
https://code.launchpad.net/~antonio-roquentin/gtg/notification_colored_icon/+merge/107491
Color the icon in the notification area when there are tasks in danger zone. Implementation of a feature described in bug #1001012. The modifications only affect the notification_area plugin. Setting a danger zone of 0 days in the preferences will reproduce the old behavior (icon is white all the time).
--
https://code.launchpad.net/~antonio-roquentin/gtg/notification_colored_icon/+merge/107491
Your team Gtg developers is requested to review the proposed merge of lp:~antonio-roquentin/gtg/notification_colored_icon into lp:gtg.
=== modified file 'AUTHORS'
--- AUTHORS 2012-05-25 16:57:38 +0000
+++ AUTHORS 2012-05-25 22:47:20 +0000
@@ -104,4 +104,7 @@
* Marta Maria Casetti <mmcasetti@xxxxxxxxx>
* Song Yangyu <flyfy1@xxxxxxxxx>
* Saurabh Anand <saurabhanandiit@xxxxxxxxx>
+<<<<<<< TREE
* Alan Gomes <alangalvino@xxxxxxxxx>
+=======
+* Antonio Roquentin <antonio.roqeuntin@xxxxxx>>>>>>>> MERGE-SOURCE
=== modified file 'GTG/plugins/notification-area.gtg-plugin'
--- GTG/plugins/notification-area.gtg-plugin 2012-03-05 15:23:05 +0000
+++ GTG/plugins/notification-area.gtg-plugin 2012-05-25 22:47:20 +0000
@@ -6,6 +6,6 @@
that keeps the list of the currently workable tasks.
To start GTG minimized, click on the 'Configure Plugin' button
at the bottom of this window."""
-Authors="Paulo Cabido <paulo.cabido@xxxxxxxxx>, Luca Invernizzi <invernizzi.l@xxxxxxxxx>, Jono Bacon <jono@xxxxxxxxxx>, Izidor Matušov <izidor.matusov@xxxxxxxxx>"
+Authors="Paulo Cabido <paulo.cabido@xxxxxxxxx>, Luca Invernizzi <invernizzi.l@xxxxxxxxx>, Jono Bacon <jono@xxxxxxxxxx>, Izidor Matušov <izidor.matusov@xxxxxxxxx>, Antonio Roquentin <antonio.roqeuntin@xxxxxx>"
Version=0.95
Enabled=False
=== added file 'GTG/plugins/notification_area/gtg-need-attention.svg'
--- GTG/plugins/notification_area/gtg-need-attention.svg 1970-01-01 00:00:00 +0000
+++ GTG/plugins/notification_area/gtg-need-attention.svg 2012-05-25 22:47:20 +0000
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg3212"
+ height="16"
+ width="16"
+ version="1.0"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="gtg-need-attention.svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="753"
+ inkscape:window-height="480"
+ id="namedview6"
+ showgrid="false"
+ inkscape:zoom="14.75"
+ inkscape:cx="8"
+ inkscape:cy="5.9661017"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg3212" />
+ <metadata
+ id="metadata13">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path
+ id="path3208"
+ d="m2 2c-1.108 0-2 0.892-2 2v10c0 1.108 0.892 2 2 2h12c1.108 0 2-0.892 2-2v-10c0-1.108-0.892-2-2-2h-12zm9.0312 2c0.05517 0.0053 0.13563 0.03589 0.1875 0.0625l1.5625 0.78125c0.2075 0.10644 0.26963 0.36771 0.15625 0.5625l-4.875 8.375c-0.0853 0.149-0.2671 0.239-0.436 0.219-0.0517-0.006-0.1076-0.006-0.1562-0.031-0.0052-0.003-4.2501-3.313-4.25-3.313-0.2075-0.106-0.2697-0.367-0.1563-0.562l1.0312-1.25c0.1134-0.195 0.3863-0.2629 0.5938-0.1565l2.3125 1.7505 3.625-6.2192c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
+ style="opacity:.3" />
+ <path
+ id="rect2386"
+ d="m2 1c-1.108 0-2 0.892-2 2v10c0 1.108 0.892 2 2 2h12c1.108 0 2-0.892 2-2v-10c0-1.108-0.892-2-2-2h-12zm9.0312 2c0.05517 0.0053 0.13563 0.03589 0.1875 0.0625l1.5625 0.78125c0.2075 0.10644 0.26963 0.36771 0.15625 0.5625l-4.875 8.375c-0.0853 0.149-0.2671 0.239-0.436 0.219-0.0517-0.006-0.1076-0.006-0.1562-0.031-0.0052-0.003-4.2501-3.3128-4.25-3.3128-0.2075-0.1064-0.2697-0.3677-0.1563-0.5624l1.0312-1.25c0.1134-0.1948 0.3863-0.2627 0.5938-0.1563l2.3125 1.75 3.625-6.2187c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
+ style="fill:#1cbbed;fill-opacity:1" />
+</svg>
=== modified file 'GTG/plugins/notification_area/notification_area.py'
--- GTG/plugins/notification_area/notification_area.py 2012-04-22 17:05:12 +0000
+++ GTG/plugins/notification_area/notification_area.py 2012-05-25 22:47:20 +0000
@@ -25,7 +25,76 @@
from GTG import _
from GTG.tools.borg import Borg
-
+from GTG.tools.dates import Date
+
+# Determine how many days are left to do a task, 1 means due today.
+def _due_within(task, danger_zone):
+ ddate = task.get_due_date()
+ if (ddate != Date.no_date()):
+ if ddate.days_left() < danger_zone:
+ return True
+ return False
+
+class _Attention:
+
+ """
+ Define need attention state depending on whether there
+ are tasks in danger zone.
+
+ There are two levels of attention:
+ 0 = "relax": there are no tasks in danger zone
+ 1 = "attention": there is at least one task in danger zone
+
+ A task is in danger zone if the number of days left is less
+ than time span (in days) defined by danger_zone.
+ """
+
+ ICONS = {'relax' : 'gtg',
+ 'attention' : 'gtg-need-attention'}
+
+ def __init__(self, tree, req, danger_zone=1):
+ self.__tree = tree
+ self.__req = req
+ self.danger_zone = danger_zone
+ # Maintain a list of tasks in danger zone, use task id
+ self.tasks_danger = []
+ for tid in self.__tree.get_all_nodes():
+ task = self.__req.get_task(tid)
+ if _due_within(task, self.danger_zone):
+ self.tasks_danger.append(tid)
+
+ def level(self):
+ return 0 if len(self.tasks_danger)==0 else 1
+
+ def __update_indicator(self, indicator, old_level, new_level):
+ if old_level == 1 and new_level == 0:
+ indicator.set_icon(self.ICONS['relax'])
+ elif old_level == 0 and new_level == 1:
+ indicator.set_icon(self.ICONS['attention'])
+
+ def update_on_task_modified(self, tid, indicator):
+ # 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):
+ self.tasks_danger.remove(tid)
+ else:
+ if _due_within(task, self.danger_zone):
+ self.tasks_danger.append(tid)
+
+ # Update icon only if attention level has changed
+ self.__update_indicator(indicator, old_lev, self.level())
+
+ def update_on_task_deleted(self, tid, indicator):
+ # 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(indicator, old_lev, self.level())
class NotificationArea:
"""
@@ -33,7 +102,8 @@
to quickly access tasks.
"""
- DEFAULT_PREFERENCES = {"start_minimized": False}
+ DEFAULT_PREFERENCES = {"start_minimized": False,
+ "danger_zone" : 1}
PLUGIN_NAME = "notification_area"
MAX_TITLE_LEN = 30
MAX_ITEMS = 10
@@ -76,12 +146,26 @@
# them given the task id. Contains tuple of this format:
# (title, key, gtk.MenuItem)
self.__init_gtk()
- self.__connect_to_tree()
- #Load the preferences
+ # We load preferences before connecting to tree
self.preference_dialog_init()
self.preferences_load()
+ # Enable attention monitor.
+ # Request a new view so we do not influence anybody.
+ self.__tree_att = self.__requester.get_tasks_tree()
+ self.__tree_att = \
+ self.__tree_att.get_basetree().get_viewtree(refresh=False)
+ # Convention: if danger zone is <=0, disable attention
+ if self.preferences['danger_zone'] > 0:
+ self.__attention = _Attention(self.__tree_att,
+ self.__requester,
+ self.preferences['danger_zone'])
+ else:
+ self.__attention = None
+
+ self.__connect_to_tree()
+
# When no windows (browser or text editors) are shown, it tries to quit
# With hidden browser and closing the only single text editor,
# GTG would quit no matter what
@@ -195,6 +279,10 @@
self.__tree.apply_filter('workview')
def __on_task_added(self, tid, path):
+ # Update icon on modification
+ if self.__attention and self.__indicator:
+ self.__attention.update_on_task_modified(tid, self.__indicator)
+
self.__task_separator.show()
task = self.__requester.get_task(tid)
if task is None:
@@ -212,6 +300,10 @@
self.__indicator.set_menu(self.__menu)
def __on_task_deleted(self, tid, path):
+ # Update icon on deletion
+ if self.__attention and self.__indicator:
+ self.__attention.update_on_task_deleted(tid, self.__indicator)
+
self.__tasks_menu.remove(tid)
if self.__tasks_menu.empty():
self.__task_separator.hide()
@@ -234,10 +326,11 @@
def preferences_load(self):
data = self.__plugin_api.load_configuration_object(self.PLUGIN_NAME,
"preferences")
- if not data or not isinstance(data, dict):
- self.preferences = self.DEFAULT_PREFERENCES
- else:
- self.preferences = data
+ # We first load the preferences then update the dict
+ # This way new default options are recognized with old cfg files
+ self.preferences = self.DEFAULT_PREFERENCES
+ if isinstance(data, dict):
+ self.preferences.update(data)
def preferences_store(self):
self.__plugin_api.save_configuration_object(self.PLUGIN_NAME,
@@ -255,6 +348,8 @@
"notification_area.ui"))
self.preferences_dialog = self.builder.get_object("preferences_dialog")
self.chbox_minimized = self.builder.get_object("pref_chbox_minimized")
+ self.spinbutton_dangerzone = \
+ self.builder.get_object("pref_spinbutton_dangerzone")
SIGNAL_CONNECTIONS_DIC = {
"on_preferences_dialog_delete_event":
self.on_preferences_cancel,
@@ -267,6 +362,7 @@
def configure_dialog(self, manager_dialog):
self.chbox_minimized.set_active(self.preferences["start_minimized"])
+ self.spinbutton_dangerzone.set_value(self.preferences["danger_zone"])
self.preferences_dialog.show_all()
self.preferences_dialog.set_transient_for(manager_dialog)
@@ -276,6 +372,7 @@
def on_preferences_ok(self, widget = None, data = None):
self.preferences["start_minimized"] = self.chbox_minimized.get_active()
+ self.preferences["danger_zone"] = self.spinbutton_dangerzone.get_value()
self.preferences_store()
self.preferences_dialog.hide()
=== modified file 'GTG/plugins/notification_area/notification_area.ui'
--- GTG/plugins/notification_area/notification_area.ui 2012-03-05 15:23:05 +0000
+++ GTG/plugins/notification_area/notification_area.ui 2012-05-25 22:47:20 +0000
@@ -1,53 +1,113 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkAccelGroup" id="accelgroup1"/>
+ <object class="GtkAdjustment" id="adjustment_dangerzone">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
<object class="GtkWindow" id="preferences_dialog">
+ <property name="can_focus">False</property>
<property name="border_width">10</property>
<property name="window_position">center-on-parent</property>
<property name="type_hint">dialog</property>
- <signal name="delete_event" handler="on_preferences_dialog_delete_event"/>
+ <signal name="delete-event" handler="on_preferences_dialog_delete_event" swapped="no"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="ypad">7</property>
<property name="label" translatable="yes">Personalize your notification area plugin</property>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<object class="GtkCheckButton" id="pref_chbox_minimized">
<property name="label" translatable="yes">Start gtg minimized</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
<property name="image_position">top</property>
<property name="draw_indicator">True</property>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="pref_spinbutton_dangerzone">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="width_chars">2</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ <property name="adjustment">adjustment_dangerzone</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_text" translatable="yes">The icon in the notification area is colored if there are tasks in the danger zone.
+A danger zone of 0 disables icon coloring.</property>
+ <property name="label" translatable="yes"> Danger zone (in days) </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkHBox" id="hbox1">
<property name="height_request">30</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="spacing">50</property>
<child>
<object class="GtkButton" id="btn_preferences_cancel">
@@ -55,10 +115,13 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
- <signal name="clicked" handler="on_btn_preferences_cancel_clicked"/>
+ <signal name="clicked" handler="on_btn_preferences_cancel_clicked" swapped="no"/>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
@@ -68,16 +131,21 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
- <signal name="clicked" handler="on_btn_preferences_ok_clicked"/>
+ <signal name="clicked" handler="on_btn_preferences_ok_clicked" swapped="no"/>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
- <property name="position">2</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
</packing>
</child>
</object>