Subversion Repositories basico

Rev

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

Rev Author Line No. Line
4 t00mlabs 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
# File: window.py
4
# Author: Tomás Vírseda
5
# License: GPL v3
6
# Description: Gtk.ApplicationWindow implementation
7
 
8
import os
9
import stat
10
import threading
11
import time
12
import platform
13
 
14
import gi
15
gi.require_version('Gtk', '3.0')
16
gi.require_version('WebKit', '3.0')
17
 
18
from gi.repository import GLib
19
from gi.repository import GObject
20
from gi.repository import Gtk
21
from gi.repository import Gdk
22
from gi.repository import Gio
23
from gi.repository import Pango
24
from gi.repository import WebKit
25
from gi.repository.GdkPixbuf import Pixbuf
26
 
27
from .log import get_logger
28
from .sapnoteview import SAPNoteView
29
 
30
 
31
MONOSPACE_FONT = 'Lucida Console' if platform.system() == 'Windows' else 'monospace'
32
 
33
class GtkAppWindow(Gtk.ApplicationWindow):
34
    def __init__(self, uiapp):
35
        self.setup_controller(uiapp)
36
        self.get_services()
37
        self.gui.add_widget('uiapp', uiapp)
38
        self.gui.set_key('cmbvalue', 'search')
39
        self.settings = {}
40
        self.settings['fullscreen'] = False
41
        self.current_notes = {}
42
 
43
        self.setup_window()
44
        self.setup_widgets()
45
        self.setup_app()
46
 
47
 
48
    def setup_controller(self, uiapp):
49
        self.uiapp = uiapp
50
        self.controller = uiapp.get_controller()
51
 
52
 
53
    def setup_app(self):
54
        sapnoteview = self.gui.get_widget('sapnoteview')
55
        searchentry = self.gui.get_widget("stySearchInfo")
56
        viewlabel = self.gui.get_widget('lblViewCurrent')
57
        try:
58
            name = sapnoteview.get_view()
59
        except:
60
            name = 'components'
61
        sapnoteview.set_view(name)
62
        label = "<span size='20000'><b>%-10s</b></span>" % name.capitalize()
63
        viewlabel.set_markup(label)
64
        self.cb.refresh_view()
65
        searchentry.set_text('')
66
        self.cb.search_notes()
67
        sapnoteview.check_states()
68
 
69
 
70
    def setup_window(self):
71
        app_title = self.controller.get_app_info('name')
72
        Gtk.Window.__init__(self, title=app_title, application=self.uiapp)
73
        self.gui.add_widget('mainwindow', self)
74
        icon = self.im.get_icon('basico')
75
        self.set_icon(icon)
76
        # FIXME
77
        # From docs: Don’t use this function. It sets the X xlib.Window
78
        # System “class” and “name” hints for a window.
79
        # But I have to do it or it doesn't shows the right title. ???
80
        self.set_wmclass (app_title, app_title)
81
        self.set_role(app_title)
82
        self.set_default_size(1024, 728)
83
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
84
        #~ self.connect('destroy', Gtk.main_quit)
85
        self.show_all()
86
 
87
 
88
    def setup_menu_views(self):
89
        # View label
90
        self.gui.add_widget('lblViewCurrent')
91
 
92
        ## Views Menu
93
        views_menu = self.gui.add_widget('mnuviews', Gio.Menu())
94
 
95
        # Last added view
96
        #~ TODO
97
        #~ views_menu.append_item(self.uif.create_item('View last added', 'app.view-lastadded', ''))
98
        #~ self.app.add_action(self.uif.create_action("view-lastadded", self.cb_show_dlnotes_window))
99
 
100
        # Most used view
101
        #~ TODO
102
        #~ views_menu.append_item(self.uif.create_item('View most used', 'app.view-mostused', ''))
103
        #~ self.app.add_action(self.uif.create_action("view-mostused", self.cb_show_dlnotes_window))
104
 
105
        # Tasks view
106
        views_menu.append_item(self.uif.create_item('View by tasks', 'app.view-tasks', 'emblem-system'))
107
        self.app.add_action(self.uif.create_action("view-tasks", self.cb.refresh_view, 'tasks'))
108
 
109
        # Projects view
110
        #~ views_menu.append_item(self.uif.create_item('View by projects', 'app.view-projects', ''))
111
        #~ self.app.add_action(self.uif.create_action("view-projects", self.cb.refresh_view, 'projects'))
112
 
113
        # Components view
114
        views_menu.append_item(self.uif.create_item('View by components', 'app.view-components', ''))
115
        self.app.add_action(self.uif.create_action("view-components", self.cb.refresh_view, 'components'))
116
 
74 t00mlabs 117
        # Component descriptions view
118
        views_menu.append_item(self.uif.create_item('View by component description', 'app.view-component-descriptions', ''))
119
        self.app.add_action(self.uif.create_action("view-component-descriptions", self.cb.refresh_view, 'description'))
120
 
4 t00mlabs 121
        # Bookmarks view
122
        views_menu.append_item(self.uif.create_item('View bookmarks', 'app.view-bookmarks', ''))
123
        self.app.add_action(self.uif.create_action("view-bookmarks", self.cb.refresh_view, 'bookmarks'))
124
 
74 t00mlabs 125
        # Category view
126
        views_menu.append_item(self.uif.create_item('View categories', 'app.view-categories', ''))
127
        self.app.add_action(self.uif.create_action("view-categories", self.cb.refresh_view, 'category'))
4 t00mlabs 128
 
74 t00mlabs 129
        # Chronologic order view
130
        views_menu.append_item(self.uif.create_item('View in chronologic order', 'app.chronologic-order', ''))
131
        self.app.add_action(self.uif.create_action("chronologic-order", self.cb.refresh_view, 'chronologic'))
132
 
133
        # Priority view
134
        views_menu.append_item(self.uif.create_item('View by priority', 'app.view-priority', ''))
135
        self.app.add_action(self.uif.create_action("view-priority", self.cb.refresh_view, 'priority'))
136
 
137
        # SAP Note Type view
138
        views_menu.append_item(self.uif.create_item('View by type', 'app.view-type', ''))
139
        self.app.add_action(self.uif.create_action("view-type", self.cb.refresh_view, 'type'))
140
 
4 t00mlabs 141
        # Annotations view
142
        #~ TODO
143
        #~ views_menu.append_item(self.uif.create_item('View by annotations', 'app.view-annotations', ''))
144
        #~ self.app.add_action(self.uif.create_action("view-annotations", self.cb_show_dlnotes_window))
145
 
146
        # Set menu model in button
147
        btnviews = self.gui.get_widget('mnuBtnViews')
148
        btnviews.set_menu_model(views_menu)
149
 
150
 
151
    def setup_menu_settings(self):
152
        ### SETTINGS POPOVER
153
        menu = Gio.Menu()
154
        #~ self.gui.add_widget("menu", menu)
155
        menu.append_item(self.uif.create_item('Fullscreen', 'app.settings-fullscreen', 'gtk-fullscreen'))
156
        menu.append_item(self.uif.create_item('Rename current project', 'app.project-rename', 'preferences-desktop-personal'))
157
        menu.append_item(self.uif.create_item('Refresh current project', 'app.project-refresh', 'view-refresh'))
158
        menu.append_item(self.uif.create_item('Close current project', 'app.project-close', 'window-close'))
159
        menu.append_item(self.uif.create_item('Delete current project', 'app.project-delete', 'list-remove'))
160
        menu.append_item(self.uif.create_item('Export current project', 'app.project-delete', 'document-save-as'))
161
        window = self.gui.get_window()
162
        window.set_app_menu(menu)
163
        app = self.gui.get_app()
164
        app.add_action(self.uif.create_item("settings-fullscreen"))
165
 
166
        #~ popover_action_group = Gio.SimpleActionGroup()
167
        btnsettings = self.gui.get_widget("mnuBtnViews")
168
        popover_settings = Gtk.Popover.new_from_model(btnsettings, menu)
169
        popover_settings.set_position(Gtk.PositionType.BOTTOM)
170
        btnsettings.connect('clicked', lambda _: popover_settings.show_all())
171
 
172
 
173
    def setup_menus(self):
174
        self.setup_menu_views()
175
        #~ self.setup_menu_actions()
176
        #~ self.setup_menu_settings()
177
 
74 t00mlabs 178
 
4 t00mlabs 179
    def show_home_page(self, *args):
180
        notebook = self.gui.get_widget('notebook')
181
        notebook.set_current_page(0)
182
 
74 t00mlabs 183
 
4 t00mlabs 184
    def show_settings_page(self, *args):
185
        sapnoteview = self.gui.get_widget('sapnoteview')
186
        sapnoteview.set_view('settings')
187
        notebook = self.gui.get_widget('notebook')
188
        notebook.set_current_page(2)
189
 
74 t00mlabs 190
 
191
    def show_stats_page(self, *args):
192
        sapnoteview = self.gui.get_widget('sapnoteview')
193
        sapnoteview.set_view('stats')
194
        notebook = self.gui.get_widget('notebook')
195
        notebook.set_current_page(4)
196
 
197
 
4 t00mlabs 198
    def show_browser_page(self, *args):
199
        notebook = self.gui.get_widget('notebook')
200
        notebook.set_current_page(1)
201
 
202
 
203
    def show_search(self, *args):
204
        revsearch = self.gui.get_widget('revSearch')
205
        tgbsearch = self.gui.get_widget('tgbSearch')
206
        if tgbsearch.get_active():
207
            revsearch.set_reveal_child(True)
208
            revsearch.set_no_show_all(False)
209
            revsearch.show_all()
210
        else:
211
            revsearch.set_reveal_child(False)
212
            revsearch.set_no_show_all(True)
213
            revsearch.hide()
214
 
215
 
74 t00mlabs 216
    def hide_props_window(self):
217
        hpnnotes = self.gui.get_widget('hpnNotesManager')
218
        boxprops = self.gui.get_widget('boxPropsWidget')
219
        size = hpnnotes.get_allocation()
4 t00mlabs 220
 
74 t00mlabs 221
        boxprops.set_no_show_all(True)
222
        boxprops.hide()
223
        hpnnotes.set_position(size.width)
4 t00mlabs 224
 
74 t00mlabs 225
 
226
    def show_props_window(self):
227
        hpnnotes = self.gui.get_widget('hpnNotesManager')
228
        boxprops = self.gui.get_widget('boxPropsWidget')
229
        size = hpnnotes.get_allocation()
230
 
231
        boxprops.set_no_show_all(False)
232
        boxprops.show_all()
233
        hpnnotes.show_all()
234
        hpnnotes.set_position(size.width/5*3)
235
 
236
 
237
    def switch_props_window(self, *args):
238
        tgbprops = self.gui.get_widget('tgbShowManage')
239
 
240
        if tgbprops.get_active():
241
            self.show_props_window()
242
        else:
243
            self.hide_props_window()
244
 
245
 
4 t00mlabs 246
    def setup_widgets(self):
247
        self.mainbox = self.gui.get_widget('mainbox')
248
        self.mainbox.reparent(self)
249
 
74 t00mlabs 250
        statusbar = self.gui.get_widget('pgbMain')
251
        statusbar.set_text("")
252
        statusbar.set_show_text(True)
253
        statusbar.set_fraction(0.0)
4 t00mlabs 254
        self.setup_menus()
74 t00mlabs 255
        #~ self.tasks.setup_widgets()
4 t00mlabs 256
        notesbox = self.gui.get_widget('notesbox')
257
        sapnoteview = SAPNoteView(self.controller)
258
        self.gui.add_widget('sapnoteview', sapnoteview)
259
        self.gui.add_widget('combobox')
260
        search = self.gui.add_widget('stySearchInfo')
261
        #~ search.connect('search_changed', self.search_notes)
262
        search.connect('activate', self.cb.search_notes)
74 t00mlabs 263
        self.setup_combobox_search()
4 t00mlabs 264
        self.swap_widget(notesbox, sapnoteview)
265
 
74 t00mlabs 266
 
267
        self.setup_props_window()
268
 
269
 
4 t00mlabs 270
        # Buttons
74 t00mlabs 271
        # Task link button
272
        self.cb.check_task_link_button_status()
4 t00mlabs 273
 
74 t00mlabs 274
        # button quit
275
        image = self.gui.get_widget('imgBtnQuit')
276
        icon = self.im.get_pixbuf_icon('power', 48, 48)
277
        image.set_from_pixbuf(icon)
278
        button = self.gui.get_widget('btnQuit')
279
        button.connect('clicked', self.gui.quit)
4 t00mlabs 280
 
74 t00mlabs 281
        # button about
282
        image = self.gui.get_widget('imgBtnAbout')
283
        icon = self.im.get_pixbuf_icon('about', 48, 48)
284
        image.set_from_pixbuf(icon)
285
        button = self.gui.get_widget('btnAbout')
286
        button.connect('clicked', self.uiapp.cb_show_about)
287
 
288
        # button settings
289
        image = self.gui.get_widget('imgBtnSettings')
290
        icon = self.im.get_pixbuf_icon('settings', 48, 48)
291
        image.set_from_pixbuf(icon)
292
        button = self.gui.get_widget('btnSettings')
293
        button.connect('clicked', self.show_settings_page)
294
 
295
        # button stats
296
        image = self.gui.get_widget('imgBtnStats')
297
        icon = self.im.get_pixbuf_icon('chart', 48, 48)
298
        image.set_from_pixbuf(icon)
299
        button = self.gui.get_widget('btnShowStats')
300
        button.connect('clicked', self.show_stats_page)
301
 
302
        # button show property details
303
        image = self.gui.get_widget('imgBtnShowProps')
304
        icon = self.im.get_pixbuf_icon('fingerprint', 48, 48)
305
        image.set_from_pixbuf(icon)
306
        button = self.gui.get_widget('btnShowProperties')
307
        button.connect('clicked', self.cb.show_properties)
308
 
309
        # button show manage window
310
        image = self.gui.get_widget('imgBtnShowManage')
311
        icon = self.im.get_pixbuf_icon('subwindow', 48, 48)
312
        image.set_from_pixbuf(icon)
313
        button = self.gui.get_widget('tgbShowManage')
314
        button.connect('toggled', self.switch_props_window)
315
 
316
        # button search
317
        image = self.gui.get_widget('imgBtnSearch')
318
        icon = self.im.get_pixbuf_icon('bsearch', 48, 48)
319
        image.set_from_pixbuf(icon)
320
        button = self.gui.get_widget('tgbSearch')
321
        button.connect('toggled', self.show_search)
322
        revsearch = self.gui.get_widget('revSearch')
323
        revsearch.hide()
324
        revsearch.set_no_show_all(True)
325
 
326
        # button import
327
        image = self.gui.get_widget('imgMnuBtnImport')
328
        icon = self.im.get_pixbuf_icon('import', 48, 48)
329
        image.set_from_pixbuf(icon)
330
        #~ button = self.gui.get_widget('mnuBtnImport')
331
        #~ button.connect('toggled', self.switch_props_window)
332
 
333
        # button refresh
334
        image = self.gui.get_widget('imgBtnRefresh')
335
        icon = self.im.get_pixbuf_icon('refresh', 48, 48)
336
        image.set_from_pixbuf(icon)
337
        button = self.gui.get_widget('btnRefreshSAPNoteView')
338
        button.connect('clicked', self.cb.refresh_and_clear_view)
339
 
340
 
341
        button = self.gui.get_widget('btnLinkTasksApply')
342
        button.connect('clicked', self.cb.link_tasks_to_sapnotes)
343
 
344
 
345
 
4 t00mlabs 346
        btnaddnote = self.gui.get_widget('btnStartDlNotes')
347
        btnaddnote.connect('clicked', self.cb.import_notes)
348
 
349
 
350
 
74 t00mlabs 351
        #~ btnShowAddSAPNotesDlg = self.gui.get_widget('btnShowAddSAPNotesDlg')
352
        #~ btnShowAddSAPNotesDlg.connect('clicked', self.show_addsapnotes_dialog)
353
 
4 t00mlabs 354
        btnStopDlNotes = self.gui.get_widget('btnStopDlNotes')
355
        btnStopDlNotes.connect('clicked', self.cb.stop_dl_notes)
356
 
74 t00mlabs 357
        #~ toggle= self.gui.get_widget('tgbFullScreen')
358
        #~ toggle.connect('toggled', self.uif.fullscreen)
4 t00mlabs 359
        switch = self.gui.get_widget('schExpandCollapse')
360
        switch.connect('state-set', sapnoteview.expand_collapse)
361
        switch = self.gui.get_widget('schSelectNotesAllNone')
362
        switch.connect('state-set', sapnoteview.select_all_none)
363
 
364
 
365
        # Actions button
366
        button = self.gui.get_widget('mnuBtnActions')
367
 
368
        # Prefs for SAP module
369
        button = self.gui.add_widget('btnPrefsSAPApply')
370
        button.connect('clicked', self.cb.apply_preferences)
371
 
372
        button = self.gui.add_widget('btnPrefsSAPCancel')
373
        button.connect('clicked', self.cb.refresh_view)
374
 
375
        button = self.gui.add_widget('btnPrefsSAPReset')
74 t00mlabs 376
        button.connect('clicked', self.cb.default_preferences)
4 t00mlabs 377
 
378
        # Notebook Import Widget
74 t00mlabs 379
        #~ ntbimport = self.gui.add_widget('ntbAddSAPNotes')
4 t00mlabs 380
 
74 t00mlabs 381
        sap_settings = self.prefs.get_custom_settings()
4 t00mlabs 382
        for setting in sap_settings:
74 t00mlabs 383
            try:
384
                widget = self.gui.add_widget(setting)
385
                widget.set_text(sap_settings[setting])
386
            except:
387
                pass
4 t00mlabs 388
 
74 t00mlabs 389
 
4 t00mlabs 390
        # Stats
391
        statsviewer = self.gui.add_widget('scrStatsViewer')
392
 
393
        btnstats = self.gui.add_widget('btnStatsByCompMain')
394
        btnstats.connect('clicked', self.cb.update_components_stats)
395
        iconwdg = self.gui.add_widget('imgStatsByCompMain')
396
        icon = self.im.get_pixbuf_icon('component', 64, 64)
397
        iconwdg.set_from_pixbuf(icon)
398
 
399
        btnstats = self.gui.add_widget('btnStatsByCategory')
400
        btnstats.connect('clicked', self.cb.update_categories_stats)
401
        iconwdg = self.gui.add_widget('imgStatsByCategory')
402
        icon = self.im.get_pixbuf_icon('category', 64, 64)
403
        iconwdg.set_from_pixbuf(icon)
404
 
74 t00mlabs 405
        self.hide_props_window()
4 t00mlabs 406
        self.show_all()
407
        self.log.debug("GUI loaded")
408
 
409
 
74 t00mlabs 410
    def setup_props_window(self):
411
        imgtitle = self.gui.get_widget('imgPropsTitle')
412
        icon = self.im.get_icon('fingerprint', 48, 48)
413
        imgtitle.set_from_pixbuf (icon)
414
        model = Gtk.TreeStore(str, str)
415
        trvprops = self.gui.add_widget('trvprops', Gtk.TreeView())
416
        trvprops.set_model(model)
417
 
418
        #~ ## key
419
        #~ renderer = Gtk.CellRendererText()
420
        #~ column = Gtk.TreeViewColumn('Id', renderer, text=0)
421
        #~ column.set_visible(False)
422
        #~ column.set_clickable(False)
423
        #~ column.set_sort_indicator(False)
424
        #~ trvprops.append_column(column)
425
 
426
        # Property
427
        renderer = Gtk.CellRendererText()
428
        renderer.set_alignment(1.0, 0.5)
429
        column = Gtk.TreeViewColumn('Property', renderer, markup=0)
430
        column.set_visible(True)
431
        column.set_expand(False)
432
        column.set_clickable(True)
433
        column.set_sort_indicator(True)
434
        trvprops.append_column(column)
435
 
436
        # Value
437
        renderer = Gtk.CellRendererText()
438
        renderer.set_alignment(0.0, 0.5)
439
        column = Gtk.TreeViewColumn('Value', renderer, markup=1)
440
        column.set_visible(True)
441
        column.set_expand(True)
442
        column.set_clickable(True)
443
        column.set_sort_indicator(True)
444
        trvprops.append_column(column)
445
        trvprops.show_all()
446
 
447
        trvprops.set_headers_visible(True)
448
        trvprops.set_enable_search(True)
449
        trvprops.set_grid_lines(Gtk.TreeViewGridLines.NONE)
450
        trvprops.set_search_column(1)
451
        #~ trvprops.connect('row-activated', self.double_click)
452
        selection = trvprops.get_selection()
453
        selection.set_mode(Gtk.SelectionMode.SINGLE)
454
        #~ trvprops.set_search_entry(self.pname)
455
 
456
        container = self.gui.get_widget('boxProps')
457
        self.gui.swap_widget(container, trvprops)
458
 
459
    def set_notes_manager_pane_position(self, pane, rectangle):
460
        pass
461
        #~ self.log.debug(type(pane.get_allocation()))
462
        position = rectangle.width/5*3
463
        pane.set_position(position)
464
        self.log.debug("Pane position: %s" % position)
465
 
466
 
467
 
4 t00mlabs 468
    def __completion_func(self, completion, key, iter):
469
        model = completion.get_model()
470
        text = model.get_value(iter, 0)
471
        if key.upper() in text.upper():
472
            return True
473
        return False
474
 
475
 
476
    def setup_combobox_completions(self, key):
477
        model = Gtk.ListStore(str)
478
        search = self.gui.get_widget("stySearchInfo")
479
        completion = Gtk.EntryCompletion()
480
        completion.set_model(model)
481
        completion.set_text_column(0)
482
        completion.set_match_func(self.__completion_func)
483
        search.set_completion(completion)
484
 
74 t00mlabs 485
        stats = self.db.get_stats()
4 t00mlabs 486
 
487
        try:
488
            items = list(stats[key])
489
            items.sort()
490
            for item in items:
491
                model.append([item])
492
        except:
493
            pass
494
 
495
 
496
    def cb_combobox_changed(self, combobox):
497
        model = combobox.get_model()
498
        treeiter = combobox.get_active_iter()
499
        key = model[treeiter][0]
500
        self.gui.set_key('cmbvalue', key)
501
        self.setup_combobox_completions(key)
502
 
503
 
74 t00mlabs 504
    def setup_combobox_search(self):
505
        combobox = self.gui.get_widget('cmbSearchInfo')
4 t00mlabs 506
        model = Gtk.TreeStore(str, str)
507
        combobox.set_model(model)
508
 
509
        ## key
510
        cell = Gtk.CellRendererText()
511
        cell.set_visible(False)
512
        combobox.pack_start(cell, True)
513
        combobox.add_attribute(cell, 'text', 0)
514
 
515
        ## value
516
        cell = Gtk.CellRendererText()
517
        cell.set_alignment(0.0, 0.5)
518
        combobox.pack_start(cell, expand=False)
519
        combobox.add_attribute(cell, 'markup', 1)
520
        combobox.connect('changed', self.cb_combobox_changed)
521
 
522
        model.append(None, ['search', 'Search in all database'])
523
        model.append(None, ['project', 'Filter by project name'])
524
        model.append(None, ['task', 'Filter by task name'])
525
        model.append(None, ['component', 'Filter by component'])
526
        model.append(None, ['category', 'Filter by category'])
527
        model.append(None, ['type', 'Filter by type'])
528
        model.append(None, ['id', 'Filter by Id'])
529
        model.append(None, ['title', 'Filter by title'])
530
        model.append(None, ['priority', 'Filter by priority'])
531
        model.append(None, ['version', 'Filter by version'])
532
        #~ model.append(None, ['released', 'Filter by release date'])
533
 
534
        combobox.set_active(0)
535
 
536
 
537
    def get_services(self):
538
        """Load services to be used in this class
539
        """
540
        self.gui = self.controller.get_service("GUI")
541
        self.app = self.gui.get_app()
542
        LOG_FILE = self.controller.get_file('LOG')
543
        self.log = get_logger('GtkAppWindow', LOG_FILE)
74 t00mlabs 544
        self.db = self.controller.get_service("DB")
4 t00mlabs 545
        self.uif = self.controller.get_service("UIF")
546
        self.prefs = self.controller.get_service("Settings")
547
        self.im = self.controller.get_service('IM')
548
        self.cb = self.controller.get_service('Callbacks')
74 t00mlabs 549
        self.tasks = self.controller.get_service('Tasks')
4 t00mlabs 550
 
551
 
552
    def swap_widget(self, container, combobox):
553
        """Shortcut to GUI.swap_widget method
554
        """
555
        self.gui.swap_widget(container, combobox)