Subversion Repositories basico

Rev

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

Rev Author Line No. Line
254 t00m 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
264 t00m 3
"""
254 t00m 4
# File: wdg_visor.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: SAPNoteViewVisor widgets
264 t00m 8
"""
254 t00m 9
 
10
import os
11
from os.path import sep as SEP
12
from cgi import escape
13
import glob
14
import json
15
 
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
271 t00m 22
from gi.repository import GObject
254 t00m 23
from gi.repository.GdkPixbuf import Pixbuf
24
from gi.repository import Pango
25
 
271 t00m 26
from basico.core.mod_srv import Service
287 t00m 27
from basico.core.mod_env import LPATH, ATYPES
254 t00m 28
from basico.widgets.wdg_cols import CollectionsMgtView
29
from basico.widgets.wdg_import import ImportWidget
281 t00m 30
from basico.core.mod_log import get_logger
254 t00m 31
 
32
 
271 t00m 33
class SAPNotesVisor(Gtk.Box, Service):
254 t00m 34
    def __init__(self, app):
35
        Gtk.Box.__init__(self, app)
281 t00m 36
        self.log = get_logger(__class__.__name__)
254 t00m 37
        self.app = app
284 t00m 38
        self.get_services()
254 t00m 39
        self.bag = []
284 t00m 40
        self.icons = {}
41
        self.icons['type'] = {}
254 t00m 42
        self.setup()
43
 
44
 
45
    def get_services(self):
46
        self.srvgui = self.app.get_service("GUI")
47
        self.srvclb = self.app.get_service('Callbacks')
48
        self.srvsap = self.app.get_service('SAP')
49
        self.srvicm = self.app.get_service('IM')
50
        self.srvstg = self.app.get_service('Settings')
51
        self.srvdtb = self.app.get_service('DB')
52
        self.srvuif = self.app.get_service("UIF")
53
        self.srvutl = self.app.get_service("Utils")
54
        self.srvant = self.app.get_service('Annotation')
55
 
56
    def get_treeview(self):
57
        return self.treeview
58
 
59
 
60
    def sort_by_timestamp(self):
61
        self.sorted_model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
62
 
63
 
64
    def setup(self):
65
        scr = Gtk.ScrolledWindow()
66
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
67
        scr.set_shadow_type(Gtk.ShadowType.IN)
275 t00m 68
        # ~ viewport = Gtk.Viewport()
254 t00m 69
        self.treeview = Gtk.TreeView()
275 t00m 70
        # ~ viewport.add(self.treeview)
71
        scr.add(self.treeview)
255 t00m 72
        self.pack_start(scr, True, True, 0)
254 t00m 73
 
74
        # Setup model
75
        self.model = Gtk.TreeStore(
76
            int,        # key
77
            Pixbuf,     # Icon
78
            int,        # checkbox
79
            str,        # sid
80
            str,        # title
81
            str,        # component
82
            str,        # category
83
            str,        # type
84
            str,        # priority
85
            str,        # last update
86
            str,        # Annotation Id (extra key)
87
            str,        # Timestamp
88
        )
89
 
90
        # Setup columns
91
        def get_column_header_widget(title, icon_name=None, width=24, height=24):
92
            hbox = Gtk.HBox()
93
            icon = self.srvicm.get_new_image_icon(icon_name, width, height)
94
            label = Gtk.Label()
95
            label.set_markup("<b>%s</b>" % title)
96
            label.modify_font(Pango.FontDescription('Monospace 10'))
97
            hbox.pack_start(icon, False, False, 3)
98
            hbox.pack_start(label, True, True, 3)
99
            hbox.show_all()
100
            return hbox
101
 
102
        # SAP Note key
103
        self.renderer_key = Gtk.CellRendererText()
104
        self.renderer_key.set_property('height', 32)
105
        self.column_key = Gtk.TreeViewColumn('Key', self.renderer_key, text=0)
106
        self.column_key.set_visible(False)
107
        self.column_key.set_expand(False)
108
        self.column_key.set_clickable(False)
109
        self.column_key.set_sort_indicator(False)
110
        self.treeview.append_column(self.column_key)
111
 
112
        # Icon
113
        self.renderer_icon = Gtk.CellRendererPixbuf()
114
        self.renderer_icon.set_alignment(0.0, 0.5)
