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 <[email protected]> * Song Yangyu <[email protected]> * Saurabh Anand <[email protected]> +<<<<<<< TREE * Alan Gomes <[email protected]> +======= +* Antonio Roquentin <[email protected]>>>>>>>> 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 <[email protected]>, Luca Invernizzi <[email protected]>, Jono Bacon <[email protected]>, Izidor Matušov <[email protected]>" +Authors="Paulo Cabido <[email protected]>, Luca Invernizzi <[email protected]>, Jono Bacon <[email protected]>, Izidor Matušov <[email protected]>, Antonio Roquentin <[email protected]>" 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>
_______________________________________________ Mailing list: https://launchpad.net/~gtg Post to : [email protected] Unsubscribe : https://launchpad.net/~gtg More help : https://help.launchpad.net/ListHelp

