Subversion Repositories basico

Rev

Rev 400 | Rev 407 | 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: srv_cb.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: UI and related callbacks service
8
"""
9
 
10
import os
11
import json
12
import time
13
from concurrent.futures import ThreadPoolExecutor as Executor
14
 
15
import gi
16
gi.require_version('Gtk', '3.0')
17
from gi.repository import Gtk
18
from gi.repository import Gdk
369 t00mlabs 19
from gi.repository import GObject
340 t00mlabs 20
 
21
from basico.core.mod_srv import Service
22
from basico.core.mod_env import FILE, LPATH, ATYPES, APP
23
from basico.widgets.wdg_cols import CollectionsMgtView
24
from basico.widgets.wdg_settingsview import SettingsView
25
 
26
 
27
class Callback(Service):
28
    def initialize(self):
29
        self.get_services()
30
 
31
    def get_services(self):
32
        self.srvstg = self.get_service('Settings')
33
        self.srvdtb = self.get_service('DB')
34
        self.srvgui = self.get_service('GUI')
35
        self.srvuif = self.get_service("UIF")
36
        self.srvsap = self.get_service('SAP')
37
        self.srvicm = self.get_service('IM')
38
        self.srvutl = self.get_service('Utils')
39
        self.srvant = self.get_service('Annotation')
40
        self.srvbnr = self.get_service('BNR')
41
        self.srvclt = self.get_service('Collections')
356 t00mlabs 42
        self.srvatc = self.get_service('Attachment')
340 t00mlabs 43
 
44
 
390 t00mlabs 45
    def stack_visor_changed(self, stack, gparam):
46
        visible_stack_name = stack.get_visible_child_name()
400 t00mlabs 47
        # ~ self.log.debug("Visor switched to: %s", visible_stack_name)
340 t00mlabs 48
 
390 t00mlabs 49
        if visible_stack_name is None:
50
            return
51
 
52
        if visible_stack_name == 'visor-sapnotes':
340 t00mlabs 53
            self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
362 t00mlabs 54
            visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
55
            visible_filter = visor_sapnotes.get_visible_filter()
56
            visor_sapnotes.update_total_sapnotes_count()
390 t00mlabs 57
        elif visible_stack_name == 'visor-annotations':
340 t00mlabs 58
            self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
362 t00mlabs 59
            visor_annotations = self.srvgui.get_widget('visor_annotations')
60
            visor_annotations.populate()
367 t00mlabs 61
        else:
362 t00mlabs 62
            self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
63
            visor_attachments = self.srvgui.get_widget('visor_attachments')
64
            visor_attachments.populate()
340 t00mlabs 65
 
393 t00mlabs 66
 
340 t00mlabs 67
    def gui_show_visor_sapnotes(self):
393 t00mlabs 68
        stack_main = self.srvgui.get_widget('gtk_stack_main')
69
        stack_main.set_visible_child_name('dashboard')
70
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
71
        stack_visors.set_visible_child_name('visor-sapnotes')
340 t00mlabs 72
 
73
 
74
    def gui_show_visor_annotations(self):
393 t00mlabs 75
        stack_main = self.srvgui.get_widget('gtk_stack_main')
76
        stack_main.set_visible_child_name('dashboard')
77
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
78
        stack_visors.set_visible_child_name('visor-annotations')
340 t00mlabs 79
 
80
 
393 t00mlabs 81
    def gui_show_visor_attachments(self):
82
        stack_main = self.srvgui.get_widget('gtk_stack_main')
83
        stack_main.set_visible_child_name('dashboard')
84
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
85
        stack_visors.set_visible_child_name('visor-attachments')
86
 
87
 
340 t00mlabs 88
    def action_search(self, entry):
390 t00mlabs 89
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
340 t00mlabs 90
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
91
        visor_annotations = self.srvgui.get_widget('visor_annotations')
92
        term = entry.get_text()
390 t00mlabs 93
 
94
        stack_visor = stack_visors.get_visible_child_name()
340 t00mlabs 95
        completion = self.srvgui.get_widget('gtk_entrycompletion_visor')
96
        completion_model = completion.get_model()
97
        completion_model.clear()
98
 
390 t00mlabs 99
        if stack_visor == 'visor-sapnotes':
340 t00mlabs 100
            bag = self.srvdtb.search(term)
362 t00mlabs 101
            visor_sapnotes.populate(bag)
340 t00mlabs 102
            ebuffer = entry.get_buffer()
103
            ebuffer.delete_text(0, -1)
104
            msg = "Found %d SAP Notes for term '%s'" % (len(bag), term)
105
            self.log.info(msg)
106
            self.srvuif.statusbar_msg(msg)
390 t00mlabs 107
        elif stack_visor == 'visor-annotations':
340 t00mlabs 108
            annotations = self.srvant.search_term(term)
362 t00mlabs 109
            visor_annotations.populate(annotations)
340 t00mlabs 110
            msg = "Found %d annotations for term '%s'" % (len(annotations), term)
111
            self.log.info(msg)
112
            self.srvuif.statusbar_msg(msg)
113
 
114
 
115
 
116
    def sapnote_browse(self, button, sid):
117
        self.log.info("Browsing SAP Note %d" % int(sid))
118
        SAP_NOTE_URL = self.srvstg.get('SAP', 'SAP_NOTE_URL')
119
        url = SAP_NOTE_URL % sid
383 t00mlabs 120
        self.srvuif.grab_focus()
340 t00mlabs 121
        self.srvutl.browse(url)
122
 
123
 
124
    def sapnote_download_pdf(self, button, sid):
125
        self.log.info("Browsing PDF for SAP Note %d" % int(sid))
126
        SAP_NOTE_URL_PDF = self.srvstg.get('SAP', 'SAP_NOTE_URL_PDF')
127
        url = SAP_NOTE_URL_PDF % sid
128
        self.srvutl.browse(url)
129
 
130
 
131
    def sapnote_delete(self, button, sid):
362 t00mlabs 132
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
340 t00mlabs 133
        viewmenu = self.srvgui.get_widget('viewmenu')
134
 
135
        answer = self.srvuif.warning_message_delete_sapnotes(button, 'Deleting SAP Notes', 'Are you sure?', [sid])
136
        if answer is True:
137
            self.srvdtb.delete(sid)
138
            self.srvuif.statusbar_msg("SAP Note %s deleted" % sid, True)
362 t00mlabs 139
            visor_sapnotes.reload()
340 t00mlabs 140
        else:
141
            self.log.info("SAP Note %s not deletd", sid)
142
 
143
 
144
    def sapnote_delete_view(self, button):
362 t00mlabs 145
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
340 t00mlabs 146
        viewmenu = self.srvgui.get_widget('viewmenu')
147
 
362 t00mlabs 148
        bag = visor_sapnotes.get_filtered_bag()
340 t00mlabs 149
        answer = self.srvuif.warning_message_delete_sapnotes(button, 'Deleting SAP Notes', 'Are you sure?', bag)
150
        if answer is True:
151
            for sid in bag:
152
                self.srvdtb.delete(sid)
362 t00mlabs 153
            visor_sapnotes.reload()
340 t00mlabs 154
            msg = "Deleted %d SAP Notes" % len(bag)
155
            self.log.info(msg)
156
            self.srvuif.statusbar_msg(msg, True)
157
        else:
158
            msg = "None of the %d SAP Notes has been deleted" % len(bag)
159
            self.log.info(msg)
160
            self.srvuif.statusbar_msg(msg, True)
362 t00mlabs 161
        visor_sapnotes.reload()
340 t00mlabs 162
        viewmenu.populate()
163
 
362 t00mlabs 164
 
340 t00mlabs 165
    def gui_hide_popover(self, popover):
166
        popover.hide()
167
 
168
 
169
    def gui_database_backup(self, *args):
170
        window = self.srvgui.get_window()
171
        question = "Backup database"
172
        message = "\nShould this backup include all your annotations?"
173
        wdialog = self.srvuif.message_dialog_question(question, message)
174
        res_bck_annot = wdialog.run()
175
        wdialog.destroy()
176
 
177
        dialog = Gtk.FileChooserDialog("Please choose target folder and backup name (without extension)", window,
178
            Gtk.FileChooserAction.SAVE,
179
            ("Cancel", Gtk.ResponseType.CANCEL,
180
            "Select", Gtk.ResponseType.OK))
181
        TIMESTAMP = self.srvutl.timestamp()
182
        TARGET_FILE = 'basico-%s' % TIMESTAMP
183
        dialog.set_filename(LPATH['BACKUP'])
184
        dialog.set_current_folder_uri(LPATH['BACKUP'])
185
        dialog.set_current_name(TARGET_FILE)
186
        dialog.set_default_size(800, 400)
187
        res_bck_file = dialog.run()
188
        self.log.debug("Backup file: %s", dialog.get_filename())
377 t00mlabs 189
 
340 t00mlabs 190
        if res_bck_file == Gtk.ResponseType.OK:
191
            backup_filename = dialog.get_filename()
192
            if res_bck_annot == Gtk.ResponseType.YES:
193
                bckname = self.srvbnr.backup(backup_filename, backup_annotations=True)
194
                msg = "Database with annotations backed up successfully to: %s" % bckname
195
                dialog.destroy()
196
            else:
197
                bckname = self.srvbnr.backup(backup_filename, backup_annotations=False)
198
                msg = "Database without annotations backed up successfully to: %s" % bckname
199
            self.log.info(msg)
200
            self.srvuif.statusbar_msg(msg, True)
201
            self.srvuif.copy_text_to_clipboard(bckname)
377 t00mlabs 202
 
340 t00mlabs 203
        else:
204
            self.srvuif.statusbar_msg("Backup aborted by user", True)
205
            self.log.info("Backup aborted")
206
        self.srvuif.grab_focus()
207
 
208
 
209
    def gui_database_restore(self, *args):
210
        visor_annotations = self.srvgui.get_widget('visor_annotations')
211
        window = self.srvgui.get_window()
212
        dialog = Gtk.FileChooserDialog("Please choose a backup file", window,
213
            Gtk.FileChooserAction.OPEN,
214
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
215
            Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
216
        dialog.set_current_folder(LPATH['BACKUP'])
217
        filter_zip = Gtk.FileFilter()
218
        filter_zip.set_name("Basico backup files")
219
        filter_zip.add_pattern("*.bco")
220
        dialog.add_filter(filter_zip)
221
        response = dialog.run()
222
        backup = dialog.get_filename()
223
        self.log.info("You are about to restore this file: %s" % backup)
224
        dialog.destroy()
225
 
226
        if response == Gtk.ResponseType.OK:
227
            res = self.srvbnr.test(backup)
228
            if res is None:
229
                dialog = self.srvuif.message_dialog_info("Backup file corrupted?", "It wasn't possible to read all data from this file")
230
                dialog.run()
231
                self.srvuif.statusbar_msg("Backup file corrupted. It wasn't possible to read all data from this file", True)
232
                self.log.info("Backup file corrupted?")
233
            else:
234
                # Ask if the process should force an overwrite in target database
235
                question = "Should the import process overwrite data?"
236
                message = "All metadata for SAP Notes will be overwrited and annotations with the same identifier will be overwriten"
237
                wdialog = self.srvuif.message_dialog_question(question, message)
238
                response = wdialog.run()
239
                wdialog.destroy()
240
                if response == Gtk.ResponseType.YES:
241
                    overwrite = True
242
                else:
243
                    overwrite = False
244
 
245
 
246
                # Ask for final confirmation
247
                sncount, ancount, clcount = res
248
                question = "Restoring backup %s" % os.path.basename(backup)
249
                message = "\n%s contains:\n\n<b>%6d SAP Notes</b>\n<b>%6d collections</b>\n<b>%6d annotations</b>\n\n" % (os.path.basename(backup), sncount, clcount, ancount)
250
                message += "Do you still want to restore this backup?\n"
251
                wdialog = self.srvuif.message_dialog_question(question, message)
252
                response = wdialog.run()
253
                wdialog.destroy()
254
                if response == Gtk.ResponseType.YES:
255
                    self.srvbnr.restore_from_backup(backup, overwrite)
256
                    self.srvdtb.load_notes()
257
                    self.srvclt.load_collections()
362 t00mlabs 258
                    visor_annotations.populate()
340 t00mlabs 259
                    self.gui_refresh_view()
260
                    self.gui_show_visor_sapnotes()
261
                    self.srvuif.statusbar_msg("Backup restored successfully", True)
262
                    self.log.info("Backup restored successfully")
263
                elif response == Gtk.ResponseType.NO:
264
                    self.srvuif.statusbar_msg("Restore aborted by user", True)
265
                    self.log.info("Restore aborted")
266
        elif response == Gtk.ResponseType.CANCEL:
267
            self.srvuif.statusbar_msg("Restore aborted by user", True)
268
            self.log.info("Restore aborted")
269
 
270
        dialog.destroy()
271
        self.srvuif.grab_focus()
272
 
273
 
274
    def gui_show_about(self, *args):
275
        about = self.srvgui.get_widget('widget_about')
276
        stack = self.srvgui.get_widget('gtk_stack_main')
277
        stack.set_visible_child_name('about')
278
        self.gui_hide_popover(self.srvgui.get_widget('gtk_popover_button_menu_system'))
279
        self.srvuif.set_widget_visibility('gtk_label_total_notes', False)
389 t00mlabs 280
        # ~ self.srvuif.set_widget_visibility('gtk_button_dashboard', True)
281
        self.srvuif.grab_focus()
340 t00mlabs 282
 
283
 
284
    def gui_show_log(self, *args):
285
        logviewer = self.srvgui.get_widget('widget_logviewer')
286
        stack = self.srvgui.get_widget('gtk_stack_main')
287
        logviewer.update()
288
        self.gui_hide_popover(self.srvgui.get_widget('gtk_popover_button_menu_system'))
289
        stack.set_visible_child_name('log')
389 t00mlabs 290
        # ~ self.srvuif.set_widget_visibility('gtk_button_dashboard', True)
340 t00mlabs 291
        self.srvuif.statusbar_msg("Displaying application log")
389 t00mlabs 292
        self.srvuif.grab_focus()
340 t00mlabs 293
 
294
 
295
    def gui_show_settings(self, button):
296
        notebook_menuview = self.srvgui.get_widget('gtk_notebook_menuview')
297
        stack = self.srvgui.get_widget('gtk_stack_main')
298
        view_settings = self.srvgui.get_widget('widget_settings')
299
        stack.set_visible_child_name('settings')
300
        view_settings.update()
301
        self.gui_hide_popover(self.srvgui.get_widget('gtk_popover_button_menu_system'))
302
        self.srvuif.set_widget_visibility('gtk_label_total_notes', False)
389 t00mlabs 303
        # ~ self.srvuif.set_widget_visibility('gtk_button_dashboard', True)
340 t00mlabs 304
 
305
        notebook_menuview.hide()
306
        view_settings.grab_focus()
307
        self.srvuif.statusbar_msg("Displaying application settings")
308
 
309
 
310
    def gui_show_dashboard(self, *args):
311
        stack = self.srvgui.get_widget('gtk_stack_main')
389 t00mlabs 312
        # ~ notebook_menuview = self.srvgui.get_widget('gtk_notebook_menuview')
340 t00mlabs 313
        viewmenu = self.srvgui.get_widget('viewmenu')
314
        current_view = viewmenu.get_view()
315
 
389 t00mlabs 316
        # ~ notebook_menuview.show_all()
317
        stack.set_visible_child_name('dashboard')
340 t00mlabs 318
        self.gui_hide_popover(self.srvgui.get_widget('gtk_popover_button_menu_system'))
389 t00mlabs 319
        # ~ self.srvuif.set_widget_visibility('gtk_button_dashboard', False)
340 t00mlabs 320
 
321
        if current_view == 'annotation':
322
            self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
323
        else:
324
            self.srvuif.set_widget_visibility('gtk_label_total_notes', True)
325
        self.srvuif.statusbar_msg("Displaying application dashboard")
326
 
327
 
328
    def gui_toggle_help_visor(self, *args):
329
        button = self.srvgui.get_widget('gtk_togglebutton_help')
330
        notebook = self.srvgui.get_widget('gtk_notebook_visor')
331
 
332
        if button.get_active():
333
            self.srvuif.set_widget_visibility('gtk_notebook_help_page', True)
334
            notebook.set_current_page(2)
335
        else:
336
            self.srvuif.set_widget_visibility('gtk_notebook_help_page', False)
337
            notebook.set_current_page(0)
338
        self.srvuif.statusbar_msg("Displaying application help")
339
 
340
 
341
    def gui_lauch_help_visor(self, *args):
342
        self.srvutl.browse("file://%s" % FILE['HELP_INDEX'])
343
 
344
 
380 t00mlabs 345
    def gui_annotation_widget_show(self, aid, action='create'):
389 t00mlabs 346
        notebook = self.srvgui.get_widget('gtk_notebook_annotations_visor')
340 t00mlabs 347
        widget_annotation = self.srvgui.get_widget('widget_annotation')
385 t00mlabs 348
        stack_main = self.srvgui.get_widget('gtk_stack_main')
377 t00mlabs 349
        widget = self.srvgui.get_widget('gtk_label_timestamp_created')
389 t00mlabs 350
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
380 t00mlabs 351
 
389 t00mlabs 352
        stack_visors.set_visible_child_name("visor-annotations")
353
        notebook.set_current_page(1)
354
        self.srvuif.set_widget_visibility('visortoolbar', False)
355
 
340 t00mlabs 356
        if action == 'create':
389 t00mlabs 357
            widget_annotation.clear()
380 t00mlabs 358
            if aid == '':
359
                aid = self.srvant.gen_aid()
360
            else:
361
                sid = aid
362
                aid = self.srvant.gen_aid(sid)
363
            widget_annotation.set_visible_stack('editor')
340 t00mlabs 364
        elif action == 'edit':
380 t00mlabs 365
            widget_annotation.set_visible_stack('editor')
366
        elif action == 'preview':
367
            widget_annotation.set_visible_stack('preview')
340 t00mlabs 368
 
383 t00mlabs 369
        self.log.debug("Action: %s annotation with Id: %s", action, aid)
370
 
340 t00mlabs 371
        widget_annotation.set_metadata_to_widget(aid, action)
389 t00mlabs 372
        # ~ stack_main.set_visible_child_name('annotations')
385 t00mlabs 373
 
380 t00mlabs 374
        self.srvuif.grab_focus()
340 t00mlabs 375
 
376
 
377
    def gui_show_popover(self, button, popover):
379 t00mlabs 378
        self.srvgui.set_key_value('LAST_POPOVER', popover)
340 t00mlabs 379
        if popover.get_visible():
383 t00mlabs 380
            popover.popdown()
340 t00mlabs 381
            popover.hide()
382
        else:
383
            popover.show_all()
383 t00mlabs 384
            popover.popup()
340 t00mlabs 385
 
386
 
387
    def switch_bookmark_current_view(self, *args):
362 t00mlabs 388
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
389
        bag = visor_sapnotes.get_filtered_bag()
340 t00mlabs 390
        try:
391
            for sid in bag:
392
                metadata = self.srvdtb.get_sapnote_metadata(sid)
393
                bookmark = metadata['bookmark']
394
                if bookmark:
395
                    self.sapnote_unbookmark([sid])
396
                else:
397
                    self.sapnote_bookmark([sid])
398
        except:
399
            self.log.error("Could not bookmark SAP Note %s" % sid)
400
            self.log.error(self.get_traceback())
362 t00mlabs 401
        visor_sapnotes.populate(bag)
340 t00mlabs 402
        msg = "%d SAP Notes (un)bookmarked" % len(bag)
403
        self.log.info(msg)
404
        self.srvuif.statusbar_msg(msg, True)
405
 
406
 
407
    def switch_bookmark(self, button, lsid, popover):
362 t00mlabs 408
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
340 t00mlabs 409
        try:
410
            for sid in lsid:
411
                metadata = self.srvdtb.get_sapnote_metadata(sid)
412
                bookmark = metadata['bookmark']
413
                if bookmark:
414
                    self.sapnote_unbookmark([sid])
415
                    self.srvuif.statusbar_msg("SAP Notes unbookmarked")
416
                else:
417
                    self.sapnote_bookmark([sid])
418
                    self.srvuif.statusbar_msg("SAP Notes bookmarked")
419
            popover.hide()
420
        except:
421
            self.log.error("Could not bookmark SAP Note %s" % sid)
422
            self.log.error(self.get_traceback())
362 t00mlabs 423
        visor_sapnotes.populate()
340 t00mlabs 424
 
425
 
426
    def sapnote_bookmark(self, lsid):
427
        self.srvdtb.set_bookmark(lsid)
428
 
429
 
430
    def sapnote_unbookmark(self, lsid):
431
        self.srvdtb.set_no_bookmark(lsid)
432
 
433
 
434
    def sapnote_import_from_launchpad(self, *args):
435
        db = self.get_service('DB')
436
        webdriver = self.get_service('Driver')
437
        textview = self.srvgui.get_widget('gtk_textview_download_launchpad')
362 t00mlabs 438
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
340 t00mlabs 439
 
440
        bag = []
441
        all_notes = []
442
        sapnotes = []
443
        dlbuffer = textview.get_buffer()
444
        istart, iend = dlbuffer.get_bounds()
445
        text = dlbuffer.get_text(istart, iend, False)
396 t00mlabs 446
        self.log.debug(text)
340 t00mlabs 447
        lines = text.replace(' ', ',')
448
        lines = lines.replace('\n', ',')
396 t00mlabs 449
        self.log.debug(lines)
340 t00mlabs 450
        for sid in lines.split(','):
451
            sid = sid.strip()
452
            if len(sid) > 0:
453
                sapnotes.append(sid)
454
        for sid in sapnotes:
455
            is_valid = self.srvdtb.is_valid(sid)
456
            is_saved = self.srvdtb.get_sapnote_metadata(sid)
457
            if is_valid and not is_saved:
458
                bag.append(sid)
459
            if is_valid:
460
                all_notes.append(sid)
461
        lbag = list(bag)
462
        lbag.sort()
463
 
464
        if len(bag)> 0:
465
            driver = webdriver.open()
466
 
467
        winroot = self.srvgui.get_widget('gtk_app_window_main')
468
        msg = "%d SAP Notes to be downloaded: %s" % (len(bag), ', '.join(list(bag)))
469
        self.log.info(msg)
470
 
471
        result = {}
472
 
473
        self.srvsap.start_fetching(len(bag))
474
        dlbag = []
475
 
476
        # FIXME: max_workers = 1 = Threads disabled
477
        # Indeed, I think this is the best option right now.
478
        with Executor(max_workers=1) as exe:
479
            jobs = []
480
            for sapnote in lbag:
481
                job = exe.submit(self.srvsap.fetch, driver, sapnote)
482
                jobs.append(job)
483
 
484
            for job in jobs:
485
                rc, sapnote = job.result()
486
                msg = "\tRC SAP Note %s: %s" % (sapnote, rc)
487
                self.log.info(msg)
488
                result[sapnote] = rc
489
                if rc:
490
                    sid = "0"*(10 - len(sapnote)) + sapnote
491
                    dlbag.append(sid)
492
                time.sleep(0.2)
493
 
494
        dlbuffer.set_text('')
495
        popover = self.srvgui.get_widget('gtk_popover_toolbutton_import')
396 t00mlabs 496
        # ~ self.gui_hide_popover(popover)
340 t00mlabs 497
        if len(bag) > 0:
498
            webdriver.close(driver)
499
 
500
        self.srvsap.stop_fetching()
501
        db.save_notes()
502
        db.build_stats()
503
        self.log.info("Download completed.")
504
        self.srvuif.statusbar_msg("Download completed", True)
362 t00mlabs 505
        visor_sapnotes.populate(all_notes)
340 t00mlabs 506
        self.gui_show_visor_sapnotes()
507
        return result
508
 
509
 
510
    def expand_menuview(self):
511
        viewmenu = self.srvgui.get_widget('viewmenu')
512
        viewmenu.expand_all()
513
 
514
 
515
    def gui_viewmenu_filter(self, *args):
516
        entry = self.srvgui.get_widget('gtk_entry_filter_view')
517
        filter = entry.get_text()
518
        viewmenu = self.srvgui.get_widget('viewmenu')
519
        selection = viewmenu.get_selection()
520
 
521
        def gui_iterate_over_data(model, path, itr):
522
            rowkey = model.get(itr, 0)[0]
523
            rowtype, rowval = rowkey.split('@')
524
            dsc = model.get(itr, 1)[0]
525
            contents = model.get(itr, 1)[0]
526
            cleanstr = contents.replace('<b>', '')
527
            cleanstr = cleanstr.replace('</b>', '')
528
            model.set(itr, 1, '%s' % cleanstr)
529
            viewmenu.collapse_row(path)
530
 
531
            if len(filter) > 0:
532
                if filter.upper() in rowval.upper() or filter.upper() in dsc.upper():
533
                    viewmenu.expand_to_path (path)
534
                    selection.select_path(path)
535
                    model.set(itr, 1, '<b>%s</b>' % contents)
536
            else:
537
                return
538
 
539
        model = viewmenu.get_model()
540
        model.foreach(gui_iterate_over_data)
541
 
542
 
543
    def gui_viewmenu_select_first_entry(self):
544
        viewmenu = self.srvgui.get_widget('viewmenu')
545
        selection = viewmenu.get_selection()
546
        selection.select_path("0")
547
 
548
 
393 t00mlabs 549
    def gui_filter_visor(self, entry=None):
390 t00mlabs 550
        stack_visors = self.srvgui.get_widget('gtk_stack_visors')
551
        visible_stack_name = stack_visors.get_visible_child_name()
552
 
553
        if visible_stack_name == 'visor-sapnotes':
362 t00mlabs 554
            visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
555
            visible_filter = visor_sapnotes.get_visible_filter()
340 t00mlabs 556
            visible_filter.refilter()
362 t00mlabs 557
            visor_sapnotes.update_total_sapnotes_count()
390 t00mlabs 558
        elif visible_stack_name == 'visor-annotations':
362 t00mlabs 559
            visor_annotations = self.srvgui.get_widget('visor_annotations')
560
            visor_annotations.populate()
400 t00mlabs 561
            visible_filter = self.srvgui.get_widget('visor_annotation_visible_filter')
340 t00mlabs 562
            visible_filter.refilter()
362 t00mlabs 563
            visor_annotations.update_total_annotations_count()
340 t00mlabs 564
 
565
 
566
    def gui_refresh_view(self, button=None, view=None):
567
        window = self.srvgui.get_widget('gtk_app_window_main')
568
        viewmenu = self.srvgui.get_widget('viewmenu')
569
        if view is None:
570
            view = viewmenu.get_view()
571
 
572
        if view is not None:
573
            viewlabel = self.srvgui.get_widget('gtk_label_current_view')
574
            name = "<b>%-10s</b>" % view.capitalize()
575
            viewlabel.set_markup(name)
576
        viewmenu.set_view(view)
577
        popover = self.srvgui.get_widget('gtk_popover_button_menu_views')
578
        popover.hide()
579
        self.gui_show_visor_sapnotes()
580
 
581
 
582
    def gui_toggle_menu_view(self, obj):
583
        paned = self.srvgui.get_widget('gtk_vbox_container_menu_view')
584
        button = self.srvgui.get_widget('gtk_toogletoolbutton_menu_view')
585
        if isinstance(obj, Gtk.ToggleToolButton):
586
            if button.get_active():
587
                paned.show_all()
588
            else:
589
                paned.hide()
590
        elif isinstance(obj, bool):
591
            if obj == True:
592
                button.set_active(True)
593
            else:
594
                button.set_active(False)
595
 
596
 
597
    def gui_toggle_fullscreen(self, button):
598
        icon_container = self.srvgui.get_widget('gtk_box_container_icon_fullscreen')
599
        icon_fullscreen = self.srvicm.get_new_image_icon('basico-fullscreen', 24, 24)
600
        icon_unfullscreen = self.srvicm.get_new_image_icon('basico-unfullscreen', 24, 24)
601
        active = button.get_active()
602
        window = self.srvgui.get_window()
603
        if active:
604
            self.srvgui.swap_widget(icon_container, icon_unfullscreen)
605
            window.fullscreen()
606
        else:
607
            self.srvgui.swap_widget(icon_container, icon_fullscreen)
608
            window.unfullscreen()
609
 
610
 
380 t00mlabs 611
    def action_annotation_create(self):
612
        self.gui_annotation_widget_show('', 'create')
613
 
614
 
397 t00mlabs 615
    def action_annotation_create_from_template(self, aid):
616
        new_aid = self.srvant.duplicate_from_template(aid)
617
        self.action_annotation_edit(new_aid)
618
 
619
 
380 t00mlabs 620
    def action_annotation_create_for_sapnote(self, sid):
621
        self.gui_annotation_widget_show(sid, 'create')
622
 
623
 
340 t00mlabs 624
    def action_annotation_edit(self, aid):
380 t00mlabs 625
        self.gui_annotation_widget_show(aid, 'edit')
340 t00mlabs 626
 
627
 
380 t00mlabs 628
    def action_annotation_preview(self, aid):
629
        self.gui_annotation_widget_show(aid, 'preview')
630
 
631
 
340 t00mlabs 632
    def action_annotation_duplicate(self, *args):
633
        self.log.debug("ACTION-DUPLICATE: %s" % args)
634
 
635
 
636
    def action_annotation_delete(self, *args):
362 t00mlabs 637
        visor_annotations = self.srvgui.get_widget('visor_annotations')
377 t00mlabs 638
        aids = visor_annotations.rows_toggled()
639
        answer = self.srvuif.warning_message_delete_annotations(None, 'Deleting annotations', 'Are you sure?', aids)
340 t00mlabs 640
        if answer is True:
377 t00mlabs 641
            for aid in aids:
642
                self.srvant.delete(aid)
362 t00mlabs 643
            visor_annotations.populate()
377 t00mlabs 644
            self.srvuif.statusbar_msg("Annotations deleted", True)
340 t00mlabs 645
        else:
377 t00mlabs 646
            self.log.info("Annotations hasn't been deleted")
340 t00mlabs 647
            self.srvuif.statusbar_msg("Action canceled. Nothing deleted.", True)
648
 
649
        self.srvuif.grab_focus()
650
 
651
 
652
    def action_annotation_accept(self, button, sid):
653
        widget_annotation = self.srvgui.get_widget('widget_annotation')
654
        visor_annotations = self.srvgui.get_widget('visor_annotations')
655
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
656
        viewmenu = self.srvgui.get_widget('viewmenu')
389 t00mlabs 657
        notebook = self.srvgui.get_widget('gtk_notebook_annotations_visor')
658
        notebook.set_current_page(0)
340 t00mlabs 659
 
660
        aid = widget_annotation.get_aid_from_widget()
377 t00mlabs 661
        annotation = widget_annotation.get_metadata_from_widget()
340 t00mlabs 662
 
663
        if self.srvant.is_valid(aid):
664
            self.srvant.update(annotation)
665
            title = self.srvant.get_title(aid)
666
            self.srvuif.statusbar_msg("Updated annotation: %s" % title, True)
667
        else:
668
            self.srvant.create(annotation)
669
            title = self.srvant.get_title(aid)
670
            self.srvuif.statusbar_msg('New annotation created: %s' % title, True)
362 t00mlabs 671
        visor_annotations.populate()
672
        visor_sapnotes.populate()
389 t00mlabs 673
        widget_annotation.clear()
674
        self.srvuif.set_widget_visibility('visortoolbar', True)
340 t00mlabs 675
        self.srvuif.grab_focus()
676
 
677
 
678
    def action_annotation_cancel(self, *args):
679
        statusbar = self.srvgui.get_widget('widget_statusbar')
389 t00mlabs 680
        widget_annotation = self.srvgui.get_widget('widget_annotation')
681
        notebook = self.srvgui.get_widget('gtk_notebook_annotations_visor')
682
        notebook.set_current_page(0)
683
 
684
        widget_annotation.clear()
685
        self.srvuif.set_widget_visibility('visortoolbar', True)
686
        # ~ page = self.srvgui.get_key_value('current_visor_tab')
687
        # ~ notebook = self.srvgui.get_widget('gtk_notebook_visor')
688
        # ~ notebook.set_current_page(page)
400 t00mlabs 689
        # ~ self.log.debug('Annotation canceled')
340 t00mlabs 690
        self.srvuif.statusbar_msg("Annotation canceled")
385 t00mlabs 691
        self.gui_show_dashboard()
340 t00mlabs 692
        self.srvuif.grab_focus()
693
 
694
 
695
    def get_sapnotes_from_current_view(self, colname=None):
696
        viewmenu = self.srvgui.get_widget('viewmenu')
697
        view = viewmenu.get_view()
698
        rowtype = viewmenu.get_row_type()
699
        rowid = viewmenu.get_row_id()
700
 
701
        if view == 'collection':
702
            cols = self.srvclt.get_collections_by_row_title(colname)
703
            bag = []
704
            for colid in cols:
705
                bag.extend(self.srvdtb.get_notes_by_node('collection', colid))
706
        else:
707
            bag = self.srvdtb.get_notes_by_node(rowtype, rowid)
708
 
709
        return bag
710
 
711
 
712
    def action_collection_export_text_csv(self, *args):
713
        rootwin = self.srvgui.get_window()
714
        timestamp = self.srvutl.timestamp()
715
        filename = "%s%s.csv" % (LPATH['EXPORT'], timestamp)
716
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
717
 
718
        bag = visor_sapnotes.get_filtered_bag()
719
 
720
        dialog = Gtk.FileChooserDialog("Save file", rootwin,
721
            Gtk.FileChooserAction.SAVE,
722
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
723
                 Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
724
        dialog.set_filename(filename)
725
        dialog.set_current_name(os.path.basename(filename))
726
        response = dialog.run()
727
 
728
        if response == Gtk.ResponseType.OK:
729
            export_path = dialog.get_filename()
730
            res = self.srvbnr.export_to_text_csv(bag, export_path)
731
            self.log.info("%d SAP Notes exported to CSV format: %s", len(bag), export_path)
732
            self.srvuif.statusbar_msg("%d SAP Notes exported to CSV format: %s" % (len(bag), export_path), True)
733
            self.srvuif.copy_text_to_clipboard(export_path)
734
        else:
735
            self.log.info("Export canceled by user")
736
            self.srvuif.statusbar_msg("Export canceled by user", True)
737
        dialog.destroy()
738
 
739
 
740
    def action_collection_export_excel(self, *args):
741
        rootwin = self.srvgui.get_window()
742
        timestamp = self.srvutl.timestamp()
743
        filename = "%s%s.xlsx" % (LPATH['EXPORT'], timestamp)
744
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
745
 
746
        bag = visor_sapnotes.get_filtered_bag()
747
 
748
        dialog = Gtk.FileChooserDialog("Save file", rootwin,
749
            Gtk.FileChooserAction.SAVE,
750
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
751
                 Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
752
        dialog.set_filename(filename)
753
        dialog.set_current_name(os.path.basename(filename))
754
        response = dialog.run()
755
 
756
        if response == Gtk.ResponseType.OK:
757
            export_path = dialog.get_filename()
758
            res = self.srvbnr.export_to_excel(bag, export_path)
759
            if res:
760
                self.log.info("Selected SAP Notes exported to MS Excel format (xlsx): %s" % export_path)
761
                self.srvuif.statusbar_msg("%d SAP Notes exported to MS Excel format: %s" % (len(bag), export_path), True)
762
                self.srvuif.copy_text_to_clipboard(export_path)
763
            else:
764
                self.log.error(self.get_traceback())
765
        else:
766
            self.log.info("Export canceled by user")
767
            self.srvuif.statusbar_msg("Export canceled by user", True)
768
        dialog.destroy()
769
 
770
 
771
    def action_collection_export_basico(self, *args):
772
        rootwin = self.srvgui.get_window()
773
        timestamp = self.srvutl.timestamp()
774
        filename = "%s%s.bco" % (LPATH['EXPORT'], timestamp)
775
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
776
 
777
        bag = visor_sapnotes.get_filtered_bag()
778
 
779
        dialog = Gtk.FileChooserDialog("Save file", rootwin,
780
            Gtk.FileChooserAction.SAVE,
781
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
782
                 Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
783
        dialog.set_filename(filename)
784
        dialog.set_current_name(os.path.basename(filename))
785
        response = dialog.run()
786
 
787
        if response == Gtk.ResponseType.OK:
788
            export_path = dialog.get_filename()
789
            target = self.srvbnr.export_to_basico(bag, export_path)
790
            self.log.info("%d SAP Notes exported to Basico %s format: %s", len(bag), APP['version'], target)
791
            self.srvuif.statusbar_msg("%d SAP Notes exported to Basico %s format: %s" % (len(bag), APP['version'], target), True)
792
            self.srvuif.copy_text_to_clipboard(export_path)
793
        else:
794
            self.log.info("Export canceled by user")
795
            self.srvuif.statusbar_msg("Export canceled by user", True)
796
        dialog.destroy()
797
 
798
 
799
    def action_collection_copy_to_clipboard(self, button):
800
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
801
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
802
 
803
        bag = visor_sapnotes.get_filtered_bag()
804
        text = ''
805
        for sid in bag:
806
            metadata = self.srvdtb.get_sapnote_metadata(sid)
807
            text += "SAP Note %s: %s - Component: %s\n" % (str(int(sid)), metadata['title'], metadata['componentkey'])
808
        clipboard.set_text(text, -1)
809
 
810
        msg = "%d SAP Notes copied to the clipboard: %s" % (len(bag), ', '.join(list(bag)))
811
        self.log.info(msg)
812
        msg = "%d SAP Notes copied to the clipboard" % len(bag)
813
        self.srvuif.statusbar_msg(msg, True)
814
 
815
 
367 t00mlabs 816
    def gui_annotation_previous_row(self, *args):
817
        visor_annotations = self.srvgui.get_widget('visor_annotations')
818
        visor_annotations.row_previous()
819
 
377 t00mlabs 820
 
367 t00mlabs 821
    def gui_annotation_next_row(self, *args):
822
        visor_annotations = self.srvgui.get_widget('visor_annotations')
823
        visor_annotations.row_next()
824
 
340 t00mlabs 825
    def gui_copy_to_clipboard_sapnote(self, widget, lsid, popover):
826
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
827
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
828
        text = ''
829
        for sid in lsid:
830
            metadata = self.srvdtb.get_sapnote_metadata(sid)
831
            text += "SAP Note %10s: %s - Component: %s\n" % (sid, metadata['title'], metadata['componentkey'])
832
        clipboard.set_text(text, -1)
833
        if popover is not None:
834
            popover.hide()
835
            self.srvuif.grab_focus()
836
 
837
 
838
    def gui_jump_to_sapnote(self, widget, sid):
839
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
362 t00mlabs 840
        visor_sapnotes.populate([sid])
340 t00mlabs 841
        self.gui_show_visor_sapnotes()
842
        self.srvuif.grab_focus()
843
        msg = "Jumping to SAP Note %s" % sid
844
        self.log.info(msg)
845
        self.srvuif.statusbar_msg(msg)
846
 
847
 
369 t00mlabs 848
    def gui_jump_to_annotation(self, widget, aid):
849
        paned = self.srvgui.get_widget('gtk_hpaned')
850
        notebook = self.srvgui.get_widget('gtk_notebook_visor')
851
        notebook_viewmenu = self.srvgui.get_widget('gtk_notebook_menuview')
852
        notebook_viewmenu.set_current_page(1)
853
        signal = self.srvgui.get_signal('gtk_notebook_visor', 'switch-page')
854
        GObject.signal_handler_block(notebook, signal)
855
        visor_annotations = self.srvgui.get_widget('visor_annotations')
856
        visor_annotations.populate([aid])
857
        self.gui_show_visor_annotations()
858
        self.srvuif.grab_focus()
859
        msg = "Jumping to annotation %s" % aid
860
        self.log.info(msg)
861
        self.srvuif.statusbar_msg(msg)
862
        GObject.signal_handler_unblock(notebook, signal)
863
        paned.set_position(400)
864
 
377 t00mlabs 865
 
340 t00mlabs 866
    def gui_link_to_sapnote(self, *args):
867
        pass
868
 
869
 
870
    def gui_sapnotes_select_all_none(self, witch, state):
362 t00mlabs 871
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
872
        model = visor_sapnotes.get_model()
340 t00mlabs 873
 
874
        def get_selected_sapnotes(model, path, itr):
875
            component = model.get(itr, 5)
876
            if component != 'Annotation':
877
                model.set(itr, 2, state)
878
 
879
        model.foreach(get_selected_sapnotes)
348 t00mlabs 880
 
881
 
385 t00mlabs 882
    # ~ def gui_maximize_annotation_window(self, *args):
883
        # ~ vpaned = self.srvgui.get_widget('gtk_vpaned_visor')
884
        # ~ stack_main = self.srvgui.get_widget('gtk_stack_main')
885
        # ~ toggle_button = self.srvgui.get_widget('gtk_togglebutton_maximize_annotation_widget')
886
        # ~ if toggle_button.get_active():
352 t00mlabs 887
            # ~ stack_main.hide()
385 t00mlabs 888
            # ~ vpaned.set_position(0)
889
        # ~ else:
352 t00mlabs 890
            # ~ stack_main.show_all()
385 t00mlabs 891
            # ~ vpaned.set_position(450)
356 t00mlabs 892
 
893
 
360 t00mlabs 894
    def gui_attachment_add_to_sapnote(self, button, sid):
895
        visor_attachemnts = self.srvgui.get_widget('visor_attachments')
896
        visor_annotations = self.srvgui.get_widget('visor_annotations')
897
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
377 t00mlabs 898
 
360 t00mlabs 899
        # Create annotation
900
        aid = self.srvant.gen_aid(sid)
901
        annotation = {}
902
        annotation["AID"] = aid
903
        annotation["Title"] = "Attachments added for SAP Note %s" % str(int(sid))
904
        annotation["Component"] = "Annotation"
905
        annotation["Type"] = "Note"
377 t00mlabs 906
        annotation["Category"] = "Inbox"
360 t00mlabs 907
        annotation["Priority"] = "Low"
377 t00mlabs 908
        annotation["Link"] = ""
360 t00mlabs 909
        annotation["LinkType"] = "Website"
910
        annotation["Origin"] = "Service-Attachment"
377 t00mlabs 911
 
360 t00mlabs 912
        # Get attachments from filechooser dialog
913
        attachments = self.gui_attachment_show_filechooser()
377 t00mlabs 914
 
360 t00mlabs 915
        # Add them to Basico database
916
        if attachments is not None:
917
            content = '== Attachments\n\n'
918
            for attachment in attachments:
919
                # only allow files (avoid directories)
920
                if os.path.isfile(attachment):
921
                    content += "* %s\n" % attachment
922
                    tid = self.srvatc.create(attachment, aid)
923
                    annotation["TID"] = tid
924
                    # ~ self.log.debug(annotation)
925
                annotation["Content"] = content
926
                self.srvant.create(annotation)
362 t00mlabs 927
            visor_attachemnts.populate()
928
            visor_annotations.populate()
929
            visor_sapnotes.populate()
360 t00mlabs 930
        else:
931
            self.log.warning("No files selected to attach")
932
 
933
 
934
    def gui_attachment_add_to_annotation(self, button):
364 t00mlabs 935
        widget_annotation = self.srvgui.get_widget('widget_annotation')
360 t00mlabs 936
        visor_attachemnts = self.srvgui.get_widget('visor_attachments')
937
        visor_annotations = self.srvgui.get_widget('visor_annotations')
356 t00mlabs 938
        aid = widget_annotation.get_aid_from_widget()
377 t00mlabs 939
 
360 t00mlabs 940
        # Create annotation
941
        sid = self.srvant.get_sid(aid)
942
        new_aid = self.srvant.gen_aid(sid)
943
        annotation = {}
944
        annotation["AID"] = new_aid
945
        annotation["Title"] = "Attachments added for annotation: %s" % self.srvant.get_title(aid)
946
        annotation["Component"] = "Annotation"
947
        annotation["Type"] = "Note"
377 t00mlabs 948
        annotation["Category"] = "Inbox"
360 t00mlabs 949
        annotation["Priority"] = "Low"
377 t00mlabs 950
        annotation["Link"] = ""
360 t00mlabs 951
        annotation["LinkType"] = "Website"
952
        annotation["Origin"] = "Service-Attachment"
377 t00mlabs 953
 
360 t00mlabs 954
        # Get attachments from filechooser dialog
356 t00mlabs 955
        attachments = self.gui_attachment_show_filechooser()
956
 
957
        # Add them to Basico database
958
        if attachments is not None:
360 t00mlabs 959
            content = '== Attachments\n\n'
356 t00mlabs 960
            for attachment in attachments:
961
                # only allow files (avoid directories)
962
                if os.path.isfile(attachment):
360 t00mlabs 963
                    content += "* %s\n" % attachment
964
                    tid = self.srvatc.create(attachment, aid)
965
                    annotation["TID"] = tid
966
                    # ~ self.log.debug(annotation)
967
                annotation["Content"] = content
968
                self.srvant.create(annotation)
969
                self.srvant.update_timestamp(aid)
362 t00mlabs 970
            visor_attachemnts.populate()
971
            visor_annotations.populate()
356 t00mlabs 972
        else:
973
            self.log.warning("No files selected to attach")
377 t00mlabs 974
 
975
 
395 t00mlabs 976
    def gui_attachment_add(self, *args):
360 t00mlabs 977
        visor_attachemnts = self.srvgui.get_widget('visor_attachments')
978
        visor_annotations = self.srvgui.get_widget('visor_annotations')
979
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
377 t00mlabs 980
 
360 t00mlabs 981
        # Create annotation
982
        aid = self.srvant.gen_aid('0000000000')
983
        annotation = {}
984
        annotation["AID"] = aid
985
        annotation["Title"] = "Attachments added"
986
        annotation["Component"] = "Annotation"
987
        annotation["Type"] = "Note"
377 t00mlabs 988
        annotation["Category"] = "Inbox"
360 t00mlabs 989
        annotation["Priority"] = "Low"
377 t00mlabs 990
        annotation["Link"] = ""
360 t00mlabs 991
        annotation["LinkType"] = "Website"
992
        annotation["Origin"] = "Service-Attachment"
377 t00mlabs 993
 
360 t00mlabs 994
        # Get attachments from filechooser dialog
995
        attachments = self.gui_attachment_show_filechooser()
377 t00mlabs 996
 
360 t00mlabs 997
        # Add them to Basico database
998
        if attachments is not None:
999
            content = '== Attachments\n\n'
1000
            for attachment in attachments:
1001
                # only allow files (avoid directories)
1002
                if os.path.isfile(attachment):
1003
                    content += "* %s\n" % attachment
1004
                    tid = self.srvatc.create(attachment, aid)
1005
                    annotation["TID"] = tid
1006
                    # ~ self.log.debug(annotation)
1007
                annotation["Content"] = content
1008
                self.srvant.create(annotation)
362 t00mlabs 1009
            visor_attachemnts.populate()
1010
            visor_annotations.populate()
360 t00mlabs 1011
        else:
1012
            self.log.warning("No files selected to attach")
356 t00mlabs 1013
 
395 t00mlabs 1014
 
356 t00mlabs 1015
    def gui_attachment_show_filechooser(self):
1016
        filenames = None
1017
        parentwin = self.srvgui.get_window()
1018
        dialog = Gtk.FileChooserDialog(title="Open file(s) ...",
1019
                                       parent=parentwin,
1020
                                       action=Gtk.FileChooserAction.OPEN,
377 t00mlabs 1021
                                       buttons=("_Cancel",
356 t00mlabs 1022
                                                Gtk.ResponseType.CANCEL,
1023
                                        "_Open", Gtk.ResponseType.ACCEPT))
1024
        dialog.set_select_multiple(True)
1025
        response = dialog.run()
1026
        if response == Gtk.ResponseType.ACCEPT:
1027
            filenames = dialog.get_filenames()
1028
            i = 0
1029
            while i < len(filenames):
1030
                filename = filenames[i]
1031
                self.log.debug("%s was selected", filename)
1032
                i += 1
1033
        dialog.destroy()
1034
        return filenames
377 t00mlabs 1035
 
368 t00mlabs 1036
    def copy_text_to_clipboard(self, widget, text):
1037
        self.srvuif.copy_text_to_clipboard(text)
380 t00mlabs 1038
        self.srvuif.grab_focus()