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 # The information below is needed by libpurple
25 __NAME__ = "nullclient-ecore"
28 __DEV_WEBSITE__ = "N/A"
30 class MainWindow(object):
32 # Connect button callback
33 self.__connect_button_cb = None
35 # Send button callback
36 self.__send_button_cb = None
38 # New account callback
39 self.__new_account_cb = None
44 def __login_window_cb(self, pointer):
46 self.login_password = etk.Entry()
48 # Confirm login button
49 confirm_login_bt = etk.Button(label='Ok')
50 confirm_login_bt.on_clicked(self.__connect_button_clicked)
54 vbox.append(self.login_password, etk.VBox.START, etk.VBox.FILL, 0)
55 vbox.append(confirm_login_bt, etk.VBox.END, etk.VBox.NONE, 0)
58 self.login_window = etk.Window(title='Password', \
59 size_request=(190, 80), child=vbox)
60 self.login_window.show_all()
62 def __connect_button_clicked(self, pointer):
63 # Call connection button callback
64 if self.__connect_button_cb:
65 self.__connect_button_cb(self.login_password.text)
66 self.login_window.destroy()
68 def __send_button_clicked(self, pointer):
69 # Get selected buddy name from buddy list
70 bname = self.blist.selected_rows[0][0]
72 # Get message from command entry
73 msg = self.cmd_entry.text
75 if bname and msg != '':
76 # Call send button callback
77 if self.__send_button_cb:
78 self.__send_button_cb(bname, msg)
80 # Clear text from command entry
81 self.cmd_entry.text = ''
83 def __new_account_button_clicked(self, pointer):
85 self.login_username = etk.Entry()
87 # Confirm username button
88 confirm_username_bt = etk.Button(label='Ok')
89 confirm_username_bt.on_clicked(self.add_account)
93 vbox.append(self.login_username, etk.VBox.START, etk.VBox.FILL, 0)
94 vbox.append(confirm_username_bt, etk.VBox.END, etk.VBox.NONE, 0)
97 self.username_window = etk.Window(title='Username', \
98 size_request=(190, 80), child=vbox)
99 self.username_window.show_all()
101 def __create_accounts_list(self):
103 self.accslistmodel = etk.ListModel()
104 self.accslist = etk.List(model=self.accslistmodel, \
105 columns=[(10, etk.TextRenderer(slot=0), False)], \
106 selectable=True, animated_changes=True)
108 #Appending accounts list to VBox
110 vbox.append(self.accslist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
113 def __create_buddies_list(self):
115 self.blistmodel = etk.ListModel()
116 self.blist = etk.List(model=self.blistmodel, \
117 columns=[(10, etk.TextRenderer(slot=0), False)], \
118 selectable=True, animated_changes=True)
120 # Appending buddies list to VBox
122 vbox.append(self.blist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
125 def __create_buttons_bar(self):
127 send_button = etk.Button(label='Send')
128 send_button.on_clicked(self.__send_button_clicked)
131 conn_button = etk.Button(label='Connect')
132 conn_button.on_clicked(self.__login_window_cb)
135 new_acc_button = etk.Button(label='New Account')
136 new_acc_button.on_clicked(self.__new_account_button_clicked)
138 # Appending all buttons to HBox
139 hbox = etk.HBox(homogeneous=False)
140 hbox.append(send_button, etk.HBox.START, etk.HBox.NONE, 0)
141 hbox.append(conn_button, etk.HBox.START, etk.HBox.NONE, 0)
142 hbox.append(new_acc_button, etk.HBox.START, etk.HBox.NONE, 0)
145 def __create_command_entry_box(self):
147 self.cmd_entry = etk.Entry()
148 self.cmd_label = etk.Label(text='Type your message: ')
150 # appending command entry and label to HBox
151 hbox = etk.HBox(homogeneous=False)
152 hbox.append(self.cmd_label, etk.HBox.START, \
154 hbox.append(self.cmd_entry, etk.HBox.START, \
155 etk.HBox.EXPAND_FILL, 0)
158 def __create_text_area(self):
159 # Text area (shows buddy messages)
160 self.txt_area = etk.Label()
161 self.txt_area.text = '<br>Nullclient-Ecore<br> '
163 # Appending text area to VBox
165 vbox.append(self.txt_area, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
168 def __create_main_panel(self):
170 txt_vbox = self.__create_text_area()
173 bdd_vbox = self.__create_buddies_list()
176 acc_vbox = self.__create_accounts_list()
178 # Appending text area, buddies list and accounts list to HBox
180 hbox.append(txt_vbox, etk.HBox.START, etk.HBox.EXPAND_FILL, 0)
181 hbox.append(bdd_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0)
182 hbox.append(acc_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0)
185 def __create_main_box(self):
187 panel_hbox = self.__create_main_panel()
190 cmd_hbox = self.__create_command_entry_box()
193 btn_hbox = self.__create_buttons_bar()
196 self.status = etk.Label(text='Connection status')
199 vbox = etk.VBox(homogeneous=False)
200 vbox.append(panel_hbox, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
201 vbox.append(cmd_hbox, etk.VBox.END, etk.VBox.FILL, 0)
202 vbox.append(btn_hbox, etk.VBox.END, etk.VBox.NONE, 5)
203 vbox.append(self.status, etk.VBox.END, etk.VBox.FILL, 0)
206 def get_selected_account(self):
207 # Catch selected account from accounts list
209 account = self.accslist.selected_rows[0][0]
217 def add_buddy(self, name):
218 # Adds a new buddy into buddy list
219 if [name] not in self.blistmodel.elements:
220 self.blistmodel.append([name])
222 def remove_buddy(self, name):
223 # Removes a buddy from buddy list
224 self.blistmodel.remove([name])
226 def add_account(self, pointer):
227 # Adds a new account into accounts list
228 if [self.login_username.text] not in self.accslistmodel.elements:
229 self.accslistmodel.append([self.login_username.text])
230 self.username_window.destroy()
231 self.window.show_all()
233 def add_connection_button_cb(self, cb):
235 self.__connect_button_cb = cb
237 def add_new_account_cb(self, cb):
239 self.__new_account_cb = cb
241 def add_send_button_cb(self, cb):
243 self.__send_button_cb = cb
245 def add_exit_cb(self, cb):
249 def init_window(self):
251 main_box = self.__create_main_box()
254 self.window = etk.Window(title='Nullclient-Ecore', \
255 size_request=(600, 600), child=main_box)
256 self.window.on_destroyed(self.__exit_cb)
257 self.window.show_all()
261 self.window.show_all()
263 class NullClient(object):
265 # Sets initial parameters
266 self.core = purple.Purple(__NAME__, __VERSION__, __WEBSITE__, \
267 __DEV_WEBSITE__, debug_enabled=True, default_path='/tmp')
270 self.conversations = {}
271 self.protocol = purple.Protocol('prpl-jabber')
272 self.window = MainWindow()
274 # Adds libpurple core callbacks
277 self.core.add_callback('blist', 'update', \
278 self.__update_blist_cb)
280 # Updates connection progress
281 self.core.add_callback('connection', 'connect-progress', \
282 self.__connection_progress_cb)
284 # Activates when an account is connected
285 self.core.add_callback('connection', 'connected', \
288 # Activates when an account is disconnected
289 self.core.add_callback('connection', 'disconnected', \
290 self.__disconected_cb)
292 # Activates when a message is sent or received from conversation
293 self.core.add_callback('conversation', 'write-im', \
296 # Signal when account signed on
297 self.core.signal_connect('signed-on', self.__signed_on_cb)
299 # Signal when account signed off
300 self.core.signal_connect('signed-off', self.__signed_off_cb)
302 # Signal when buddy signed on
303 self.core.signal_connect('buddy-signed-on', self.__buddy_signed_on_cb)
305 # Signed when buddy signed off
306 self.core.signal_connect('buddy-signed-off', self.__buddy_signed_off_cb)
309 self.window.add_connection_button_cb(self.connect)
310 self.window.add_send_button_cb(self.send_message)
311 self.window.add_exit_cb(self.exit)
313 # Initializes libpurple
314 self.core.purple_init()
317 self.window.init_window()
319 def __update_blist_cb(self, type, name=None, alias=None):
320 if self.account and name and type == 2:
321 if name not in self.buddies:
322 self.buddies[name] = purple.Buddy(name, self.account)
323 if self.buddies[name].online:
324 self.window.add_buddy(name)
326 def __connection_progress_cb(self, text, step, step_count):
328 self.window.status.text = text
330 def __connected_cb(self, *data):
332 self.window.status.text = 'Connected'
334 def __disconected_cb():
336 self.window.status.text = 'Disconnected'
338 def __write_im_cb(self, username, name, alias, message, flags):
341 self.window.txt_area.text += username + ": " + message + "<br> "
343 self.window.txt_area.text += alias + ": " + message + "<br> "
345 self.window.txt_area.text += name + ": " + message + "<br> "
348 def __signed_on_cb(self, username, protocol_id):
350 self.window.txt_area += 'Signed on: %s (%s)' % (username, protocol_id)
353 def __signed_off_cb(self, username, protocol_id):
355 self.window.txt_area += 'Signed off: %s (%s)' % (username, protocol_id)
358 def __buddy_signed_on_cb(self, name, alias):
360 self.window.txt_area += 'Buddy signed on: %s (%s)' % (name, alias)
363 def __buddy_signed_off_cb(self, name, alias):
364 if name in self.buddies:
365 del self.buddies[name]
368 self.window.txt_area += 'Buddy signed off: %s (%s)' % (name, alias)
369 self.window.remove_buddy(name)
372 def connect(self, password):
373 username = self.window.get_selected_account()
374 if username and password:
375 self.account = purple.Account(username, self.protocol, self.core)
376 if not self.account.exists:
379 info['connect_server'] = 'talk.google.com'
381 info['old_ssl'] = True
382 self.account.set_protocol_options(info)
384 self.account.set_password(password)
385 self.account.set_enabled(True)
387 def send_message(self, name, message):
389 if name not in self.conversations:
390 self.conversations[name] = purple.Conversation('IM', self.account, name)
391 self.conversations[name].new()
393 self.conversations[name].im_send(message)
395 def exit(self, pointer):
396 ecore.main_loop_quit()
398 if __name__ == '__main__':
399 client = NullClient()
401 # Initializes ecore mainloop
402 ecore.main_loop_begin()