Subversion Repositories basico

Rev

Rev 378 | Rev 380 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
340 t00mlabs 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
"""
4
# File: wdg_visor_annotations.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: SAPNoteViewVisor widgets
8
"""
9
 
10
import os
11
from os.path import sep as SEP
12
from html import escape
13
import glob
14
import json
15
import html
16
 
17
import gi
18
gi.require_version('Gdk', '3.0')
19
gi.require_version('Gtk', '3.0')
20
from gi.repository import Gdk
21
from gi.repository import Gio
22
from gi.repository import Gtk
23
from gi.repository.GdkPixbuf import Pixbuf
24
from gi.repository import Pango
25
 
26
from basico.core.mod_env import LPATH, ATYPES
27
from basico.core.mod_wdg import BasicoWidget
28
from basico.widgets.wdg_cols import CollectionsMgtView
29
from basico.widgets.wdg_import import ImportWidget
30
 
31
 
32
class AnnotationsVisor(BasicoWidget, Gtk.HBox):
33
    def __init__(self, app):
34
        super().__init__(app, __class__.__name__)
35
        Gtk.HBox.__init__(self, app)
36
        self.set_homogeneous(False)
37
        self.bag = []
38
        self.get_services()
39
        self.setup_left_panel()
40
        self.set_initial_panel_button_status()
41
        self.setup_visor()
42
        self.icons = {}
43
        self.icons['type'] = {}
44
        for atype in ATYPES:
45
            self.icons['type'][atype.lower()] = self.srvicm.get_pixbuf_icon('basico-annotation-type-%s' % atype.lower())
46
        self.log.debug("Annotation Visor initialized")
47
 
48
 
49
    def get_services(self):
50
        self.srvgui = self.get_service("GUI")
51
        self.srvclb = self.get_service('Callbacks')
52
        self.srvsap = self.get_service('SAP')
53
        self.srvicm = self.get_service('IM')
54
        self.srvstg = self.get_service('Settings')
55
        self.srvdtb = self.get_service('DB')
56
        self.srvuif = self.get_service("UIF")
57
        self.srvutl = self.get_service("Utils")
58
        self.srvant = self.get_service('Annotation')
59
 
60
 
61
    def set_initial_panel_button_status(self):
62
        # Categories
63
        self.srvgui.set_key_value('ANNOTATIONS_CATEGORY_INBOX_VISIBLE', True)
64
        self.srvgui.set_key_value('ANNOTATIONS_CATEGORY_DRAFTS_VISIBLE', False)
65
        self.srvgui.set_key_value('ANNOTATIONS_CATEGORY_ARCHIVED_VISIBLE', False)
66
 
67
        # Types
68
        for atype in ATYPES:
69
            self.srvgui.set_key_value('ANNOTATIONS_TYPE_%s_VISIBLE' % atype.upper(), True)
70
 
71
        # Priorty
72
        for priority in ['High', 'Normal', 'Low']:
73
            self.srvgui.set_key_value('ANNOTATIONS_PRIORITY_%s_VISIBLE' % priority.upper(), True)
74
 
369 t00mlabs 75
 
340 t00mlabs 76
    def get_treeview(self):
77
        return self.treeview
78
 
79
 
80
    def sort_by_timestamp(self):
81
        self.sorted_model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
82
 
83
 
84
    def setup_left_panel(self):
85
        pass
86
 
87
 
88
    def set_visible_categories(self, togglebutton):
89
        types = self.srvgui.get_widget('gtk_togglebutton_types')
90
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_categories')
91
 
92
        active = togglebutton.get_active()
93
        if active:
94
            types.set_active(False)
95
        revealer.set_reveal_child(active)
96
 
97
 
98
    def set_visible_types(self, togglebutton):
99
        categories = self.srvgui.get_widget('gtk_togglebutton_categories')
100
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_types')
101
 
102
        active = togglebutton.get_active()
103
        if active:
104
            categories.set_active(False)
105
        revealer.set_reveal_child(active)
106
 
107
 
108
    def set_visible_priority(self, togglebutton):
109
        categories = self.srvgui.get_widget('gtk_togglebutton_categories')
110
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_priority')
111
 
112
        active = togglebutton.get_active()
113
        if active:
114
            priority.set_active(False)
115
        revealer.set_reveal_child(active)
116
 
117
 
118
    def set_visible_category(self, togglebutton, title):
119
        active = togglebutton.get_active()
120
        self.srvgui.set_key_value('ANNOTATIONS_CATEGORY_%s_VISIBLE' % title.upper(), active)
369 t00mlabs 121
        self.set_bag()
