~remy/+junk/gtg_mydate

« back to all changes in this revision

Viewing changes to GTG/taskbrowser/tagtree.py

  • Committer: Bertrand Rousseau
  • Date: 2009-08-05 12:40:52 UTC
  • mfrom: (246.1.54 refactor)
  • Revision ID: bertrand.rousseau@gmail.com-20090805124052-43xdlce8u6iepwf2
Complete rewrite of task models and tag models. Seems okay. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
import gtk
 
3
import gobject
 
4
 
 
5
from GTG import _
 
6
from GTG.core.task     import Task
 
7
from GTG.tools         import colors
 
8
from GTG.taskbrowser.CellRendererTags import CellRendererTags
 
9
 
 
10
COL_ID    = 0
 
11
COL_NAME  = 1
 
12
COL_LABEL = 2
 
13
COL_OBJ   = 3
 
14
COL_COLOR = 4
 
15
COL_COUNT = 5
 
16
COL_SEP   = 6
 
17
 
 
18
class TagTreeModel(gtk.GenericTreeModel):
 
19
 
 
20
    column_types = (str,\
 
21
                    str,\
 
22
                    str,\
 
23
                    gobject.TYPE_PYOBJECT,\
 
24
                    str,\
 
25
                    str,\
 
26
                    bool)
 
27
 
 
28
    def __init__(self, requester):
 
29
        gtk.GenericTreeModel.__init__(self)
 
30
        self.req  = requester
 
31
        self.tree = self.req.get_tag_tree()
 
32
        self.workable_only = False
 
33
 
 
34
### MODEL METHODS ############################################################
 
35
 
 
36
    def update_tags_for_task(self, tid):
 
37
        task = self.req.get_task(tid)
 
38
        for t in task.get_tags():
 
39
            path = self.tree.get_path_for_node(t)
 
40
            iter = self.get_iter(path)
 
41
            self.row_changed(path, iter)
 
42
 
 
43
    def set_workable_only(self, val):
 
44
        self.workable_only = val
 
45
 
 
46
### TREEMODEL INTERFACE ######################################################
 
47
#
 
48
    def on_get_flags(self):
 
49
        return gtk.TREE_MODEL_ITERS_PERSIST|gtk.TREE_MODEL_LIST_ONLY
 
50
 
 
51
    def on_get_n_columns(self):
 
52
        return len(self.column_types)
 
53
 
 
54
    def on_get_column_type(self, n):
 
55
        return self.column_types[n]
 
56
 
 
57
    def on_get_iter(self, path):
 
58
        #print "on_get_iter: %s" % str(path)
 
59
        return self.tree.get_rowref_for_path(path)
 
60
 
 
61
    def on_get_path(self, rowref):
 
62
        #print "on_get_path: %s" % rowref
 
63
        return self.tree.get_path_for_rowref(rowref)
 
64
 
 
65
    def on_get_value(self, rowref, column):
 
66
        #print "on_get_value: %s" % rowref
 
67
        tag = self.tree.get_node_for_rowref(rowref)
 
68
        if   column == COL_ID:
 
69
            return tag.get_name()
 
70
        if   column == COL_NAME:
 
71
            return tag.get_name()[1:]
 
72
        if   column == COL_LABEL:
 
73
            if tag.get_attribute("label"):
 
74
                return tag.get_attribute("label")
 
75
            else:
 
76
                if tag.get_attribute("nonworkview"):
 
77
                    nwv = eval(tag.get_attribute("nonworkview"))
 
78
                else:
 
79
                    nwv = False
 
80
                if nwv:
 
81
                    return "<span color='#AAAAAA'>%s</span>"\
 
82
                         % tag.get_name()[1:]
 
83
                else:
 
84
                    return tag.get_name()[1:]
 
85
        if   column == COL_OBJ:
 
86
            return tag
 
87
        elif column == COL_COLOR:
 
88
            return task.get_attribute("color")
 
89
        elif column == COL_COUNT:
 
90
            sp_id = tag.get_attribute("special")
 
91
            if not sp_id:
 
92
                count = len(self.req.get_active_tasks_list(\
 
93
                       tags=[tag], workable=self.workable_only))
 
94
                return  count
 
95
            else:
 
96
                if sp_id == "all":
 