115
        self.column_icon = Gtk.TreeViewColumn('Bookmark', self.renderer_icon, pixbuf=1)
116
        widget = get_column_header_widget('', 'basico-bookmarks')
117
        self.column_icon.set_widget(widget)
118
        self.column_icon.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
119
        self.column_icon.set_visible(True)
120
        self.column_icon.set_expand(False)
121
        self.column_icon.set_clickable(False)
122
        self.column_icon.set_sort_indicator(False)
123
        self.treeview.append_column(self.column_icon)
124
 
125
        # SAP Note Checkbox
126
        self.renderer_checkbox = Gtk.CellRendererToggle()
127
        self.renderer_checkbox.connect("toggled", self.toggle_checkbox)
128
        self.column_checkbox = Gtk.TreeViewColumn('', self.renderer_checkbox, active=2)
129
        self.column_checkbox.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
264 t00m 130
        self.column_checkbox.set_visible(True)
254 t00m 131
        self.column_checkbox.set_expand(False)
132
        self.column_checkbox.set_clickable(True)
133
        self.column_checkbox.set_sort_indicator(False)
134
        self.column_checkbox.set_property('spacing', 50)
135
        self.treeview.append_column(self.column_checkbox)
136
 
137
        # SAP Note Id
138
        self.renderer_sid = Gtk.CellRendererText()
139
        self.renderer_sid.set_property('xalign', 1.0)
140
        self.renderer_sid.set_property('height', 36)
141
        self.renderer_sid.set_property('background', '#F0E3E3')
142
        self.column_sid = Gtk.TreeViewColumn('SAP Note Id', self.renderer_sid, markup=3)
143
        widget = get_column_header_widget('SAP Note Id', 'basico-sid')
144
        self.column_sid.set_widget(widget)
145
        self.column_sid.set_visible(True)
146
        self.column_sid.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
147
        self.column_sid.set_expand(False)
148
        self.column_sid.set_clickable(True)
149
        self.column_sid.set_sort_indicator(True)
150
        self.column_sid.set_sort_column_id(0)
151
        self.column_sid.set_sort_order(Gtk.SortType.ASCENDING)
152
        self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
153
        self.treeview.append_column(self.column_sid)
154
 
155
        # SAP Note title
156
        self.renderer_title = Gtk.CellRendererText()
157
        self.renderer_title.set_property('background', '#FFFEEA')
158
        self.renderer_title.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
159
        self.column_title = Gtk.TreeViewColumn('Title', self.renderer_title, markup=4)
160
        widget = get_column_header_widget('Title', 'basico-tag')
161
        self.column_title.set_widget(widget)
162
        self.column_title.set_visible(True)
163
        self.column_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
164
        self.column_title.set_expand(True)
165
        self.column_title.set_clickable(True)
166
        self.column_title.set_sort_indicator(True)
167
        self.column_title.set_sort_column_id(4)
168
        self.treeview.append_column(self.column_title)
169
 
170
        # SAP Note Component
171
        self.renderer_component = Gtk.CellRendererText()
172
        self.renderer_component.set_property('background', '#E3E3F0')
173
        self.column_component = Gtk.TreeViewColumn('Component', self.renderer_component, markup=5)
174
        widget = get_column_header_widget('Component', 'basico-component')
175
        self.column_component.set_widget(widget)
176
        self.column_component.set_visible(True)
177
        self.column_component.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
178
        self.column_component.set_expand(False)
179
        self.column_component.set_clickable(True)
180
        self.column_component.set_sort_indicator(True)
181
        self.column_component.set_sort_column_id(5)
182
        self.treeview.append_column(self.column_component)
183
 
184
        # SAP Note Category
185
        self.renderer_category = Gtk.CellRendererText()
186
        self.renderer_category.set_property('background', '#E3F1E3')
187
        self.column_category = Gtk.TreeViewColumn('Category', self.renderer_category, markup=6)
188
        widget = get_column_header_widget('Category', 'basico-category')
189
        self.column_category.set_widget(widget)
190
        self.column_category.set_visible(False)
191
        self.column_category.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
192
        self.column_category.set_expand(False)
193
        self.column_category.set_clickable(True)
194
        self.column_category.set_sort_indicator(True)
195
        self.column_category.set_sort_column_id(6)
196
        self.treeview.append_column(self.column_category)
