Subversion Repositories basico

Rev

Rev 355 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
353 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: Attachments Visor
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
import gi
17
gi.require_version('Gdk', '3.0')
18
gi.require_version('Gtk', '3.0')
19
from gi.repository import Gdk
20
from gi.repository import Gio
21
from gi.repository import Gtk
22
from gi.repository.GdkPixbuf import Pixbuf
23
from gi.repository import Pango
24
 
25
from basico.core.mod_env import LPATH, ATYPES
26
from basico.core.mod_wdg import BasicoWidget
27
from basico.widgets.wdg_cols import CollectionsMgtView
28
from basico.widgets.wdg_import import ImportWidget
29
 
30
 
31
# ~ total, used, free = shutil.disk_usage('/home/t00m/.basico/opt/webdrivers/geckodriver')
32
# ~ ft = float(ceil(total/(1024*1024*1024)))
33
# ~ ff = float(ceil(free/(1024*1024*1024)))
34
# ~ pf = (ft-ff)*100/ft
35
 
36
# ~ ft = int(ceil(total/(1024*1024*1024)))
37
# ~ ff = int(ceil(free/(1024*1024*1024)))
38
# ~ pf = (ft-ff)*100/ft
39
 
40
class AttachmentsVisor(BasicoWidget, Gtk.VBox):
41
    def __init__(self, app):
42
        super().__init__(app, __class__.__name__)
43
        Gtk.HBox.__init__(self, app)
44
        self.set_homogeneous(False)
45
        self.bag = []
46
        self.get_services()
47
        self.setup_visor()
48
        self.icons = {}
49
        self.icons['type'] = {}
50
        for atype in ATYPES:
51
            self.icons['type'][atype.lower()] = self.srvicm.get_pixbuf_icon('basico-attachment-type-%s' % atype.lower())
52
        self.log.debug("Attachments Visor initialized")
53
 
54
 
55
    def get_services(self):
56
        self.srvgui = self.get_service("GUI")
57
        self.srvclb = self.get_service('Callbacks')
58
        self.srvsap = self.get_service('SAP')
59
        self.srvicm = self.get_service('IM')
60
        self.srvstg = self.get_service('Settings')
61
        self.srvdtb = self.get_service('DB')
62
        self.srvuif = self.get_service("UIF")
63
        self.srvutl = self.get_service("Utils")
64
        self.srvant = self.get_service('Annotation')
65
 
66
 
67
    def get_treeview(self):
68
        return self.treeview
69
 
70
 
71
    def sort_by_timestamp(self):
72
        self.sorted_model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
73
 
74
 
75
    def set_visible_categories(self, togglebutton):
76
        types = self.srvgui.get_widget('gtk_togglebutton_types')
77
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_categories')
78
 
79
        active = togglebutton.get_active()
80
        if active:
81
            types.set_active(False)
82
        revealer.set_reveal_child(active)
83
 
84
 
85
    def set_visible_types(self, togglebutton):
86
        categories = self.srvgui.get_widget('gtk_togglebutton_categories')
87
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_types')
88
 
89
        active = togglebutton.get_active()
90
        if active:
91
            categories.set_active(False)
92
        revealer.set_reveal_child(active)
93
 
94
 
95
    def set_visible_priority(self, togglebutton):
96
        categories = self.srvgui.get_widget('gtk_togglebutton_categories')
97
        revealer = self.srvgui.get_widget('gtk_revealer_annotations_priority')
98
 
99
        active = togglebutton.get_active()
100
        if active:
101
            priority.set_active(False)
102
        revealer.set_reveal_child(active)
103
 
104
 
105
    def set_visible_category(self, togglebutton, title):
106
        active = togglebutton.get_active()
107
        self.srvgui.set_key_value('ANNOTATIONS_CATEGORY_%s_VISIBLE' % title.upper(), active)
108
        self.populate_annotations()
109
 
110
 
111
    def set_visible_annotation_type(self, togglebutton, atype):
112
        active = togglebutton.get_active()
113
        self.srvgui.set_key_value('ANNOTATIONS_TYPE_%s_VISIBLE' % atype.upper(), active)
114
        self.populate_annotations()
115
 
116
 
117
    def set_visible_priority(self, togglebutton, title):
118
        active = togglebutton.get_active()
119
        self.srvgui.set_key_value('ANNOTATIONS_PRIORITY_%s_VISIBLE' % title.upper(), active)
120
        self.populate_annotations()
121
 
122
 
123
    def setup_visor(self):
124
        scr = Gtk.ScrolledWindow()
125
        scr.set_hexpand(True)
126
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
127
        scr.set_shadow_type(Gtk.ShadowType.NONE)
128
        self.treeview = Gtk.TreeView()
129
        scr.add(self.treeview)
130
        scr.set_hexpand(True)
131
        self.pack_start(scr, True, True, 0)
132
 
133
        hbox = Gtk.HBox()
134
        pgb = self.srvgui.add_widget('gtk_progressbar_diskusage', Gtk.ProgressBar())
135
        fraction = self.srvutl.get_disk_usage_fraction(LPATH['DB'])
136
        text = self.srvutl.get_disk_usage_human(LPATH['DB'])
137
        pgb.set_fraction(fraction)
138
        pgb.set_text(text)
139
        pgb.set_show_text(True)
140
        hbox.pack_start(pgb, True, True, 0)
141
        self.pack_start(hbox, False, False, 0)
142
 
143
        # Setup model
144
        self.model = Gtk.TreeStore(
145
            int,        # key
146
            Pixbuf,     # Icon
147
            int,        # checkbox
148
            str,        # sid
149
            str,        # title
150
            str,        # component
151
            str,        # category
152
            str,        # type
153
            str,        # priority
154
            str,        # last update
155
            str,        # Annotation Id (extra key)
156
            str,        # Timestamp updated
157
            str,        # Annotation created
158
            str,        # Timestamp created
159
        )
160
 
161
        # Setup columns
162
        def get_column_header_widget(title, icon_name=None, width=24, height=24):
163
            hbox = Gtk.HBox()
164
            icon = self.srvicm.get_new_image_icon(icon_name, width, height)
165
            label = Gtk.Label()
166
            label.set_markup("<b>%s</b>" % title)
167
            # ~ label.modify_font(Pango.FontDescription('Monospace 10'))
168
            hbox.pack_start(icon, False, False, 3)
169
            hbox.pack_start(label, True, True, 3)
170
            hbox.show_all()
171
            return hbox
172
 
173
        # SAP Note key
174
        self.renderer_key = Gtk.CellRendererText()
175
        self.column_key = Gtk.TreeViewColumn('Key', self.renderer_key, text=0)
176
        self.column_key.set_visible(False)
177
        self.column_key.set_expand(False)
178
        self.column_key.set_clickable(False)
179
        self.column_key.set_sort_indicator(True)
180
        self.treeview.append_column(self.column_key)
181
 
182
        # Icon
183
        self.renderer_icon = Gtk.CellRendererPixbuf()
184
        self.renderer_icon.set_alignment(0.0, 0.5)
185
        self.column_icon = Gtk.TreeViewColumn('', self.renderer_icon, pixbuf=1)
186
        widget = get_column_header_widget('', 'basico-empty')
187
        self.column_icon.set_widget(widget)
188
        self.column_icon.set_visible(True)
189
        self.column_icon.set_expand(False)
190
        self.column_icon.set_clickable(False)
191
        self.column_icon.set_sort_indicator(True)
192
        self.treeview.append_column(self.column_icon)
193
 
194
        # SAP Note Checkbox
195
        self.renderer_checkbox = Gtk.CellRendererToggle()
196
        self.renderer_checkbox.connect("toggled", self.toggle_checkbox)
197
        self.column_checkbox = Gtk.TreeViewColumn('', self.renderer_checkbox, active=2)
198
        self.column_checkbox.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
199
        self.column_checkbox.set_visible(False)
200
        self.column_checkbox.set_expand(False)
201
        self.column_checkbox.set_clickable(True)
202
        self.column_checkbox.set_sort_indicator(True)
203
        self.column_checkbox.set_property('spacing', 50)
204
        self.treeview.append_column(self.column_checkbox)
205
 
206
        # SAP Note Id
207
        self.renderer_sid = Gtk.CellRendererText()
208
        self.renderer_sid.set_property('xalign', 1.0)
209
        self.renderer_sid.set_property('height', 36)
210
        self.renderer_sid.set_property('background', '#F0E3E3')
211
        self.column_sid = Gtk.TreeViewColumn('SAP Note Id', self.renderer_sid, markup=3)
212
        widget = get_column_header_widget('SAP Note Id', 'basico-sid')
213
        self.column_sid.set_widget(widget)
214
        self.column_sid.set_visible(True)
215
        self.column_sid.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
216
        self.column_sid.set_expand(False)
217
        self.column_sid.set_clickable(True)
218
        self.column_sid.set_sort_indicator(True)
219
        self.column_sid.set_sort_column_id(0)
220
        self.treeview.append_column(self.column_sid)
221
 
222
        # SAP Note title
223
        self.renderer_title = Gtk.CellRendererText()
224
        self.renderer_title.set_property('background', '#FFFEEA')
225
        self.renderer_title.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
226
        self.column_title = Gtk.TreeViewColumn('Title', self.renderer_title, markup=4)
227
        widget = get_column_header_widget('Title', 'basico-tag')
228
        self.column_title.set_widget(widget)
229
        self.column_title.set_visible(True)
230
        self.column_title.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
231
        self.column_title.set_expand(True)
232
        self.column_title.set_clickable(True)
233
        self.column_title.set_sort_indicator(True)
234
        self.column_title.set_sort_column_id(4)
235
        self.treeview.append_column(self.column_title)
236
 
237
        # SAP Note Component
238
        self.renderer_component = Gtk.CellRendererText()
239
        self.renderer_component.set_property('background', '#E3E3F0')
240
        self.column_component = Gtk.TreeViewColumn('Component', self.renderer_component, markup=5)
241
        widget = get_column_header_widget('Component', 'basico-component')
242
        self.column_component.set_widget(widget)
243
        self.column_component.set_visible(True)
244
        self.column_component.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
245
        self.column_component.set_expand(False)
246
        self.column_component.set_clickable(True)
247
        self.column_component.set_sort_indicator(True)
248
        self.column_component.set_sort_column_id(5)
249
        self.treeview.append_column(self.column_component)
250
 
251
        # SAP Note Category
252
        self.renderer_category = Gtk.CellRendererText()
253
        self.renderer_category.set_property('background', '#E3F1E3')
254
        self.column_category = Gtk.TreeViewColumn('Category', self.renderer_category, markup=6)
255
        widget = get_column_header_widget('Category', 'basico-category')
256
        self.column_category.set_widget(widget)
257
        self.column_category.set_visible(False)
258
        self.column_category.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
259
        self.column_category.set_expand(False)
260
        self.column_category.set_clickable(True)
261
        self.column_category.set_sort_indicator(True)
262
        self.column_category.set_sort_column_id(6)
263
        self.treeview.append_column(self.column_category)
264
 
265
        # SAP Note Type
266
        self.renderer_type = Gtk.CellRendererText()
267
        self.renderer_type.set_property('background', '#DADAFF')
268
        self.column_type = Gtk.TreeViewColumn('Type', self.renderer_type, markup=7)
269
        self.column_type.set_visible(True)
270
        self.column_type.set_expand(False)
271
        self.column_type.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
272
        self.column_type.set_clickable(True)
273
        self.column_type.set_sort_indicator(True)
274
        self.column_type.set_sort_column_id(7)
275
        self.treeview.append_column(self.column_type)
276
 
277
        # SAP Note Priority
278
        self.renderer_priority = Gtk.CellRendererText()
279
        self.renderer_priority.set_property('background', '#e4f1f1')
280
        self.column_priority = Gtk.TreeViewColumn('Priority', self.renderer_priority, markup=8)
281
        self.column_priority.set_visible(True)
282
        self.column_priority.set_expand(False)
283
        self.column_priority.set_clickable(True)
284
        self.column_priority.set_sort_indicator(True)
285
        self.column_priority.set_sort_column_id(8)
286
        self.treeview.append_column(self.column_priority)
287
 
288
        # Annotation Updated On
289
        self.renderer_updated = Gtk.CellRendererText()
290
        self.renderer_updated.set_property('background', '#FFE6D1')
291
        self.column_updated = Gtk.TreeViewColumn('Updated', self.renderer_updated, markup=9)
292
        self.column_updated.set_visible(True)
293
        self.column_updated.set_expand(False)
294
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
295
        self.column_updated.set_clickable(True)
296
        self.column_updated.set_sort_indicator(True)
297
        self.column_updated.set_sort_column_id(11)
298
        self.column_updated.set_sort_order(Gtk.SortType.DESCENDING)
299
        self.model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
300
        self.treeview.append_column(self.column_updated)
301
 
302
        # Annotation Id
303
        self.renderer_annotation = Gtk.CellRendererText()
304
        self.column_annotation = Gtk.TreeViewColumn('Annotation Id', self.renderer_annotation, markup=10)
305
        self.column_annotation.set_visible(False)
306
        self.column_annotation.set_expand(False)
307
        self.column_annotation.set_clickable(False)
308
        self.column_annotation.set_sort_indicator(True)
309
        self.treeview.append_column(self.column_annotation)
310
 
311
        # Timestamp updated
312
        self.renderer_timestamp = Gtk.CellRendererText()
313
        self.column_timestamp = Gtk.TreeViewColumn('Timestamp updated', self.renderer_timestamp, text=11)
314
        self.column_timestamp.set_visible(False)
315
        self.column_timestamp.set_expand(False)
316
        self.column_timestamp.set_clickable(False)
317
        self.column_timestamp.set_sort_indicator(True)
318
        self.column_timestamp.set_sort_column_id(11)
319
        self.column_timestamp.set_sort_order(Gtk.SortType.ASCENDING)
320
        self.treeview.append_column(self.column_timestamp)
321
 
322
        # Annotation Created On
323
        self.renderer_updated = Gtk.CellRendererText()
324
        self.renderer_updated.set_property('background', '#FFE6D1')
325
        self.column_updated = Gtk.TreeViewColumn('Created', self.renderer_updated, markup=12)
326
        self.column_updated.set_visible(True)
327
        self.column_updated.set_expand(False)
328
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
329
        self.column_updated.set_clickable(True)
330
        self.column_updated.set_sort_indicator(True)
331
        self.column_updated.set_sort_column_id(13)
332
        self.column_updated.set_sort_order(Gtk.SortType.DESCENDING)
333
        self.model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
334
        self.treeview.append_column(self.column_updated)
335
 
336
        # Timestamp
337
        self.renderer_timestamp = Gtk.CellRendererText()
338
        self.column_timestamp = Gtk.TreeViewColumn('Timestamp created', self.renderer_timestamp, text=13)
339
        self.column_timestamp.set_visible(False)
340
        self.column_timestamp.set_expand(False)
341
        self.column_timestamp.set_clickable(False)
342
        self.column_timestamp.set_sort_indicator(True)
343
        self.column_timestamp.set_sort_column_id(11)
344
        self.column_timestamp.set_sort_order(Gtk.SortType.ASCENDING)
345
        self.treeview.append_column(self.column_timestamp)
346
 
347
        # Treeview properties
348
        self.treeview.set_can_focus(False)
349
        self.treeview.set_enable_tree_lines(True)
350
        self.treeview.set_headers_visible(True)
351
        self.treeview.set_enable_search(True)
352
        self.treeview.set_hover_selection(False)
353
        self.treeview.set_grid_lines(Gtk.TreeViewGridLines.NONE)
354
        self.treeview.set_enable_tree_lines(True)
355
        self.treeview.set_level_indentation(10)
356
        self.treeview.connect('button_press_event', self.right_click)
357
 
358
 
359
 
360
        # DOC: In order to have a Gtk.Widged with sorting and filtering
361
        # capabilities, you have to filter the model first, and use this
362
        # new model to create the sorted model. Then, attach the sorted
363
        # model to the treeview...
364
 
365
        # Treeview filtering:
366
        self.visible_filter = self.model.filter_new()
367
        self.visible_filter.set_visible_func(self.visible_function)
368
 
369
        # TreeView sorting
370
        self.sorted_model = Gtk.TreeModelSort(model=self.visible_filter)
371
        self.sorted_model.set_sort_func(0, self.sort_function, None)
372
 
373
        # Selection
374
        self.selection = self.treeview.get_selection()
375
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)
376
        self.selection.connect('changed', self.row_changed)
377
 
378
        # Set model (filtered and sorted)
379
        self.sorted_model.set_sort_column_id(9, Gtk.SortType.ASCENDING)
380
        self.treeview.set_model(self.sorted_model)
381
 
382
        self.show_all()
383
 
384
 
385
    def sort_function(self, model, row1, row2, user_data):
386
        sort_column = 0
387
 
388
        value1 = model.get_value(row1, sort_column)
389
        value2 = model.get_value(row2, sort_column)
390
 
391
        if value1 < value2:
392
            return -1
393
        elif value1 == value2:
394
            return 0
395
        else:
396
            return 1
397
 
398
 
399
    def always_visible(self, model, itr, data):
400
        return False
401
 
402
 
403
    def visible_function(self, model, itr, data):
404
        entry = self.srvgui.get_widget('gtk_entry_filter_visor')
405
        text = self.srvutl.clean_html(entry.get_text())
406
        title = model.get(itr, 4)[0]
407
        match = text.upper() in title.upper()
408
 
409
        return match
410
 
411
 
412
    def update_total_annotations_count(self):
413
        statusbar = self.srvgui.get_widget('widget_statusbar')
414
        lblnotescount = self.srvgui.get_widget('gtk_label_total_notes')
415
        total = self.srvant.get_total()
416
        count = len(self.visible_filter)
417
        lblnotescount.set_markup("<b>%d/<big>%d annotations</big></b>" % (count, total))
418
        msg = 'View populated with %d annotations' % count
419
        self.srvuif.statusbar_msg(msg)
420
 
421
 
422
    def get_visible_filter(self):
423
        return self.visible_filter
424
 
425
 
426
    def row_changed(self, selection):
427
        try:
428
            model, treeiter = selection.get_selected()
429
            if treeiter is not None:
430
                component = model[treeiter][5]
431
                if component == 'Annotation':
432
                    aid = model[treeiter][10]
433
                    is_valid = self.srvant.is_valid(aid)
434
                    if is_valid:
435
                        self.srvclb.action_annotation_edit(aid)
436
                else:
437
                    aid = None
438
                    self.srvuif.set_widget_visibility('gtk_vbox_container_annotations', False)
439
        except Exception as error:
440
            head = "Error reading annotation's contents"
441
            body = "<i>%s</i>\n\n" % error
442
            body += "As a workaround, a new file will be created"
443
            dialog = self.srvuif.message_dialog_error(head, body)
444
            self.log.debug(error)
445
            self.log.debug(self.get_traceback())
446
            dialog.run()
447
            dialog.destroy()
448
            #FIXME: create an empty file for contents
449
 
450
 
451
    def toggle_checkbox(self, cell, path):
452
        path = self.sorted_model.convert_path_to_child_path(Gtk.TreePath(path))
453
        self.model[path][2] = not self.model[path][2]
454
 
455
 
456
    def get_node(self, key, icon, checkbox, sid, title, component, category='', sntype='', priority='', updated='', aid='', ts_updated='', created='', ts_created=''):
457
        # Add completion entries
458
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
459
        completion_model = completion.get_model()
460
        title = self.srvutl.clean_html(title)
461
        completion_model.append([title])
462
 
463
        node = []
464
        node.append(key)
465
        node.append(icon)
466
        node.append(checkbox)
467
        node.append(sid)
468
        node.append(title)
469
        node.append(component)
470
        node.append(category)
471
        node.append(sntype)
472
        node.append(priority)
473
        node.append(updated)
474
        node.append(aid) # Extra key for annotations id (aid)
475
        node.append(ts_updated)
476
        node.append(created)
477
        node.append(ts_created)
478
        return node
479
 
480
 
481
    def set_bag(self, annotations):
482
        self.bag = annotations
483
 
484
 
485
    def get_bag(self):
486
        return self.bag
487
 
488
 
489
    def reload(self):
490
        bag = self.get_bag()
491
        self.populate_annotations(bag)
492
 
493
 
494
    def populate_annotations(self, annotations=None):
495
        self.column_sid.set_visible(False)
496
        self.column_checkbox.set_visible(False)
497
        self.column_category.set_visible(True)
498
        self.column_component.set_visible(False)
499
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
500
        completion_model = completion.get_model()
501
        completion_model.clear()
502
 
503
        self.treeview.set_model(None)
504
        self.model.clear()
505
 
506
        if annotations is None:
507
            annotations = self.srvant.get_all()
508
        else:
509
            self.set_bag(annotations)
510
 
511
        dcats = {}
512
        snpids = {}
513
        nodes = []
514
        for fname in annotations:
515
            try:
516
                with open(fname, 'r') as fa:
517
                    try:
518
                        annotation = json.load(fa)
519
                        category = annotation['Category']
520
                        atype = annotation['Type']
521
                        cat_key = 'ANNOTATIONS_CATEGORY_%s_VISIBLE' % category.upper()
522
                        type_key = 'ANNOTATIONS_TYPE_%s_VISIBLE' % atype.upper()
523
                        category_active = self.srvgui.get_key_value(cat_key)
524
                        try:
525
                            type_active = self.srvgui.get_key_value(type_key)
526
                        except Exception as error:
527
                            self.log.error(error)
528
                            type_active = True
529
                        if category_active:
530
                            if type_active:
531
                                ppid = None
532
                                sid = self.srvant.get_sid(annotation['AID'])
533
                                try:
534
                                    icon = self.icons['type']['%s' % atype.lower()]
535
                                except:
536
                                    icon = None
537
                                if sid != '0000000000':
538
                                    title = "<b>[SAP Note %d]</b> %s" % (int(sid), annotation['Title'])
539
                                else:
540
                                    title = annotation['Title']
541
 
542
                                try:
543
                                    annotation['Priority']
544
                                except:
545
                                    annotation['Priority'] = 'Normal'
546
 
547
                                node = self.get_node(   0,
548
                                                        icon,
549
                                                        False,
550
                                                        str(int(sid)),
551
                                                        title,
552
                                                        annotation['Component'],
553
                                                        annotation['Category'],
554
                                                        annotation['Type'],
555
                                                        annotation['Priority'],
556
                                                        self.srvutl.fuzzy_date_from_timestamp(annotation['Timestamp']),
557
                                                        annotation['AID'],
558
                                                        annotation['Timestamp'],
559
                                                        self.srvutl.fuzzy_date_from_timestamp(annotation['Created']),
560
                                                        annotation['Created']
561
                                                    )
562
                                nodes.append(node)
563
                    except Exception as error:
564
                        self.log.error(error)
565
                        self.log.error(self.get_traceback())
566
            except Exception as error:
567
                # Whenever an annotation is deleted, after reloading
568
                # the view, it fails. Then, skip it
569
                self.log.error("Annotation: %s", fname)
570
                self.log.error(error)
571
 
572
        for node in nodes:
573
            self.model.append(ppid, node)
574
 
575
        self.treeview.set_model(self.sorted_model)
576
        self.sort_by_timestamp()
577
        self.update_total_annotations_count()
578
 
579
 
580
    def show_widgets(self):
581
        self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
582
 
583
 
584
    def right_click(self, treeview, event, data=None):
585
        if event.button == 3:
586
            rect = Gdk.Rectangle()
587
            rect.x = x = int(event.x)
588
            rect.y = y = int(event.y)
589
            pthinfo = self.treeview.get_path_at_pos(x,y)
590
            if pthinfo is not None:
591
                path,col,cellx,celly = pthinfo
592
                model = treeview.get_model()
593
                treeiter = model.get_iter(path)
594
                component = model[treeiter][5]
595
                aid = model[treeiter][10]
596
                toolbar = self.srvgui.get_widget('visortoolbar')
597
                popover = self.srvgui.add_widget('gtk_popover_visor_row', Gtk.Popover.new(treeview))
598
                popover.set_position(Gtk.PositionType.TOP)
599
                popover.set_pointing_to(rect)
600
                box = self.build_popover(aid, popover, component)
601
                if box is not None:
602
                    popover.add(box)
603
                    self.srvclb.gui_show_popover(None, popover)
604
 
605
 
606
    def build_popover(self, aid, popover, component):
607
        sid = self.srvant.get_sid(aid)
608
 
609
        def get_popover_button(text, icon_name):
610
            button = Gtk.Button()
611
            button.set_relief(Gtk.ReliefStyle.NONE)
612
            hbox = Gtk.HBox()
613
            icon = self.srvicm.get_new_image_icon(icon_name, 24, 24)
614
            lbltext = Gtk.Label()
615
            lbltext.set_xalign(0.0)
616
            lbltext.set_markup('%s' % text)
617
            hbox.pack_start(icon, False, False, 3)
618
            hbox.pack_start(lbltext, True, True, 3)
619
            button.add(hbox)
620
            return button
621
 
622
        if component == 'Annotation':
623
            box = Gtk.Box(spacing = 3, orientation="vertical")
624
 
625
            # Popover button "Delete annotation"
626
            button = get_popover_button("<b>Delete</b> annotation", 'basico-delete')
627
            button.show_all()
628
            button.connect('clicked', self.srvclb.action_annotation_delete)
629
            box.pack_start(button, False, False, 0)
630
 
631
            # Popover button "Duplicate annotation"
632
            if sid != '0000000000':
633
                # Jump to SAP Note
634
                button = get_popover_button("Jump to SAP Note %d" % int(sid), 'basico-jump-sapnote')
635
                button.show_all()
636
                button.connect('clicked', self.srvclb.gui_jump_to_sapnote, sid)
637
                box.pack_start(button, False, False, 0)
638
            else:
639
                pass
640
            return box
641
 
642
 
643
    def connect_menuview_signals(self):
644
        # Categories
645
        button = self.srvgui.get_widget('gtk_togglebutton_categories')
646
        button.connect('toggled', self.set_visible_categories)
647
 
648
        for name in ['inbox', 'drafts', 'archived']:
649
            button = self.srvgui.get_widget('gtk_button_category_%s' % name)
650
            button.connect('toggled', self.set_visible_category, name)
651
 
652
        # Types
653
        button = self.srvgui.get_widget('gtk_togglebutton_types')
654
        button.connect('toggled', self.set_visible_types)
655
 
656
        for name in ATYPES:
657
            button = self.srvgui.get_widget('gtk_button_type_%s' % name.lower())
658
            button.connect('toggled', self.set_visible_annotation_type, name)
659
 
660
 
661
    def set_active_categories(self):
662
        category = self.srvgui.get_widget('gtk_togglebutton_inbox')
663
        category.set_active(True)
664