97
                    return len(self.req.get_active_tasks_list(\
 
98
                        workable=self.workable_only))
 
99
                elif sp_id == "notag":
 
100
                    return len(self.req.get_active_tasks_list(\
 
101
                        workable=self.workable_only, notag_only=True))
 
102
                else:
 
103
                    return 0
 
104
        elif column == COL_SEP:
 
105
            sp_id = tag.get_attribute("special")
 
106
            if not sp_id:
 
107
                return False
 
108
            else:
 
109
                if sp_id == "sep":
 
110
                    return True
 
111
 
 
112
    def on_iter_next(self, rowref):
 
113
        #print "on_iter_next: %s" % (rowref)
 
114
        node        = self.tree.get_node_for_rowref(rowref)
 
115
        parent_node = node.get_parent()
 
116
        if parent_node:
 
117
            next_idx = parent_node.get_child_index(node.get_id()) + 1
 
118
            if parent_node.get_n_children()-1 < next_idx:
 
119
                return None
 
120
            else:
 
121
                return self.tree.get_rowref_for_node(\
 
122
                    parent_node.get_nth_child(next_idx))
 
123
        else:
 
124
            return None
 
125
 
 
126
    def on_iter_children(self, rowref):
 
127
        #print "on_iter_children: %s" % (rowref)
 
128
        if rowref:
 
129
            node = self.tree.get_node_for_rowref(rowref)
 
130
            if node.has_child():
 
131
                return self.tree.get_rowref_for_node(node.get_nth_child(0))
 
132
            else:
 
133
                return None
 
134
        else:
 
135
            node = self.root.get_nth_child(0)
 
136
            return self.tree.get_rowref_for_node(node)
 
137
 
 
138
    def on_iter_has_child(self, rowref):
 
139
        #print "on_iter_has_child: %s" % (rowref)
 
140
        node = self.tree.get_node_for_rowref(rowref)
 
141
        return node.has_child()
 
142
 
 
143
    def on_iter_n_children(self, rowref):
 
144
        #print "on_iter_n_children: %s" % (rowref)
 
145
        if rowref:
 
146
            node = self.tree.get_node_for_rowref(rowref)
 
147
        else:
 
148
            node = self.tree.get_root()
 
149
        return node.get_n_children()
 
150
 
 
151
    def on_iter_nth_child(self, rowref, n):
 
152
        #print "on_iter_nth_child: %s %d" % (rowref, n)
 
153
        if rowref:
 
154
            node = self.tree.get_node_from_rowref(rowref)
 
155
        else:
 
156
            node = self.tree.get_root()
 
157
        nth_child = node.get_nth_child(n)
 
158
        return self.tree.get_rowref_for_node(nth_child)
 
159
 
 
160
    def on_iter_parent(self, rowref):
 
161
        #print "on_iter_parent: %s" % (rowref)
 
162
        node = self.tree.get_node_from_rowref(rowref)
 
163
        if node.has_parent():
 
164
            parent = node.get_parent()
 
165
            return self.tree.get_rowref_for_node(parent)
 
166
        else:
 
167
            return None
 
168
 
 
169
    def add_tag(self, tname, tag):
 
170
        root      = self.tree.get_root()
 
171
        root.add_child(tname, tag)
 
172
        tag.set_parent(root)
 
173
        tag_index = root.get_child_index(tname)
 
174
        tag_path  = (tag_index,)
 
175
        tag_iter  = self.get_iter(tag_path)
 
176
        self.row_inserted(tag_path, tag_iter)
 
177
#
 
178
#    def remove_task(self, tid):
 
179
#        # get the task
 
180
#        task = self.req.get_task(tid)
 
181
#        # Remove every row of this task
 
182
#        if task.has_parents():
 
183
#            # get every paths leading to this task
 
184
#            path_list = self._get_paths_for_task(task)
 
185
#            # remove every path
 
186
#            for task_path in path_list:
 
187
#                self.row_deleted(task_path)
 
188
#        if tid in self.root_tasks:
 
189
#            task_index = self._get_root_task_index(tid)
 
190
#            task_path  = (task_index,)
 
191
#            task_iter  = self.get_iter(task_path)
 
192
#            self.row_deleted(task_path)
 
193
#            self.root_tasks.remove(tid)
 
194
#                    
 