197
 
198
        # SAP Note Type
199
        self.renderer_type = Gtk.CellRendererText()
200
        self.renderer_type.set_property('background', '#e4f1f1')
201
        self.column_type = Gtk.TreeViewColumn('Type', self.renderer_type, markup=7)
202
        self.column_type.set_visible(True)
203
        self.column_type.set_expand(False)
204
        self.column_type.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
205
        self.column_type.set_clickable(True)
206
        self.column_type.set_sort_indicator(True)
207
        self.column_type.set_sort_column_id(7)
208
        self.treeview.append_column(self.column_type)
209
 
210
        # SAP Note Priority
211
        self.renderer_priority = Gtk.CellRendererText()
212
        self.column_priority = Gtk.TreeViewColumn('Priority', self.renderer_priority, markup=8)
213
        self.column_priority.set_visible(False)
214
        self.column_priority.set_expand(True)
215
        self.column_priority.set_clickable(True)
216
        self.column_priority.set_sort_indicator(True)
217
        self.column_priority.set_sort_column_id(8)
218
        self.treeview.append_column(self.column_priority)
219
 
220
        # SAP Note UpdatedOn
221
        self.renderer_updated = Gtk.CellRendererText()
222
        self.renderer_updated.set_property('background', '#FFE6D1')
223
        self.column_updated = Gtk.TreeViewColumn('Updated On', self.renderer_updated, markup=9)
224
        self.column_updated.set_visible(True)
225
        self.column_updated.set_expand(False)
226
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
227
        self.column_updated.set_clickable(True)
228
        self.column_updated.set_sort_indicator(True)
229
        self.column_updated.set_sort_column_id(11)
230
        self.treeview.append_column(self.column_updated)
231
 
232
        # Annotation Id
233
        self.renderer_annotation = Gtk.CellRendererText()
234
        self.column_annotation = Gtk.TreeViewColumn('Annotation Id', self.renderer_annotation, markup=10)
235
        self.column_annotation.set_visible(False)
236
        self.column_annotation.set_expand(False)
237
        self.column_annotation.set_clickable(False)
238
        self.column_annotation.set_sort_indicator(False)
239
        self.treeview.append_column(self.column_annotation)
240
 
241
        # Timestamp
242
        self.renderer_timestamp = Gtk.CellRendererText()
243
        self.column_timestamp = Gtk.TreeViewColumn('Annotation Id', self.renderer_timestamp, text=11)
244
        self.column_timestamp.set_visible(False)
245
        self.column_timestamp.set_expand(False)
246
        self.column_timestamp.set_clickable(False)
247
        self.column_timestamp.set_sort_indicator(False)
248
        self.treeview.append_column(self.column_timestamp)
249
 
250
        # Treeview properties
251
        self.treeview.set_can_focus(False)
252
        self.treeview.set_enable_tree_lines(True)
253
        self.treeview.set_headers_visible(True)
254
        self.treeview.set_enable_search(True)
255
        self.treeview.set_hover_selection(False)
256
        self.treeview.set_grid_lines(Gtk.TreeViewGridLines.NONE)
257
        self.treeview.set_enable_tree_lines(True)
258
        self.treeview.set_level_indentation(10)
259
        self.treeview.modify_font(Pango.FontDescription('Monospace 10'))
260
        self.treeview.connect('button_press_event', self.right_click)
261
 
262
        # DOC: In order to have a Gtk.Widged with sorting and filtering
263
        # capabilities, you have to filter the model first, and use this
264
        # new model to create the sorted model. Then, attach the sorted
265
        # model to the treeview...
266
 
267
        # Treeview filtering:
268
        self.visible_filter = self.model.filter_new()
269
        self.visible_filter.set_visible_func(self.visible_function)
270
        # ~ treeview.set_search_equal_func(self.search_function)
271
        # https://stackoverflow.com/questions/23355866/user-search-collapsed-rows-in-a-gtk-treeview
272
 
273
        # TreeView sorting
274
        self.sorted_model = Gtk.TreeModelSort(model=self.visible_filter)
275
        self.sorted_model.set_sort_func(0, self.sort_function, None)
276
 
277
        # Selection
278
        self.selection = self.treeview.get_selection()
279
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)
280
        self.selection.connect('changed', self.row_changed)
281
 
