Merging some code in from DoneIt
[gc-dialer] / src / gtk_toolbox.py
1 #!/usr/bin/python
2
3 import warnings
4 import contextlib
5
6 import gobject
7 import gtk
8
9
10 @contextlib.contextmanager
11 def gtk_lock():
12         gtk.gdk.threads_enter()
13         try:
14                 yield
15         finally:
16                 gtk.gdk.threads_leave()
17
18
19 class LoginWindow(object):
20
21         def __init__(self, widgetTree):
22                 """
23                 @note Thread agnostic
24                 """
25                 self._dialog = widgetTree.get_widget("loginDialog")
26                 self._parentWindow = widgetTree.get_widget("mainWindow")
27                 self._serviceCombo = widgetTree.get_widget("serviceCombo")
28                 self._usernameEntry = widgetTree.get_widget("usernameentry")
29                 self._passwordEntry = widgetTree.get_widget("passwordentry")
30
31                 self._serviceList = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING)
32                 self._serviceCombo.set_model(self._serviceList)
33                 cell = gtk.CellRendererText()
34                 self._serviceCombo.pack_start(cell, True)
35                 self._serviceCombo.add_attribute(cell, 'text', 1)
36                 self._serviceCombo.set_active(0)
37
38                 callbackMapping = {
39                         "on_loginbutton_clicked": self._on_loginbutton_clicked,
40                         "on_loginclose_clicked": self._on_loginclose_clicked,
41                 }
42                 widgetTree.signal_autoconnect(callbackMapping)
43
44         def request_credentials(self, parentWindow = None):
45                 """
46                 @note UI Thread
47                 """
48                 if parentWindow is None:
49                         parentWindow = self._parentWindow
50
51                 self._serviceCombo.hide()
52                 self._serviceList.clear()
53
54                 try:
55                         self._dialog.set_transient_for(parentWindow)
56                         self._dialog.set_default_response(gtk.RESPONSE_OK)
57                         response = self._dialog.run()
58                         if response != gtk.RESPONSE_OK:
59                                 raise RuntimeError("Login Cancelled")
60
61                         username = self._usernameEntry.get_text()
62                         password = self._passwordEntry.get_text()
63                         self._passwordEntry.set_text("")
64                 finally:
65                         self._dialog.hide()
66
67                 return username, password
68
69         def request_credentials_from(self, services, parentWindow = None):
70                 """
71                 @note UI Thread
72                 """
73                 if parentWindow is None:
74                         parentWindow = self._parentWindow
75
76                 self._serviceList.clear()
77                 for serviceIdserviceName in services.iteritems():
78                         self._serviceList.append(serviceIdserviceName)
79                 self._serviceCombo.set_active(0)
80                 self._serviceCombo.show()
81
82                 try:
83                         self._dialog.set_transient_for(parentWindow)
84                         self._dialog.set_default_response(gtk.RESPONSE_OK)
85                         response = self._dialog.run()
86                         if response != gtk.RESPONSE_OK:
87                                 raise RuntimeError("Login Cancelled")
88
89                         username = self._usernameEntry.get_text()
90                         password = self._passwordEntry.get_text()
91                         self._passwordEntry.set_text("")
92                 finally:
93                         self._dialog.hide()
94
95                 itr = self._serviceCombo.get_active_iter()
96                 serviceId = int(self._serviceList.get_value(itr, 0))
97                 self._serviceList.clear()
98                 return serviceId, username, password
99
100         def _on_loginbutton_clicked(self, *args):
101                 self._dialog.response(gtk.RESPONSE_OK)
102
103         def _on_loginclose_clicked(self, *args):
104                 self._dialog.response(gtk.RESPONSE_CANCEL)
105
106
107 class ErrorDisplay(object):
108
109         def __init__(self, widgetTree):
110                 super(ErrorDisplay, self).__init__()
111                 self.__errorBox = widgetTree.get_widget("errorEventBox")
112                 self.__errorDescription = widgetTree.get_widget("errorDescription")
113                 self.__errorClose = widgetTree.get_widget("errorClose")
114                 self.__parentBox = self.__errorBox.get_parent()
115
116                 self.__errorBox.connect("button_release_event", self._on_close)
117
118                 self.__messages = []
119                 self.__parentBox.remove(self.__errorBox)
120
121         def push_message_with_lock(self, message):
122                 gtk.gdk.threads_enter()
123                 try:
124                         self.push_message(message)
125                 finally:
126                         gtk.gdk.threads_leave()
127
128         def push_message(self, message):
129                 if 0 < len(self.__messages):
130                         self.__messages.append(message)
131                 else:
132                         self.__show_message(message)
133
134         def push_exception(self, exception):
135                 self.push_message(exception.message)
136                 warnings.warn(exception, stacklevel=3)
137
138         def pop_message(self):
139                 if 0 < len(self.__messages):
140                         self.__show_message(self.__messages[0])
141                         del self.__messages[0]
142                 else:
143                         self.__hide_message()
144
145         def _on_close(self, *args):
146                 self.pop_message()
147
148         def __show_message(self, message):
149                 self.__errorDescription.set_text(message)
150                 self.__parentBox.pack_start(self.__errorBox, False, False)
151                 self.__parentBox.reorder_child(self.__errorBox, 1)
152
153         def __hide_message(self):
154                 self.__errorDescription.set_text("")
155                 self.__parentBox.remove(self.__errorBox)
156
157
158 class MessageBox(gtk.MessageDialog):
159
160         def __init__(self, message):
161                 parent = None
162                 gtk.MessageDialog.__init__(
163                         self,
164                         parent,
165                         gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
166                         gtk.MESSAGE_ERROR,
167                         gtk.BUTTONS_OK,
168                         message,
169                 )
170                 self.set_default_response(gtk.RESPONSE_OK)
171                 self.connect('response', self._handle_clicked)
172
173         def _handle_clicked(self, *args):
174                 self.destroy()
175
176
177 class MessageBox2(gtk.MessageDialog):
178
179         def __init__(self, message):
180                 parent = None
181                 gtk.MessageDialog.__init__(
182                         self,
183                         parent,
184                         gtk.DIALOG_DESTROY_WITH_PARENT,
185                         gtk.MESSAGE_ERROR,
186                         gtk.BUTTONS_OK,
187                         message,
188                 )
189                 self.set_default_response(gtk.RESPONSE_OK)
190                 self.connect('response', self._handle_clicked)
191
192         def _handle_clicked(self, *args):
193                 self.destroy()