2 # Copyright (c) 2008 INdT - Instituto Nokia de Tecnologia
4 # This file is part of python-purple.
6 # python-purple is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # python-purple is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL)
28 # The information below is needed by libpurple
29 __NAME__ = "nullclient-ecore"
32 __DEV_WEBSITE__ = "N/A"
34 class MainWindow(object):
36 # Connect button callback
37 self.__connect_button_cb = None
39 # Send button callback
40 self.__send_button_cb = None
42 # New account callback
43 self.__new_account_cb = None
48 def __login_window_cb(self, pointer):
50 self.login_password = etk.Entry()
52 # Confirm login button
53 confirm_login_bt = etk.Button(label='Ok')
54 confirm_login_bt.on_clicked(self.__connect_button_clicked)
58 vbox.append(self.login_password, etk.VBox.START, etk.VBox.FILL, 0)
59 vbox.append(confirm_login_bt, etk.VBox.END, etk.VBox.NONE, 0)
62 self.login_window = etk.Window(title='Password', \
63 size_request=(190, 80), child=vbox)
64 self.login_window.show_all()
66 def __connect_button_clicked(self, pointer):
67 # Call connection button callback
68 if self.__connect_button_cb:
69 self.__connect_button_cb(self.login_password.text)
70 self.login_window.destroy()
72 def __send_button_clicked(self, pointer):
73 # Get selected buddy name from buddy list
74 bname = self.blist.selected_rows[0][0]
76 # Get message from command entry
77 msg = self.cmd_entry.text
79 if bname and msg != '':
80 # Call send button callback
81 if self.__send_button_cb:
82 self.__send_button_cb(bname, msg)
84 # Clear text from command entry
85 self.cmd_entry.text = ''
87 def __new_account_button_clicked(self, pointer):
89 self.login_username = etk.Entry()
91 # Confirm username button
92 confirm_username_bt = etk.Button(label='Ok')
93 confirm_username_bt.on_clicked(self.add_account)
97 vbox.append(self.login_username, etk.VBox.START, etk.VBox.FILL, 0)
98 vbox.append(confirm_username_bt, etk.VBox.END, etk.VBox.NONE, 0)
101 self.username_window = etk.Window(title='Username', \
102 size_request=(190, 80), child=vbox)
103 self.username_window.show_all()
105 def __create_accounts_list(self):
107 self.accslistmodel = etk.ListModel()
108 self.accslist = etk.List(model=self.accslistmodel, \
109 columns=[(10, etk.TextRenderer(slot=0), False)], \
110 selectable=True, animated_changes=True)
112 #Appending accounts list to VBox
114 vbox.append(self.accslist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
117 def __create_buddies_list(self):
119 self.blistmodel = etk.ListModel()
120 self.blist = etk.List(model=self.blistmodel, \
121 columns=[(10, etk.TextRenderer(slot=0), False)], \
122 selectable=True, animated_changes=True)
124 # Appending buddies list to VBox
126 vbox.append(self.blist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
129 def __create_buttons_bar(self):
131 send_button = etk.Button(label='Send')
132 send_button.on_clicked(self.__send_button_clicked)
135 conn_button = etk.Button(label='Connect')
136 conn_button.on_clicked(self.__login_window_cb)
139 new_acc_button = etk.Button(label='New Account')
140 new_acc_button.on_clicked(self.__new_account_button_clicked)
142 # Appending all buttons to HBox
143 hbox = etk.HBox(homogeneous=False)
144 hbox.append(send_button, etk.HBox.START, etk.HBox.NONE, 0)
145 hbox.append(conn_button, etk.HBox.START, etk.HBox.NONE, 0)
146 hbox.append(new_acc_button, etk.HBox.START, etk.HBox.NONE, 0)
149 def __create_command_entry_box(self):
151 self.cmd_entry = etk.Entry()
152 self.cmd_label = etk.Label(text='Type your message: ')
154 # appending command entry and label to HBox
155 hbox = etk.HBox(homogeneous=False)
156 hbox.append(self.cmd_label, etk.HBox.START, \
158 hbox.append(self.cmd_entry, etk.HBox.START, \
159 etk.HBox.EXPAND_FILL, 0)
162 def __create_text_area(self):
163 # Text area (shows buddy messages)
164 self.txt_area = etk.Label()
165 self.txt_area.text = '<br>Nullclient-Ecore<br> '
167 # Appending text area to VBox
169 vbox.append(self.txt_area, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
172 def __create_main_panel(self):
174 txt_vbox = self.__create_text_area()
177 bdd_vbox = self.__create_buddies_list()
180 acc_vbox = self.__create_accounts_list()
182 # Appending text area, buddies list and accounts list to HBox
184 hbox.append(txt_vbox, etk.HBox.START, etk.HBox.EXPAND_FILL, 0)
185 hbox.append(bdd_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0)
186 hbox.append(acc_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0)
189 def __create_main_box(self):
191 panel_hbox = self.__create_main_panel()
194 cmd_hbox = self.__create_command_entry_box()
197 btn_hbox = self.__create_buttons_bar()
200 self.status = etk.Label(text='Connection status')
203 vbox = etk.VBox(homogeneous=False)
204 vbox.append(panel_hbox, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
205 vbox.append(cmd_hbox, etk.VBox.END, etk.VBox.FILL, 0)
206 vbox.append(btn_hbox, etk.VBox.END, etk.VBox.NONE, 5)
207 vbox.append(self.status, etk.VBox.END, etk.VBox.FILL, 0)
210 def get_selected_account(self):
211 # Catch selected account from accounts list
213 account = self.accslist.selected_rows[0][0]
221 def add_buddy(self, name):
222 # Adds a new buddy into buddy list
223 if [name] not in self.blistmodel.elements:
224 self.blistmodel.append([name])
226 def remove_buddy(self, name):
227 # Removes a buddy from buddy list
228 self.blistmodel.remove([name])
230 def add_account(self, pointer):
231 # Adds a new account into accounts list
232 if [self.login_username.text] not in self.accslistmodel.elements:
233 self.accslistmodel.append([self.login_username.text])
234 self.username_window.destroy()
235 self.window.show_all()
237 def add_connection_button_cb(self, cb):
239 self.__connect_button_cb = cb
241 def add_new_account_cb(self, cb):
243 self.__new_account_cb = cb
245 def add_send_button_cb(self, cb):
247 self.__send_button_cb = cb
249 def add_exit_cb(self, cb):
253 def init_window(self):
255 main_box = self.__create_main_box()
258 self.window = etk.Window(title='Nullclient-Ecore', \
259 size_request=(600, 600), child=main_box)
260 self.window.on_destroyed(self.__exit_cb)
261 self.window.show_all()
265 self.window.show_all()
267 class NullClient(object):
269 # Sets initial parameters
270 self.core = purple.Purple(__NAME__, __VERSION__, __WEBSITE__, \
271 __DEV_WEBSITE__, debug_enabled=True, default_path='/tmp')
272 ecore.Timer(0.01, self.core.iterate_main_loop)
275 self.conversations = {}
276 self.protocol = purple.Protocol('prpl-jabber')
277 self.window = MainWindow()
279 # Adds libpurple core callbacks
282 self.core.add_callback('blist', 'update', \
283 self.__update_blist_cb)
285 # Updates connection progress
286 self.core.add_callback('connection', 'connect-progress', \
287 self.__connection_progress_cb)
289 # Activates when an account is connected
290 self.core.add_callback('connection', 'connected', \
293 # Activates when an account is disconnected
294 self.core.add_callback('connection', 'disconnected', \
295 self.__disconected_cb)
297 # Activates when a message is sent or received from conversation
298 self.core.add_callback('conversation', 'write-im', \
301 # Signal when account signed on
302 self.core.signal_connect('signed-on', self.__signed_on_cb)
304 # Signal when account signed off
305 self.core.signal_connect('signed-off', self.__signed_off_cb)
307 # Signal when buddy signed on
308 self.core.signal_connect('buddy-signed-on', self.__buddy_signed_on_cb)
310 # Signed when buddy signed off
311 self.core.signal_connect('buddy-signed-off', self.__buddy_signed_off_cb)
314 self.window.add_connection_button_cb(self.connect)
315 self.window.add_send_button_cb(self.send_message)
316 self.window.add_exit_cb(self.exit)
318 # Initializes libpurple
319 self.core.purple_init()
322 self.window.init_window()
324 def __update_blist_cb(self, type, name=None, alias=None):
325 if self.account and name and type == 2:
326 if name not in self.buddies:
327 self.buddies[name] = purple.Buddy(name, self.account)
328 if self.buddies[name].online:
329 self.window.add_buddy(name)
331 def __connection_progress_cb(self, text, step, step_count):
333 self.window.status.text = text
335 def __connected_cb(self, *data):
337 self.window.status.text = 'Connected'
339 def __disconected_cb():
341 self.window.status.text = 'Disconnected'
343 def __write_im_cb(self, username, name, alias, message, flags):
346 self.window.txt_area.text += username + ": " + message + "<br> "
348 self.window.txt_area.text += alias + ": " + message + "<br> "
350 self.window.txt_area.text += name + ": " + message + "<br> "
353 def __signed_on_cb(self, username, protocol_id):
355 self.window.txt_area += 'Signed on: %s (%s)' % (username, protocol_id)
358 def __signed_off_cb(self, username, protocol_id):
360 self.window.txt_area += 'Signed off: %s (%s)' % (username, protocol_id)
363 def __buddy_signed_on_cb(self, name, alias):
365 self.window.txt_area += 'Buddy signed on: %s (%s)' % (name, alias)
368 def __buddy_signed_off_cb(self, name, alias):
369 if name in self.buddies:
370 del self.buddies[name]
373 self.window.txt_area += 'Buddy signed off: %s (%s)' % (name, alias)
374 self.window.remove_buddy(name)
377 def connect(self, password):
378 username = self.window.get_selected_account()
379 if username and password:
380 self.account = purple.Account(username, self.protocol, self.core)
381 if not self.account.exists:
384 info['connect_server'] = 'talk.google.com'
386 info['old_ssl'] = True
387 self.account.set_protocol_options(info)
389 self.account.set_password(password)
390 self.account.set_enabled(True)
392 def send_message(self, name, message):
394 if name not in self.conversations:
395 self.conversations[name] = purple.Conversation('IM', self.account, name)
396 self.conversations[name].new()
398 self.conversations[name].im_send(message)
400 def exit(self, pointer):
401 ecore.main_loop_quit()
403 if __name__ == '__main__':
404 client = NullClient()
406 # Initializes ecore mainloop
407 ecore.main_loop_begin()