Subversion Repositories basico

Rev

Rev 401 | Rev 405 | 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.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 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
22
from gi.repository import GObject
23
from gi.repository.GdkPixbuf import Pixbuf
24
from gi.repository import Pango
25
 
26
from basico.core.mod_wdg import BasicoWidget
27
from basico.core.mod_env import LPATH, ATYPES
363 t00mlabs 28
from basico.services.srv_collections import COL_DOWNLOADED
340 t00mlabs 29
from basico.widgets.wdg_cols import CollectionsMgtView
30
from basico.widgets.wdg_import import ImportWidget
31
from basico.core.mod_log import get_logger
389 t00mlabs 32
from basico.widgets.wdg_menuview import MenuView
340 t00mlabs 33
 
34
 
35
class SAPNotesVisor(BasicoWidget, Gtk.Box):
36
    def __init__(self, app):
37
        super().__init__(app, __class__.__name__)
380 t00mlabs 38
        Gtk.Box.__init__(self, app)
340 t00mlabs 39
        self.get_services()
40
        self.bag = []
41
        self.icons = {}
42
        self.icons['type'] = {}
389 t00mlabs 43
        panel = self.setup_panel()
44
        visor = self.setup_visor()
45
        paned = Gtk.HPaned()
46
        paned.add1(panel)
47
        paned.add2(visor)
48
        paned.set_position(400)
49
        paned.show_all()
50
        self.add(paned)
340 t00mlabs 51
        self.log.debug("SAP Notes Visor initialized")
52
 
53
 
54
    def get_services(self):
55
        self.srvgui = self.get_service("GUI")
56
        self.srvclb = self.get_service('Callbacks')
57
        self.srvsap = self.get_service('SAP')
58
        self.srvicm = self.get_service('IM')
59
        self.srvstg = self.get_service('Settings')
60
        self.srvdtb = self.get_service('DB')
61
        self.srvuif = self.get_service("UIF")
62
        self.srvutl = self.get_service("Utils")
63
        self.srvant = self.get_service('Annotation')
361 t00mlabs 64
        self.srvatc = self.get_service('Attachment')
340 t00mlabs 65
 
66
 
67
    def get_treeview(self):
68
        return self.treeview
69
 
70
 
71
    def sort_by_timestamp(self):
402 t00mlabs 72
        sorted_model = self.srvgui.get_widget('visor_sapnotes_sorted_model')
73
        sorted_model.set_sort_column_id(11, Gtk.SortType.DESCENDING)
340 t00mlabs 74
 
75
 
389 t00mlabs 76
    def setup_panel(self):
77
        ## Left view - SAP Notes Menu view
78
        box = self.srvgui.add_widget('gtk_vbox_container_menu_view', Gtk.VBox())
79
        # ~ self.pack_start(box, False, True, 3)
80
        # ~ separator = Gtk.Separator(orientation = Gtk.Orientation.VERTICAL)
81
        # ~ self.pack_start(separator, False, False, 3)
82
        box.set_property('margin-left', 0)
83
        box.set_property('margin-right', 0)
84
        box.set_property('margin-bottom', 0)
85
 
86
        # View combobox button/popover
87
        lhbox = Gtk.HBox()
88
        menuviews = self.srvgui.add_widget('gtk_button_menu_views', Gtk.Button())
89
        menuviews.set_relief(Gtk.ReliefStyle.NONE)
90
        hbox = Gtk.HBox()
91
        label = self.srvgui.add_widget('gtk_label_current_view', Gtk.Label())
92
        label.set_xalign(0.0)
93
        image = self.srvgui.add_widget('gtk_image_current_view', Gtk.Image())
94
        hbox.pack_start(image, False, False, 3)
95
        hbox.pack_start(label, True, True, 3)
96
        menuviews.add(hbox)
97
        lhbox.pack_start(menuviews, True, True, 3)
98
        lhbox.show_all()
99
        box.pack_start(lhbox, False, False, 3)
100
 
101
        ### Popover menuviews
102
        popover = self.srvgui.add_widget('gtk_popover_button_menu_views', Gtk.Popover.new(menuviews))
103
        menuviews.connect('clicked', self.srvclb.gui_show_popover, popover)
104
        box_views = Gtk.Box(spacing = 0, orientation="vertical")
105
        popover.add(box_views)
106
 
107
        box_views.pack_start(self.srvuif.create_menuview_button('collection'), False, False, 0)
108
        separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
109
        box_views.pack_start(separator, False, False, 0)
110
        box_views.pack_start(self.srvuif.create_menuview_button('component'), False, False, 0)
111
        box_views.pack_start(self.srvuif.create_menuview_button('description'), False, False, 0)
112
        box_views.pack_start(self.srvuif.create_menuview_button('bookmarks'), False, False, 0)
113
        box_views.pack_start(self.srvuif.create_menuview_button('category'), False, False, 0)
114
        box_views.pack_start(self.srvuif.create_menuview_button('chronologic'), False, False, 0)
115
        box_views.pack_start(self.srvuif.create_menuview_button('priority'), False, False, 0)
116
        box_views.pack_start(self.srvuif.create_menuview_button('type'), False, False, 0)
117
 
118
        ### Toolbar
119
        toolbar = Gtk.Toolbar()
120
        toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
121
 
122
        #### Filter entry tool
123
        tool = Gtk.ToolItem.new()
124
 
125
        hbox = Gtk.HBox()
126
        viewfilter = self.srvgui.add_widget('gtk_entry_filter_view', Gtk.Entry())
127
        completion = self.srvgui.get_widget('gtk_entrycompletion_viewmenu')
128
        viewfilter.set_completion(completion)
129
        viewfilter.connect('activate', self.srvclb.gui_viewmenu_filter)
130
 
131
        icon = self.srvicm.get_pixbuf_icon('basico-refresh')
132
        viewfilter.set_icon_from_pixbuf(Gtk.EntryIconPosition.PRIMARY, icon)
133
        viewfilter.set_icon_sensitive(Gtk.EntryIconPosition.PRIMARY, True)
134
        viewfilter.set_icon_tooltip_markup (Gtk.EntryIconPosition.PRIMARY, "Refresh and collapse")
135
 
136
        icon = self.srvicm.get_pixbuf_icon('basico-filter')
137
        viewfilter.set_icon_from_pixbuf(Gtk.EntryIconPosition.SECONDARY, icon)
138
        viewfilter.set_icon_sensitive(Gtk.EntryIconPosition.SECONDARY, True)
139
        viewfilter.set_icon_tooltip_markup (Gtk.EntryIconPosition.SECONDARY, "Click here to expand the tree")
140
        viewfilter.set_placeholder_text("Filter this view...")
141
 
142
        def on_icon_pressed(entry, icon_pos, event):
143
            if icon_pos == Gtk.EntryIconPosition.PRIMARY:
144
                viewmenu = self.srvgui.get_widget('viewmenu')
145
                viewmenu.refresh()
146
            elif icon_pos == Gtk.EntryIconPosition.SECONDARY:
147
                self.srvclb.expand_menuview()
148
 
149
        viewfilter.connect("icon-press", on_icon_pressed)
150
 
151
        hbox.pack_start(viewfilter, True, True, 0)
152
        tool.add(hbox)
153
        tool.set_expand(True)
154
        toolbar.insert(tool, -1)
155
 
156
        box.pack_start(toolbar, False, False, 0)
157
 
158
        ### View treeview
159
        box_trv = Gtk.VBox()
160
        box_trv.set_property('margin-left', 3)
161
        box_trv.set_property('margin-right', 3)
162
        box_trv.set_property('margin-bottom', 0)
340 t00mlabs 163
        scr = Gtk.ScrolledWindow()
389 t00mlabs 164
        # ~ scr.set_hexpand(True)
340 t00mlabs 165
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
166
        scr.set_shadow_type(Gtk.ShadowType.IN)
389 t00mlabs 167
        vwp = Gtk.Viewport()
168
        vwp.set_hexpand(True)
169
        viewsbox = self.srvgui.add_widget('gtk_box_container_views', Gtk.Box())
170
        # ~ viewsbox.set_hexpand(True)
171
        viewmenu = self.srvgui.add_widget('viewmenu', MenuView(self.app))
172
        # ~ viewmenu.set_hexpand(True)
173
        viewmenu.set_vexpand(True)
174
        viewsbox.pack_start(viewmenu, True, True, 0)
175
        vwp.add(viewsbox)
176
        scr.add(vwp)
177
        box_trv.pack_start(scr, True, True, 0)
178
        box.pack_start(box_trv, True, True, 0)
179
        # ~ box.show_all()
180
        # ~ box.add(viewmenu)
181
        return box
182
 
183
 
184
 
185
    def setup_visor(self):
186
        visor = Gtk.VBox()
187
        scr = Gtk.ScrolledWindow()
188
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
189
        scr.set_shadow_type(Gtk.ShadowType.IN)
340 t00mlabs 190
        self.treeview = Gtk.TreeView()
191
        scr.add(self.treeview)
389 t00mlabs 192
        visor.pack_start(scr, True, True, 0)
193
        visor.show_all()
340 t00mlabs 194
 
195
        # Setup model
383 t00mlabs 196
        self.model = Gtk.ListStore(
340 t00mlabs 197
            int,        # key
198
            Pixbuf,     # Icon
199
            int,        # checkbox
200
            str,        # sid
201
            str,        # title
202
            str,        # component
203
            str,        # category
204
            str,        # type
205
            str,        # priority
206
            str,        # last update
207
            str,        # Annotation Id (extra key)
208
            str,        # Timestamp
209
        )
210
 
211
        # Setup columns
389 t00mlabs 212
        def get_column_header_widget(title, icon_name=None, width=28, height=28):
340 t00mlabs 213
            hbox = Gtk.HBox()
214
            icon = self.srvicm.get_new_image_icon(icon_name, width, height)
215
            label = Gtk.Label()
216
            label.set_markup("<b>%s</b>" % title)
217
            # ~ label.modify_font(Pango.FontDescription('Monospace 10'))
218
            hbox.pack_start(icon, False, False, 3)
219
            hbox.pack_start(label, True, True, 3)
220
            hbox.show_all()
221
            return hbox
222
 
223
        # SAP Note key
224
        self.renderer_key = Gtk.CellRendererText()
225
        self.renderer_key.set_property('height', 32)
226
        self.column_key = Gtk.TreeViewColumn('Key', self.renderer_key, text=0)
227
        self.column_key.set_visible(False)
228
        self.column_key.set_expand(False)
229
        self.column_key.set_clickable(False)
230
        self.column_key.set_sort_indicator(False)
231
        self.treeview.append_column(self.column_key)
232
 
233
        # Icon
234
        self.renderer_icon = Gtk.CellRendererPixbuf()
235
        self.renderer_icon.set_alignment(0.0, 0.5)
384 t00mlabs 236
        self.column_icon = Gtk.TreeViewColumn('', self.renderer_icon, pixbuf=1)
402 t00mlabs 237
        # ~ widget = get_column_header_widget('', '')
238
        # ~ self.column_icon.set_widget(widget)
340 t00mlabs 239
        self.column_icon.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
401 t00mlabs 240
        self.column_icon.set_visible(True)
340 t00mlabs 241
        self.column_icon.set_expand(False)
242
        self.column_icon.set_clickable(False)
243
        self.column_icon.set_sort_indicator(False)
244
        self.treeview.append_column(self.column_icon)
245
 
246
        # SAP Note Checkbox
247
        self.renderer_checkbox = Gtk.CellRendererToggle()
402 t00mlabs 248
        self.renderer_checkbox.connect("toggled", self.__clb_row_toggled)
340 t00mlabs 249
        self.column_checkbox = Gtk.TreeViewColumn('', self.renderer_checkbox, active=2)
402 t00mlabs 250
        widget = get_column_header_widget('', 'basico-check-accept')
251
        self.column_checkbox.set_widget(widget)
340 t00mlabs 252
        self.column_checkbox.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
253
        self.column_checkbox.set_visible(True)
254
        self.column_checkbox.set_expand(False)
255
        self.column_checkbox.set_clickable(True)
256
        self.column_checkbox.set_sort_indicator(False)
257
        self.column_checkbox.set_property('spacing', 50)
258
        self.treeview.append_column(self.column_checkbox)
259
 
260
        # SAP Note Id
261
        self.renderer_sid = Gtk.CellRendererText()
262
        self.renderer_sid.set_property('xalign', 1.0)
263
        self.renderer_sid.set_property('height', 36)
264
        self.renderer_sid.set_property('background', '#F0E3E3')
383 t00mlabs 265
        self.column_sid = Gtk.TreeViewColumn('SAP Note', self.renderer_sid, markup=3)
402 t00mlabs 266
        # ~ widget = get_column_header_widget('SAP Note', 'basico-sapnote')
267
        # ~ self.column_sid.set_widget(widget)
340 t00mlabs 268
        self.column_sid.set_visible(True)
269
        self.column_sid.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
270
        self.column_sid.set_expand(False)
271
        self.column_sid.set_clickable(True)
272
        self.column_sid.set_sort_indicator(True)
273
        self.column_sid.set_sort_column_id(0)
274
        self.column_sid.set_sort_order(Gtk.SortType.ASCENDING)
275
        self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
276
        self.treeview.append_column(self.column_sid)
277
 
278
        # SAP Note title
279
        self.renderer_title = Gtk.CellRendererText()
280
        self.renderer_title.set_property('background', '#FFFEEA')
281
        self.renderer_title.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
282
        self.column_title = Gtk.TreeViewColumn('Title', self.renderer_title, markup=4)
283
        widget = get_column_header_widget('Title', 'basico-tag')
284
        self.column_title.set_widget(widget)
285
        self.column_title.set_visible(True)
286
        self.column_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
287
        self.column_title.set_expand(True)
288
        self.column_title.set_clickable(True)
289
        self.column_title.set_sort_indicator(True)
290
        self.column_title.set_sort_column_id(4)
291
        self.treeview.append_column(self.column_title)
292
 
293
        # SAP Note Component
294
        self.renderer_component = Gtk.CellRendererText()
295
        self.renderer_component.set_property('background', '#E3E3F0')
296
        self.column_component = Gtk.TreeViewColumn('Component', self.renderer_component, markup=5)
297
        widget = get_column_header_widget('Component', 'basico-component')
298
        self.column_component.set_widget(widget)
299
        self.column_component.set_visible(True)
300
        self.column_component.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
301
        self.column_component.set_expand(False)
302
        self.column_component.set_clickable(True)
303
        self.column_component.set_sort_indicator(True)
304
        self.column_component.set_sort_column_id(5)
305
        self.treeview.append_column(self.column_component)
306
 
307
        # SAP Note Category
308
        self.renderer_category = Gtk.CellRendererText()
309
        self.renderer_category.set_property('background', '#E3F1E3')
310
        self.column_category = Gtk.TreeViewColumn('Category', self.renderer_category, markup=6)
311
        widget = get_column_header_widget('Category', 'basico-category')
312
        self.column_category.set_widget(widget)
313
        self.column_category.set_visible(False)
314
        self.column_category.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
315
        self.column_category.set_expand(False)
316
        self.column_category.set_clickable(True)
317
        self.column_category.set_sort_indicator(True)
318
        self.column_category.set_sort_column_id(6)
319
        self.treeview.append_column(self.column_category)
320
 
321
        # SAP Note Type
322
        self.renderer_type = Gtk.CellRendererText()
323
        self.renderer_type.set_property('background', '#e4f1f1')
324
        self.column_type = Gtk.TreeViewColumn('Type', self.renderer_type, markup=7)
389 t00mlabs 325
        widget = get_column_header_widget('Type', 'basico-type')
326
        self.column_type.set_widget(widget)
340 t00mlabs 327
        self.column_type.set_visible(True)
328
        self.column_type.set_expand(False)
329
        self.column_type.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
330
        self.column_type.set_clickable(True)
331
        self.column_type.set_sort_indicator(True)
332
        self.column_type.set_sort_column_id(7)
333
        self.treeview.append_column(self.column_type)
334
 
335
        # SAP Note Priority
336
        self.renderer_priority = Gtk.CellRendererText()
337
        self.column_priority = Gtk.TreeViewColumn('Priority', self.renderer_priority, markup=8)
389 t00mlabs 338
        widget = get_column_header_widget('Type', 'basico-priority')
339
        self.column_priority.set_widget(widget)
340 t00mlabs 340
        self.column_priority.set_visible(False)
341
        self.column_priority.set_expand(True)
342
        self.column_priority.set_clickable(True)
343
        self.column_priority.set_sort_indicator(True)
344
        self.column_priority.set_sort_column_id(8)
345
        self.treeview.append_column(self.column_priority)
346
 
347
        # SAP Note UpdatedOn
348
        self.renderer_updated = Gtk.CellRendererText()
349
        self.renderer_updated.set_property('background', '#FFE6D1')
390 t00mlabs 350
        self.column_updated = Gtk.TreeViewColumn('Updated', self.renderer_updated, markup=9)
351
        widget = get_column_header_widget('Updated', 'basico-chronologic')
389 t00mlabs 352
        self.column_updated.set_widget(widget)
340 t00mlabs 353
        self.column_updated.set_visible(True)
354
        self.column_updated.set_expand(False)
355
        self.column_updated.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
356
        self.column_updated.set_clickable(True)
357
        self.column_updated.set_sort_indicator(True)
358
        self.column_updated.set_sort_column_id(11)
359
        self.treeview.append_column(self.column_updated)
360
 
361
        # Annotation Id
362
        self.renderer_annotation = Gtk.CellRendererText()
363
        self.column_annotation = Gtk.TreeViewColumn('Annotation Id', self.renderer_annotation, markup=10)
364
        self.column_annotation.set_visible(False)
365
        self.column_annotation.set_expand(False)
366
        self.column_annotation.set_clickable(False)
367
        self.column_annotation.set_sort_indicator(False)
368
        self.treeview.append_column(self.column_annotation)
369
 
370
        # Timestamp
371
        self.renderer_timestamp = Gtk.CellRendererText()
372
        self.column_timestamp = Gtk.TreeViewColumn('Annotation Id', self.renderer_timestamp, text=11)
373
        self.column_timestamp.set_visible(False)
374
        self.column_timestamp.set_expand(False)
375
        self.column_timestamp.set_clickable(False)
376
        self.column_timestamp.set_sort_indicator(False)
377
        self.treeview.append_column(self.column_timestamp)
378
 
379
        # Treeview properties
380
        self.treeview.set_can_focus(False)
381
        self.treeview.set_enable_tree_lines(True)
382
        self.treeview.set_headers_visible(True)
383
        self.treeview.set_enable_search(True)
384
        self.treeview.set_hover_selection(False)
384 t00mlabs 385
        self.treeview.set_grid_lines(Gtk.TreeViewGridLines.HORIZONTAL)
340 t00mlabs 386
        self.treeview.set_enable_tree_lines(True)
387
        self.treeview.set_level_indentation(10)
388
        # ~ self.treeview.modify_font(Pango.FontDescription('Monospace 10'))
389
        self.treeview.connect('button_press_event', self.right_click)
390
 
391
        # DOC: In order to have a Gtk.Widged with sorting and filtering
392
        # capabilities, you have to filter the model first, and use this
393
        # new model to create the sorted model. Then, attach the sorted
394
        # model to the treeview...
395
 
396
        # Treeview filtering:
397
        self.visible_filter = self.model.filter_new()
398
        self.visible_filter.set_visible_func(self.visible_function)
399
        # https://stackoverflow.com/questions/23355866/user-search-collapsed-rows-in-a-gtk-treeview
400
 
401
        # TreeView sorting
402 t00mlabs 402
        sorted_model = Gtk.TreeModelSort(model=self.visible_filter)
403
        self.srvgui.add_widget('visor_sapnotes_sorted_model', sorted_model)
404
        sorted_model.set_sort_func(0, self.sort_function, None)
340 t00mlabs 405
 
406
        # Selection
407
        self.selection = self.treeview.get_selection()
408
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)
409
        self.selection.connect('changed', self.row_changed)
410
 
411
        # Set model (filtered and sorted)
402 t00mlabs 412
        self.treeview.set_model(sorted_model)
340 t00mlabs 413
 
414
        self.show_all()
389 t00mlabs 415
        return visor
340 t00mlabs 416
 
417
 
418
    def sort_function(self, model, row1, row2, user_data):
419
        sort_column = 0
420
 
421
        value1 = model.get_value(row1, sort_column)
422
        value2 = model.get_value(row2, sort_column)
423
 
424
        if value1 < value2:
425
            return -1
426
        elif value1 == value2:
427
            return 0
428
        else:
429
            return 1
430
 
431
 
432
    def always_visible(self, model, itr, data):
433
        return False
434
 
435
 
436
    def visible_function(self, model, itr, data):
437
        entry = self.srvgui.get_widget('gtk_entry_filter_visor')
438
        text = self.srvutl.clean_html(entry.get_text())
439
        title = model.get(itr, 4)[0]
343 t00mlabs 440
        component = model.get(itr, 5)[0]
441
        fields = title + ' ' + component
442
        match = text.upper() in fields.upper()
340 t00mlabs 443
 
444
        return match
445
 
446
 
447
    def update_total_sapnotes_count(self):
448
        statusbar = self.srvgui.get_widget('widget_statusbar')
449
        lblnotescount = self.srvgui.get_widget('gtk_label_total_notes')
450
        total = self.srvdtb.get_total()
451
        count = len(self.visible_filter)
452
        lblnotescount.set_markup("<b>%d/<big>%d SAP Notes</big></b>" % (count, total))
453
        msg = 'View populated with %d SAP Notes' % count
454
        self.srvuif.statusbar_msg(msg)
455
 
456
 
457
    def get_visible_filter(self):
458
        return self.visible_filter
459
 
460
 
461
    def row_changed(self, selection):
462
        try:
463
            model, treeiter = selection.get_selected()
464
            if treeiter is not None:
465
                component = model[treeiter][5]
466
                if component == 'Annotation':
467
                    aid = model[treeiter][10]
468
                    is_valid = self.srvant.is_valid(aid)
469
                    if is_valid:
470
                        self.srvclb.action_annotation_edit(aid)
471
                else:
472
                    aid = None
389 t00mlabs 473
                    # ~ self.srvuif.set_widget_visibility('gtk_vbox_container_annotations', False)
340 t00mlabs 474
        except Exception as error:
475
            self.log.debug(error)
476
 
477
 
402 t00mlabs 478
    def __clb_row_toggled(self, cell, path):
479
        sorted_model = self.srvgui.get_widget('visor_sapnotes_sorted_model')
480
        model = sorted_model.get_model()
481
        rpath = sorted_model.convert_path_to_child_path(Gtk.TreePath(path))
482
        model[rpath][2] = not model[rpath][2]
340 t00mlabs 483
 
484
 
485
    def get_node(self, key, icon, checkbox, sid, title, component, category='', sntype='', priority='', updated='', aid='', timestamp=''):
486
        # Add completion entries
487
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
488
        completion_model = completion.get_model()
489
        title = self.srvutl.clean_html(title)
490
        completion_model.append([title])
491
 
492
        node = []
493
        node.append(key)
494
        node.append(icon)
495
        node.append(checkbox)
496
        node.append(sid)
497
        node.append(title)
498
        node.append(component)
499
        node.append(category)
500
        node.append(sntype)
501
        node.append(priority)
502
        node.append(updated)
503
        node.append(aid) # Extra key for annotations id (aid)
504
        node.append(timestamp)
505
        return node
506
 
507
 
508
    def get_model(self):
509
        return self.model
510
 
511
 
512
    def get_sorted_model(self):
513
        return self.sorted_model
514
 
515
 
516
    def get_bag(self):
517
        return self.bag
518
 
519
 
520
    def reload(self):
362 t00mlabs 521
        self.populate(self.bag)
340 t00mlabs 522
 
523
 
362 t00mlabs 524
    def populate(self, bag=None, cid=None):
402 t00mlabs 525
        sorted_model = self.srvgui.get_widget('visor_sapnotes_sorted_model')
340 t00mlabs 526
        icon_sapnote = self.srvicm.get_pixbuf_icon('basico-sapnote', 32, 32)
401 t00mlabs 527
        # ~ icon_sap_note = self.srvicm.get_pixbuf_icon('basico-sap-note', 32, 32)
528
        # ~ icon_sap_note_standard = self.srvicm.get_pixbuf_icon('basico-sap-note', 32, 32)
340 t00mlabs 529
        icon_bookmark = self.srvicm.get_pixbuf_icon('basico-bookmarks', 32, 32)
530
        for atype in ATYPES:
531
            self.icons['type'][atype.lower()] = self.srvicm.get_pixbuf_icon('basico-annotation-type-%s' % atype.lower())
532
        self.column_sid.set_visible(True)
402 t00mlabs 533
        # ~ self.column_checkbox.set_visible(False)
534
        # ~ self.column_category.set_visible(False)
535
        # ~ self.column_component.set_visible(True)
340 t00mlabs 536
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
537
        completion_model = completion.get_model()
538
        completion_model.clear()
539
        self.model.clear()
540
 
541
        if bag is None:
542
            bag = self.bag
543
        else:
544
            self.bag = bag
545
 
546
 
547
        for sid in self.bag:
548
            metadata = self.srvdtb.get_sapnote_metadata(sid)
549
            if metadata is not None:
384 t00mlabs 550
                # ~ self.log.debug("%s:\n%s", sid, metadata)
340 t00mlabs 551
                bookmark = metadata['bookmark']
552
                title = escape(metadata['title'])
553
                sid = str(int(metadata['id']))
384 t00mlabs 554
 
555
                has_annotations = self.srvant.get_by_sid(sid)
556
                has_attachments = self.srvatc.get_by_sid(sid)
386 t00mlabs 557
                # ~ self.log.debug("Annotations: %d, Attachments: %d", len(has_annotations), len(has_attachments))
340 t00mlabs 558
                if bookmark:
559
                    icon = icon_bookmark
560
                    title = "<b>%s</b>" % title
561
                    sid = "<b>%s</b>" % sid
562
                else:
384 t00mlabs 563
                    if len(has_annotations) > 0 and len(has_attachments) > 0:
564
                        icon = self.srvicm.get_pixbuf_icon('basico-annotation-attachment', 32, 32)
565
                    elif len(has_annotations) > 0 and len(has_attachments) == 0:
566
                        icon = self.srvicm.get_pixbuf_icon('basico-annotation', 32, 32)
567
                    elif len(has_annotations) == 0 and len(has_attachments) > 0:
568
                        icon = self.srvicm.get_pixbuf_icon('basico-attachment', 32, 32)
569
                    else:
570
                        icon = icon_sapnote
340 t00mlabs 571
 
572
                timestamp = metadata['releasedon']
573
                timestamp = timestamp.replace('-', '')
574
                timestamp = timestamp.replace(':', '')
575
                timestamp = timestamp.replace('T', '_')
401 t00mlabs 576
                stype = escape(metadata['type'].lower())
577
                icon_name = 'basico-%s' % stype.replace(' ', '-')
578
                self.log.debug(icon_name)
579
                icon = self.srvicm.get_pixbuf_icon(icon_name, 36, 36)
580
                self.log.debug(icon)
581
                # ~ self.log.debug(icon_name)
582
                icon_name = None
340 t00mlabs 583
                node = self.get_node(   int(metadata['id']),
584
                                        icon,
585
                                        False,
586
                                        '<b>%s</b>' % sid,
587
                                        title,
588
                                        escape(metadata['componentkey']),
589
                                        escape(metadata['category']),
590
                                        escape(metadata['type']),
591
                                        escape(metadata['priority']),
592
                                        self.srvutl.fuzzy_date_from_timestamp(timestamp),
593
                                        '',
594
                                        timestamp
595
                                    )
383 t00mlabs 596
                pid = self.model.append(node)
340 t00mlabs 597
 
598
                # Load annotations
383 t00mlabs 599
                # ~ files = self.srvant.get_by_sid(metadata['id'])
600
                # ~ for fname in files:
601
                    # ~ with open(fname, 'r') as fa:
602
                        # ~ annotation = json.load(fa)
603
                        # ~ atype = annotation['Type']
604
                        # ~ try:
605
                            # ~ icon = self.icons['type']['%s' % atype.lower()]
606
                        # ~ except:
607
                            # ~ icon = None
608
                        # ~ node = self.get_node(   0,
609
                                                # ~ icon,
610
                                                # ~ False,
611
                                                # ~ '',
612
                                                # ~ annotation['Title'],
613
                                                # ~ annotation['Component'],
614
                                                # ~ '',
615
                                                # ~ annotation['Type'],
616
                                                # ~ '',
617
                                                # ~ self.srvutl.fuzzy_date_from_timestamp(annotation['Timestamp']),
618
                                                # ~ annotation['AID'],
619
                                                # ~ annotation['Timestamp']
620
                                            # ~ )
621
                        # ~ self.model.append(pid, node)
361 t00mlabs 622
 
623
                # Load attachments
383 t00mlabs 624
                # ~ files = self.srvatc.get_by_sid(metadata['id'])
625
                # ~ for fname in files:
626
                    # ~ with open(fname, 'r') as ft:
627
                        # ~ attachment = json.load(ft)
628
                        # ~ icon = self.srvicm.get_pixbuf_icon('basico-attachment')
629
                        # ~ node = self.get_node(   0,
630
                                                # ~ icon,
631
                                                # ~ False,
632
                                                # ~ '',
633
                                                # ~ attachment['Title'],
634
                                                # ~ 'Attachment',
635
                                                # ~ '',
636
                                                # ~ attachment['Description'],
637
                                                # ~ '',
638
                                                # ~ self.srvutl.fuzzy_date_from_timestamp(attachment['Created']),
639
                                                # ~ attachment['TID'],
640
                                                # ~ attachment['Created']
641
                                            # ~ )
642
                        # ~ self.model.append(pid, node)
380 t00mlabs 643
 
402 t00mlabs 644
        self.treeview.set_model(sorted_model)
340 t00mlabs 645
        self.update_total_sapnotes_count()
646
        self.show_widgets()
389 t00mlabs 647
        self.srvclb.gui_show_dashboard()
648
        # ~ stack = self.srvgui.get_widget('gtk_stack_main')
649
        # ~ stack.set_visible_child_name('dashboard')
383 t00mlabs 650
        # ~ self.log.debug("Visor updated")
340 t00mlabs 651
 
652
    def show_widgets(self):
653
        self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
654
 
655
 
656
    def right_click(self, treeview, event, data=None):
657
        if event.button == 3:
658
            rect = Gdk.Rectangle()
659
            rect.x = x = int(event.x)
660
            rect.y = y = int(event.y)
661
            pthinfo = self.treeview.get_path_at_pos(x,y)
662
            if pthinfo is not None:
663
                path,col,cellx,celly = pthinfo
664
                model = treeview.get_model()
665
                treeiter = model.get_iter(path)
666
                component = model[treeiter][5]
667
                sid = model[treeiter][0]
361 t00mlabs 668
                if sid == 0:
669
                    return
340 t00mlabs 670
                sid = "0"*(10 - len(str(sid))) + str(sid)
389 t00mlabs 671
                # ~ toolbar = self.srvgui.get_widget('visortoolbar')
340 t00mlabs 672
                popover = self.srvgui.add_widget('gtk_popover_visor_row', Gtk.Popover.new(treeview))
673
                popover.set_position(Gtk.PositionType.TOP)
674
                popover.set_pointing_to(rect)
675
                box = self.build_popover(sid, popover, component)
676
                popover.add(box)
677
                self.srvclb.gui_show_popover(None, popover)
678
 
679
 
380 t00mlabs 680
    def clb_create_annotation(self, button, sid):
681
        self.srvclb.action_annotation_create_for_sapnote(sid)
682
 
683
 
340 t00mlabs 684
    def build_popover(self, sid, popover, component):
685
        box = Gtk.Box(spacing = 3, orientation="vertical")
686
        isid = int(sid)
687
 
688
        def get_popover_button(text, icon_name):
689
            button = Gtk.Button()
690
            button.set_relief(Gtk.ReliefStyle.NONE)
691
            hbox = Gtk.HBox()
692
            icon = self.srvicm.get_new_image_icon(icon_name, 24, 24)
693
            lbltext = Gtk.Label()
694
            lbltext.set_xalign(0.0)
695
            lbltext.set_markup('%s' % text)
696
            hbox.pack_start(icon, False, False, 3)
697
            hbox.pack_start(lbltext, True, True, 3)
698
            button.add(hbox)
699
            return button
700
 
701
        if component == 'Annotation':
702
            # Popover button "Delete annotation"
703
            button = get_popover_button("<b>Delete annotation</b>", 'basico-delete')
704
            button.show_all()
705
            button.connect('clicked', self.srvclb.action_annotation_delete)
706
            box.pack_start(button, False, False, 0)
707
 
708
            # Popover button "Duplicate annotation"
709
            button = get_popover_button("<b>Duplicate annotation</b>", 'basico-duplicate')
710
            button.show_all()
711
            button.connect('clicked', self.srvclb.action_annotation_duplicate)
712
            box.pack_start(button, False, False, 0)
713
 
714
        else:
715
            # Popover button "Add an annotation"
716
            button = get_popover_button("<b>Add an annotation</b> to SAP Note %d" % isid, 'basico-annotation')
717
            button.show_all()
380 t00mlabs 718
            button.connect('clicked', self.clb_create_annotation, sid)
340 t00mlabs 719
            box.pack_start(button, False, False, 0)
720
 
383 t00mlabs 721
            fbox = Gtk.VBox()
722
            frame = Gtk.Frame()
723
            frame.set_border_width(3)
724
            label = Gtk.Label()
725
            label.set_markup(' <b>Attachments</b> ')
726
            frame.set_label_widget(label)
360 t00mlabs 727
            # Popover button "Add attachments"
383 t00mlabs 728
            button = get_popover_button("<b>Add</b> new to SAP Note %d" % isid, 'basico-attachment')
729
            button.set_property('margin', 3)
360 t00mlabs 730
            button.show_all()
731
            button.connect('clicked', self.srvclb.gui_attachment_add_to_sapnote, sid)
383 t00mlabs 732
            fbox.pack_start(button, False, False, 0)
380 t00mlabs 733
 
383 t00mlabs 734
            # Popover button "Show attachments"
735
            if len(self.srvatc.get_by_sid(sid)) > 0:
736
                button = get_popover_button("<b>Show</b> linked to SAP Note %d" % isid, 'basico-attachment')
737
                button.set_property('margin', 3)
738
                button.show_all()
739
                # ~ button.connect('clicked', self.srvclb.gui_attachment_show_, sid)
740
                fbox.pack_start(button, False, False, 0)
741
            frame.add(fbox)
742
            box.pack_start(frame, False, False, 0)
743
 
340 t00mlabs 744
            # Popover button "Open SAP Note"
383 t00mlabs 745
            button = get_popover_button("<b>Browse</b> SAP Note %d" % isid, 'basico-preview')
340 t00mlabs 746
            button.connect('clicked', self.srvclb.sapnote_browse, sid)
747
            box.pack_start(button, False, False, 0)
748
 
749
            # Popover button "Download SAP Note in PDF"
750
            button = get_popover_button("See SAP Note %d in <b>PDF</b>" % isid, 'basico-browse')
751
            button.connect('clicked', self.srvclb.sapnote_download_pdf, sid)
752
            box.pack_start(button, False, False, 0)
753
 
754
            # Popover button "Bookmark"
755
            button = get_popover_button("<b>(Un)bookmark</b> SAP Note %d" % isid, 'basico-bookmarks')
756
            button.connect('clicked', self.srvclb.switch_bookmark, [sid], popover)
757
            box.pack_start(button, False, False, 0)
758
 
759
            # Popover button "Copy to clipboard"
760
            button = get_popover_button("<b>Copy</b> SAP Note %d details <b>to clipboard</b>" % isid, 'basico-clipboard')
761
            button.connect('clicked', self.srvclb.gui_copy_to_clipboard_sapnote, [sid], popover)
762
            box.pack_start(button, False, False, 0)
763
 
764
            # Separator
765
            separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
766
            box.pack_start(separator, True, True, 0)
767
 
768
            # Assing SAP Notes in current view to a category
769
            # Only available in Donwloaded category
770
            viewmenu = self.srvgui.get_widget('viewmenu')
771
            current_viewmenu = viewmenu.get_view()
772
            current_collection = viewmenu.get_current_collection()
773
            view_is_collection = current_viewmenu == 'collection'
774
            collection_is_downloaded = current_collection == COL_DOWNLOADED
775
 
776
            # Popover button Collection Management
777
            button = get_popover_button("<b>Manage collections</b> for SAP Note %d" % isid, 'basico-collection')
778
            box.pack_start(button, False, False, 0)
779
            self.popcollections = self.srvgui.add_widget('gtk_popover_button_manage_collections_single_note', Gtk.Popover.new(button))
780
            self.popcollections.set_position(Gtk.PositionType.RIGHT)
781
            button.connect('clicked', self.srvclb.gui_show_popover, self.popcollections)
782
            colmgt = CollectionsMgtView(self.app, sid, overwrite=True)
783
            self.popcollections.add(colmgt)
784
 
785
            # Separator
786
            separator = Gtk.Separator(orientation = Gtk.Orientation.HORIZONTAL)
787
            box.pack_start(separator, True, True, 0)
788
 
789
 
790
            # Popover button "Delete SAP Note"
791
            button = get_popover_button("<b>Delete</b> SAP Note %d" % isid, 'basico-delete')
792
            button.connect('clicked', self.srvclb.sapnote_delete, sid)
793
            button.set_tooltip_text("Checkbox must be activated in order to trigger the deletion")
794
            box.pack_start(button, False, False, 0)
795
 
796
        return box
797
 
798
 
799
    def get_filtered_bag(self):
402 t00mlabs 800
        sorted_model = self.srvgui.get_widget('visor_sapnotes_sorted_model')
362 t00mlabs 801
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
340 t00mlabs 802
        selected = []
803
 
804
        def get_selected_sapnotes(model, path, itr):
805
            sid = model.get(itr, 0)[0]
806
            aid = model.get(itr, 10)[0]
807
            if len(aid) == 0:
808
                selected.append(str(sid))
809
 
402 t00mlabs 810
        sorted_model.foreach(get_selected_sapnotes)
340 t00mlabs 811
        return selected