GTG

Merge lp:~gtg/gtg/viewcount into lp:~gtg/gtg/old-trunk

Proposed by Lionel Dricot
Status: Merged
Merged at revision: 1235
Proposed branch: lp:~gtg/gtg/viewcount
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: 555 lines (+128/-148)
10 files modified
CHANGELOG (+1/-0)
GTG/core/__init__.py (+1/-1)
GTG/core/datastore.py (+0/-2)
GTG/core/requester.py (+17/-0)
GTG/core/tag.py (+40/-18)
GTG/core/task.py (+6/-19)
GTG/core/treefactory.py (+5/-5)
GTG/gtk/browser/browser.py (+55/-50)
GTG/gtk/browser/treeview_factory.py (+2/-52)
GTG/tools/import_liblarch.py (+1/-1)
To merge this branch: bzr merge lp:~gtg/gtg/viewcount
Reviewer Review Type Date Requested Status
Izidor Matušov Approve
Bertrand Rousseau (community) run Approve
Review via email: mp+130696@code.launchpad.net

Description of the change

This branch solves the @t @ta @tag problem by using a new liblarch feature : the viewcount (which is a simpler viewtree).

It also removes any use of the "transparent" concept, which has been removed from liblarch.

Thing to test : performance regression and tag counting regressions.

To post a comment you must log in.
Revision history for this message
Izidor Matušov (izidor) wrote :

I played with your patch.

First to say, you updated "trunk" of liblarch immediately and it was distributed into PPA and made people to report bug #1069963.

Another thing is, that you should have increased LIBLARCH_API number both in GTG & liblarch.

About performance. I measured it on my real tasks (220+):

Current GTG & liblarch:
real 0m4.775s
user 0m4.384s
sys 0m0.244s

Viewcount:
real 0m6.155s
user 0m5.808s
sys 0m0.260s

It is a little bit slower, UI is slower a little bit too. It is not an order of magnitude, it is bearable.

Please, get rid of commented code. Look at your diff and get rid of those print statetements or just commented code.

I get an error message when I start GTG: "There's no filter called gtg-tags-sep" --> Please, solve it.

I found a regression:

Make a tag @a child of tag @b by drag-and-drop. While you do it, the main pane is refreshed two times - it is slow and the user can see it. In the trunk, the main pane is not refreshed.

Same thing happens when you delete the last task in the tag -> the main pane is refreshed and it is so slow.

Another regression is that the tags are not expanded by default. When you have a tag tree @a -> @b, tag @a should be expanded by default during the boot time.

Another regression + performance issue: Try to search for "!not @gtg". I get 189 out of 213 results in trunk (althought initialy the count is 0). In your branch it is slow (I guess the refreshing something) but more important, it put there count 238 out of 213!!! Switching back and forth into workview and back doesn't help. (Workview shows correct count though) I would say it counts closed tasks as well.

Another regression: Strat GTG with the firstboot tasks. Look at the "Tasks without tags" count -> 7. Now mark some tasks without tags as done. The count doesn't change although the count of all tasks does -> you can have 7 of 6 tasks if you want. I guess it would be similar regression.

There are quite much work to do, it is not completed yet :) However, it looks promising!

review: Needs Fixing (code, run)
Revision history for this message
Lionel Dricot (ploum-deactivatedaccount) wrote :

Izidor > Regarding performances, I agree that the startup time is a bit slower but, on my tasks, use is *way* better. Normal GTG make it impossible for me to add a task with the quick add (there's a 4-5 seconds delay) while, with my branch, it just works.

Regarding liblarch, I merged it by mistake. Maybe you can revert it.

lp:~gtg/gtg/viewcount updated
1225. By Lionel Dricot

no viewcount for gtg-tags-sep

1226. By Lionel Dricot

solve the notag counting bug

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

1) increased LIBLARCH_API number both in GTG & liblarch : TODO
2) get rid of commented code : TODO
3) There's no filter called gtg-tags-sep : FIXED
4) the main pane is refreshed two times : TODO
5) tags are not expanded by default : TODO
6) !not @gtg : TODO
7) Tasks without tags : FIXED

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

1) increased LIBLARCH_API number both in GTG & liblarch : TODO
2) get rid of commented code : TODO
4) the main pane is refreshed two times : TODO
5) tags are not expanded by default : TODO
6) !not @gtg : TODO (in fact, viewcount for search is not yet implemented)
8) Crash on tag drag-n-drop : TODO

lp:~gtg/gtg/viewcount updated
1227. By Lionel Dricot

removing some commented lines

1228. By Lionel Dricot

update liblarch requirement

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

1) increased LIBLARCH_API number both in GTG & liblarch : FIXED
2) get rid of commented code : FIXED
4) the main pane is refreshed two times : TODO
5) tags are not expanded by default : TODO
6) !not @gtg : TODO (in fact, viewcount for search is not yet implemented)
8) Crash on tag drag-n-drop : TODO

lp:~gtg/gtg/viewcount updated
1229. By Lionel Dricot

solve the counting bug for search tags and remove useless filter settings

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

4) the main pane is refreshed two times : TODO
5) tags are not expanded by default : TODO
6) !not @gtg : FIXED
8) Crash on tag drag-n-drop : TODO

lp:~gtg/gtg/viewcount updated
1230. By Lionel Dricot

remove the deprecated has_parents in task

1231. By Lionel Dricot

take benefit from viewcount refresh

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

