Merge lp:~wolterh/gtg/urgency_gradient into lp:~gtg/gtg/old-trunk

Proposed by Wolter Hellmund on 2013-02-09
Status: Merged
Merged at revision: 1284
Proposed branch: lp:~wolterh/gtg/urgency_gradient
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: 197 lines (+115/-25)
1 file modified
GTG/plugins/urgency_color/urgency_color.py (+115/-25)
To merge this branch: bzr merge lp:~wolterh/gtg/urgency_gradient
Reviewer Review Type Date Requested Status
Izidor Matušov code,run 2013-02-09 Approve on 2013-02-11
Review via email: mp+147529@code.launchpad.net

Description of the change

This branch implements a new feature to GTG (and it includes the fix to bug #1039655, which might be a mistake of mine). The feature gives a task a colour from a gradient, so it is no longer only one of 3 colours. This was proposed by Izidor since the beginnings of the plugin, but until now I cope with the idea and so implement it.

To post a comment you must log in.
Izidor Matušov (izidor) wrote :

Thanks for your patch. (By the way, you inserted randomly 'f' letters in the code. I removed them)

review: Approve (code,run)
Wolter Hellmund (wolterh) wrote :

@2013-02-11 06:09 - Izidor Matušov:
> Review: Approve code,run
>
> Thanks for your patch. (By the way, you inserted randomly 'f' letters in the code. I removed them)

Oh my bad! I use vim and well... to long a story to write here. Thanks
for fixing it!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'GTG/plugins/urgency_color/urgency_color.py'
2--- GTG/plugins/urgency_color/urgency_color.py 2013-01-15 20:57:34 +0000
3+++ GTG/plugins/urgency_color/urgency_color.py 2013-02-09 21:25:22 +0000
4@@ -14,7 +14,7 @@
5 # You should have received a copy of the GNU General Public License along with
6 # this program. If not, see <http://www.gnu.org/licenses/>.
7
8-from math import ceil
9+from math import ceil, floor
10 import gtk
11 import os
12
13@@ -58,26 +58,101 @@
14 return self._pref_data['color_overdue']
15 else:
16 return None
17-
18+
19+ def _get_gradient_color(self, color1, color2, position):
20+ """This function returns a gtk.gdk.Color which corresponds to the
21+ position (a float value from 0 to 1) in the gradient formed by the
22+ colors color1 and color2, both of type gtk.gdk.Color"""
23+ color1 = gtk.gdk.color_parse(color1)
24+ color2 = gtk.gdk.color_parse(color2)
25+ R1, G1, B1 = color1.red, color1.green, color1.blue
26+ R2, G2, B2 = color2.red, color2.green, color2.blue
27+ R = R1 + (R2-R1) * position
28+ G = G1 + (G2-G1) * position
29+ B = B1 + (B2-B1) * position
30+ return gtk.gdk.Color(int(R),int(G),int(B))
31+
32 def get_node_bgcolor(self, node):
33- """ This method checks the background color of a node and returns the color """
34+ """ This method checks the urgency of a node (task) and returns its urgency background color"""
35 sdate = node.get_start_date()
36 ddate = node.get_due_date()
37- if (sdate != Date.no_date() != ddate):
38+ daysleft = ddate.days_left()
39+
40+ # Dates undefined (Fix to bug #1039655)
41+ if (ddate == Date.today()):
42+ return self._get_color(2) # High urgency
43+ elif (daysleft < 0 and ddate != Date.no_date()):
44+ return self._get_color(3) # Overdue
45+ elif (sdate == Date.no_date() != ddate):
46+ return self._get_color(1) # Normal
47+
48+ # Fuzzy dates (now, soon, someday)
49+ if (ddate == Date.now()):
50+ return self._get_color(2)
51+ elif (ddate == Date.soon()):
52+ return self._get_color(1)
53+ elif (ddate == Date.someday()):
54+ return self._get_color(0)
55+
56+ # Dates fully defined. Calculate gradient color
57+ elif (sdate != Date.no_date() != ddate):
58 dayspan = (ddate - sdate).days
59- daysleft = ddate.days_left()
60-
61+
62+ # Reddays
63 redf = self._pref_data['reddays']
64- reddays = int(ceil(redf*dayspan/100))
65- color = 0
66- if daysleft <= dayspan:
67- color = 1
68- if daysleft <= reddays:
69- color = 2
70- if daysleft < 0:
71- color = 3
72+ reddays = int(ceil(redf/100.0 * dayspan))
73+
74+ # Gradient variables
75+ grad_dayspan = dayspan - reddays
76+ grad_half_dayspan = grad_dayspan/2
77+
78+ # Default to low urgency color
79+ color = self._get_color(0)
80+
81+ # CL : low urgency color
82+ # CN : normal urgency color
83+ # CH : high urgency color
84+ # CO : overdue color
85+ # To understand this section, it is easier to draw out a
86+ # timeline divided into 3 sections: CL to CN, CN to CH and
87+ # the reddays section. Then point out the spans of the
88+ # different variables (dayspan, daysleft, reddays,
89+ # grad_dayspan, grad_half_dayspan)
90+ # print node.get_title(), "dayspan: %d | reddays: %d | daysleft: %d" % (dayspan, reddays, daysleft)
91+ if daysleft < 0: # CO
92+ color = self._get_color(3)
93+ elif daysleft <= reddays: # CH
94+ color = self._get_color(2)
95+ elif daysleft <= (dayspan - grad_half_dayspan): # Gradient CN to CH
96+ steps = float(grad_half_dayspan) # Has to be float so division by it is non-zero
97+ step = grad_half_dayspan - (daysleft - reddays)
98+ color = self._get_gradient_color(self._get_color(1), \
99+ self._get_color(2), step/steps)
100+ # print "%s (%d/%d = %f from CN to CH)" % (node.get_title(), step, steps, step/steps)
101+ elif daysleft <= dayspan: # Gradient CL to CN
102+ steps = float(grad_half_dayspan)
103+ step = grad_half_dayspan - (daysleft - reddays - grad_half_dayspan)
104+ color = self._get_gradient_color(self._get_color(0), \
105+ self._get_color(1), step/steps)
106
107 return color
108+
109+ # # Dates fully defined. Calculate color
110+ # elif (sdate != Date.no_date() != ddate):
111+ # dayspan = (ddate - sdate).days
112+ #
113+ # redf = self._pref_data['reddays']
114+ # reddays = int(ceil(redf*dayspan/100))
115+ # color = 0
116+ # if daysleft <= dayspan:
117+ # color = 1
118+ # if daysleft <= reddays:
119+ # color = 2
120+ # if daysleft < 0:
121+ # color = 3
122+ # return color
123+
124+ # Insufficient data to determine urgency
125 else:
126 return None
127
128@@ -98,21 +173,36 @@
129
130 child_list = __get_active_child_list(node)
131
132+ daysleft = None
133 for child_id in child_list:
134 child = self.req.get_task(child_id)
135- color_of_child = self.get_node_bgcolor(child)
136- if color_of_child > color:
137- color = color_of_child
138- # This list should be implemented in the settings
139- #print "Giving color"
140- return self._get_color(color)
141+
142+ if child.get_due_date() == Date.no_date(): continue
143+
144+ # color_of_child = self.get_node_bgcolor(child)
145+ # if color_of_child > color:
146+ # color = color_of_child
147+ # # This list should be implemented in the settings
148+ # #print "Giving color"
149+
150+ daysleft_of_child = child.get_due_date().days_left()
151+ if daysleft is None:
152+ daysleft = daysleft_of_child
153+ color = self.get_node_bgcolor(child)
154+ elif daysleft_of_child < daysleft:
155+ daysleft = daysleft_of_child
156+ color = self.get_node_bgcolor(child)
157+
158+ # return self._get_color(color)
159+ if color is None: print daysleft
160+ return color
161
162 def deactivate(self, plugin_api):
163 """ Plugin is deactivated """
164 self._plugin_api.set_bgcolor_func()
165
166 # Preferences dialog
167- def is_configurable(self):
168+ def is_cfonfigurable(self):
169 """Requisite function for configurable plugins"""
170 return True
171
172@@ -179,7 +269,7 @@
173 self.builder.connect_signals(SIGNAL_CONNECTIONS_DIC)
174
175 def prefs_update_widgets(self):
176- """ Synchronizes the widgets with the data in _pref_data """
177+ """ Synchfronizes the widgets with the data in _pref_data """
178 # Spin button
179 self.spinbutton_reddays.set_value(self._pref_data['reddays'])
180 # Colorbutton - OVERDUE
181@@ -227,13 +317,13 @@
182 self._pref_data[new_key] = self._pref_data.pop(old_key)
183
184 def prefs_store(self):
185- self._plugin_api.save_configuration_object( \
186- self.PLUGIN_NAME,
187+ self._pluginf_api.save_configuration_object( \
188+ self.PLUGfIN_NAME,
189 'preferences',
190 self._pref_data)
191
192 def on_prefs_spinbutton_reddays_changed(self, widget=None, data=None):
193- self._pref_data_potential['reddays'] = \
194+ self._pfref_data_potential['reddays'] = \
195 self.spinbutton_reddays.get_value()
196
197 def on_prefs_colorbutton_overdue_changed(self, widget=None, data=None):

Subscribers

People subscribed via source and target branches

to status/vote changes: