Subversion Repositories basico

Rev

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