~jaap.karssenberg/zim/pyzim-0.43-backports

« back to all changes in this revision

Viewing changes to zim/plugins/tasklist.py

  • Committer: Jaap Karssenberg
  • Date: 2010-01-17 18:15:48 UTC
  • Revision ID: pardus@cpan.org-20100117181548-znbf7jiswarc35gh
* Fixed issue with remove_link while some other text is selected
* Trigger Find after Search for simple queries
* Allow selecting multiple tags in Task List plugin
* Improved color highlighting in Task list
* Allow negative query in task list, like "not @waiting"

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
from zim.parsing import parse_date
12
12
from zim.plugins import PluginClass
13
 
from zim.gui.widgets import Dialog, Button, IconButton, BrowserTreeView
 
13
from zim.gui.widgets import Dialog, Button, IconButton, BrowserTreeView, SingleClickTreeView
14
14
from zim.formats import UNCHECKED_BOX, CHECKED_BOX, XCHECKED_BOX
15
15
 
16
16
 
139
139
                Dialog.do_response(self, response)
140
140
 
141
141
 
142
 
class TagListTreeView(BrowserTreeView):
 
142
class TagListTreeView(SingleClickTreeView):
143
143
        '''TreeView with a single column 'Tags' which shows all tags available
144
144
        in a TaskListTreeView. Selecting a tag will filter the task list to
145
145
        only show tasks with that tag.
147
147
 
148
148
        def __init__(self, task_list):
149
149
                model = gtk.ListStore(str, bool) # tag name, is seperator bool
150
 
                BrowserTreeView.__init__(self, model)
 
150
                SingleClickTreeView.__init__(self, model)
 
151
                self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
151
152
                self.task_list = task_list
152
153
 
153
154
                cell_renderer = gtk.CellRendererText()
158
159
                self.set_row_separator_func(lambda m, i: m[i][1])
159
160
                        # just returns the bool in the second column
160
161
 
 
162
                self.get_selection().connect('changed', self.on_selection_changed)
 
163
 
161
164
                self.on_update(task_list)
162
165
                task_list.connect('updated', self.on_update)
163
166
 
164
 
        def get_tag(self):
165
 
                '''Returns current selected tag, or None for all tags'''
166
 
                model, iter = self.get_selection().get_selected()
167
 
                if model.get_path(iter) == (0,):
 
167
        def get_tags(self):
 
168
                '''Returns current selected tags, or None for all tags'''
 
169
                model, paths = self.get_selection().get_selected_rows()
 
170
                if not paths or (0,) in paths:
168
171
                        return None
169
172
                else:
170
 
                        return model[iter][0]
 
173
                        return [model[path][0] for path in paths]
171
174
 
172
175
        def on_update(self, task_list):
173
176
                model = self.get_model()
178
181
                for tag in sorted(self.task_list.get_tags()):
179
182
                        model.append((tag, False))
180
183
 
181
 
        def do_row_activated(self, path, col):
182
 
                if path == (0,):
183
 
                        self.task_list.set_tag_filter(None)
184
 
                else:
185
 
                        model = self.get_model()
186
 
                        self.task_list.set_tag_filter(model[path][0])
187
 
 
188
 
# Need to register classes defining gobject signals
189
 
gobject.type_register(TagListTreeView)
 
184
        def on_selection_changed(self, selection):
 
185
                tags = self.get_tags()
 
186
                self.task_list.set_tag_filter(tags)
190
187
 
191
188
 
192
189
style = gtk.Label().get_style() # HACK - how to get default style ?
246
243
                def render_prio(col, cell, model, i):
247
244
                        prio = model.get_value(i, self.PRIO_COL)
248
245
                        cell.set_property('text', str(prio))
249
 
                        if prio == 0: color = NORMAL_COLOR
250
 
                        elif prio == self.maxprio: color = HIGH_COLOR
251
 
                        elif prio == self.maxprio - 1: color = MEDIUM_COLOR
252
 
                        elif prio == self.maxprio - 2: color = ALERT_COLOR
 
246
                        if prio >= 3: color = ALERT_COLOR
 
247
                        elif prio == 2: color = MEDIUM_COLOR
 
248
                        elif prio == 1: color = ALERT_COLOR
253
249
                        else: color = NORMAL_COLOR
254
250
                        cell.set_property('cell-background-gdk', color)
255
251
 
272
268
                                cell.set_property('text', date)
273
269
                                # TODO allow strftime here
274
270
                                
275
 
                        if date == today: color = HIGH_COLOR
 
271
                        if date <= today: color = HIGH_COLOR
276
272
                        elif date == tomorrow: color = MEDIUM_COLOR
277
273
                        elif date == dayafter: color = ALERT_COLOR
278
274
                        else: color = NORMAL_COLOR
299
295
                # TODO - switch between tree view and list view
300
296
 
301
297
        def set_filter(self, string):
302
 
                self.filter = string
 
298
                # TODO allow more complex queries here - same parse as for search
 
299
                if string:
 
300
                        inverse = False
 
301
                        if string.lower().startswith('not '):
 
302
                                # Quick HACK to support e.g. "not @waiting"
 
303
                                inverse = True
 
304
                                string = string[4:]
 
305
                        self.filter = (inverse, string.strip())
 
306
                else:
 
307
                        self.filter = None
303
308
                self._eval_filter()
304
309
 
305
310
        def get_tags(self):
 
311
                '''Returns list of all tags that are in use for tasks'''
306
312
                return self.tags.keys()
307
313
 
308
314
        def get_statistics(self):
309
 
                highest = max(self.prio.keys())
310
 
                keys = range(highest+1)
311
 
                stats = [self.prio.get(k, 0) for k in keys]
 
315
                highest = max([0] + self.prio.keys())
 
316
                stats = [self.prio.get(k, 0) for k in range(highest+1)]
312
317
                stats.reverse() # highest first
313
318
                return self.total, stats
314
319
 
315
 
        def set_tag_filter(self, tag):
316
 
                if tag:
317
 
                        self.tag_filter = '@'+tag
 
320
        def set_tag_filter(self, tags):
 
321
                # TODO support multiple tags
 
322
                if tags:
 
323
                        self.tag_filter = ["@"+tag for tag in tags]
318
324
                else:
319
325
                        self.tag_filter = None
320
326
                self._eval_filter()
324
330
                self.real_model.foreach(self._filter_item)
325
331
 
326
332
        def _filter_item(self, model, path, iter):
327
 
                filterout = False
328
 
 
329
 
                if self.tag_filter:
330
 
                        if not self.tag_filter in model[iter][self.TASK_COL]:
331
 
                                filterout |= True
332
 
 
333
 
                if self.filter:
334
 
                        if not (
335
 
                                self.filter in model[iter][self.TASK_COL]
336
 
                                or self.filter in model[iter][self.PAGE_COL]
337
 
                        ):
338
 
                                filterout |= True
339
 
 
340
 
                filterout |= not (
341
 
                        model[iter][self.ACT_COL] and model[iter][self.OPEN_COL]) # TODO
342
 
 
343
 
                model[iter][self.VIS_COL] = not filterout
 
333
                visible = True
 
334
 
 
335
                if not (model[iter][self.ACT_COL] and model[iter][self.OPEN_COL]):
 
336
                        visible = False
 
337
 
 
338
                if visible and self.tag_filter:
 
339
                        match = False
 
340
                        description = model[iter][self.TASK_COL]
 
341
                        for tag in self.tag_filter:
 
342
                                if tag in description:
 
343
                                        match = True
 
344
                                        break
 
345
                        if not match:
 
346
                                visible = False
 
347
 
 
348
                if visible and self.filter:
 
349
                        inverse, string = self.filter
 
350
                        match = string in model[iter][self.TASK_COL] \
 
351
                                or string in model[iter][self.PAGE_COL]
 
352
                        if (not inverse and not match) or (inverse and match):
 
353
                                visible = False
 
354
 
 
355
                model[iter][self.VIS_COL] = visible
344
356
 
345
357
 
346
358
        def do_row_activated(self, path, column):