362 t00mlabs 122
        self.populate()
340 t00mlabs 123
 
124
 
125
    def set_visible_annotation_type(self, togglebutton, atype):
126
        active = togglebutton.get_active()
127
        self.srvgui.set_key_value('ANNOTATIONS_TYPE_%s_VISIBLE' % atype.upper(), active)
369 t00mlabs 128
        self.set_bag()
362 t00mlabs 129
        self.populate()
340 t00mlabs 130
 
131
 
132
    def set_visible_priority(self, togglebutton, title):
133
        active = togglebutton.get_active()
134
        self.srvgui.set_key_value('ANNOTATIONS_PRIORITY_%s_VISIBLE' % title.upper(), active)
369 t00mlabs 135
        self.set_bag()
362 t00mlabs 136
        self.populate()
340 t00mlabs 137
 
138
 
139
    def setup_visor(self):
140
        scr = Gtk.ScrolledWindow()
141
        scr.set_hexpand(True)
142
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
143
        scr.set_shadow_type(Gtk.ShadowType.NONE)
144
        self.treeview = Gtk.TreeView()
145
        scr.add(self.treeview)
146
        scr.set_hexpand(True)
147
        self.pack_start(scr, True, True, 0)
148
 
149
        # Setup model
377 t00mlabs 150
        self.model = Gtk.ListStore(
340 t00mlabs 151
            int,        # key
351 t00mlabs 152
            Pixbuf,     # Icon
340 t00mlabs 153
            int,        # checkbox
154
            str,        # sid
155
            str,        # title
156
            str,        # component
157
            str,        # category
158
            str,        # type
159
            str,        # priority
160
            str,        # last update
161
            str,        # Annotation Id (extra key)
351 t00mlabs 162
            str,        # Timestamp updated
163
            str,        # Annotation created
164
            str,        # Timestamp created
340 t00mlabs 165
        )
367 t00mlabs 166
        self.srvgui.add_widget('gtk_model_annotation', self.model)
340 t00mlabs 167
 
168
        # Setup columns
169
        def get_column_header_widget(title, icon_name=None, width=24, height=24):
170
            hbox = Gtk.HBox()
171
            icon = self.srvicm.get_new_image_icon(icon_name, width, height)
172
            label = Gtk.Label()
173
            label.set_markup("<b>%s</b>" % title)
174
            # ~ label.modify_font(Pango.FontDescription('Monospace 10'))
175
            hbox.pack_start(icon, False, False, 3)
176
            hbox.pack_start(label, True, True, 3)
177
            hbox.show_all()
178
            return hbox
179
 
180
        # SAP Note key
181
        self.renderer_key = Gtk.CellRendererText()
182
        self.column_key = Gtk.TreeViewColumn('Key', self.renderer_key, text=0)
183
        self.column_key.set_visible(False)
184
        self.column_key.set_expand(False)
185
        self.column_key.set_clickable(False)
186
        self.column_key.set_sort_indicator(True)
187
        self.treeview.append_column(self.column_key)
188
 
189
        # Icon
190
        self.renderer_icon = Gtk.CellRendererPixbuf()
191
        self.renderer_icon.set_alignment(0.0, 0.5)
192
        self.column_icon = Gtk.TreeViewColumn('', self.renderer_icon, pixbuf=1)
193
        widget = get_column_header_widget('', 'basico-empty')
194
        self.column_icon.set_widget(widget)
195
        self.column_icon.set_visible(True)
196
        self.column_icon.set_expand(False)
197
        self.column_icon.set_clickable(False)
198
        self.column_icon.set_sort_indicator(True)
199
        self.treeview.append_column(self.column_icon)
200
 
201
        # SAP Note Checkbox
202
        self.renderer_checkbox = Gtk.CellRendererToggle()
203
        self.renderer_checkbox.connect("toggled", self.toggle_checkbox)
204
        self.column_checkbox = Gtk.TreeViewColumn('', self.renderer_checkbox, active=2)
205
        self.column_checkbox.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
377 t00mlabs 206
        self.column_checkbox.set_visible(True)
340 t00mlabs 207
        self.column_checkbox.set_expand(False)
208
        self.column_checkbox.set_clickable(True)
209
        self.column_checkbox.set_sort_indicator(True)
210
        self.column_checkbox.set_property('spacing', 50)
211
        self.treeview.append_column(self.column_checkbox)
212
 
213
        # SAP Note Id
214
        self.renderer_sid = Gtk.CellRendererText()
215
        self.renderer_sid.set_property('xalign', 1.0)
216
        self.renderer_sid.set_property('height', 36)
217
        self.renderer_sid.set_property('background', '#F0E3E3')
218
        self.column_sid = Gtk.TreeViewColumn('SAP Note Id', self.renderer_sid, markup=3)
219
        widget = get_column_header_widget('SAP Note Id', 'basico-sid')
220
        self.column_sid.set_widget(widget)
221
        self.column_sid.set_visible(True)
222
        self.column_sid.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
223
        self.column_sid.set_expand(False)
224
        self.column_sid.set_clickable(True)
225
        self.column_sid.set_sort_indicator(True)
226
        self.column_sid.set_sort_column_id(0)
227
        self.treeview.append_column(self.column_sid)
228
 
229
        # SAP Note title
230
        self.renderer_title = Gtk.CellRendererText()
231
        self.renderer_title.set_property('background', '#FFFEEA')
232
        self.renderer_title.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
233
        self.column_title = Gtk.TreeViewColumn('Title', self.renderer_title, markup=4)
234
        widget = get_column_header_widget('Title', 'basico-tag')
235
        self.column_title.set_widget(widget)
236
        self.column_title.set_visible(True)
237
        self.column_title.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
238
        self.column_title.set_expand(True)
239
        self.column_title.set_clickable(True)
240
        self.column_title.set_sort_indicator(True)
241
        self.column_title.set_sort_column_id(4)
242
        self.treeview.append_column(self.column_title)
243
 
244
        # SAP Note Component
245
        self.renderer_component = Gtk.CellRendererText()
246
        self.renderer_component.set_property('background', '#E3E3F0')
247
        self.column_component = Gtk.TreeViewColumn('Component', self.renderer_component, markup=5)
248
        widget = get_column_header_widget('Component', 'basico-component')
249
        self.column_component.set_widget(widget)
250
        self.column_component.set_visible(True)
251
        self.column_component.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
252
        self.column_component.set_expand(False)
253
        self.column_component.set_clickable(True)
254
        self.column_component.set_sort_indicator(True)
255
        self.column_component.set_sort_column_id(5)
256
        self.treeview.append_column(self.column_component)
257
 
258
        # SAP Note Category
259
        self.renderer_category = Gtk.CellRendererText()
260
        self.renderer_category.set_property('background', '#E3F1E3')
261
        self.column_category = Gtk.TreeViewColumn('Category', self.renderer_category, markup=6)
262
        widget = get_column_header_widget('Category', 'basico-category')
263
        self.column_category.set_widget(widget)
264
        self.column_category.set_visible(False)
265
        self.column_category.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
266
        self.column_category.set_expand(False)
267
        self.column_category.set_clickable(True)
268
        self.column_category.set_sort_indicator(True)
269
        self.column_category.set_sort_column_id(6)
270
        self.treeview.append_column(self.column_category)
271
 
272
        # SAP Note Type
273
        self.renderer_type = Gtk.CellRendererText()
274
        self.renderer_type.set_property('background', '#DADAFF')
275
        self.column_type = Gtk.TreeViewColumn('Type', self.renderer_type, markup=7)
276
        self.column_type.set_visible(True)
277
        self.column_type.set_expand(False)
278
        self.column_type.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
279
        self.column_type.set_clickable(True)
280
        self.column_type.set_sort_indicator(True)
281
        self.column_type.set_sort_column_id(7)
282
        self.treeview.append_column(self.column_type)
283
 
284
        # SAP Note Priority
285
        self.renderer_priority = Gtk.CellRendererText()
286
        self.renderer_priority.set_property('background', '#e4f1f1')
287
        self.column_priority = Gtk.TreeViewColumn('Priority', self.renderer_priority, markup=8)
288
        self.column_priority.set_visible(True)
289
        self.column_priority.set_expand(False)
290
        self.column_priority.set_clickable(True)
291
        self.column_priority.set_sort_indicator(True)
292
        self.column_priority.set_sort_column_id(8)
293
        self.treeview.append_column(self.column_priority)
294
 
351 t00mlabs 295
        # Annotation Updated On
340 t00mlabs 296
        self.renderer_updated = Gtk.CellRendererText()
297
        self.renderer_updated.set_property('background', '#FFE6D1')
351 t00mlabs 298
        self.column_updated = Gtk.TreeViewColumn('Updated', self.renderer_updated, markup=9)
340 t00mlabs 299
        self.column_updated.set_visible(True)
300
        self.column_updated.set_expand(False)
301
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
302
        self.column_updated.set_clickable(True)
303
        self.column_updated.set_sort_indicator(True)
304
        self.column_updated.set_sort_column_id(11)
305
        self.column_updated.set_sort_order(Gtk.SortType.DESCENDING)
306
        self.model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
307
        self.treeview.append_column(self.column_updated)
308
 
309
        # Annotation Id
310
        self.renderer_annotation = Gtk.CellRendererText()
311
        self.column_annotation = Gtk.TreeViewColumn('Annotation Id', self.renderer_annotation, markup=10)
312
        self.column_annotation.set_visible(False)
313
        self.column_annotation.set_expand(False)
314
        self.column_annotation.set_clickable(False)
315
        self.column_annotation.set_sort_indicator(True)
316
        self.treeview.append_column(self.column_annotation)
317
 
351 t00mlabs 318
        # Timestamp updated
319
        self.renderer_timestamp = Gtk.CellRendererText()
320
        self.column_timestamp = Gtk.TreeViewColumn('Timestamp updated', self.renderer_timestamp, text=11)
321
        self.column_timestamp.set_visible(False)
322
        self.column_timestamp.set_expand(False)
323
        self.column_timestamp.set_clickable(False)
324
        self.column_timestamp.set_sort_indicator(True)
325
        self.column_timestamp.set_sort_column_id(11)
326
        self.column_timestamp.set_sort_order(Gtk.SortType.ASCENDING)
327
        self.treeview.append_column(self.column_timestamp)
328
 
329
        # Annotation Created On
330
        self.renderer_updated = Gtk.CellRendererText()
331
        self.renderer_updated.set_property('background', '#FFE6D1')
332
        self.column_updated = Gtk.TreeViewColumn('Created', self.renderer_updated, markup=12)
333
        self.column_updated.set_visible(True)
334
        self.column_updated.set_expand(False)
335
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
336
        self.column_updated.set_clickable(True)
337
        self.column_updated.set_sort_indicator(True)
338
        self.column_updated.set_sort_column_id(13)
339
        self.column_updated.set_sort_order(Gtk.SortType.DESCENDING)
340
        self.model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
341
        self.treeview.append_column(self.column_updated)
342
 
340 t00mlabs 343
        # Timestamp
344
        self.renderer_timestamp = Gtk.CellRendererText()
351 t00mlabs 345
        self.column_timestamp = Gtk.TreeViewColumn('Timestamp created', self.renderer_timestamp, text=13)
340 t00mlabs 346
        self.column_timestamp.set_visible(False)
347
        self.column_timestamp.set_expand(False)
348
        self.column_timestamp.set_clickable(False)
349
        self.column_timestamp.set_sort_indicator(True)
350
        self.column_timestamp.set_sort_column_id(11)
351
        self.column_timestamp.set_sort_order(Gtk.SortType.ASCENDING)
352
        self.treeview.append_column(self.column_timestamp)
377 t00mlabs 353
 
340 t00mlabs 354
        # Treeview properties
355
        self.treeview.set_can_focus(False)
356
        self.treeview.set_enable_tree_lines(True)
357
        self.treeview.set_headers_visible(True)
358
        self.treeview.set_enable_search(True)
359
        self.treeview.set_hover_selection(False)
360
        self.treeview.set_grid_lines(Gtk.TreeViewGridLines.NONE)
361
        self.treeview.set_enable_tree_lines(True)
362
        self.treeview.set_level_indentation(10)
362 t00mlabs 363
        self.treeview.connect('button_press_event', self.row_right_click)
340 t00mlabs 364
 
359 t00mlabs 365
        self.treeview.modify_font(Pango.FontDescription('Monospace 9'))
377 t00mlabs 366
 
340 t00mlabs 367
        # DOC: In order to have a Gtk.Widged with sorting and filtering
368
        # capabilities, you have to filter the model first, and use this
369
        # new model to create the sorted model. Then, attach the sorted
370
        # model to the treeview...
371
 
372
        # Treeview filtering:
373
        self.visible_filter = self.model.filter_new()
374
        self.visible_filter.set_visible_func(self.visible_function)
375
 
376
        # TreeView sorting
377
        self.sorted_model = Gtk.TreeModelSort(model=self.visible_filter)
378
        self.sorted_model.set_sort_func(0, self.sort_function, None)
379
 
380
        # Selection
381
        self.selection = self.treeview.get_selection()
382
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)
383
        self.selection.connect('changed', self.row_changed)
384
 
385
        # Set model (filtered and sorted)
386
        self.sorted_model.set_sort_column_id(9, Gtk.SortType.ASCENDING)
387
        self.treeview.set_model(self.sorted_model)
388
 
361 t00mlabs 389
        # Other signals
362 t00mlabs 390
        self.treeview.connect('row-activated', self.row_double_click)
361 t00mlabs 391
 
340 t00mlabs 392
        self.show_all()
393
 
394
 
395
    def sort_function(self, model, row1, row2, user_data):
396
        sort_column = 0
397
 
398
        value1 = model.get_value(row1, sort_column)
399
        value2 = model.get_value(row2, sort_column)
400
 
401
        if value1 < value2:
402
            return -1
403
        elif value1 == value2:
404
            return 0
405
        else:
406
            return 1
407
 
408
 
409
    def always_visible(self, model, itr, data):
410
        return False
411
 
412
 
413
    def visible_function(self, model, itr, data):
414
        entry = self.srvgui.get_widget('gtk_entry_filter_visor')
415
        text = self.srvutl.clean_html(entry.get_text())
416
        title = model.get(itr, 4)[0]
417
        match = text.upper() in title.upper()
418
 
419
        return match
420
 
421
 
422
    def update_total_annotations_count(self):
423
        statusbar = self.srvgui.get_widget('widget_statusbar')
424
        lblnotescount = self.srvgui.get_widget('gtk_label_total_notes')
425
        total = self.srvant.get_total()
426
        count = len(self.visible_filter)
427
        lblnotescount.set_markup("<b>%d/<big>%d annotations</big></b>" % (count, total))
428
        msg = 'View populated with %d annotations' % count
429
        self.srvuif.statusbar_msg(msg)
430
 
431
 
432
    def get_visible_filter(self):
433
        return self.visible_filter
434
 
435
 
367 t00mlabs 436
    def row_current(self, *args):
437
        selection = self.treeview.get_selection()
438
        model, treeiter = selection.get_selected()
439
        return treeiter
440
 
377 t00mlabs 441
 
367 t00mlabs 442
    def row_previous(self, *args):
443
        selection = self.treeview.get_selection()
444
        model, iter_current = selection.get_selected()
445
        if iter_current is not None:
446
            iter_previous = model.iter_previous(iter_current)
447
            if iter_previous:
448
                selection.select_iter(iter_previous)
449
 
377 t00mlabs 450
 
367 t00mlabs 451
    def row_next(self, *args):
452
        selection = self.treeview.get_selection()
453
        model, iter_current = selection.get_selected()
454
        if iter_current is not None:
455
            iter_next = model.iter_next(iter_current)
456
            if iter_next:
457
                selection.select_iter(iter_next)
458
                path, col = self.treeview.get_cursor()
459
                row = self.srvuif.tree_path_to_row(path)
460
                self.treeview.scroll_to_cell(row, column=None, use_align=False, row_align=0.5, col_align=0)
461
 
462
 
377 t00mlabs 463
    def rows_toggled(self):
464
        selected = []
465
 
466
        def get_selected_sapnotes(model, path, itr):
467
            aid = self.sorted_model.get(itr, 10)[0]
468
            checked = self.sorted_model.get(itr, 2)[0]
469
            if checked:
470
                selected.append(str(aid))
471
 
472
        self.sorted_model.foreach(get_selected_sapnotes)
473
        return selected
474
 
475
 
340 t00mlabs 476
    def row_changed(self, selection):
477
        try:
478
            model, treeiter = selection.get_selected()
479
            if treeiter is not None:
480
                component = model[treeiter][5]
481
                if component == 'Annotation':
482
                    aid = model[treeiter][10]
483
                    is_valid = self.srvant.is_valid(aid)
484
                    if is_valid:
361 t00mlabs 485
                        widget_annotation = self.srvgui.get_widget('widget_annotation')
486
                        widget_annotation.set_metadata_to_widget(aid)
487
                        # ~ self.srvclb.action_annotation_edit(aid)
340 t00mlabs 488
                else:
489
                    aid = None
377 t00mlabs 490
                    self.srvuif.set_widget_visibility('gtk_vbox_container_annotations', False)
340 t00mlabs 491
        except Exception as error:
361 t00mlabs 492
            pass
493
            # ~ head = "Error reading annotation's contents"
494
            # ~ body = "<i>%s</i>\n\n" % error
495
            # ~ body += "As a workaround, a new file will be created"
496
            # ~ dialog = self.srvuif.message_dialog_error(head, body)
497
            # ~ self.log.debug(error)
498
            # ~ self.log.debug(self.get_traceback())
499
            # ~ dialog.run()
500
            # ~ dialog.destroy()
340 t00mlabs 501
            #FIXME: create an empty file for contents
502
 
503
 
504
    def toggle_checkbox(self, cell, path):
377 t00mlabs 505
        model = self.sorted_model.get_model()
506
        # ~ path = model.convert_path_to_child_path(Gtk.TreePath(path))
507
        model[path][2] = not model[path][2]
340 t00mlabs 508
 
509
 
351 t00mlabs 510
    def get_node(self, key, icon, checkbox, sid, title, component, category='', sntype='', priority='', updated='', aid='', ts_updated='', created='', ts_created=''):
340 t00mlabs 511
        # Add completion entries
512
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
513
        completion_model = completion.get_model()
514
        title = self.srvutl.clean_html(title)
515
        completion_model.append([title])
516
 
517
        node = []
518
        node.append(key)
519
        node.append(icon)
520
        node.append(checkbox)
521
        node.append(sid)
522
        node.append(title)
523
        node.append(component)
524
        node.append(category)
525
        node.append(sntype)
526
        node.append(priority)
527
        node.append(updated)
528
        node.append(aid) # Extra key for annotations id (aid)
351 t00mlabs 529
        node.append(ts_updated)
530
        node.append(created)
531
        node.append(ts_created)
340 t00mlabs 532
        return node
533
 
534
 
369 t00mlabs 535
    def set_bag(self, annotations=None):
340 t00mlabs 536
        self.bag = annotations
537
 
538
 
539
    def get_bag(self):
540
        return self.bag
541
 
542
 
543
    def reload(self):
544
        bag = self.get_bag()
362 t00mlabs 545
        self.populate(bag)
340 t00mlabs 546
 
547
 
362 t00mlabs 548
    def populate(self, annotations=None):
340 t00mlabs 549
        self.column_sid.set_visible(False)
377 t00mlabs 550
        self.column_checkbox.set_visible(True)
340 t00mlabs 551
        self.column_category.set_visible(True)
552
        self.column_component.set_visible(False)
553
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
554
        completion_model = completion.get_model()
555
        completion_model.clear()
556
 
557
        self.treeview.set_model(None)
558
        self.model.clear()
559
 
560
        if annotations is None:
369 t00mlabs 561
            annotations = self.get_bag()
562
            if annotations is None:
563
                annotations = self.srvant.get_all()
564
                self.log.debug("Displaying all annotations")
565
            else:
566
                self.log.debug("Displaying last query")
340 t00mlabs 567
        else:
369 t00mlabs 568
            self.log.debug("Displaying following annotations: %s", annotations)
340 t00mlabs 569
            self.set_bag(annotations)
570
 
571
        dcats = {}
572
        snpids = {}
573
        nodes = []
574
        for fname in annotations:
575
            try:
576
                with open(fname, 'r') as fa:
577
                    try:
578
                        annotation = json.load(fa)
369 t00mlabs 579
                        # ~ self.log.debug("Annotation: %s", annotation['Title'])
340 t00mlabs 580
                        category = annotation['Category']
581
                        atype = annotation['Type']
582
                        cat_key = 'ANNOTATIONS_CATEGORY_%s_VISIBLE' % category.upper()
583
                        type_key = 'ANNOTATIONS_TYPE_%s_VISIBLE' % atype.upper()
584
                        category_active = self.srvgui.get_key_value(cat_key)
585
                        try:
586
                            type_active = self.srvgui.get_key_value(type_key)
587
                        except Exception as error:
588
                            self.log.error(error)
589
                            type_active = True
590
                        if category_active:
591
                            if type_active:
592
                                ppid = None
593
                                sid = self.srvant.get_sid(annotation['AID'])
594
                                try:
595
                                    icon = self.icons['type']['%s' % atype.lower()]
596
                                except:
597
                                    icon = None
598
                                if sid != '0000000000':
599
                                    title = "<b>[SAP Note %d]</b> %s" % (int(sid), annotation['Title'])
600
                                else:
601
                                    title = annotation['Title']
602
 
603
                                try:
604
                                    annotation['Priority']
605
                                except:
606
                                    annotation['Priority'] = 'Normal'
607
 
608
                                node = self.get_node(   0,
609
                                                        icon,
610
                                                        False,
611
                                                        str(int(sid)),
612
                                                        title,
613
                                                        annotation['Component'],
614
                                                        annotation['Category'],
615
                                                        annotation['Type'],
616
                                                        annotation['Priority'],
617
                                                        self.srvutl.fuzzy_date_from_timestamp(annotation['Timestamp']),
618
                                                        annotation['AID'],
351 t00mlabs 619
                                                        annotation['Timestamp'],
620
                                                        self.srvutl.fuzzy_date_from_timestamp(annotation['Created']),
621
                                                        annotation['Created']
340 t00mlabs 622
                                                    )
623
                                nodes.append(node)
368 t00mlabs 624
 
625
 
340 t00mlabs 626
                    except Exception as error:
627
                        self.log.error(error)
351 t00mlabs 628
                        self.log.error(self.get_traceback())
340 t00mlabs 629
            except Exception as error:
630
                # Whenever an annotation is deleted, after reloading
631
                # the view, it fails. Then, skip it
632
                self.log.error("Annotation: %s", fname)
633
                self.log.error(error)
634
 
635
        for node in nodes:
377 t00mlabs 636
            self.model.append(node)
340 t00mlabs 637
 
638
        self.treeview.set_model(self.sorted_model)
639
        self.sort_by_timestamp()
640
        self.update_total_annotations_count()
362 t00mlabs 641
        self.log.debug("Visor updated")
340 t00mlabs 642
 
369 t00mlabs 643
 
340 t00mlabs 644
    def show_widgets(self):
377 t00mlabs 645
        self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
340 t00mlabs 646
 
647
 
362 t00mlabs 648
    def row_double_click(self, treeview, row, col):
361 t00mlabs 649
        try:
650
            selection = treeview.get_selection()
651
            model, treeiter = selection.get_selected()
652
            if treeiter is not None:
653
                component = model[treeiter][5]
654
                if component == 'Annotation':
655
                    aid = model[treeiter][10]
656
                    is_valid = self.srvant.is_valid(aid)
657
                    if is_valid:
658
                        fullscreen_annotation = self.srvgui.get_widget('gtk_togglebutton_maximize_annotation_widget')
659
                        fullscreen_annotation.set_active(True)
660
                        self.srvclb.action_annotation_edit(aid)
661
                else:
369 t00mlabs 662
                    # ~ aid = None
663
                    self.srvuif.set_widget_visibility('gtk_vbox_container_annotations', True)
361 t00mlabs 664
        except Exception as error:
665
            head = "Error reading annotation's contents"
666
            body = "<i>%s</i>\n\n" % error
667
            body += "As a workaround, a new file will be created"
668
            dialog = self.srvuif.message_dialog_error(head, body)
669
            self.log.debug(error)
670
            self.log.debug(self.get_traceback())
671
            dialog.run()
672
            dialog.destroy()
673
            # ~ #FIXME: create an empty file for contents
674
 
362 t00mlabs 675
    def row_right_click(self, treeview, event, data=None):
340 t00mlabs 676
        if event.button == 3:
677
            rect = Gdk.Rectangle()
678
            rect.x = x = int(event.x)
679
            rect.y = y = int(event.y)
680
            pthinfo = self.treeview.get_path_at_pos(x,y)
681
            if pthinfo is not None:
682
                path,col,cellx,celly = pthinfo
683
                model = treeview.get_model()
684
                treeiter = model.get_iter(path)
685
                component = model[treeiter][5]
686
                aid = model[treeiter][10]
687
                toolbar = self.srvgui.get_widget('visortoolbar')
688
                popover = self.srvgui.add_widget('gtk_popover_visor_row', Gtk.Popover.new(treeview))
379 t00mlabs 689
                # ~ popover.set_position(Gtk.PositionType.TOP)
340 t00mlabs 690
                popover.set_pointing_to(rect)
691
                box = self.build_popover(aid, popover, component)
692
                if box is not None:
361 t00mlabs 693
                    vpaned = self.srvgui.get_widget('gtk_vpaned_visor')
694
                    visor_annotations = self.srvgui.get_widget('visor_annotations')
695
                    width, height = visor_annotations.get_size_request()
696
                    vpaned.set_position(1000)
340 t00mlabs 697
                    popover.add(box)
698
                    self.srvclb.gui_show_popover(None, popover)
699
 
700
 
377 t00mlabs 701
 
340 t00mlabs 702
    def build_popover(self, aid, popover, component):
703
        sid = self.srvant.get_sid(aid)
704
 
705
        def get_popover_button(text, icon_name):
706
            button = Gtk.Button()
707
            button.set_relief(Gtk.ReliefStyle.NONE)
708
            hbox = Gtk.HBox()
709
            icon = self.srvicm.get_new_image_icon(icon_name, 24, 24)
710
            lbltext = Gtk.Label()
711
            lbltext.set_xalign(0.0)
712
            lbltext.set_markup('%s' % text)
713
            hbox.pack_start(icon, False, False, 3)
714
            hbox.pack_start(lbltext, True, True, 3)
715
            button.add(hbox)
716
            return button
717
 
718
        if component == 'Annotation':
719
            box = Gtk.Box(spacing = 3, orientation="vertical")
720
 
377 t00mlabs 721
            button = get_popover_button("<b>Select all</b>", 'basico-check-all')
340 t00mlabs 722
            button.show_all()
377 t00mlabs 723
            button.connect('clicked', self.select_all, True)
340 t00mlabs 724
            box.pack_start(button, False, False, 0)
725
 
377 t00mlabs 726
            button = get_popover_button("<b>Select none</b>", 'basico-check-none')
727
            button.show_all()
728
            button.connect('clicked', self.select_all, False)
729
            box.pack_start(button, False, False, 0)
730
 
378 t00mlabs 731
            button = get_popover_button("<b>Invert selection</b>", 'basico-check-invert')
732
            button.show_all()
733
            button.connect('clicked', self.select_all, None)
734
            box.pack_start(button, False, False, 0)
735
 
377 t00mlabs 736
            if len(self.rows_toggled()) > 0:
378 t00mlabs 737
                separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
738
                box.pack_start(separator, False, False, 0)
739
 
377 t00mlabs 740
                button = get_popover_button("<b>Delete</b> annotations", 'basico-delete')
741
                button.show_all()
742
                button.connect('clicked', self.srvclb.action_annotation_delete)
743
                box.pack_start(button, False, False, 0)
744
 
378 t00mlabs 745
                button = get_popover_button("<b>Backup</b> annotations", 'basico-backup')
746
                button.show_all()
747
                # ~ button.connect('clicked', self.srvclb.action_annotation_backup)
748
                box.pack_start(button, False, False, 0)
749
 
379 t00mlabs 750
            else:
751
                separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
752
                box.pack_start(separator, False, False, 0)
753
 
754
                # Popover button "Jump to SAP Note"
755
                if sid != '0000000000':
756
                    # Jump to SAP Note
757
                    button = get_popover_button("Jump to SAP Note %d" % int(sid), 'basico-jump-sapnote')
758
                    button.show_all()
759
                    button.connect('clicked', self.srvclb.gui_jump_to_sapnote, sid)
760
                    box.pack_start(button, False, False, 0)
761
 
762
                button = get_popover_button("Preview annotation", 'basico-preview')
340 t00mlabs 763
                button.show_all()
379 t00mlabs 764
                # ~ button.connect('clicked', self.srvclb.duplicate_sapnote, aid)
340 t00mlabs 765
                box.pack_start(button, False, False, 0)
379 t00mlabs 766
 
767
                button = get_popover_button("Edit annotation", 'basico-edit')
768
                button.show_all()
769
                # ~ button.connect('clicked', self.srvclb.duplicate_sapnote, aid)
770
                box.pack_start(button, False, False, 0)
771
 
772
                button = get_popover_button("Duplicate annotation", 'basico-copy-paste')
773
                button.show_all()
774
                # ~ button.connect('clicked', self.srvclb.duplicate_sapnote, aid)
775
                box.pack_start(button, False, False, 0)
776
 
340 t00mlabs 777
            return box
778
 
779
 
377 t00mlabs 780
    def select_all(self, button, checked):
781
        def check_row(model, path, itr):
782
            # ~ model[path][2] = not model[path][2]
378 t00mlabs 783
            if checked is not None:
784
                model[path][2] = checked
785
            else:
786
                state = model[path][2]
787
                model[path][2] = not state
377 t00mlabs 788
 
789
        model = self.sorted_model.get_model()
790
        model.foreach(check_row)
379 t00mlabs 791
        self.srvuif.grab_focus()
377 t00mlabs 792
 
793
 
340 t00mlabs 794
    def connect_menuview_signals(self):
795
        # Categories
796
        button = self.srvgui.get_widget('gtk_togglebutton_categories')
797
        button.connect('toggled', self.set_visible_categories)
798
 
799
        for name in ['inbox', 'drafts', 'archived']:
800
            button = self.srvgui.get_widget('gtk_button_category_%s' % name)
801
            button.connect('toggled', self.set_visible_category, name)
802
 
803
        # Types
804
        button = self.srvgui.get_widget('gtk_togglebutton_types')
805
        button.connect('toggled', self.set_visible_types)
806
 
807
        for name in ATYPES:
808
            button = self.srvgui.get_widget('gtk_button_type_%s' % name.lower())
809
            button.connect('toggled', self.set_visible_annotation_type, name)
810
 
811
 
812
    def set_active_categories(self):
813
        category = self.srvgui.get_widget('gtk_togglebutton_inbox')
814
        category.set_active(True)
815