~saurabhanandiit/gtg/exportFixed

« back to all changes in this revision

Viewing changes to GTG/gtk/browser/custominfobar.py

Merge of my work on liblarch newbase and all the backends ported to liblarch
(which mainly means porting the datastore).
One failing test, will check it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
# -----------------------------------------------------------------------------
 
3
# Getting Things Gnome! - a personal organizer for the GNOME desktop
 
4
# Copyright (c) 2008-2009 - Lionel Dricot & Bertrand Rousseau
 
5
#
 
6
# This program is free software: you can redistribute it and/or modify it under
 
7
# the terms of the GNU General Public License as published by the Free Software
 
8
# Foundation, either version 3 of the License, or (at your option) any later
 
9
# version.
 
10
#
 
11
# This program is distributed in the hope that it will be useful, but WITHOUT
 
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
13
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 
14
# details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License along with
 
17
# this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
# -----------------------------------------------------------------------------
 
19
 
 
20
import gtk
 
21
import threading
 
22
 
 
23
from GTG                         import _
 
24
from GTG.backends.backendsignals import BackendSignals
 
25
from GTG.tools.networkmanager    import is_connection_up
 
26
 
 
27
 
 
28
 
 
29
class CustomInfoBar(gtk.InfoBar):
 
30
    '''
 
31
    A gtk.InfoBar specialized for displaying errors and requests for
 
32
    interaction coming from the backends
 
33
    '''
 
34
 
 
35
 
 
36
    AUTHENTICATION_MESSAGE = _("The <b>%s</b> backend cannot login with the "
 
37
                               "supplied authentication data and has been"
 
38
                               " disabled. To retry the login, re-enable the backend.")
 
39
 
 
40
    NETWORK_MESSAGE = _("Due to a network problem, I cannot contact "
 
41
                        "the <b>%s</b> backend.")
 
42
 
 
43
    DBUS_MESSAGE = _("Cannot connect to DBUS, I've disabled "
 
44
                        "the <b>%s</b> backend.")
 
45
 
 
46
    def __init__(self, req, browser, vmanager, backend_id):
 
47
        '''
 
48
        Constructor, Prepares the infobar.
 
49
 
 
50
        @param req: a Requester object
 
51
        @param browser: a TaskBrowser object
 
52
        @param vmanager: a ViewManager object
 
53
        @param backend_id: the id of the backend linked to the infobar
 
54
        '''
 
55
        super(CustomInfoBar, self).__init__()
 
56
        self.req = req
 
57
        self.browser = browser
 
58
        self.vmanager = vmanager
 
59
        self.backend_id = backend_id
 
60
        self.backend = self.req.get_backend(backend_id)
 
61
 
 
62
    def get_backend_id(self):
 
63
        '''
 
64
        Getter function to return the id of the backend for which this
 
65
        gtk.InfoBar was created
 
66
        '''
 
67
        return self.backend_id
 
68
 
 
69
    def _populate(self):
 
70
        '''Setting up gtk widgets'''
 
71
        content_hbox = self.get_content_area()
 
72
        content_hbox.set_homogeneous(False)
 
73
        self.label = gtk.Label()
 
74
        self.label.set_line_wrap(True)
 
75
        self.label.set_alignment(0.5, 0.5)
 
76
        self.label.set_justify(gtk.JUSTIFY_FILL)
 
77
        content_hbox.pack_start(self.label, True, True)
 
78
 
 
79
    def _on_error_response(self, widget, event):
 
80
        '''
 
81
        Signal callback executed when the user acknowledges the error displayed
 
82
        in the infobar
 
83
 
 
84
        @param widget: not used, here for compatibility with signals callbacks
 
85
        @param event: the code of the gtk response
 
86
        '''
 
87
        self.hide()
 
88
        if event == gtk.RESPONSE_ACCEPT:
 
89
            self.vmanager.configure_backend(backend_id = self.backend_id)
 
90
 
 
91
    def set_error_code(self, error_code):
 
92
        '''
 
93
        Sets this infobar to show an error to the user
 
94
 
 
95
        @param error_code: the code of the error to show. Error codes are listed
 
96
                           in BackendSignals
 
97
        '''
 
98
        self._populate()
 
99
        self.connect("response", self._on_error_response)
 
100
        backend_name = self.backend.get_human_name()
 
101
 
 
102
        if error_code == BackendSignals.ERRNO_AUTHENTICATION:
 
103
            self.set_message_type(gtk.MESSAGE_ERROR)
 
104
            self.label.set_markup(self.AUTHENTICATION_MESSAGE % backend_name)
 
105
            self.add_button(_('Configure backend'), gtk.RESPONSE_ACCEPT)
 
106
            self.add_button(_('Ignore'), gtk.RESPONSE_CLOSE)
 
107
 
 
108
        elif error_code == BackendSignals.ERRNO_NETWORK:
 
109
            if not is_connection_up():
 
110
                return
 
111
            self.set_message_type(gtk.MESSAGE_WARNING)
 
112
            self.label.set_markup(self.NETWORK_MESSAGE % backend_name)
 
113
            #FIXME: use gtk stock button instead
 
114
            self.add_button(_('Ok'), gtk.RESPONSE_CLOSE)
 
115
        
 
116
        elif error_code == BackendSignals.ERRNO_DBUS:
 
117
            self.set_message_type(gtk.MESSAGE_WARNING)
 
118
            self.label.set_markup(self.DBUS_MESSAGE % backend_name)
 
119
            self.add_button(_('Ok'), gtk.RESPONSE_CLOSE)
 
120
 
 
121
        self.show_all()
 
122
 
 
123
    def set_interaction_request(self, description, interaction_type, callback):
 
124
        '''
 
125
        Sets this infobar to request an interaction from the user
 
126
 
 
127
        @param description: a string describing the interaction needed
 
128
        @param interaction_type: a string describing the type of interaction
 
129
                                 (yes/no, only confirm, ok/cancel...)
 
130
        @param callback: the function to call when the user provides the
 
131
                         feedback
 
132
        '''
 
133
        self._populate()
 
134
        self.callback = callback
 
135
        self.set_message_type(gtk.MESSAGE_INFO)
 
136
        self.label.set_markup(description)
 
137
        self.connect("response", self._on_interaction_response)
 
138
        self.interaction_type = interaction_type
 
139
        if interaction_type == BackendSignals().INTERACTION_CONFIRM:
 
140
            self.add_button(_('Confirm'), gtk.RESPONSE_ACCEPT)
 
141
        elif interaction_type == BackendSignals().INTERACTION_TEXT:
 
142
            self.add_button(_('Continue'), gtk.RESPONSE_ACCEPT)
 
143
        self.show_all()
 
144
 
 
145
    def _on_interaction_response(self, widget, event):
 
146
        '''
 
147
        Signal callback executed when the user gives the feedback for a
 
148
        requested interaction
 
149
 
 
150
        @param widget: not used, here for compatibility with signals callbacks
 
151
        @param event: the code of the gtk response
 
152
        '''
 
153
        if event == gtk.RESPONSE_ACCEPT:
 
154
            if self.interaction_type == BackendSignals().INTERACTION_TEXT:
 
155
                self._prepare_textual_interaction()
 
156
                print "done"
 
157
            elif self.interaction_type == BackendSignals().INTERACTION_CONFIRM:
 
158
                self.hide()
 
159
                threading.Thread(target = getattr(self.backend,
 
160
                                            self.callback)).start()
 
161
 
 
162
    def _prepare_textual_interaction(self):
 
163
        '''
 
164
        Helper function. gtk calls to populate the infobar in the case of
 
165
        interaction request
 
166
        '''
 
167
        title, description\
 
168
                = getattr(self.backend,
 
169
                          self.callback)("get_ui_dialog_text")
 
170
        self.dialog = gtk.Window()#type = gtk.WINDOW_POPUP)
 
171
        self.dialog.set_title(title)
 
172
        self.dialog.set_transient_for(self.browser.window)
 
173
        self.dialog.set_destroy_with_parent(True)
 
174
        self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
 
175
        self.dialog.set_modal(True)
 
176
        #        self.dialog.set_size_request(300,170)
 
177
        vbox = gtk.VBox()
 
178
        self.dialog.add(vbox)
 
179
        description_label = gtk.Label()
 
180
        description_label.set_justify(gtk.JUSTIFY_FILL)
 
181
        description_label.set_line_wrap(True)
 
182
        description_label.set_markup(description)
 
183
        align = gtk.Alignment(0.5, 0.5, 1, 1)
 
184
        align.set_padding(10, 0, 20, 20)
 
185
        align.add(description_label)
 
186
        vbox.pack_start(align)
 
187
        self.text_box = gtk.Entry()
 
188
        self.text_box.set_size_request(-1, 40)
 
189
        align = gtk.Alignment(0.5, 0.5, 1, 1)
 
190
        align.set_padding(20, 20, 20, 20)
 
191
        align.add(self.text_box)
 
192
        vbox.pack_start(align)
 
193
        button = gtk.Button(stock = gtk.STOCK_OK)
 
194
        button.connect("clicked", self._on_text_confirmed)
 
195
        button.set_size_request(-1, 40)
 
196
        vbox.pack_start(button, False)
 
197
        self.dialog.show_all()
 
198
        self.hide()
 
199
 
 
200
    def _on_text_confirmed(self, widget):
 
201
        '''
 
202
        Signal callback, used when the interaction needs a textual input to be
 
203
        completed (e.g, the twitter OAuth, requesting a pin)
 
204
 
 
205
        @param widget: not used, here for signal callback compatibility
 
206
        '''
 
207
        text = self.text_box.get_text()
 
208
        self.dialog.destroy()
 
209
        threading.Thread(target = getattr(self.backend, self.callback), 
 
210
                          args = ("set_text", text)).start()
 
211