I improved quite a lot the startup performance (went from 12s to 9s on my machine with my tasks).

Revision history for this message
Izidor Matušov (izidor) wrote :

I can confirm that the regressions you fixed are fixed. The performance on my tasks went down to 4 seconds and effectively there is no performance lost on boot. I haven't found any other regression.

lp:~gtg/gtg/viewcount updated
1232. By Lionel Dricot

The collapsed status of tags is now saved. Requires liblarch 2.1

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

4) the main pane is refreshed two times : TODO
5) tags are not expanded by default : IMPLEMENTED

By default, tags are indeed not expanded. I have no idea why. But I have implemented the fact that the expanded/collapsed status is remembered (which was not the case previously).

8) Crash on tag drag-n-drop : TODO

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

Should we fix 8) before merging? Not sure I've the time to fix it this week (I already spent some time on it without success).

I can confirm that this branch solves a lot of the performances issues.

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

Could you tell a bit more about this bug? Is there a related bug
report? When does it happen?

On Mon 29 Oct 2012 02:09:17 PM CET, Lionel Dricot wrote:
> Should we fix 8) before merging? Not sure I've the time to fix it this week (I already spent some time on it without success).
>
> I can confirm that this branch solves a lot of the performances issues.

--
Bertrand Rousseau
<email address hidden>

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

No reported.

1. Launch GTG with default tasks
2. Display sidebar (F9)
3. Drag a tag and drop it on another

That's all.

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

Then we should either disable tag DnD or solve it, but we can't let it
crash GTG for such a common feature.

I'd like to release GTG 0.3 asap, so let's disable it if it require
advanced fix/testing. I'll let you judge about that.

Bertrand

On Mon 29 Oct 2012 03:13:25 PM CET, Lionel Dricot wrote:
> No reported.
>
> 1. Launch GTG with default tasks
> 2. Display sidebar (F9)
> 3. Drag a tag and drop it on another
>
> That's all.

--
Bertrand Rousseau
<email address hidden>

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

Le 29/10/2012 15:29, Bertrand Rousseau a écrit :
> Then we should either disable tag DnD or solve it, but we can't let it
> crash GTG for such a common feature.

It crashes only in that very specific configuration. I've been unable to
reproduce this bug in any other circumstances. I'm really wondering what
this bug is.

>
> I'd like to release GTG 0.3 asap, so let's disable it if it require
> advanced fix/testing. I'll let you judge about that.

We cannot disable tag drag-n-drop, that's a major feature.

>
> Bertrand
>
> On Mon 29 Oct 2012 03:13:25 PM CET, Lionel Dricot wrote:
>> No reported.
>>
>> 1. Launch GTG with default tasks
>> 2. Display sidebar (F9)
>> 3. Drag a tag and drop it on another
>>
>> That's all.
> --
> Bertrand Rousseau
> <email address hidden>
>

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

On Mon 29 Oct 2012 03:34:31 PM CET, Lionel Dricot wrote:
> Le 29/10/2012 15:29, Bertrand Rousseau a écrit :
>> Then we should either disable tag DnD or solve it, but we can't let it
>> crash GTG for such a common feature.
>
> It crashes only in that very specific configuration. I've been unable to
> reproduce this bug in any other circumstances. I'm really wondering what
> this bug is.

The (very) annoying thing is that those default tasks invite the new
user to try and test tag DnD. What is your estimation of the required
work to fix this bug?

>>
>> I'd like to release GTG 0.3 asap, so let's disable it if it require
>> advanced fix/testing. I'll let you judge about that.
>
> We cannot disable tag drag-n-drop, that's a major feature.
>
>>
>> Bertrand
>>
>> On Mon 29 Oct 2012 03:13:25 PM CET, Lionel Dricot wrote:
>>> No reported.
>>>
>>> 1. Launch GTG with default tasks
>>> 2. Display sidebar (F9)
>>> 3. Drag a tag and drop it on another
>>>
>>> That's all.
>> --
>> Bertrand Rousseau
>> <email address hidden>
>>
>
>

--
Bertrand Rousseau
<email address hidden>

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :
Download full text (3.4 KiB)

Btw, it doesn't crash on my computer, but leave the following trace
(after dropping "money" on "errands"):

Traceback (most recent call last):
  File
"/home/rousseau/workspace/personal/gtg/viewcount/GTG/gtk/browser/browser.py",
line 1152, in on_select_tag
    self.apply_filter_on_panes(tagname)
  File
"/home/rousseau/workspace/personal/gtg/viewcount/GTG/gtk/browser/browser.py",
line 1122, in apply_filter_on_panes
    vtree.apply_filter(filter_name, refresh=refresh)
  File "../liblarch/liblarch/viewtree.py", line 276, in apply_filter
    self.__ft.apply_filter(filter_name, parameters, reset, refresh)
  File "../liblarch/liblarch/filteredtree.py", line 635, in apply_filter
    self.refilter()
  File "../liblarch/liblarch/filteredtree.py", line 313, in refilter
    self.send_remove_tree(node_id, self.root_id)
  File "../liblarch/liblarch/filteredtree.py", line 287, in
send_remove_tree
    self.callback('deleted', node_id, path)
  File "../liblarch/liblarch/filteredtree.py", line 124, in callback
    func(node_id,path)
  File "../liblarch/liblarch/viewtree.py", line 115, in __emit
    func(node_id,path)
  File
"/home/rousseau/workspace/personal/gtg/viewcount/GTG/gtk/browser/treeview_factory.py",
line 346, in _update_tags
    tree.refresh_node(t.get_name())
  File "../liblarch/liblarch/__init__.py", line 87, in refresh_node
    self.__tree.modify_node(node_id, priority)
  File "../liblarch/liblarch/tree.py", line 88, in modify_node
    self._queue.push(self._modify_node, node_id, priority=priority)
  File "../liblarch/liblarch/processqueue.py", line 65, in push
    func(*element[1:])
  File "../liblarch/liblarch/tree.py", line 269, in _modify_node
    self._callback('node-modified', node_id)
  File "../liblarch/liblarch/tree.py", line 78, in _callback
    func(node_id)
  File "../liblarch/liblarch/filteredtree.py", line 129, in
__external_modify
    return self.__update_node(node_id,direction="both")
  File "../liblarch/liblarch/filteredtree.py", line 219, in
__update_node
    for path in self.get_paths_for_node(node_id):
  File "../liblarch/liblarch/filteredtree.py", line 440, in
get_paths_for_node
    raise Exception("%s is not children of %s\n%s" % (node_id,
parent_id, s))
Exception: @money is not children of @errands

On Wed 31 Oct 2012 02:35:27 PM CET, Bertrand Rousseau wrote:
>
>
> On Mon 29 Oct 2012 03:34:31 PM CET, Lionel Dricot wrote:
>> Le 29/10/2012 15:29, Bertrand Rousseau a écrit :
>>> Then we should either disable tag DnD or solve it, but we can't let it
>>> crash GTG for such a common feature.
>>
>> It crashes only in that very specific configuration. I've been unable to
>> reproduce this bug in any other circumstances. I'm really wondering what
>> this bug is.
>
> The (very) annoying thing is that those default tasks invite the new
> user to try and test tag DnD. What is your estimation of the required
> work to fix this bug?
>
>>>
>>> I'd like to release GTG 0.3 asap, so let's disable it if it require
>>> advanced fix/testing. I'll let you judge about that.
>>
>> We cannot disable tag drag-n-drop, that's a major feature.
>>
>>>
>>> Bertrand
>>>
>>> On Mon 29 Oct 2012 03:13:25 PM CET, Lionel Dricot wrote:
>>>> No repor...

Read more...

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

Le 31/10/2012 14:40, Bertrand Rousseau a écrit :
> Btw, it doesn't crash on my computer, but leave the following trace
> (after dropping "money" on "errands"):
>

This is what I call "the crash". Indeed, it doesn't seem to have any
impact other than making a trace. *any* hint on what could explain this
trace is very welcome. I would like to fix this.

Revision history for this message
Izidor Matušov (izidor) wrote :

I found a reason for the bug: There are still active hacks for counting in GTG -> enable/disable_update_tags() and _update_tags() in GTG/gtk/browser/treeview_factory.py (If you put a "return" statement at the beginning of _update_tags(), i.e. comment out the method body, it works perfect)

Revision history for this message
Izidor Matušov (izidor) wrote :

Please get rid of commented AutoExpandTreeView class.

review: Needs Fixing
lp:~gtg/gtg/viewcount updated
1233. By Lionel Dricot

Removed loft of things now useless thanks to viewcount. Fixed the crash.

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

I've solved the crash. Thanks Izidor. I've removed an incredible amount of useless refresh everywhere. It should make the performance a lot better. And now, it can be merged once you test it :-)

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

I spent some time playing with tasks and tags with your branch (even with the infamous "bryce" data set), I haven't spot any bugs. It seems for me that it can be merged (that would also enabled broader testing).

review: Approve (run)
lp:~gtg/gtg/viewcount updated
1234. By Bertrand Rousseau

Update CHANGELOG

1235. By Bertrand Rousseau

Merge trunk

Revision history for this message
Izidor Matušov (izidor) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CHANGELOG'
--- CHANGELOG 2012-09-08 08:10:51 +0000
+++ CHANGELOG 2012-11-01 10:11:21 +0000
@@ -53,6 +53,7 @@
53 * Fix for bug-1037051 (Due date is not set for a new subtask), by Nimit Shah53 * Fix for bug-1037051 (Due date is not set for a new subtask), by Nimit Shah
54 * Fix for bug #1036955: Due date is not preselected when start date is filled, by Steve Scheel54 * Fix for bug #1036955: Due date is not preselected when start date is filled, by Steve Scheel
55 * Fix for bug #1045036: Slovak Translation Updated by Slavko55 * Fix for bug #1045036: Slovak Translation Updated by Slavko
56 * Remove use of liblarch's "transparent" concept (since it's been removed from liblarch), fixes bugs #1001962, #1001962, #1069257, #1069963: intermediary tags, counter initialization, and regressions caused by initial versions of the patch
5657
572012-02-13 Getting Things GNOME! 0.2.9582012-02-13 Getting Things GNOME! 0.2.9
58 * Big refractorization of code, now using liblarch59 * Big refractorization of code, now using liblarch
5960
=== modified file 'GTG/core/__init__.py'
--- GTG/core/__init__.py 2012-08-08 18:16:38 +0000
+++ GTG/core/__init__.py 2012-11-01 10:11:21 +0000
@@ -55,7 +55,7 @@
55 'toolbar': True,55 'toolbar': True,
56 'quick_add': True,56 'quick_add': True,
57 'collapsed_tasks': [],57 'collapsed_tasks': [],
58 'collapsed_tags': [],58 'expanded_tags': [],
59 'view': 'default',59 'view': 'default',
60 "opened_tasks": [],60 "opened_tasks": [],
61 'width': 400,61 'width': 400,
6262
=== modified file 'GTG/core/datastore.py'
--- GTG/core/datastore.py 2012-08-12 22:32:09 +0000
+++ GTG/core/datastore.py 2012-11-01 10:11:21 +0000
@@ -114,8 +114,6 @@
114 if self.__tagstore.has_node(name):114 if self.__tagstore.has_node(name):
115 raise IndexError('tag %s was already in the datastore' % name)115 raise IndexError('tag %s was already in the datastore' % name)
116116
117 parameters['transparent'] = True
118
119 self.__tasks.add_filter(name, filter_func, parameters=parameters)117 self.__tasks.add_filter(name, filter_func, parameters=parameters)
120 self.__tagstore.add_node(tag, parent_id=parent_id)118 self.__tagstore.add_node(tag, parent_id=parent_id)
121 tag.set_save_callback(self.save)119 tag.set_save_callback(self.save)
122120
=== modified file 'GTG/core/requester.py'
--- GTG/core/requester.py 2012-07-13 17:24:28 +0000
+++ GTG/core/requester.py 2012-11-01 10:11:21 +0000
@@ -54,6 +54,23 @@
5454
55 def is_displayed(self, task):55 def is_displayed(self, task):
56 return self.__basetree.get_viewtree(name='active').is_displayed(task)56 return self.__basetree.get_viewtree(name='active').is_displayed(task)
57
58 def get_basetree(self):
59 return self.__basetree
60
61 #this method also update the viewcount of tags
62 def apply_global_filter(self,tree,filtername):
63 tree.apply_filter(filtername)
64 for t in self.get_all_tags():
65 ta = self.get_tag(t)
66 ta.apply_filter(filtername)
67
68 def unapply_global_filter(self,tree,filtername):
69 tree.unapply_filter(filtername)
70 for t in self.get_all_tags():
71 ta = self.get_tag(t)
72 ta.unapply_filter(filtername)
73
5774
58 ######### Filters bank #######################75 ######### Filters bank #######################
59 # List, by name, all available filters76 # List, by name, all available filters
6077
=== modified file 'GTG/core/tag.py'
--- GTG/core/tag.py 2012-07-23 14:43:13 +0000
+++ GTG/core/tag.py 2012-11-01 10:11:21 +0000
@@ -56,6 +56,39 @@
56 self._attributes = {'name': self._name}56 self._attributes = {'name': self._name}
57 for key, value in attributes.iteritems():57 for key, value in attributes.iteritems():
58 self.set_attribute(key, value)58 self.set_attribute(key, value)
59
60 self.viewcount = None
61
62 def __get_viewcount(self):
63 if not self.viewcount and self.get_name() != "gtg-tags-sep":
64 self.viewcount = self.req.get_basetree().get_viewcount\
65 (name=self.get_name(),refresh=False)
66
67 sp_id = self.get_attribute("special")
68 if sp_id == "all":
69 pass
70 if sp_id == "notag":
71 self.viewcount.apply_filter('notag',refresh=False)
72 #No special means a normal tag
73 else:
74 self.viewcount.apply_filter(self.get_name(),refresh=False)
75 self.viewcount.apply_filter('active')
76 self.viewcount.register_cllbck(self.modified)
77 return self.viewcount
78
79 def apply_filter(self,filtername):
80 if self.viewcount:
81 self.viewcount.apply_filter(filtername)
82
83 def unapply_filter(self,filtername):
84 if self.viewcount:
85 self.viewcount.unapply_filter(filtername)
86
87 #When a task change a tag, we may want to manually update
88 #To ensure that the task is well counted/uncounted for that tag
89 def update_task(self,nid):
90 vc = self.__get_viewcount()
91 vc.modify(nid)
5992
60 #overiding some functions to not allow dnd of special tags93 #overiding some functions to not allow dnd of special tags
61 def add_parent(self, parent_id):94 def add_parent(self, parent_id):
@@ -163,22 +196,11 @@
163 # this method purposefully doesn't rely on get_related_tasks()196 # this method purposefully doesn't rely on get_related_tasks()
164 # which does a similar job, in order to benefit from liblarch197 # which does a similar job, in order to benefit from liblarch
165 # optimizations198 # optimizations
166 if not tasktree:199 vc = self.__get_viewcount()
167 tasktree = self.req.get_tasks_tree()200 if vc:
168 sp_id = self.get_attribute("special")201 return vc.get_n_nodes()
169 if sp_id == "all":
170 toreturn = tasktree.get_n_nodes(\
171 withfilters=['active'], include_transparent=False)
172 elif sp_id == "notag":
173 toreturn = tasktree.get_n_nodes(\
174 withfilters=['notag'], include_transparent=False)
175 elif sp_id == "sep":
176 toreturn = 0
177 else:202 else:
178 tname = self.get_name()203 return 0
179 toreturn = tasktree.get_n_nodes(\
180 withfilters=[tname], include_transparent=False)
181 return toreturn
182204
183 def get_related_tasks(self, tasktree=None):205 def get_related_tasks(self, tasktree=None):
184 """Returns all related tasks node ids"""206 """Returns all related tasks node ids"""
@@ -187,16 +209,16 @@
187 sp_id = self.get_attribute("special")209 sp_id = self.get_attribute("special")
188 if sp_id == "all":210 if sp_id == "all":
189 toreturn = tasktree.get_nodes(\211 toreturn = tasktree.get_nodes(\
190 withfilters=['active'], include_transparent=False)212 withfilters=['active'])
191 elif sp_id == "notag":213 elif sp_id == "notag":
192 toreturn = tasktree.get_nodes(\214 toreturn = tasktree.get_nodes(\
193 withfilters=['notag'], include_transparent=False)215 withfilters=['notag'])
194 elif sp_id == "sep" :216 elif sp_id == "sep" :
195 toreturn = []217 toreturn = []
196 else:218 else:
197 tname = self.get_name()219 tname = self.get_name()
198 toreturn = tasktree.get_nodes(\220 toreturn = tasktree.get_nodes(\
199 withfilters=[tname], include_transparent=False)221 withfilters=[tname])
200 return toreturn222 return toreturn
201223
202 def notify_related_tasks(self):224 def notify_related_tasks(self):
203225
=== modified file 'GTG/core/task.py'
--- GTG/core/task.py 2012-08-15 15:23:45 +0000
+++ GTG/core/task.py 2012-11-01 10:11:21 +0000
@@ -208,7 +208,7 @@
208 # (old_status check is necessary to avoid false positive a start)208 # (old_status check is necessary to avoid false positive a start)
209 elif status in [self.STA_ACTIVE] and\209 elif status in [self.STA_ACTIVE] and\
210 old_status in [self.STA_DONE, self.STA_DISMISSED]:210 old_status in [self.STA_DONE, self.STA_DISMISSED]:
211 if self.has_parents():211 if self.has_parent():
212 for p_tid in self.get_parents():212 for p_tid in self.get_parents():
213 par = self.req.get_task(p_tid)213 par = self.req.get_task(p_tid)
214 if par.is_loaded() and par.get_status() in\214 if par.is_loaded() and par.get_status() in\
@@ -476,24 +476,6 @@
476 """476 """
477 return self.req.get_task(tid)477 return self.req.get_task(tid)
478478
479 #Return true is the task has parent
480 #If tag is provided, return True only
481 #if the parent has this particular tag
482 #FIXME : this function should be removed. Use the liblarch instead !
483 def has_parents(self, tag=None):
484 print "DEPRECATED: has_parent"
485 has_par = TreeNode.has_parent(self)
486 #The "all tag" argument
487 if tag and has_par:
488 a = 0
489 for tid in self.get_parents():
490 p = self.req.get_task(tid)
491 a += p.has_tags(tag)
492 to_return = a
493 else:
494 to_return = has_par
495 return to_return
496
497 def set_attribute(self, att_name, att_value, namespace=""):479 def set_attribute(self, att_name, att_value, namespace=""):
498 """Set an arbitrary attribute.480 """Set an arbitrary attribute.
499481
@@ -601,6 +583,7 @@
601583
602 #remove by tagname584 #remove by tagname
603 def remove_tag(self, tagname):585 def remove_tag(self, tagname):
586# print "remove tag %s" %tagname
604 modified = False587 modified = False
605 if tagname in self.tags:588 if tagname in self.tags:
606 self.tags.remove(tagname)589 self.tags.remove(tagname)
@@ -611,8 +594,12 @@
611 self.content = self._strip_tag(self.content, tagname)594 self.content = self._strip_tag(self.content, tagname)
612 if modified:595 if modified:
613 tag = self.req.get_tag(tagname)596 tag = self.req.get_tag(tagname)
597 # The ViewCount of the tag still doesn't know that
598 # the task was removed. We need to update manually
599 tag.update_task(self.get_id())
614 if tag:600 if tag:
615 tag.modified()601 tag.modified()
602# print "removing now %s and tag is %s - %s" %(tagname,tag, tag.get_active_tasks_count())
616603
617 def set_only_these_tags(self, tags_list):604 def set_only_these_tags(self, tags_list):
618 '''605 '''
619606
=== modified file 'GTG/core/treefactory.py'
--- GTG/core/treefactory.py 2012-07-13 17:24:28 +0000
+++ GTG/core/treefactory.py 2012-11-01 10:11:21 +0000
@@ -45,14 +45,14 @@
45 'workview': [self.workview],45 'workview': [self.workview],
46 'active': [self.active],46 'active': [self.active],
47 'closed': [self.closed, {'flat': True}],47 'closed': [self.closed, {'flat': True}],
48 'notag': [self.notag, {'transparent': True}],48 'notag': [self.notag],
49 'workable': [self.is_workable],49 'workable': [self.is_workable],
50 'started': [self.is_started],50 'started': [self.is_started],
51 'workdue': [self.workdue],51 'workdue': [self.workdue],
52 'workstarted': [self.workstarted],52 'workstarted': [self.workstarted],
53 'worktostart': [self.worktostart],53 'worktostart': [self.worktostart],
54 'worklate': [self.worklate],54 'worklate': [self.worklate],
55 'no_disabled_tag': [self.no_disabled_tag, {'transparent': True}],55 'no_disabled_tag': [self.no_disabled_tag],
56 }56 }
5757
58 for f in f_dic:58 for f in f_dic:
@@ -80,7 +80,7 @@
80 alltag.set_attribute("icon", "gtg-tags-all")80 alltag.set_attribute("icon", "gtg-tags-all")
81 alltag.set_attribute("order", 0)81 alltag.set_attribute("order", 0)
82 tagtree.add_node(alltag)82 tagtree.add_node(alltag)
83 p = {'transparent': True}83 p = {}
84 self.tasktree.add_filter(CoreConfig.ALLTASKS_TAG,\84 self.tasktree.add_filter(CoreConfig.ALLTASKS_TAG,\
85 self.alltag, parameters=p)85 self.alltag, parameters=p)
86 # Build the "without tag tag"86 # Build the "without tag tag"
@@ -91,7 +91,7 @@
91 notag_tag.set_attribute("icon", "gtg-tags-none")91 notag_tag.set_attribute("icon", "gtg-tags-none")
92 notag_tag.set_attribute("order", 2)92 notag_tag.set_attribute("order", 2)
93 tagtree.add_node(notag_tag)93 tagtree.add_node(notag_tag)
94 p = {'transparent': True}94 p = {}
95 self.tasktree.add_filter(CoreConfig.NOTAG_TAG,\95 self.tasktree.add_filter(CoreConfig.NOTAG_TAG,\
96 self.notag, parameters=p)96 self.notag, parameters=p)
9797
@@ -103,7 +103,7 @@
103 search_tag.set_attribute("icon", "search")103 search_tag.set_attribute("icon", "search")
104 search_tag.set_attribute("order", 1)104 search_tag.set_attribute("order", 1)
105 tagtree.add_node(search_tag)105 tagtree.add_node(search_tag)
106 p = {'transparent': True}106 p = {}
107 self.tasktree.add_filter(CoreConfig.SEARCH_TAG,107 self.tasktree.add_filter(CoreConfig.SEARCH_TAG,
108 search_filter, parameters=p)108 search_filter, parameters=p)
109109
110110
=== modified file 'GTG/gtk/browser/browser.py'
--- GTG/gtk/browser/browser.py 2012-08-12 23:01:10 +0000
+++ GTG/gtk/browser/browser.py 2012-11-01 10:11:21 +0000
@@ -79,6 +79,7 @@
79 self.vmanager = vmanager79 self.vmanager = vmanager
80 self.config = self.req.get_config('browser')80 self.config = self.req.get_config('browser')
81 self.tag_active = False81 self.tag_active = False
82 self.applied_tags = []
8283
83 #treeviews handlers84 #treeviews handlers
84 self.vtree_panes = {}85 self.vtree_panes = {}
@@ -95,7 +96,7 @@
9596
96 # Set up models97 # Set up models
97 # Active Tasks98 # Active Tasks
98 self.activetree.apply_filter('active')99 self.req.apply_global_filter(self.activetree,'active')
99 # Tags100 # Tags
100 self.tagtree = None101 self.tagtree = None
101 self.tagtreeview = None102 self.tagtreeview = None
@@ -201,19 +202,18 @@
201 self.tagtree = self.req.get_tag_tree()202 self.tagtree = self.req.get_tag_tree()
202 self.tagtreeview = self.tv_factory.tags_treeview(self.tagtree)203 self.tagtreeview = self.tv_factory.tags_treeview(self.tagtree)
203 #Tags treeview204 #Tags treeview
204 self.tagtreeview.connect('cursor-changed', \205 self.tagtreeview.get_selection().connect('changed', \
205 self.on_select_tag)
206 self.tagtreeview.connect('row-activated', \
207 self.on_select_tag)206 self.on_select_tag)
208 self.tagtreeview.connect('button-press-event', \207 self.tagtreeview.connect('button-press-event', \
209 self.on_tag_treeview_button_press_event)208 self.on_tag_treeview_button_press_event)
210 self.tagtreeview.connect('key-press-event', \209 self.tagtreeview.connect('key-press-event', \
211 self.on_tag_treeview_key_press_event)210 self.on_tag_treeview_key_press_event)
211 self.tagtreeview.connect('node-expanded', \
212 self.on_tag_expanded)
213 self.tagtreeview.connect('node-collapsed', \
214 self.on_tag_collapsed)
212 self.sidebar_container.add(self.tagtreeview)215 self.sidebar_container.add(self.tagtreeview)
213216
214 # Refresh tree
215 self.tagtree.reset_filters(transparent_only=True)
216
217 # expanding search tag does not work automatically, request it217 # expanding search tag does not work automatically, request it
218 self.expand_search_tag()218 self.expand_search_tag()
219219
@@ -510,10 +510,15 @@
510 path = path[:-1]510 path = path[:-1]
511 self.vtree_panes['active'].collapse_node(path)511 self.vtree_panes['active'].collapse_node(path)
512512
513 for t in self.config.get("collapsed_tags"):513 for path_t in self.config.get("expanded_tags"):
514 #FIXME514 #the tuple was stored as a string. we have to reconstruct it
515 print "Collapsing tag %s not implememted in browser.py" %t515 path = ()
516# self.tagtreeview.set_collapsed_tags(toset)516 for p in path_t[1:-1].split(","):
517 p = p.strip(" '")
518 path += (p, )
519 if path[-1] == '':
520 path = path[:-1]
521 self.tagtreeview.expand_node(path)
517522
518 self.set_view(self.config.get("view"))523 self.set_view(self.config.get("view"))
519524
@@ -550,25 +555,20 @@
550 return555 return
551556
552 self.in_toggle_workview = True557 self.in_toggle_workview = True
553 self.tv_factory.disable_update_tags()
554558
555 if self.config.get('view') == 'workview':559 if self.config.get('view') == 'workview':
556 self.set_view('default')560 self.set_view('default')
557 else:561 else:
558 self.set_view('workview')562 self.set_view('workview')
559563
560 if self.tagtree is not None:
561 self.tv_factory.enable_update_tags()
562 self.tagtree.refresh_all()
563
564 self.in_toggle_workview = False564 self.in_toggle_workview = False
565565
566 def set_view(self, viewname):566 def set_view(self, viewname):
567 if viewname == 'default':567 if viewname == 'default':
568 self.activetree.unapply_filter('workview')568 self.req.unapply_global_filter(self.activetree,'workview')
569 workview = False569 workview = False
570 elif viewname == 'workview':570 elif viewname == 'workview':
571 self.activetree.apply_filter('workview')571 self.req.apply_global_filter(self.activetree,'workview')
572 workview = True572 workview = True
573 else:573 else:
574 raise Exception('Cannot set the view %s' %viewname)574 raise Exception('Cannot set the view %s' %viewname)
@@ -613,13 +613,6 @@
613### SIGNAL CALLBACKS ##########################################################613### SIGNAL CALLBACKS ##########################################################
614# Typically, reaction to user input & interactions with the GUI614# Typically, reaction to user input & interactions with the GUI
615#615#
616 def register_filter_callback(self, cb):
617 print "DEPRECATED function register_filter_callback."
618 print "It is only dummy funnction now, ready for removing"
619
620 def unregister_filter_callback(self, cb):
621 print "DEPRECATED function unregister_filter_callback."
622 print "It is only dummy funnction now, ready for removing"
623616
624 def on_sort_column_changed(self, model):617 def on_sort_column_changed(self, model):
625 sort_column, sort_order = model.get_sort_column_id()618 sort_column, sort_order = model.get_sort_column_id()
@@ -762,6 +755,16 @@
762 colt = self.config.get("collapsed_tasks")755 colt = self.config.get("collapsed_tasks")
763 if tid not in colt:756 if tid not in colt:
764 colt.append(str(tid))757 colt.append(str(tid))
758
759 def on_tag_expanded(self, sender, tag):
760 colt = self.config.get("expanded_tags")
761 if tag not in colt:
762 colt.append(tag)
763
764 def on_tag_collapsed(self, sender, tag):
765 colt = self.config.get("expanded_tags")
766 if tag in colt:
767 colt.remove(str(tag))
765768
766 def on_quickadd_activate(self, widget):769 def on_quickadd_activate(self, widget):
767 """ Add a new task from quickadd toolbar """770 """ Add a new task from quickadd toolbar """
@@ -1107,12 +1110,17 @@
1107 task.set_status(Task.STA_DISMISSED)1110 task.set_status(Task.STA_DISMISSED)
1108 self.close_all_task_editors(uid)1111 self.close_all_task_editors(uid)
11091112
1110 def apply_filter_on_panes(self, filter_name):1113 def apply_filter_on_panes(self, filter_name,refresh=True):
1111 """ Apply filters for every pane: active tasks, closed tasks """1114 """ Apply filters for every pane: active tasks, closed tasks """
1112 for pane in self.vtree_panes:1115 for pane in self.vtree_panes:
1113 vtree = self.req.get_tasks_tree(name=pane, refresh=False)1116 vtree = self.req.get_tasks_tree(name=pane, refresh=False)
1114 vtree.reset_filters(refresh=False, transparent_only=True)1117 vtree.apply_filter(filter_name, refresh=refresh)
1115 vtree.apply_filter(filter_name, refresh=True)1118
1119 def unapply_filter_on_panes(self, filter_name,refresh=True):
1120 """ Apply filters for every pane: active tasks, closed tasks """
1121 for pane in self.vtree_panes:
1122 vtree = self.req.get_tasks_tree(name=pane, refresh=False)
1123 vtree.unapply_filter(filter_name, refresh=refresh)
11161124
1117 def on_select_tag(self, widget=None, row=None, col=None):1125 def on_select_tag(self, widget=None, row=None, col=None):
1118 """1126 """
@@ -1120,26 +1128,23 @@
1120 """1128 """
1121 # FIXME add support for multiple selection of tags in future1129 # FIXME add support for multiple selection of tags in future
11221130
1123 # When enable_update_tags we should update all tags to match
1124 # the current state. However, applying tag filter does not influence
1125 # other tags, because of transparent filter. Therefore there is no
1126 # self.tagree.refresh_all() => a significant optimization!
1127 # See do_toggle_workview()
1128 self.tv_factory.disable_update_tags()
1129
1130 #When you click on a tag, you want to unselect the tasks1131 #When you click on a tag, you want to unselect the tasks
1131 taglist = self.get_selected_tags()1132 new_taglist = self.get_selected_tags()
1132 if len(taglist) > 0:1133
1133 tagname = taglist[0]1134 for tagname in self.applied_tags:
1134 self.apply_filter_on_panes(tagname)1135 if tagname not in new_taglist:
11351136 self.unapply_filter_on_panes(tagname,refresh=False)
1136 # In case of search tag, set query in quickadd for1137
1137 # refining search query1138 for tagname in new_taglist:
1138 tag = self.req.get_tag(tagname)1139 if tagname not in self.applied_tags:
1139 if tag.is_search_tag():1140 self.apply_filter_on_panes(tagname)
1140 self.quickadd_entry.set_text(tag.get_attribute("query"))1141 # In case of search tag, set query in quickadd for
11411142 # refining search query
1142 self.tv_factory.enable_update_tags()1143 tag = self.req.get_tag(tagname)
1144 if tag.is_search_tag():
1145 self.quickadd_entry.set_text(tag.get_attribute("query"))
1146
1147 self.applied_tags = new_taglist
11431148
1144 def on_taskdone_cursor_changed(self, selection=None):1149 def on_taskdone_cursor_changed(self, selection=None):
1145 """Called when selection changes in closed task view.1150 """Called when selection changes in closed task view.
11461151
=== modified file 'GTG/gtk/browser/treeview_factory.py'
--- GTG/gtk/browser/treeview_factory.py 2012-07-13 17:24:28 +0000
+++ GTG/gtk/browser/treeview_factory.py 2012-11-01 10:11:21 +0000
@@ -31,26 +31,6 @@
31from GTG.gtk import colors31from GTG.gtk import colors
32from GTG.tools.dates import Date32from GTG.tools.dates import Date
3333
34
35class AutoExpandTreeView(TreeView):
36 """TreeView which hide the expander column when not needed"""
37
38 def __init__(self, tree, desc):
39 TreeView.__init__(self, tree, desc)
40 self.show_expander = False
41 self.treemodel.connect("row-has-child-toggled", self.__show_expander_col)
42 self.__show_expander_col(self.treemodel, None, None)
43
44 def __has_child(self, model, path, iter):
45 if model.iter_has_child(iter):
46 self.show_expander = True
47 return True
48
49 def __show_expander_col(self, treemodel, path, iter):
50 self.show_expander = False
51 treemodel.foreach(self.__has_child)
52 self.set_show_expanders(self.show_expander)
53
54class TreeviewFactory():34class TreeviewFactory():
5535
56 def __init__(self,requester,config):36 def __init__(self,requester,config):
@@ -311,37 +291,7 @@
311 col['order'] = 3291 col['order'] = 3
312 desc[col_name] = col292 desc[col_name] = col
313293
314 self.enable_update_tags()
315
316 return self.build_tag_treeview(tree,desc)294 return self.build_tag_treeview(tree,desc)
317
318 def enable_update_tags(self):
319 self.tag_cllbcks = []
320
321 tasks = self.req.get_tasks_tree()
322 for event in 'node-added-inview', 'node-modified-inview', 'node-deleted-inview':
323 handle = tasks.register_cllbck(event, self._update_tags)
324 self.tag_cllbcks.append((event, handle))
325
326 def disable_update_tags(self):
327 tasks = self.req.get_tasks_tree()
328 for event, handle in self.tag_cllbcks:
329 tasks.deregister_cllbck(event, handle)
330 self.tag_cllbcks = []
331
332 def _update_tags(self, node_id, path):
333 tree = self.req.get_tag_tree().get_basetree()
334 tree.refresh_node('gtg-tags-all')
335 tree.refresh_node('gtg-tags-none')
336
337 search_parent = self.req.get_tag(CoreConfig.SEARCH_TAG)
338 for search_tag in search_parent.get_children():
339 tree.refresh_node(search_tag)
340
341 task = self.req.get_task(node_id)
342 if task:
343 for t in self.req.get_task(node_id).get_tags():
344 tree.refresh_node(t.get_name())
345 295
346 def active_tasks_treeview(self,tree):296 def active_tasks_treeview(self,tree):
347 #Build the title/label/tags columns297 #Build the title/label/tags columns
@@ -457,7 +407,7 @@
457 407
458 408
459 def build_task_treeview(self,tree,desc):409 def build_task_treeview(self,tree,desc):
460 treeview = AutoExpandTreeView(tree,desc)410 treeview = TreeView(tree,desc)
461 #Now that the treeview is done, we can polish411 #Now that the treeview is done, we can polish
462 treeview.set_main_search_column('label')412 treeview.set_main_search_column('label')
463 treeview.set_expander_column('label')413 treeview.set_expander_column('label')
@@ -474,7 +424,7 @@
474 return treeview424 return treeview
475 425
476 def build_tag_treeview(self,tree,desc):426 def build_tag_treeview(self,tree,desc):
477 treeview = AutoExpandTreeView(tree,desc)427 treeview = TreeView(tree,desc)
478 # Global treeview properties428 # Global treeview properties
479 treeview.set_property("enable-tree-lines", False)429 treeview.set_property("enable-tree-lines", False)
480 treeview.set_rules_hint(False)430 treeview.set_rules_hint(False)
481431
=== modified file 'GTG/tools/import_liblarch.py'
--- GTG/tools/import_liblarch.py 2012-07-23 14:31:44 +0000
+++ GTG/tools/import_liblarch.py 2012-11-01 10:11:21 +0000
@@ -22,7 +22,7 @@
2222
23import sys23import sys
2424
25REQUIRED_LIBLARCH_API = "1.2"25REQUIRED_LIBLARCH_API = "2.1"
26GIT_CMD = "git clone https://github.com/liblarch/liblarch ../liblarch"26GIT_CMD = "git clone https://github.com/liblarch/liblarch ../liblarch"
2727
28def import_liblarch(use_local=False):28def import_liblarch(use_local=False):

Subscribers

People subscribed via source and target branches

to status/vote changes: