Subversion Repositories basico

Rev

Rev 232 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 t00mlabs 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
# File: callbacks.py
4
# Author: Tomás Vírseda
5
# License: GPL v3
6
# Description: UI and related callbacks service
7
 
8
import os
9
import json
74 t00mlabs 10
import time
4 t00mlabs 11
 
12
import gi
13
gi.require_version('Gtk', '3.0')
14
from gi.repository import Gtk
15
 
150 t00m 16
 
74 t00mlabs 17
from concurrent.futures import ThreadPoolExecutor as Executor
18
 
233 t00m 19
from basico.core.service import Service
20
from basico.widgets.sapnoteviewvisor import SAPNoteViewVisor, SAPNoteViewVisorToolbar
21
from basico.widgets.collections import CollectionsMgtView
22
from basico.widgets.annotation import AnnotationWidget
23
from basico.widgets.settings import SettingsView
24
from basico.core.env import FILE, LPATH
4 t00mlabs 25
 
26
 
74 t00mlabs 27
# PROPKEYS = CSV headers. SAP Note metadata
28
PROPKEYS = ['id', 'title', 'type', 'componentkey',
29
            'componenttxt', 'category', 'priority', 'releaseon',
30
            'language', 'version']
31
 
32
# Extend PROPKEYS with custom basico metadata
149 t00m 33
PROPKEYS.extend (['Bookmark'])
74 t00mlabs 34
 
4 t00mlabs 35
class Callback(Service):
36
    def initialize(self):
37
        self.get_services()
38
 
39
    def get_services(self):
126 t00mlabs 40
        self.settings = self.app.get_service('Settings')
112 t00mlabs 41
        self.db = self.app.get_service('DB')
4 t00mlabs 42
        self.gui = self.app.get_service('GUI')
43
        self.uif = self.app.get_service("UIF")
44
        self.sap = self.app.get_service('SAP')
45
        self.alert = self.app.get_service('Notify')
81 t00mlabs 46
        self.im = self.app.get_service('IM')
74 t00mlabs 47
        self.utils = self.app.get_service('Utils')
217 t00m 48
        self.annot = self.app.get_service('Annotation')
4 t00mlabs 49
 
174 t00m 50
 
201 t00m 51
    def action_search(self, entry):
223 t00m 52
        visor = self.gui.get_widget('visor')
233 t00m 53
        viewmenu = self.gui.get_widget('viewmenu')
54
        view = viewmenu.get_view()
223 t00m 55
 
233 t00m 56
        if view != 'annotation':
57
            term = entry.get_text()
58
            bag = self.db.search(term)
59
            visor.populate(bag)
201 t00m 60
 
61
 
188 t00m 62
    def sapnote_browse(self, button, sid):
171 t00m 63
        self.debug("Browsing SAP Note %d" % int(sid))
174 t00m 64
        SAP_NOTE_URL = self.settings.get('SAP', 'SAP_NOTE_URL')
65
        url = SAP_NOTE_URL % sid
66
        self.utils.browse(url)
225 t00m 67
        # ~ popover = self.gui.get_widget('poprowsid')
68
        # ~ popover.hide()
171 t00m 69
 
174 t00m 70
 
212 t00m 71
    def sapnote_delete(self, button, lsid):
72
        self.debug("Deleting SAP Notes %s" % lsid)
73
        if lsid == '0000000000':
74
            visor = self.gui.get_widget('visor')
75
            bag = visor.get_bag()
76
        else:
77
            bag = [lsid]
78
        answer = self.uif.warning_message(button, 'Deleting SAP Notes', 'Are you sure?', bag)
79
        if answer is True:
80
            for sid in bag:
81
                self.db.delete(sid)
82
            viewmenu = self.gui.get_widget('viewmenu')
83
            viewmenu.refresh()
84
        else:
85
            self.debug("Nothing deleted")
174 t00m 86
 
87
 
188 t00m 88
    def gui_hide_popover(self, popover):
206 t00m 89
        popover.hide()
150 t00m 90
 
187 t00m 91
 
188 t00m 92
    def gui_show_about(self, *args):
215 t00m 93
        stack = self.gui.get_widget('gtk_stack_main')
94
        stack.set_visible_child_name('about')
230 t00m 95
        self.gui_toggle_menu_view(False)
213 t00m 96
        self.gui_hide_popover(self.gui.get_widget('gtk_popover_button_menu_system'))
233 t00m 97
        self.uif.set_widget_visibility('gtk_button_total_notes', False)
231 t00m 98
        self.uif.set_widget_visibility('gtk_button_dashboard', True)
133 t00mlabs 99
 
150 t00m 100
 
216 t00m 101
    def gui_show_log(self, *args):
102
        logviewer = self.gui.get_widget('widget_logviewer')
231 t00m 103
        stack = self.gui.get_widget('gtk_stack_main')
104
        button_total_notes = self.gui.get_widget('gtk_button_total_notes')
105
 
106
 
216 t00m 107
        logviewer.update()
231 t00m 108
        self.gui_hide_popover(self.gui.get_widget('gtk_popover_button_menu_system'))
216 t00m 109
        stack.set_visible_child_name('log')
231 t00m 110
        self.uif.set_widget_visibility('gtk_button_dashboard', True)
111
        # ~ self.uif.set_widget_visibility(button_total_notes, False)
216 t00m 112
 
113
 
188 t00m 114
    def gui_show_settings(self, button):
215 t00m 115
        stack = self.gui.get_widget('gtk_stack_main')
116
        stack.set_visible_child_name('settings')
117
        view_settings = self.gui.get_widget('widget_settings')
180 t00m 118
        view_settings.update()
213 t00m 119
        self.gui_hide_popover(self.gui.get_widget('gtk_popover_button_menu_system'))
233 t00m 120
        self.uif.set_widget_visibility('gtk_button_total_notes', False)
231 t00m 121
        self.uif.set_widget_visibility('gtk_button_dashboard', True)
79 t00mlabs 122
 
218 t00m 123
 
217 t00m 124
    def gui_show_dashboard(self, *args):
125
        stack = self.gui.get_widget('gtk_stack_main')
126
        stack.set_visible_child_name('visor')
127
        self.gui_hide_popover(self.gui.get_widget('gtk_popover_button_menu_system'))
231 t00m 128
        self.uif.set_widget_visibility('gtk_button_dashboard', False)
233 t00m 129
        viewmenu = self.gui.get_widget('viewmenu')
130
        current_view = viewmenu.get_view()
131
        self.debug("SHOW-DASHBOARD::CURRENT-VIEW: %s" % current_view)
132
        if current_view == 'annotation':
133
            self.uif.set_widget_visibility('gtk_button_total_notes', False)
134
            self.debug("Hidding button")
135
        else:
136
            self.uif.set_widget_visibility('gtk_button_total_notes', True)
137
            self.debug("Showing button")
216 t00m 138
 
217 t00m 139
 
224 t00m 140
    def gui_annotation_widget_show(self, widget, sid='0000000000', action='create'):
141
        widget_annotation = self.gui.get_widget('widget_annotation')
233 t00m 142
        widget = self.gui.get_widget('gtk_label_annotation_sid')
224 t00m 143
 
228 t00m 144
 
222 t00m 145
        if action == 'create':
146
            self.gui_annotation_widget_clear()
224 t00m 147
            aid = self.annot.gen_aid(sid)
148
        elif action == 'edit':
149
            aid = sid
233 t00m 150
        widget_annotation.set_metadata_to_widget(aid, action)
223 t00m 151
        self.uif.set_widget_visibility('gtk_vbox_container_annotations', True)
228 t00m 152
        widget.grab_focus()
207 t00m 153
 
154
 
188 t00m 155
    def gui_show_popover(self, button, popover):
110 t00mlabs 156
        if popover.get_visible():
157
            popover.hide()
158
        else:
159
            popover.show_all()
79 t00mlabs 160
 
122 t00mlabs 161
 
212 t00m 162
    def switch_bookmark_current_set(self, button, popover):
198 t00m 163
        visor = self.gui.get_widget('visor')
212 t00m 164
        bag = visor.get_bag()
165
        try:
166
            for sid in bag:
167
                metadata = self.db.get_sapnote_metadata(sid)
168
                bookmark = metadata['bookmark']
169
                if bookmark:
170
                    self.sapnote_unbookmark([sid])
171
                else:
172
                    self.sapnote_bookmark([sid])
173
            popover.hide()
174
        except:
218 t00m 175
            self.debug("Could not bookmark SAP Note %s" % sid)
213 t00m 176
        visor.populate()
198 t00m 177
 
212 t00m 178
 
179
    def switch_bookmark(self, button, lsid, popover):
213 t00m 180
        visor = self.gui.get_widget('visor')
212 t00m 181
        try:
182
            for sid in lsid:
183
                metadata = self.db.get_sapnote_metadata(sid)
184
                bookmark = metadata['bookmark']
185
                if bookmark:
186
                    self.sapnote_unbookmark([sid])
187
                else:
188
                    self.sapnote_bookmark([sid])
189
            popover.hide()
190
        except:
218 t00m 191
            self.debug("Could not bookmark SAP Note %s" % sid)
213 t00m 192
        visor.populate()
212 t00m 193
 
188 t00m 194
    def sapnote_bookmark(self, lsid):
118 t00mlabs 195
        self.db.set_bookmark(lsid)
112 t00mlabs 196
 
187 t00m 197
 
188 t00m 198
    def sapnote_unbookmark(self, lsid):
118 t00mlabs 199
        self.db.set_no_bookmark(lsid)
112 t00mlabs 200
 
118 t00mlabs 201
 
188 t00m 202
    def sapnote_import_from_launchpad(self, *args):
74 t00mlabs 203
        db = self.get_service('DB')
171 t00m 204
        webdriver = self.get_service('Driver')
213 t00m 205
        textview = self.gui.get_widget('gtk_textview_download_launchpad')
180 t00m 206
        visor = self.gui.get_widget('visor')
207
 
213 t00m 208
        bag = []
209
        all_notes = []
180 t00m 210
        sapnotes = []
211
 
212
        dlbuffer = textview.get_buffer()
213
        istart, iend = dlbuffer.get_bounds()
214
        text = dlbuffer.get_text(istart, iend, False)
215
        lines = text.replace(' ', ',')
216
        lines = lines.replace('\n', ',')
217
        sapnotes.extend(lines.split(','))
218
        for sapnote in sapnotes:
213 t00m 219
            sid = sapnote.strip()
220
            is_valid = self.db.is_valid(sid)
221
            is_saved = self.db.get_sapnote_metadata(sid)
222
            if is_valid and not is_saved:
223
                bag.append(sid)
224
            if is_valid:
225
                all_notes.append(sid)
180 t00m 226
        lbag = list(bag)
227
        lbag.sort()
228
 
213 t00m 229
        if len(bag)> 0:
230
            driver = webdriver.open()
231
 
232
        winroot = self.gui.get_widget('gtk_app_window_main')
133 t00mlabs 233
        self.debug("%d SAP Notes to be downloaded: %s" % (len(bag), ', '.join(list(bag))))
4 t00mlabs 234
 
144 t00mlabs 235
        result = {}
4 t00mlabs 236
 
74 t00mlabs 237
        self.sap.start_fetching(len(bag))
142 t00mlabs 238
        dlbag = []
74 t00mlabs 239
 
240
        # FIXME: max_workers = 1 = Threads disabled
180 t00m 241
        # Indeed, I think this is the best option right now.
130 t00mlabs 242
        with Executor(max_workers=1) as exe:
74 t00mlabs 243
            jobs = []
180 t00m 244
            for sapnote in lbag:
171 t00m 245
                job = exe.submit(self.sap.fetch, driver, sapnote)
74 t00mlabs 246
                jobs.append(job)
247
 
248
            for job in jobs:
249
                rc, sapnote = job.result()
133 t00mlabs 250
                self.debug("\tRC SAP Note %s: %s" % (sapnote, rc))
144 t00mlabs 251
                result[sapnote] = rc
142 t00mlabs 252
                if rc:
253
                    sid = "0"*(10 - len(sapnote)) + sapnote
254
                    dlbag.append(sid)
127 t00mlabs 255
                time.sleep(0.2)
74 t00mlabs 256
 
180 t00m 257
        dlbuffer.set_text('')
213 t00m 258
        popover = self.gui.get_widget('gtk_popover_toolbutton_import')
188 t00m 259
        self.gui_hide_popover(popover)
213 t00m 260
        if len(bag) > 0:
261
            webdriver.close(driver)
262
 
74 t00mlabs 263
        self.sap.stop_fetching()
264
        db.save_notes()
265
        db.build_stats()
229 t00m 266
        self.debug("Collection completed.")
213 t00m 267
        # ~ self.gui_display_visor
268
        viewmenu = self.gui.get_widget('viewmenu')
269
        viewmenu.row_changed(None)
270
        visor.populate(all_notes)
144 t00mlabs 271
        return result
272
 
74 t00mlabs 273
 
175 t00m 274
    def expand_menuview(self):
275
        viewmenu = self.gui.get_widget('viewmenu')
276
        viewmenu.expand_all()
277
 
278
 
222 t00m 279
    def gui_viewmenu_filter(self, *args):
213 t00m 280
        entry = self.gui.get_widget('gtk_entry_filter_view')
159 t00m 281
        filter = entry.get_text()
282
        viewmenu = self.gui.get_widget('viewmenu')
164 t00m 283
        selection = viewmenu.get_selection()
74 t00mlabs 284
 
188 t00m 285
        def gui_iterate_over_data(model, path, itr):
165 t00m 286
            rowkey = model.get(itr, 0)[0]
287
            rowtype, rowval = rowkey.split('@')
161 t00m 288
            dsc = model.get(itr, 3)[0]
159 t00m 289
            contents = model.get(itr, 3)[0]
290
            cleanstr = contents.replace('<b>', '')
291
            cleanstr = cleanstr.replace('</b>', '')
292
            model.set(itr, 3, '%s' % cleanstr)
293
            viewmenu.collapse_row(path)
294
 
295
            if len(filter) > 0:
165 t00m 296
                if filter.upper() in rowval.upper() or filter.upper() in dsc.upper():
159 t00m 297
                    viewmenu.expand_to_path (path)
164 t00m 298
                    selection.select_path(path)
159 t00m 299
                    model.set(itr, 3, '<b>%s</b>' % contents)
300
            else:
301
                return
302
 
303
        model = viewmenu.get_model()
188 t00m 304
        model.foreach(gui_iterate_over_data)
159 t00m 305
 
306
 
188 t00m 307
    def gui_filter_visor(self, entry):
178 t00m 308
        visor = self.gui.get_widget('visor')
199 t00m 309
        visible_filter = visor.get_visible_filter()
310
        visible_filter.refilter()
202 t00m 311
        visor.update_total_sapnotes_count(len(visible_filter))
159 t00m 312
 
203 t00m 313
 
188 t00m 314
    def gui_refresh_view(self, button, view=None):
203 t00m 315
        self.debug("Refresh & clear view (II). View(%s)" % (view))
213 t00m 316
        window = self.gui.get_widget('gtk_app_window_main')
116 t00mlabs 317
        viewmenu = self.gui.get_widget('viewmenu')
203 t00m 318
        if view is None:
319
            view = viewmenu.get_view()
74 t00mlabs 320
 
4 t00mlabs 321
        if view is not None:
213 t00m 322
            viewlabel = self.gui.get_widget('gtk_label_current_view')
91 t00mlabs 323
            name = "<b>%-10s</b>" % view.capitalize()
4 t00mlabs 324
            viewlabel.set_markup(name)
116 t00mlabs 325
        viewmenu.set_view(view)
213 t00m 326
        popover = self.gui.get_widget('gtk_popover_button_menu_views')
157 t00m 327
        popover.hide()
4 t00mlabs 328
 
329
 
188 t00m 330
    def gui_toggle_menu_view(self, obj):
213 t00m 331
        paned = self.gui.get_widget('gtk_vbox_container_menu_view')
332
        button = self.gui.get_widget('gtk_toogletoolbutton_menu_view')
180 t00m 333
 
203 t00m 334
        if isinstance(obj, Gtk.ToggleToolButton):
180 t00m 335
            if button.get_active():
336
                paned.show_all()
337
            else:
338
                paned.hide()
339
        elif isinstance(obj, bool):
340
            if obj == True:
341
                # ~ paned.show_all()
342
                button.set_active(True)
343
            else:
344
                # ~ paned.hide()
345
                button.set_active(False)
201 t00m 346
 
347
 
203 t00m 348
    def gui_toggle_fullscreen(self, button):
213 t00m 349
        icon_container = self.gui.get_widget('gtk_box_container_icon_fullscreen')
203 t00m 350
        icon_fullscreen = self.im.get_new_image_icon('basico-fullscreen', 24, 24)
351
        icon_unfullscreen = self.im.get_new_image_icon('basico-unfullscreen', 24, 24)
352
        active = button.get_active()
353
        ui = self.gui.get_window()
354
        window = ui.get_window()
355
        if active:
356
            self.gui.swap_widget(icon_container, icon_unfullscreen)
357
            window.fullscreen()
358
        else:
359
            self.gui.swap_widget(icon_container, icon_fullscreen)
360
            window.unfullscreen()
361
 
362
 
222 t00m 363
    def action_annotation_edit(self, aid):
364
        self.gui_annotation_widget_show(None, aid, 'edit')
217 t00m 365
 
366
 
226 t00m 367
    def action_annotation_duplicate(self, *args):
368
        self.debug("ACTION-DUPLICATE: %s" % args)
369
 
370
 
225 t00m 371
    def action_annotation_delete(self, *args):
372
        statusbar = self.gui.get_widget('widget_statusbar')
373
        visor = self.gui.get_widget('visor')
374
        widget_annotation = self.gui.get_widget('widget_annotation')
233 t00m 375
        aid = widget_annotation.get_aid_from_widget()
225 t00m 376
        self.annot.delete(aid)
377
        self.gui_annotation_widget_clear()
378
        self.uif.set_widget_visibility('gtk_vbox_container_annotations', False)
226 t00m 379
        # ~ visor.refresh()
380
        visor.populate_annotations()
225 t00m 381
        statusbar.message("Annotation deleted")
382
 
383
 
222 t00m 384
    def action_annotation_accept(self, button, sid):
223 t00m 385
        statusbar = self.gui.get_widget('widget_statusbar')
221 t00m 386
        widget_annotation = self.gui.get_widget('widget_annotation')
207 t00m 387
        visor = self.gui.get_widget('visor')
221 t00m 388
 
233 t00m 389
        aid = widget_annotation.get_aid_from_widget()
221 t00m 390
 
233 t00m 391
        annotation = widget_annotation.get_metadata_from_widget(aid)
226 t00m 392
 
223 t00m 393
        if self.annot.is_valid(aid):
226 t00m 394
            self.annot.update(annotation)
225 t00m 395
            statusbar.message('<b>Anotation edited</b>')
226 t00m 396
            self.debug("Updated annotation: %s" % aid)
223 t00m 397
        else:
398
            self.annot.create(annotation)
225 t00m 399
            statusbar.message('<b>New annotation added to SAP Note %d</b>' % int(sid))
226 t00m 400
            self.debug("Created annotation: %s" % aid)
401
 
222 t00m 402
        self.gui_annotation_widget_clear()
226 t00m 403
        visor.populate_annotations()
223 t00m 404
 
205 t00m 405
 
222 t00m 406
    def action_annotation_cancel(self, *args):
213 t00m 407
        statusbar = self.gui.get_widget('widget_statusbar')
222 t00m 408
        self.gui_annotation_widget_clear()
225 t00m 409
        self.uif.set_widget_visibility('gtk_vbox_container_annotations', False)
205 t00m 410
        statusbar.message('<b>Annotation canceled</b>')
411
 
412
 
227 t00m 413
    def action_backup(self, *args):
414
        TIMESTAMP = self.utils.timestamp()
415
        SOURCE_DIRECTORY = LPATH['DB']
416
        TARGET_DIRECTORY = LPATH['EXPORT']
417
        TARGET_FILE = TARGET_DIRECTORY + 'basico-' + TIMESTAMP
418
        self.utils.zip(TARGET_FILE, SOURCE_DIRECTORY)
419
 
420
 
222 t00m 421
    def gui_annotation_widget_clear(self):
233 t00m 422
        a_wdg_timestamp = self.gui.get_widget('gtk_label_human_timestamp')
221 t00m 423
        a_wdg_title = self.gui.get_widget('gtk_entry_annotation_title')
424
        a_wdg_type = self.gui.get_widget('gtk_combobox_annotation_type')
425
        a_wdg_text = self.gui.get_widget('gtk_textview_annotation_text')
426
        a_wdg_link = self.gui.get_widget('gtk_entry_annotation_link')
427
        a_wdg_link_type = self.gui.get_widget('gtk_combobox_annotation_link_type')
428
 
233 t00m 429
        a_wdg_timestamp.set_text('')
221 t00m 430
        a_wdg_title.set_text('')
431
        textbuffer = a_wdg_text.get_buffer()
432
        textbuffer.set_text('')
433
        a_wdg_link.set_text('')
225 t00m 434
        self.uif.set_widget_visibility('gtk_vbox_container_annotations', False)