Subversion Repositories basico

Rev

Rev 374 | Rev 380 | 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_uif.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: Generic UI functions service
8
"""
9
 
10
from html import escape
11
from gi.repository import Gdk
12
from gi.repository import Gtk
13
from gi.repository import Gio
14
from gi.repository import Pango
15
from gi.repository.GdkPixbuf import Pixbuf
16
 
17
from basico.core.mod_srv import Service
18
 
19
class UIFuncs(Service):
20
    def initialize(self):
21
        self.get_services()
22
 
23
 
24
    def get_services(self):
25
        self.srvgui = self.get_service('GUI')
26
        self.srvclb = self.get_service('Callbacks')
27
        self.srvicm = self.get_service('IM')
374 t00mlabs 28
        # ~ self.srvdtb = self.get_service('DB')
340 t00mlabs 29
        self.srvant = self.get_service('Annotation')
30
        self.srvutl = self.get_service('Utils')
31
        self.srvntf = self.get_service('Notify')
32
 
33
 
34
    def get_gtk_version(self):
35
        return Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()
36
 
37
 
38
    def check_gtk_version(self):
39
        vmajor, vminor, vmicro =  self.get_gtk_version()
40
        self.log.debug("GTK+ Version: %d.%d.%d" % (vmajor, vminor, vmicro))
41
 
42
        if vmajor == 3 and vminor >= 18:
43
            return True
44
        else:
45
            self.log.error("Please, install a modern version of GTK+ (>= 3.18)")
46
            return False
47
 
48
    def get_window_parent(self):
49
        return self.srvgui.get_window()
50
 
51
 
52
    def message_dialog_error(self, head, body):
53
        parent = self.get_window_parent()
54
        dialog = Gtk.MessageDialog(parent, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "%s" % head)
55
        dialog.format_secondary_markup("%s" % body)
56
        return dialog
57
 
58
    def message_dialog_info(self, head, body):
59
        parent = self.get_window_parent()
60
        dialog = Gtk.MessageDialog(parent, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, "%s" % head)
61
        dialog.format_secondary_markup("%s" % body)
62
        return dialog
63
 
64
 
65
    def message_dialog_question(self, head, body):
66
        parent = self.get_window_parent()
67
        dialog = Gtk.MessageDialog(parent, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, head)
68
        dialog.format_secondary_markup("%s" % body)
69
        return dialog
70
 
71
 
374 t00mlabs 72
    def statusbar_msg(self, message, important=False):
340 t00mlabs 73
        statusbar = self.srvgui.get_widget('widget_statusbar')
74
        htimestamp = self.srvutl.get_human_date_from_timestamp()
75
        msg = htimestamp + '\t-\t' + message
76
        if statusbar is not None:
77
            # Maybe the widget hasn't been created yet
374 t00mlabs 78
            statusbar.message(msg)
340 t00mlabs 79
        if important:
80
            self.srvntf.show(htimestamp, message)
81
 
82
 
83
    def create_menuview_button(self, view):
84
        hbox = Gtk.Box(spacing = 0, orientation="horizontal")
85
        icon = self.srvicm.get_pixbuf_icon('basico-%s' % view, 24, 24)
86
        image = Gtk.Image()
87
        image.set_from_pixbuf(icon)
88
        label = Gtk.Label("View by %s" % view)
89
        hbox.pack_start(image, False, False, 3)
90
        hbox.pack_start(label, False, False, 3)
91
        button = Gtk.Button()
92
        button.add(hbox)
93
        button.set_relief(Gtk.ReliefStyle.NONE)
94
        button.connect('clicked', self.srvclb.gui_refresh_view, '%s' % view)
95
 
96
        return button
97
 
98
    def create_notebook_tab_label(self, iconname, title):
99
        hbox = Gtk.HBox()
100
        icon = self.srvicm.get_new_image_icon(iconname)
101
        label = Gtk.Label()
102
        label.set_markup(title)
103
        hbox.pack_start(icon, False, False, 3)
104
        hbox.pack_start(label, False, False, 0)
105
        hbox.show_all()
106
 
107
        return hbox
108
 
109
 
110
    def create_button(self, icon_name=None, icon_width=32, icon_heigth=32, title=''):
111
        button = Gtk.Button()
112
        button.set_relief(Gtk.ReliefStyle.NONE)
113
        hbox = Gtk.HBox()
114
        icon = self.srvicm.get_new_image_icon(icon_name, icon_width, icon_heigth)
115
        label = Gtk.Label()
116
        label.set_markup(title)
117
        label.set_xalign(0.0)
118
        hbox.pack_start(icon, False, False, 6)
119
        hbox.pack_start(label, True, True, 0)
120
        button.add(hbox)
121
 
122
        return button
123
 
124
 
125
    def warning_message_delete_annotations(self, widget, question, explanation, bag):
126
        window = self.srvgui.get_widget('gtk_app_window_main')
127
        icon = self.srvicm.get_new_image_icon('basico-delete', 96, 96)
128
        icon.show_all()
129
        dialog = Gtk.MessageDialog(window, 0, Gtk.MessageType.QUESTION,
130
            Gtk.ButtonsType.YES_NO, question)
131
        dialog.set_size_request(600, 380);
132
        content_area = dialog.get_content_area()
133
        vbox = Gtk.VBox()
134
        label = Gtk.Label()
135
        label.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
136
        label.set_property('selectable', True)
137
        label.set_xalign(0.0)
138
        label.grab_focus()
139
        msg = '\t<b>This is the list of annotations to be deleted:</b>'
140
        vbox.pack_start(label, False, False, 0)
141
        scr = Gtk.ScrolledWindow()
142
        scr.set_shadow_type(Gtk.ShadowType.NONE)
143
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
144
 
145
        msg += '\n\n'
146
        for aid in bag:
147
            msg += '\t%s\t\n' % self.srvant.get_title(aid)
148
        msg += '\n'
149
        label.set_markup(msg)
150
 
151
        vbox.pack_start(scr, True, True, 0)
152
        content_area.pack_start(vbox, True, True, 0)
153
        content_area.show_all()
154
        dialog.set_image(icon)
155
        dialog.format_secondary_text(explanation)
156
        response = dialog.run()
157
        if response == Gtk.ResponseType.YES:
158
            answer = True
159
        else:
160
            answer = False
161
        dialog.destroy()
162
 
163
        return answer
164
 
165
 
166
    def warning_message_delete_sapnotes(self, widget, question, explanation, bag):
374 t00mlabs 167
        self.srvdtb = self.get_service('DB')
340 t00mlabs 168
        window = self.srvgui.get_widget('gtk_app_window_main')
169
        icon = self.srvicm.get_new_image_icon('basico-delete', 96, 96)
170
        icon.show_all()
171
        dialog = Gtk.MessageDialog(window, 0, Gtk.MessageType.QUESTION,
172
            Gtk.ButtonsType.YES_NO, question)
173
        dialog.set_size_request(800, 600);
174
        content_area = dialog.get_content_area()
175
        vbox = Gtk.VBox()
176
        label = Gtk.Label()
177
        label.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
178
        label.set_property('selectable', True)
179
        label.set_xalign(0.0)
180
        label.grab_focus()
181
        msg = '\t<b>You are about to delete %d SAP Notes:</b>' % len(bag)
182
        scr = Gtk.ScrolledWindow()
183
        scr.set_shadow_type(Gtk.ShadowType.NONE)
184
        scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
185
 
186
        msg += '\n\n'
187
        for sid in bag:
188
            msg += '\t%010d - %s\t\n' % (int(sid), escape(self.srvdtb.get_title(sid)))
189
        msg += '\n'
190
        label.set_markup(msg)
191
        scr.add(label)
192
        vbox.pack_start(scr, True, True, 0)
193
        content_area.pack_start(vbox, True, True, 0)
194
        content_area.show_all()
195
        dialog.set_image(icon)
196
        dialog.format_secondary_text(explanation)
197
        response = dialog.run()
198
        if response == Gtk.ResponseType.YES:
199
            answer = True
200
        else:
201
            answer = False
202
        dialog.destroy()
203
 
204
        return answer
205
 
206
 
207
    def set_widget_visibility(self, widget_name, visibility):
208
        widget = self.srvgui.get_widget(widget_name)
209
        if visibility:
210
            widget.set_no_show_all(False)
211
            widget.show_all()
212
        else:
213
            widget.set_no_show_all(True)
214
            widget.hide()
215
 
216
 
217
    def get_combobox_text(self, combobox, col):
218
        treeiter = combobox.get_active_iter()
219
        model = combobox.get_model()
220
        return model[treeiter][col]
221
 
222
 
223
    def set_combobox_active(self, combobox, value):
224
        model = combobox.get_model()
225
        for treeiter in model:
226
            self.log.debug (model[treeiter][0])
227
 
228
 
229
    def get_textview_text(self, textview):
230
        textbuffer = textview.get_buffer()
231
        istart, iend = textbuffer.get_bounds()
232
        return textbuffer.get_text(istart, iend, False)
233
 
234
 
235
    def set_textview_text(self, textview, text):
236
        textbuffer = textview.get_buffer()
237
        textbuffer.set_text(text)
238
 
239
    def dialog_info(self, title, message):
240
        window = self.srvgui.get_window()
241
        dialog = Gtk.MessageDialog(window, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, title)
242
        dialog.format_secondary_text(message)
243
        dialog.run()
244
        dialog.destroy()
245
 
246
 
247
    def grab_focus(self):
379 t00mlabs 248
        popover = self.srvgui.get_key_value('LAST_POPOVER')
249
        popover.popdown()
340 t00mlabs 250
 
251
 
252
    def action_collection_copy_to_clipboard(self, button):
374 t00mlabs 253
        self.srvdtb = self.get_service('DB')
340 t00mlabs 254
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
255
        visor_sapnotes = self.srvgui.get_widget('visor_sapnotes')
256
 
257
        bag = visor_sapnotes.get_filtered_bag()
258
        text = ''
259
        for sid in bag:
260
            metadata = self.srvdtb.get_sapnote_metadata(sid)
261
            text += "SAP Note %s: %s - Component: %s\n" % (str(int(sid)), metadata['title'], metadata['componentkey'])
262
        clipboard.set_text(text, -1)
263
 
264
        msg = "%d SAP Notes copied to the clipboard" % (len(bag))
368 t00mlabs 265
        self.statusbar_msg(msg)
340 t00mlabs 266
        self.log.debug(msg)
267
 
268
 
269
    def copy_text_to_clipboard(self, text):
270
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
271
        clipboard.set_text(text, -1)
368 t00mlabs 272
        msg = "Copied '%s' to clipboard" % text
273
        self.statusbar_msg(msg)
340 t00mlabs 274
 
364 t00mlabs 275
 
276
    def get_toolbar_separator(self, draw=False, expand=False):
277
        tool = Gtk.SeparatorToolItem.new()
278
        tool.set_draw(draw)
279
        tool.set_expand(expand)
280
        return tool
367 t00mlabs 281
 
282
 
283
    def tree_path_to_row(self, path):
284
        """
285
        Convert `path` to a list row integer.
286
 
287
        `path` can be either a :class:`Gtk.Treepath` instance or a string
288
        representation of it (as commonly used by various callbacks).
289
        """
290
        if path is None: return None
291
        if isinstance(path, Gtk.TreePath):
292
            return path.get_indices()[0]
293
        if isinstance(path, str):
294
            return int(path)
295
        raise TypeError("Bad type {} for path {}"
296
                        .format(repr(type(path)), repr(path)))
297
 
298
 
299
    def tree_row_to_path(self, row):
300
        """Convert list row integer to a :class:`Gtk.TreePath`."""
301
        if row is None: return None
302
        return Gtk.TreePath.new_from_string(str(row))
368 t00mlabs 303
 
304
 
305
    def select_folder(self, folder=None):
306
        window = self.srvgui.get_window()
307
        dialog = Gtk.FileChooserDialog("Please, choose a folder", window, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK))
308
        response = dialog.run()
309
        if response == Gtk.ResponseType.OK:
310
            folder = folder = dialog.get_filename()
311
        else:
312
            folder = None
313
        dialog.destroy()
314
        return folder
315
 
374 t00mlabs 316