GTG

Merge lp:~antonio-roquentin-deactivatedaccount/gtg/notification_colored_icon into lp:~gtg/gtg/old-trunk

Proposed by Roquentin
Status: Merged
Merged at revision: 1210
Proposed branch: lp:~antonio-roquentin-deactivatedaccount/gtg/notification_colored_icon
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: 607 lines (+367/-27)
5 files modified
GTG/plugins/notification-area.gtg-plugin (+1/-1)
GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22/apps/gtg_need_attention.svg (+60/-0)
GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22/apps/gtg_need_attention.svg (+60/-0)
GTG/plugins/notification_area/notification_area.py (+167/-19)
GTG/plugins/notification_area/notification_area.ui (+79/-7)
To merge this branch: bzr merge lp:~antonio-roquentin-deactivatedaccount/gtg/notification_colored_icon
Reviewer Review Type Date Requested Status
Bertrand Rousseau (community) Approve
Lionel Dricot (community) Needs Fixing
Review via email: mp+107491@code.launchpad.net

Description of the change

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).

To post a comment you must log in.
1198. By Roquentin

Use two independents views for attention and menu; this way we are able to set different filters. Use generic __connect_to_tree method

1199. By Roquentin

refactor Attention interface, store reference to indicator; use different callbacks for attention and menu trees.

Revision history for this message
Lionel Dricot (ploum-deactivatedaccount) wrote :

1. I enabled the tray plugin and, instead of having an icon, I had only an empty space.

2. I've set a task due for today and it raised the following:

"(gtg:4177): LIBDBUSMENU-GLIB-WARNING **: Trying to remove a child that doesn't believe we're it's parent."

review: Needs Fixing
Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

> 1. I enabled the tray plugin and, instead of having an icon, I had only an
> empty space.

It works for me on ubuntu 12.04. Which distribution are you using? In order to get the colored icon, you need to update the gtk icon theme. Temporarily I have added the colored icon to the plugin directory, its name is gtg-need-attention.svg. In my case, I copied it as

/usr/share/icons/ubuntu-mono-dark/apps/16/gtg-need-attention.svg

and then did sudo gtk-update-icon-cache. The actual path depends on the theme in use. Once things are working, I will update setup.py. Also I don't have an icon for the hicolor theme yet, sorry.

> 2. I've set a task due for today and it raised the following:
>
> "(gtg:4177): LIBDBUSMENU-GLIB-WARNING **: Trying to remove a child that
> doesn't believe we're it's parent."

This seems a bug of the plugin in trunk, it existed before my modifications. We should open a separate bug report for that.

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

Sorry, of course the correct command to update the icon cache is (for ambiance)

sudo gtk-update-icon-cache /usr/share/icons/ubuntu-mono-dark

I am hope it fixes the problem with the empty space.

1200. By Roquentin

If gtg-need-attention icon is not found in theme, disable attention monitor, thus avoiding having a blank space in the panel.

1201. By Roquentin

Comply with PEP8

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

I have filed bug #1009689 to track the problem with the warnings.

1202. By Roquentin

Added refresh method; refresh attention monitor when changing the danger zone in the preferences.

1203. By Roquentin

Added __init_attention method to setup attention monitor; it is called also when danger zone turns from 0 to 1 upon changing it in the preferences.

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

I implemented a dynamic refresh of the tasks in the danger zone when changing the value of the latter in the preferences. This way one doesn't need to restart gtg to get the new danger zone to work.

In a previous revision, I changed the code so that it prints a warning if gtg-need-attention is not in the icon theme and disables the attention monitor. Lionel: could you check if it is working now?

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

Sorry, could anyone have a look at the current version of this branch? I have fixed a few things since the last revision by Lionel.

Please also let me know what I should do to properly update the gtk theme.

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

Hi,

I activated your plugin, left the default settings (1-day danger zone), and defined a task as due for tomorrow. The icon color did not change. Now, I'm not familiar with this feature, so this could be caused by something else.

Also, as I can understand, your patch require to manually register a new icon. This isn't right. You have to create a custom icon them in the plugin directory and append this theme dynamically to GTG. For help, look at https://bazaar.launchpad.net/~gtg/gtg/trunk/view/head:/GTG/gtk/browser/browser.py#L142 and at the directory structure under the data/ directory in the trunk. I also recommend you search for documentation on the web. This is not really difficult, so don't panic ;-)

review: Needs Fixing (run)
1204. By Roquentin