195
#    def move_task(self, parent, child):
 
196
#        #print "Moving %s below %s" % (child, parent)
 
197
#        # Get child
 
198
#        child_tid  = self.get_value(child, COL_TID)
 
199
#        child_task = self.req.get_task(child_tid)
 
200
#        child_path = self.get_path(child)
 
201
#        # Get old parent
 
202
#        old_par = self.iter_parent(child)
 
203
#        if old_par:
 
204
#            old_par_tid  = self.get_value(old_par, COL_TID)
 
205
#            old_par_task = self.req.get_task(old_par_tid)
 
206
#        else:
 
207
#            old_par_task = None
 
208
#        # Get new parent
 
209
#        if parent:
 
210
#            new_par_tid  = self.get_value(parent, COL_TID)
 
211
#            new_par_task = self.req.get_task(new_par_tid)
 
212
#        else:
 
213
#            new_par_task = None
 
214
#        # Remove child from old parent
 
215
#        if old_par_task:
 
216
#            old_par_task.remove_subtask(child_tid)
 
217
#        else:
 
218
#            self.root_tasks.remove(child_tid)
 
219
#        # Remove old parent from child
 
220
#        if old_par_task:
 
221
#            child_task.remove_parent(old_par_tid)
 
222
#        # Add child to new parent (add_subtask also add new parent to child)
 
223
#        if new_par_task:
 
224
#            new_par_task.add_subtask(child_tid)
 
225
#        else:
 
226
#            self.root_tasks.append(child_tid)
 
227
#        # Warn tree about deleted row
 
228
#        self.row_deleted(child_path)
 
229
#        # Warn tree about inserted row
 
230
#        if new_par_task:
 
231
#            new_child_index = new_par_task.get_subtask_index(child_tid)
 
232
#        else:
 
233
#            new_child_index = self._get_root_task_index(child_tid)
 
234
#        if parent:
 
235
#            new_child_path = self.get_path(parent) + (new_child_index,)
 
236
#        else:
 
237
#            new_child_path = (new_child_index,)
 
238
#        new_child_iter = self.get_iter(new_child_path)
 
239
#        self.row_inserted(new_child_path, new_child_iter)
 
240
 
 
241
class TagTreeView(gtk.TreeView):
 
242
    """TreeView for display of a list of task. Handles DnD primitives too."""
 
243
 
 
244
    DND_TARGETS = [
 
245
        ('gtg/task-iter-str', gtk.TARGET_SAME_WIDGET, 0)
 
246
    ]
 
247
 
 
248
    def __init__(self):
 
249
        gtk.TreeView.__init__(self)
 
250
        self.show()
 
251
        self._init_tree_view()
 
252
 
 
253
        # Drag and drop
 
254
#        self.enable_model_drag_source(\
 
255
#            gtk.gdk.BUTTON1_MASK,
 
256
#            self.DND_TARGETS,
 
257
#            gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
 
258
#        self.enable_model_drag_dest(\
 
259
#            self.DND_TARGETS,
 
260
#            gtk.gdk.ACTION_DEFAULT)
 
261
 
262
#        self.drag_source_set(\
 
263
#            gtk.gdk.BUTTON1_MASK,
 
264
#            self.DND_TARGETS,
 
265
#            gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
 
266
#
 
267
#        self.drag_dest_set(\
 
268
#            gtk.DEST_DEFAULT_ALL,
 
269
#            self.DND_TARGETS,
 
270
#            gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
 
271
#
 
272
#        self.connect('drag_drop', self.on_drag_drop)
 
273
#        self.connect('drag_data_get', self.on_drag_data_get)
 
274
#        self.connect('drag_data_received', self.on_drag_data_received)
 
275
 
 
276
    def refresh(self):
 
277
        self.get_model().foreach(self._refresh_func)
 
278
 
 
279
    def _refresh_func(self, model, path, iter, user_data=None):
 
280
        model.row_changed(path, iter)
 
281
 
 
282
    def _tag_separator_filter(self, model, itera, user_data=None):
 
283
        return self.get_model().get_value(itera, COL_SEP)
 
284
 
 
285
    def _init_tree_view(self):
 
286
        
 
287
         # Tag column
 
288
        tag_col      = gtk.TreeViewColumn()
 
289
        render_text  = gtk.CellRendererText()
 
290
        render_count = gtk.CellRendererText()
 
291
        render_tags  = CellRendererTags()
 
292
        tag_col.set_title(_("Tags"))
 
293
        tag_col.set_clickable(False)
 
294
        tag_col.pack_start(render_tags, expand=False)
 
295
        tag_col.set_attributes(render_tags, tag=COL_OBJ)
 
296
        tag_col.pack_start(render_text, expand=True)
 
297
        tag_col.set_attributes(render_text, markup=COL_LABEL)
 
298
        tag_col.pack_end(render_count, expand=False)
 
299
        tag_col.set_attributes(render_count, markup=COL_COUNT)
 
300
        render_count.set_property("foreground", "#888a85")
 
301
        render_count.set_property('xalign', 1.0)
 
302
        render_tags.set_property('ypad', 3)
 
303
        render_text.set_property('ypad', 3)
 
304
        render_count.set_property('xpad', 3)
 
305
        render_count.set_property('ypad', 3)
 
306
        tag_col.set_sort_column_id(-1)
 
307
        tag_col.set_expand(True)
 
308
        self.append_column(tag_col)
 
309
 
 
310
        # Global treeview properties
 
311
        self.set_row_separator_func(self._tag_separator_filter)
 
312
        self.set_headers_visible(False)
 
313
 
 
314
    ### DRAG AND DROP ########################################################
 
315
 
 
316
#    def on_drag_drop(self, treeview, context, selection, info, timestamp):
 
317
#        self.emit_stop_by_name('drag_drop')
 
318
#
 
319
#    def on_drag_data_get(self, treeview, context, selection, info, timestamp):
 
320
#        """Extract data from the source of the DnD operation. Here the id of
 
321
#        the parent task and the id of the selected task is passed to the
 
322
#        destination"""
 
323
#        treeselection = treeview.get_selection()
 
324
#        model, iter = treeselection.get_selected()
 
325
#        iter_str = model.get_string_from_iter(iter)
 
326
#        selection.set('gtg/task-iter-str', 0, iter_str)
 
327
#        return
 
328
#
 
329
#    def on_drag_data_received(self, treeview, context, x, y, selection, info,\
 
330
#                              timestamp):
 
331
#
 
332
#        model          = treeview.get_model()
 
333
#        model_filter   = model.get_model()
 
334
#        tasktree_model = model_filter.get_model()
 
335
#
 
336
#        drop_info = treeview.get_dest_row_at_pos(x, y)
 
337
#
 
338
#        if drop_info:
 
339
#            path, position = drop_info
 
340
#            iter = model.get_iter(path)
 
341
#            if position == gtk.TREE_VIEW_DROP_BEFORE or\
 
342
#               position == gtk.TREE_VIEW_DROP_AFTER:
 
343
#                # Must add the task to the parent of the task situated\
 
344
#                # before/after
 
345
#                # Get sibling parent
 
346
#                par_iter = model.iter_parent(iter)
 
347
#            else:
 
348
#                # Must add task as a child of the dropped-on iter
 
349
#                # Get parent
 
350
#                par_iter = iter
 
351
#        else:
 
352
#            # Must add the task to the root
 
353
#            # Parent = root => iter=None
 
354
#            par_iter = None
 
355
#
 
356
#        # Get parent iter as a TaskTreeModel iter
 
357
#        if par_iter:
 
358
#            par_iter_filter   =\
 
359
#                model.convert_iter_to_child_iter(None, par_iter)
 
360
#            par_iter_tasktree =\
 
361
#                model_filter.convert_iter_to_child_iter(par_iter_filter)
 
362
#        else:
 
363
#            par_iter_tasktree = None
 
364
#
 
365
#        # Get dragged iter as a TaskTreeModel iter
 
366
#        drag_iter = model.get_iter_from_string(selection.data)
 
367
#        drag_iter_filter   =\
 
368
#            model.convert_iter_to_child_iter(None, drag_iter)
 
369
#        drag_iter_tasktree =\
 
370
#            model_filter.convert_iter_to_child_iter(drag_iter_filter)
 
371
#        tasktree_model.move_task(par_iter_tasktree, drag_iter_tasktree)
 
372
#
 
373
#        self.emit_stop_by_name('drag_data_received')