Subversion Repositories basico

Rev

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