Set icon_theme_path of indicator so that it can find custom icons, seems to work. Prepend data path to GTK theme search path, it finds the icon but the indicator does not load it.

1205. By Roquentin

Icon theme path

1206. By Roquentin

Refactored attention methods; update indicator status instead of icon.

1207. By Roquentin

Attempt to fix status icon

1208. By Roquentin

Dropped previous attempt.

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

Thank you for the pointers, Bertrand. I got it to work with the application indicator (the icon is now loaded at runtime) and also cleaned up the code a bit. I hope it's ok now.

I still have troubles with the status icon, in that I don't get any icon in the system tray when I disable appindicator (same problem in trunk) and I am afraid this has to do with something in unity. So for the moment this feature is disabled when the application indicator is not available (i.e. the icon won't change).

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

Hi,

I tried again your code, and still couldn't see any change with the icon. Now, I'm using GNOME 3.4 and I don't know what API you're using, and if it's even supposed to work. So maybe another developer with another setup can test this particular feature here.

I have some remarks for your code:

- first, you left some text merge conflict-related strings in AUTHORS, those must be removed
- in notification_area.py, you left useless commented code on line 205-207
- I would advise you to put some padding in the plugin configuration window, right now the widgets are really tightly packed.

review: Needs Fixing (code, run)
1209. By Roquentin

Fixed email address in plugin authors; removed myself from AUTHORS; deleted commented lines

1210. By Roquentin

Added some padding between widgets in plugin preferences nemu

1211. By Roquentin

If there is no indicator, Attention is passed a status icon and __update_indicator() updates the status icon instead. Thus it should work even outside ubuntu now.

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

> I tried again your code, and still couldn't see any change with the icon. Now,
> I'm using GNOME 3.4 and I don't know what API you're using, and if it's even
> supposed to work.