282
        # Set model (filtered and sorted)
283
        self.treeview.set_model(self.sorted_model)
284
 
285
        self.show_all()
286
 
287
 
288
    def sort_function(self, model, row1, row2, user_data):
289
        sort_column = 0
290
 
291
        value1 = model.get_value(row1, sort_column)
292
        value2 = model.get_value(row2, sort_column)
293
 
294
        if value1 < value2:
295
            return -1
296
        elif value1 == value2:
297
            return 0
298
        else:
299
            return 1
300
 
301
    def always_visible(self, model, itr, data):
302
        return False
303
 
268 t00m 304
 
254 t00m 305
    def visible_function(self, model, itr, data):
306
        entry = self.srvgui.get_widget('gtk_entry_filter_visor')
307
        text = entry.get_text()
308
        sid = str(model.get(itr, 3)[0])
309
        if sid.startswith('<'):
310
            sid = sid[3:-4]
311
        title = model.get(itr, 4)[0]
312
        component = str(model.get(itr, 5)[0])
313
        category = model.get(itr, 6)[0]
314
        rtype = model.get(itr, 7)[0]
281 t00m 315
        # ~ string = ' '.join(['SAP Note %s' % sid, title, component, category, rtype])
316
        # ~ match = text.upper() in string.upper()
317
        match = text.upper() in title.upper()
254 t00m 318
 
319
        return match
320
 
321
 
322
    def update_total_sapnotes_count(self, count=0):
323
        statusbar = self.srvgui.get_widget('widget_statusbar')
324
        lblnotescount = self.srvgui.get_widget('gtk_label_total_notes')
325
        total = self.srvdtb.get_total()
267 t00m 326
        lblnotescount.set_markup("<b>%d/<big>%d SAP Notes</big></b>" % (count, total))
254 t00m 327
        # ~ self.info('View populated with %d SAP Notes' % count)
328
 
329
 
330
    def get_visible_filter(self):
331
        return self.visible_filter
332
 
333
 
334
    def row_changed(self, selection):
271 t00m 335
        # ~ selection = self.srvgui.get_key_value('menuview-selection')
336
        # ~ signal = self.srvgui.get_key_value('menuview-row-changed')
337
        # ~ GObject.signal_handler_block(selection, signal)
254 t00m 338
        try:
339
            model, treeiter = selection.get_selected()
340
            if treeiter is not None:
341
                component = model[treeiter][5]
342
                if component == 'Annotation':
343
                    aid = model[treeiter][10]
344
                    is_valid = self.srvant.is_valid(aid)
345
                    if is_valid:
346
                        self.srvclb.action_annotation_edit(aid)
347
                else:
348
                    aid = None
349
                    self.srvuif.set_widget_visibility('gtk_vbox_container_annotations', False)
350
        except Exception as error:
279 t00m 351
            self.log.debug(error)
255 t00m 352
            # ~ self.print_traceback()
271 t00m 353
        # ~ GObject.signal_handler_unblock(selection, signal)
254 t00m 354
 
355
 
356
    def toggle_checkbox(self, cell, path):
357
        path = self.sorted_model.convert_path_to_child_path(Gtk.TreePath(path))
358
        self.model[path][2] = not self.model[path][2]
359
 
360
 
361
    def get_node(self, key, icon, checkbox, sid, title, component, category='', sntype='', priority='', updated='', aid='', timestamp=''):
362
        # Add completion entries
363
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
364
        completion_model = completion.get_model()
365
        completion_model.append([title])
366
 
367
        node = []
368
        node.append(key)
369
        node.append(icon)
370
        node.append(checkbox)
371
        node.append(sid)
372
        node.append(title)
373
        node.append(component)
374
        node.append(category)
375
        node.append(sntype)
376
        node.append(priority)
377
        node.append(updated)
378
        node.append(aid) # Extra key for annotations id (aid)
379
        node.append(timestamp)
380
        return node
381
 
264 t00m 382
    def get_sorted_model(self):
383
        return self.sorted_model
254 t00m 384
 
264 t00m 385
 
254 t00m 386
    def get_bag(self):
387
        return self.bag
388
 
389
 
264 t00m 390
    def reload(self):
391
        self.populate_sapnotes(self.bag)
392
 
393
 
254 t00m 394
    def populate_sapnotes(self, bag=None, cid=None):
395
        icon_annotation = self.srvicm.get_pixbuf_icon('basico-annotation', 32, 32)
287 t00m 396
        # ~ icon_content = self.srvicm.get_pixbuf_icon('basico-logviewer', 32, 32)
397
        # ~ icon_link = self.srvicm.get_pixbuf_icon('basico-browser', 32, 32)
254 t00m 398
        icon_empty = self.srvicm.get_pixbuf_icon('basico-empty', 32, 32)
399
        icon_sapnote = self.srvicm.get_pixbuf_icon('basico-sapnote', 32, 32)
400
        icon_bookmark = self.srvicm.get_pixbuf_icon('basico-bookmarks', 32, 32)
287 t00m 401
        for atype in ATYPES:
402
            self.icons['type'][atype.lower()] = self.srvicm.get_pixbuf_icon('basico-annotation-type-%s' % atype.lower())
254 t00m 403
        self.column_sid.set_visible(True)
264 t00m 404
        self.column_checkbox.set_visible(True)
254 t00m 405
        self.column_category.set_visible(False)
406
        self.column_component.set_visible(True)
407
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
408
        completion_model = completion.get_model()
409
        completion_model.clear()
275 t00m 410
        self.model.clear()
411
 
254 t00m 412
        if bag is None:
413
            bag = self.bag
414
        else:
415
            self.bag = bag
416
 
275 t00m 417
 
254 t00m 418
        for sid in self.bag:
419
            metadata = self.srvdtb.get_sapnote_metadata(sid)
420
            if metadata is not None:
421
                bookmark = metadata['bookmark']
422
                title = escape(metadata['title'])
423
                sid = str(int(metadata['id']))
424
                if bookmark:
425
                    icon = icon_bookmark
426
                    title = "<b>%s</b>" % title
427
                    sid = "<b>%s</b>" % sid
428
                else:
429
                    icon = icon_sapnote
430
 
431
                timestamp = metadata['releaseon']
432
                timestamp = timestamp.replace('-', '')
433
                timestamp = timestamp.replace(':', '')
434
                timestamp = timestamp.replace('T', '_')
435
 
436
                node = self.get_node(   int(metadata['id']),
437
                                        icon,
438
                                        bookmark,
439
                                        '<b>%s</b>' % sid,
440
                                        title,
441
                                        escape(metadata['componentkey']),
442
                                        escape(metadata['category']),
443
                                        escape(metadata['type']),
444
                                        escape(metadata['priority']),
445
                                        self.srvutl.fuzzy_date_from_timestamp(timestamp),
446
                                        '',
447
                                        timestamp
448
                                    )
449
                pid = self.model.append(None, node)
450
 
451
                # Load annotations
452
                files = self.srvant.get_by_sid(metadata['id'])
453
                for fname in files:
454
                    with open(fname, 'r') as fa:
455
                        annotation = json.load(fa)
284 t00m 456
                        atype = annotation['type']
457
                        try:
458
                            icon = self.icons['type']['%s' % atype.lower()]
459
                        except:
460
                            icon = None
254 t00m 461
                        node = self.get_node(   0,
284 t00m 462
                                                icon,
254 t00m 463
                                                False,
464
                                                '',
465
                                                annotation['title'],
466
                                                annotation['component'],
467
                                                '',
468
                                                annotation['type'],
469
                                                '',
470
                                                self.srvutl.fuzzy_date_from_timestamp(annotation['timestamp']),
471
                                                annotation['aid'],
472
                                                annotation['timestamp']
473
                                            )
474
                        self.model.append(pid, node)
475
        self.treeview.set_model(self.sorted_model)
476
        self.update_total_sapnotes_count(len(self.model))
477
        self.show_widgets()
478
        stack = self.srvgui.get_widget('gtk_stack_main')
479
        stack.set_visible_child_name('visor')
480
 
481
 
482
    def show_widgets(self):
483
        self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
484
 
485
 
486
    def right_click(self, treeview, event, data=None):
487
        if event.button == 3:
488
            rect = Gdk.Rectangle()
489
            rect.x = x = int(event.x)
490
            rect.y = y = int(event.y)
491
            pthinfo = self.treeview.get_path_at_pos(x,y)
492
            if pthinfo is not None:
493
                path,col,cellx,celly = pthinfo
494
                model = treeview.get_model()
495
                treeiter = model.get_iter(path)
496
                component = model[treeiter][5]
497
                sid = model[treeiter][0]
498
                sid = "0"*(10 - len(str(sid))) + str(sid)
499
                toolbar = self.srvgui.get_widget('visortoolbar')
500
                popover = self.srvgui.add_widget('gtk_popover_visor_row', Gtk.Popover.new(treeview))
501
                popover.set_position(Gtk.PositionType.TOP)
502
                popover.set_pointing_to(rect)
503
                box = self.build_popover(sid, popover, component)
504
                popover.add(box)
505
                self.srvclb.gui_show_popover(None, popover)
506
 
507
 
508
    def build_popover(self, sid, popover, component):
509
        box = Gtk.Box(spacing = 3, orientation="vertical")
510
 
511
        def get_popover_button(text, icon_name):
512
            button = Gtk.Button()
513
            button.set_relief(Gtk.ReliefStyle.NONE)
514
            hbox = Gtk.HBox()
515
            icon = self.srvicm.get_new_image_icon(icon_name, 24, 24)
516
            lbltext = Gtk.Label()
517
            lbltext.set_xalign(0.0)
518
            lbltext.set_markup('%s' % text)
519
            hbox.pack_start(icon, False, False, 3)
520
            hbox.pack_start(lbltext, True, True, 3)
521
            button.add(hbox)
522
            return button
523
 
524
        if component == 'Annotation':
525
            # Popover button "Delete annotation"
526
            button = get_popover_button("Delete annotation", 'basico-delete')
527
            button.show_all()
528
            button.connect('clicked', self.srvclb.action_annotation_delete)
529
            box.pack_start(button, False, False, 0)
530
 
531
            # Popover button "Duplicate annotation"
532
            button = get_popover_button("Duplicate annotation", 'basico-duplicate')
533
            button.show_all()
534
            button.connect('clicked', self.srvclb.action_annotation_duplicate)
535
            box.pack_start(button, False, False, 0)
536
 
537
        else:
538
            # Popover button "Add an annotation"
539
            button = get_popover_button("Add an annotation", 'basico-annotation')
540
            button.show_all()
541
            button.connect('clicked', self.srvclb.gui_annotation_widget_show, sid, 'create')
542
            box.pack_start(button, False, False, 0)
543
 
544
            # Popover button "Open SAP Note"
545
            button = get_popover_button("See SAP Note", 'basico-browse')
546
            button.connect('clicked', self.srvclb.sapnote_browse, sid)
547
            box.pack_start(button, False, False, 0)
548
 
549
            # Popover button "Bookmark"
550
            button = get_popover_button("(Un)bookmark SAP Note", 'basico-bookmarks')
551
            button.connect('clicked', self.srvclb.switch_bookmark, [sid], popover)
552
            box.pack_start(button, False, False, 0)
553
 
282 t00m 554
            # Popover button "Copy to clipboard"
555
            button = get_popover_button("Copy to clipboard", 'basico-clipboard')
556
            button.connect('clicked', self.srvclb.gui_copy_to_clipboard_sapnote, [sid], popover)
557
            box.pack_start(button, False, False, 0)
558
 
254 t00m 559
            # Separator
560
            separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
561
            box.pack_start(separator, True, True, 0)
562
 
563
            # Popover button Collection Management
564
            button = get_popover_button("Manage collections", 'basico-collection')
565
            box.pack_start(button, False, False, 0)
566
            self.popcollections = self.srvgui.add_widget('gtk_popover_button_manage_collections_single_note', Gtk.Popover.new(button))
567
            self.popcollections.set_position(Gtk.PositionType.RIGHT)
568
            button.connect('clicked', self.srvclb.gui_show_popover, self.popcollections)
271 t00m 569
            colmgt = CollectionsMgtView(self.app, sid)
570
            self.popcollections.add(colmgt)
254 t00m 571
 
572
            # Separator
573
            separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
574
            box.pack_start(separator, True, True, 0)
575
 
576
 
577
            # Popover button "Delete SAP Note"
578
            button = get_popover_button("Delete SAP Note", 'basico-delete')
579
            button.connect('clicked', self.srvclb.sapnote_delete, sid)
580
            box.pack_start(button, False, False, 0)
581
 
582
        return box
583
 
584