It should work now also when the appindicator module (ubuntu) is not available. In this case the plugin simply changes the status icon in the notification area. However, I could not get any icon to display anywhere in GNOME Shell, not even with the plugin version in trunk :-(

> - first, you left some text merge conflict-related strings in AUTHORS, those
> must be removed
> - in notification_area.py, you left useless commented code on line 205-207
> - I would advise you to put some padding in the plugin configuration window,
> right now the widgets are really tightly packed.

I fixed these issues, thank you. The preferences menu will be improved soon anyway (bug #945553).

1212. By Roquentin

Updated custom icon themes. Icon in hicolor now fits with the hicolor theme, it has a yellow background. Added custom icons for ambiance and radiance themes.

1213. By Roquentin

Actually it is a 22x22 icon

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

I got the colored status icon to appear also in GNOME Shell in the system tray (bottom right corner).

So far I successfully tested the plugin using the following setups in ubuntu 12.04:

* Unity using the appindicator with both ambiance and adwaita themes

* GNOME Shell disabling the appindicator and with the adwaita theme. This should be a typical setup for distros not based on ubuntu.

When using GNOME Shell with the appindicator (default in ubuntu) it seems like the "gtg" icon is not found and nothing except "Getting Things GNOME" is displayed in the system tray. However, the colored icon is displayed when there are tasks in danger zone. This problem could be fixed for instance by adding the "gtg" icon to the plugin icons directory or using "gtg-panel" instead. I believe this problem is not related to my branch - it's there in trunk too.

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

I approve the code, and it works in my computer (ubuntu 12.04/GNOME 3.4.3) as you describe. It would be great however if you could fix the issue with icon not appearing when not colored as well since you seem to see how to fix it. You can always load GTG icon theme and reuse the gtg icon, it should not be necessary to copy the icon in the plugin directory. Could you do that?

review: Needs Fixing
1214. By Roquentin

Use gtg-panel icon instead of gtg. This fixes the problem of gtg not finding the gtg icon in ubuntu 12.04/gnome 3.4 with adwaita theme

Revision history for this message
Roquentin (antonio-roquentin-deactivatedaccount) wrote :

Using the gtg-panel icon fixed the problem with GS under ubuntu. Tested in all other setups I have.

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

Ok. Approved!

review: Approve
Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

And, btw, thanks a lot for your effort!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'GTG/plugins/notification-area.gtg-plugin'
2--- GTG/plugins/notification-area.gtg-plugin 2012-05-23 08:55:31 +0000
3+++ GTG/plugins/notification-area.gtg-plugin 2012-07-17 18:04:22 +0000
4@@ -6,6 +6,6 @@
5 that keeps the list of the currently workable tasks.
6 To start GTG minimized, click on the 'Configure Plugin' button
7 at the bottom of this window."""
8-Authors="Paulo Cabido <paulo.cabido@gmail.com>, Luca Invernizzi <invernizzi.l@gmail.com>, Jono Bacon <jono@ubuntu.com>, Izidor Matušov <izidor.matusov@gmail.com>"
9+Authors="Paulo Cabido <paulo.cabido@gmail.com>, Luca Invernizzi <invernizzi.l@gmail.com>, Jono Bacon <jono@ubuntu.com>, Izidor Matušov <izidor.matusov@gmail.com>, Antonio Roquentin <antonio.roquentin@sfr.fr>"
10 Version=0.95
11 Enabled=False
12
13=== added directory 'GTG/plugins/notification_area/data'
14=== added directory 'GTG/plugins/notification_area/data/icons'
15=== added directory 'GTG/plugins/notification_area/data/icons/hicolor'
16=== added directory 'GTG/plugins/notification_area/data/icons/hicolor/22x22'
17=== added directory 'GTG/plugins/notification_area/data/icons/hicolor/22x22/apps'
18=== added file 'GTG/plugins/notification_area/data/icons/hicolor/22x22/apps/gtg_need_attention.png'
19Binary files GTG/plugins/notification_area/data/icons/hicolor/22x22/apps/gtg_need_attention.png 1970-01-01 00:00:00 +0000 and GTG/plugins/notification_area/data/icons/hicolor/22x22/apps/gtg_need_attention.png 2012-07-17 18:04:22 +0000 differ
20=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-dark'
21=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22'
22=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22/apps'
23=== added file 'GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22/apps/gtg_need_attention.svg'
24--- GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22/apps/gtg_need_attention.svg 1970-01-01 00:00:00 +0000
25+++ GTG/plugins/notification_area/data/icons/ubuntu-mono-dark/22x22/apps/gtg_need_attention.svg 2012-07-17 18:04:22 +0000
26@@ -0,0 +1,60 @@
27+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
28+<!-- Created with Inkscape (http://www.inkscape.org/) -->
29+
30+<svg
31+ xmlns:dc="http://purl.org/dc/elements/1.1/"
32+ xmlns:cc="http://creativecommons.org/ns#"
33+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
34+ xmlns:svg="http://www.w3.org/2000/svg"
35+ xmlns="http://www.w3.org/2000/svg"
36+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
37+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
38+ id="svg3212"
39+ height="22"
40+ width="22"
41+ version="1.0"
42+ inkscape:version="0.48.3.1 r9886"
43+ sodipodi:docname="gtg-panel.svg">
44+ <defs
45+ id="defs8" />
46+ <sodipodi:namedview
47+ pagecolor="#ffffff"
48+ bordercolor="#666666"
49+ borderopacity="1"
50+ objecttolerance="10"
51+ gridtolerance="10"
52+ guidetolerance="10"
53+ inkscape:pageopacity="0"
54+ inkscape:pageshadow="2"
55+ inkscape:window-width="762"
56+ inkscape:window-height="480"
57+ id="namedview6"
58+ showgrid="false"
59+ inkscape:zoom="10.727273"
60+ inkscape:cx="27.173729"
61+ inkscape:cy="11"
62+ inkscape:window-x="0"
63+ inkscape:window-y="24"
64+ inkscape:window-maximized="0"
65+ inkscape:current-layer="svg3212" />
66+ <metadata
67+ id="metadata13">
68+ <rdf:RDF>
69+ <cc:Work
70+ rdf:about="">
71+ <dc:format>image/svg+xml</dc:format>
72+ <dc:type
73+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
74+ <dc:title></dc:title>
75+ </cc:Work>
76+ </rdf:RDF>
77+ </metadata>
78+ <path
79+ id="path3208"
80+ d="m5 5c-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.00526 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.085 0.149-0.267 0.239-0.436 0.219-0.0517-0.0061-0.10762-0.0063-0.15625-0.03125-0.0052-0.0024-4.25-3.3125-4.25-3.3125-0.2075-0.106-0.2697-0.367-0.1563-0.562l1.0312-1.25c0.1134-0.195 0.3863-0.263 0.5938-0.156l2.3125 1.75 3.625-6.2192c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
81+ style="opacity:.3" />
82+ <path
83+ id="rect2386"
84+ d="m5 4c-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.00526 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.085 0.149-0.267 0.239-0.436 0.219-0.0517-0.0061-0.10762-0.0063-0.15625-0.03125-0.0052-0.0024-4.25-3.3125-4.25-3.3125-0.2075-0.106-0.2697-0.367-0.1563-0.562l1.0312-1.25c0.1134-0.195 0.3863-0.263 0.5938-0.156l2.3125 1.75 3.625-6.2192c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
85+ style="fill:#1cbbed;fill-opacity:1" />
86+</svg>
87
88=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-light'
89=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22'
90=== added directory 'GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22/apps'
91=== added file 'GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22/apps/gtg_need_attention.svg'
92--- GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22/apps/gtg_need_attention.svg 1970-01-01 00:00:00 +0000
93+++ GTG/plugins/notification_area/data/icons/ubuntu-mono-light/22x22/apps/gtg_need_attention.svg 2012-07-17 18:04:22 +0000
94@@ -0,0 +1,60 @@
95+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
96+<!-- Created with Inkscape (http://www.inkscape.org/) -->
97+
98+<svg
99+ xmlns:dc="http://purl.org/dc/elements/1.1/"
100+ xmlns:cc="http://creativecommons.org/ns#"
101+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
102+ xmlns:svg="http://www.w3.org/2000/svg"
103+ xmlns="http://www.w3.org/2000/svg"
104+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
105+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
106+ id="svg3212"
107+ height="22"
108+ width="22"
109+ version="1.0"
110+ inkscape:version="0.48.3.1 r9886"
111+ sodipodi:docname="gtg-panel.svg">
112+ <defs
113+ id="defs8" />
114+ <sodipodi:namedview
115+ pagecolor="#ffffff"
116+ bordercolor="#666666"
117+ borderopacity="1"
118+ objecttolerance="10"
119+ gridtolerance="10"
120+ guidetolerance="10"
121+ inkscape:pageopacity="0"
122+ inkscape:pageshadow="2"
123+ inkscape:window-width="762"
124+ inkscape:window-height="480"
125+ id="namedview6"
126+ showgrid="false"
127+ inkscape:zoom="10.727273"
128+ inkscape:cx="27.173729"
129+ inkscape:cy="11"
130+ inkscape:window-x="0"
131+ inkscape:window-y="24"
132+ inkscape:window-maximized="0"
133+ inkscape:current-layer="svg3212" />
134+ <metadata
135+ id="metadata13">
136+ <rdf:RDF>
137+ <cc:Work
138+ rdf:about="">
139+ <dc:format>image/svg+xml</dc:format>
140+ <dc:type
141+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
142+ <dc:title></dc:title>
143+ </cc:Work>
144+ </rdf:RDF>
145+ </metadata>
146+ <path
147+ id="path3208"
148+ d="m5 5c-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.00526 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.085 0.149-0.267 0.239-0.436 0.219-0.0517-0.0061-0.10762-0.0063-0.15625-0.03125-0.0052-0.0024-4.25-3.3125-4.25-3.3125-0.2075-0.106-0.2697-0.367-0.1563-0.562l1.0312-1.25c0.1134-0.195 0.3863-0.263 0.5938-0.156l2.3125 1.75 3.625-6.2192c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
149+ style="opacity:.3" />
150+ <path
151+ id="rect2386"
152+ d="m5 4c-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.00526 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.085 0.149-0.267 0.239-0.436 0.219-0.0517-0.0061-0.10762-0.0063-0.15625-0.03125-0.0052-0.0024-4.25-3.3125-4.25-3.3125-0.2075-0.106-0.2697-0.367-0.1563-0.562l1.0312-1.25c0.1134-0.195 0.3863-0.263 0.5938-0.156l2.3125 1.75 3.625-6.2192c0.085-0.1461 0.241-0.2346 0.406-0.2188z"
153+ style="fill:#1cbbed;fill-opacity:1" />
154+</svg>
155
156=== modified file 'GTG/plugins/notification_area/notification_area.py'
157--- GTG/plugins/notification_area/notification_area.py 2012-05-23 08:55:31 +0000
158+++ GTG/plugins/notification_area/notification_area.py 2012-07-17 18:04:22 +0000
159@@ -24,7 +24,99 @@
160 pass
161
162 from GTG import _
163+from GTG import PLUGIN_DIR
164 from GTG.tools.borg import Borg
165+from GTG.tools.dates import Date
166+
167+
168+def _due_within(task, danger_zone):
169+ """
170+ Determine if a task is the danger zone.
171+ Convention: a danger zone of 1 day includes tasks due today.
172+ """
173+ ddate = task.get_due_date()
174+ if (ddate != Date.no_date()):
175+ if ddate.days_left() < danger_zone:
176+ return True
177+ return False
178+
179+
180+class _Attention:
181+
182+ """
183+ Define need attention state depending on whether there
184+ are tasks in danger zone.
185+
186+ There are two levels of attention:
187+ "normal": there are no tasks in danger zone
188+ "high": there is at least one task in danger zone
189+
190+ A task is in danger zone if the number of days left is less
191+ than time span (in days) defined by danger_zone.
192+ """
193+
194+ STATUS = {'normal': appindicator.STATUS_ACTIVE,
195+ 'high': appindicator.STATUS_ATTENTION}
196+
197+ ICON = {'normal': 'gtg-panel',
198+ 'high': 'gtg_need_attention'}
199+
200+ def __init__(self, danger_zone, indicator, tree, req):
201+ self.__tree = tree
202+ self.__req = req
203+ self.__indicator = indicator
204+ self.danger_zone = danger_zone
205+
206+ # Setup list of tasks in danger zone
207+ """ Setup a list of tasks in danger zone, use task id """
208+ self.tasks_danger = []
209+ for tid in self.__tree.get_all_nodes():
210+ task = self.__req.get_task(tid)
211+ if _due_within(task, self.danger_zone):
212+ self.tasks_danger.append(tid)
213+
214+ # Set initial status
215+ self.__update_indicator(self.level())
216+
217+ def level(self):
218+ """ Two states only: attention is either needed or not """
219+ return 'high' if len(self.tasks_danger)>0 else 'normal'
220+
221+ def __update_indicator(self, new, old=None):
222+ """ Reset indicator status or update upon change in status """
223+ if old is None or not old == new:
224+ try:
225+ # This works if __indicator implements the appindicator api
226+ self.__indicator.set_status(self.STATUS[new])
227+ except AttributeError:
228+ # If we passed a status icon instead try this
229+ self.__indicator.set_from_icon_name(self.ICON[new])
230+ except:
231+ raise
232+
233+ def update_on_task_modified(self, tid):
234+ # Store current attention level
235+ old_lev = self.level()
236+ task = self.__req.get_task(tid)
237+ if tid in self.tasks_danger:
238+ if not _due_within(task, self.danger_zone):
239+ self.tasks_danger.remove(tid)
240+ else:
241+ if _due_within(task, self.danger_zone):
242+ self.tasks_danger.append(tid)
243+
244+ # Update icon only if attention level has changed
245+ self.__update_indicator(self.level(), old_lev)
246+
247+ def update_on_task_deleted(self, tid):
248+ # Store current attention level
249+ old_lev = self.level()
250+
251+ if tid in self.tasks_danger:
252+ self.tasks_danger.remove(tid)
253+
254+ # Update icon only if attention level has changed
255+ self.__update_indicator(self.level(), old_lev)
256
257
258 class NotificationArea:
259@@ -33,7 +125,8 @@
260 to quickly access tasks.
261 """
262
263- DEFAULT_PREFERENCES = {"start_minimized": False}
264+ DEFAULT_PREFERENCES = {"start_minimized": False,
265+ "danger_zone": 1}
266 PLUGIN_NAME = "notification_area"
267 MAX_TITLE_LEN = 30
268 MAX_ITEMS = 10
269@@ -55,7 +148,6 @@
270 "gtg",
271 "indicator-messages",
272 appindicator.CATEGORY_APPLICATION_STATUS)
273- self._indicator.set_icon("gtg")
274 except:
275 self._indicator = None
276
277@@ -76,12 +168,28 @@
278 # them given the task id. Contains tuple of this format:
279 # (title, key, gtk.MenuItem)
280 self.__init_gtk()
281- self.__connect_to_tree()
282
283- #Load the preferences
284+ # We load preferences before connecting to tree
285 self.preference_dialog_init()
286 self.preferences_load()
287
288+ # Enable attention monitor.
289+ self.__attention = None
290+ self.__tree_att = self.__connect_to_tree([
291+ ("node-added-inview", self.__on_task_added_att),
292+ ("node-modified-inview", self.__on_task_added_att),
293+ ("node-deleted-inview", self.__on_task_deleted_att),
294+ ])
295+ self.__tree_att.apply_filter('workview')
296+ self.__init_attention()
297+
298+ self.__tree = self.__connect_to_tree([
299+ ("node-added-inview", self.__on_task_added),
300+ ("node-modified-inview", self.__on_task_added),
301+ ("node-deleted-inview", self.__on_task_deleted),
302+ ])
303+ self.__tree.apply_filter('workview')
304+
305 # When no windows (browser or text editors) are shown, it tries to quit
306 # With hidden browser and closing the only single text editor,
307 # GTG would quit no matter what
308@@ -153,18 +261,41 @@
309 self.__tasks_menu = SortedLimitedMenu(self.MAX_ITEMS,
310 self.__menu, self.__menu_top_length)
311
312+ # Update the icon theme
313+ icon_theme = os.path.join('notification_area', 'data', 'icons')
314+ abs_theme_path = os.path.join(PLUGIN_DIR[0], icon_theme)
315+ theme = gtk.icon_theme_get_default()
316+ theme.append_search_path(abs_theme_path)
317+
318 if self.__indicator:
319+ self.__indicator.set_icon_theme_path(abs_theme_path)
320+ self.__indicator.set_icon("gtg-panel")
321+ self.__indicator.set_attention_icon("gtg_need_attention")
322 self.__indicator.set_menu(self.__menu)
323 self.__indicator.set_status(appindicator.STATUS_ACTIVE)
324 else:
325 self.status_icon = gtk.StatusIcon()
326- self.status_icon.set_from_icon_name("gtg")
327+ self.status_icon.set_from_icon_name("gtg-panel")
328 self.status_icon.set_tooltip("Getting Things Gnome!")
329 self.status_icon.set_visible(True)
330 self.status_icon.connect('activate', self.__toggle_browser)
331 self.status_icon.connect('popup-menu',
332 self.__on_icon_popup, self.__menu)
333
334+ def __init_attention(self):
335+ # Use two different viewtree for attention and menu
336+ # This way we can filter them independently.
337+ # Convention: if danger zone is <=0, disable attention
338+ # Fallback: if there is no indicator we pass the status icon instead
339+ if self.preferences['danger_zone'] > 0:
340+ self.__attention = _Attention( \
341+ self.preferences['danger_zone'],
342+ self.__indicator if self.__indicator else self.status_icon,
343+ self.__tree_att,
344+ self.__requester)
345+ else:
346+ self.__attention = None
347+
348 def __open_task(self, widget, task_id = None):
349 """
350 Opens a task in the TaskEditor, if it's not currently opened.
351@@ -178,21 +309,22 @@
352
353 self.__view_manager.open_task(task_id, thisisnew=new_task)
354
355- def __connect_to_tree(self):
356- self.__tree = self.__requester.get_tasks_tree()
357+ def __connect_to_tree(self, signal_cllbck):
358+ """ Return a new view tree """
359+ tree = self.__requester.get_tasks_tree()
360 # Request a new view so we do not influence anybody
361- self.__tree = self.__tree.get_basetree().get_viewtree(refresh=False)
362+ tree = tree.get_basetree().get_viewtree(refresh=False)
363
364 self.__liblarch_callbacks = []
365- for signal, cllbck in [
366- ("node-added-inview", self.__on_task_added),
367- ("node-modified-inview", self.__on_task_added),
368- ("node-deleted-inview", self.__on_task_deleted),
369- ]:
370- cb_id = self.__tree.register_cllbck(signal, cllbck)
371+ for signal, cllbck in signal_cllbck:
372+ cb_id = tree.register_cllbck(signal, cllbck)
373 self.__liblarch_callbacks.append((cb_id, signal))
374+ return tree
375
376- self.__tree.apply_filter('workview')
377+ def __on_task_added_att(self, tid, path):
378+ # Update icon on modification
379+ if self.__attention:
380+ self.__attention.update_on_task_modified(tid)
381
382 def __on_task_added(self, tid, path):
383 self.__task_separator.show()
384@@ -211,6 +343,11 @@
385 if self.__indicator:
386 self.__indicator.set_menu(self.__menu)
387
388+ def __on_task_deleted_att(self, tid, path):
389+ # Update icon on deletion
390+ if self.__attention:
391+ self.__attention.update_on_task_deleted(tid)
392+
393 def __on_task_deleted(self, tid, path):
394 self.__tasks_menu.remove(tid)
395 if self.__tasks_menu.empty():
396@@ -234,10 +371,11 @@
397 def preferences_load(self):
398 data = self.__plugin_api.load_configuration_object(self.PLUGIN_NAME,
399 "preferences")
400- if not data or not isinstance(data, dict):
401- self.preferences = self.DEFAULT_PREFERENCES
402- else:
403- self.preferences = data
404+ # We first load the preferences then update the dict
405+ # This way new default options are recognized with old cfg files
406+ self.preferences = self.DEFAULT_PREFERENCES
407+ if isinstance(data, dict):
408+ self.preferences.update(data)
409
410 def preferences_store(self):
411 self.__plugin_api.save_configuration_object(self.PLUGIN_NAME,
412@@ -255,6 +393,8 @@
413 "notification_area.ui"))
414 self.preferences_dialog = self.builder.get_object("preferences_dialog")
415 self.chbox_minimized = self.builder.get_object("pref_chbox_minimized")
416+ self.spinbutton_dangerzone = \
417+ self.builder.get_object("pref_spinbutton_dangerzone")
418 SIGNAL_CONNECTIONS_DIC = {
419 "on_preferences_dialog_delete_event":
420 self.on_preferences_cancel,
421@@ -267,6 +407,7 @@
422
423 def configure_dialog(self, manager_dialog):
424 self.chbox_minimized.set_active(self.preferences["start_minimized"])
425+ self.spinbutton_dangerzone.set_value(self.preferences["danger_zone"])
426 self.preferences_dialog.show_all()
427 self.preferences_dialog.set_transient_for(manager_dialog)
428
429@@ -275,6 +416,13 @@
430 return True
431
432 def on_preferences_ok(self, widget = None, data = None):
433+ dzone = self.spinbutton_dangerzone.get_value()
434+ # update danger zone only if it has changed
435+ # and refresh attention monitor
436+ if not dzone == self.preferences["danger_zone"]:
437+ self.preferences["danger_zone"] = dzone
438+ self.__init_attention()
439+
440 self.preferences["start_minimized"] = self.chbox_minimized.get_active()
441 self.preferences_store()
442 self.preferences_dialog.hide()
443
444=== modified file 'GTG/plugins/notification_area/notification_area.ui'
445--- GTG/plugins/notification_area/notification_area.ui 2012-05-23 08:55:31 +0000
446+++ GTG/plugins/notification_area/notification_area.ui 2012-07-17 18:04:22 +0000
447@@ -1,53 +1,116 @@
448-<?xml version="1.0"?>
449+<?xml version="1.0" encoding="UTF-8"?>
450 <interface>
451 <requires lib="gtk+" version="2.16"/>
452 <!-- interface-naming-policy toplevel-contextual -->
453 <object class="GtkAccelGroup" id="accelgroup1"/>
454+ <object class="GtkAdjustment" id="adjustment_dangerzone">
455+ <property name="upper">100</property>
456+ <property name="step_increment">1</property>
457+ <property name="page_increment">10</property>
458+ </object>
459 <object class="GtkWindow" id="preferences_dialog">
460+ <property name="can_focus">False</property>
461 <property name="border_width">10</property>
462 <property name="window_position">center-on-parent</property>
463 <property name="type_hint">dialog</property>
464- <signal name="delete_event" handler="on_preferences_dialog_delete_event"/>
465+ <signal name="delete-event" handler="on_preferences_dialog_delete_event" swapped="no"/>
466 <child>
467 <object class="GtkVBox" id="vbox1">
468 <property name="visible">True</property>
469- <property name="orientation">vertical</property>
470+ <property name="can_focus">False</property>
471 <child>
472 <object class="GtkLabel" id="label1">
473 <property name="visible">True</property>
474+ <property name="can_focus">False</property>
475 <property name="ypad">7</property>
476 <property name="label" translatable="yes">Personalize your notification area plugin</property>
477 </object>
478 <packing>
479+ <property name="expand">True</property>
480+ <property name="fill">True</property>
481 <property name="position">0</property>
482 </packing>
483 </child>
484 <child>
485 <object class="GtkVBox" id="vbox2">
486 <property name="visible">True</property>
487- <property name="orientation">vertical</property>
488+ <property name="can_focus">False</property>
489 <child>
490 <object class="GtkCheckButton" id="pref_chbox_minimized">
491 <property name="label" translatable="yes">Start gtg minimized</property>
492 <property name="visible">True</property>
493 <property name="can_focus">True</property>
494 <property name="receives_default">False</property>
495+ <property name="use_action_appearance">False</property>
496 <property name="image_position">top</property>
497 <property name="draw_indicator">True</property>
498 </object>
499 <packing>
500+ <property name="expand">True</property>
501+ <property name="fill">True</property>
502 <property name="position">0</property>
503 </packing>
504 </child>
505 </object>
506 <packing>
507+ <property name="expand">True</property>
508+ <property name="fill">True</property>
509+ <property name="padding">5</property>
510 <property name="position">1</property>
511 </packing>
512 </child>
513 <child>
514+ <object class="GtkHBox" id="hbox2">
515+ <property name="visible">True</property>
516+ <property name="can_focus">False</property>
517+ <child>
518+ <object class="GtkSpinButton" id="pref_spinbutton_dangerzone">
519+ <property name="visible">True</property>
520+ <property name="can_focus">True</property>
521+ <property name="invisible_char">●</property>
522+ <property name="width_chars">2</property>
523+ <property name="primary_icon_activatable">False</property>
524+ <property name="secondary_icon_activatable">False</property>
525+ <property name="primary_icon_sensitive">True</property>
526+ <property name="secondary_icon_sensitive">True</property>
527+ <property name="adjustment">adjustment_dangerzone</property>
528+ <property name="numeric">True</property>
529+ </object>
530+ <packing>
531+ <property name="expand">False</property>
532+ <property name="fill">True</property>
533+ <property name="position">0</property>
534+ </packing>
535+ </child>
536+ <child>
537+ <object class="GtkLabel" id="label2">
538+ <property name="visible">True</property>
539+ <property name="can_focus">False</property>
540+ <property name="has_tooltip">True</property>
541+ <property name="tooltip_text" translatable="yes">The icon in the notification area is colored if there are tasks in the danger zone.
542+A danger zone of 0 disables icon coloring.</property>
543+ <property name="xpad">4</property>
544+ <property name="label" translatable="yes"> Danger zone (in days) </property>
545+ </object>
546+ <packing>
547+ <property name="expand">False</property>
548+ <property name="fill">True</property>
549+ <property name="position">1</property>
550+ </packing>
551+ </child>
552+ </object>
553+ <packing>
554+ <property name="expand">True</property>
555+ <property name="fill">True</property>
556+ <property name="padding">5</property>
557+ <property name="position">2</property>
558+ </packing>
559+ </child>
560+ <child>
561 <object class="GtkHBox" id="hbox1">
562 <property name="height_request">30</property>
563 <property name="visible">True</property>
564+ <property name="can_focus">False</property>
565 <property name="spacing">50</property>
566 <child>
567 <object class="GtkButton" id="btn_preferences_cancel">
568@@ -55,10 +118,13 @@
569 <property name="visible">True</property>
570 <property name="can_focus">True</property>
571 <property name="receives_default">True</property>
572+ <property name="use_action_appearance">False</property>
573 <property name="use_stock">True</property>
574- <signal name="clicked" handler="on_btn_preferences_cancel_clicked"/>
575+ <signal name="clicked" handler="on_btn_preferences_cancel_clicked" swapped="no"/>
576 </object>
577 <packing>
578+ <property name="expand">True</property>
579+ <property name="fill">True</property>
580 <property name="position">0</property>
581 </packing>
582 </child>
583@@ -68,16 +134,22 @@
584 <property name="visible">True</property>
585 <property name="can_focus">True</property>
586 <property name="receives_default">True</property>
587+ <property name="use_action_appearance">False</property>
588 <property name="use_stock">True</property>
589- <signal name="clicked" handler="on_btn_preferences_ok_clicked"/>
590+ <signal name="clicked" handler="on_btn_preferences_ok_clicked" swapped="no"/>
591 </object>
592 <packing>
593+ <property name="expand">True</property>
594+ <property name="fill">True</property>
595 <property name="position">1</property>
596 </packing>
597 </child>
598 </object>
599 <packing>
600- <property name="position">2</property>
601+ <property name="expand">True</property>
602+ <property name="fill">True</property>
603+ <property name="padding">5</property>
604+ <property name="position">3</property>
605 </packing>
606 </child>
607 </object>

Subscribers

People subscribed via source and target branches

to status/vote changes: