From: Bruno Abinader Date: Mon, 15 Dec 2008 16:56:51 +0000 (+0000) Subject: Updated nullclient-ecore. X-Git-Url: http://git.maemo.org/git/?p=python-purple;a=commitdiff_plain;h=89e1eede36a307e39a28834e52e78a14d12515be Updated nullclient-ecore. FIXES: - Updated nullclient-ecore.py example. Signed-off-by: Bruno Abinader Acked-by: Anderson Briglia git-svn-id: https://garage.maemo.org/svn/carman/branches/carman-0.7-beta2/python-purple@1716 596f6dd7-e928-0410-a184-9e12fd12cf7e --- diff --git a/README b/README index edef032..2cc9935 100644 --- a/README +++ b/README @@ -55,3 +55,26 @@ $ LD_PRELOAD=/usr/lib/libpurple.so.0 python2.5 nullclient.py It will ask for a username and then password. Insert it and it will automatically connect to the given account. + +There is also another example client (nullclient-ecore), which provides some +callback examples from libpurple interacting with UI. In order to execute it, +issue the following command: + +$ LD_PRELOAD=/usr/lib/libpurple.so.0 python2.5 nullclient-ecore.py + +An Etk-based window will pop up showing text windows, a command entry and +three buttons ('Send', 'Connect', 'Add account'). In order to test it, follow +the steps below: + +1. Click on 'Add account' button. A pop-up window appears, and you can enter +there a gmail-based account (e.g. jsmith@gmail.com). Click 'Ok' when done. + +2. Click on 'Connect' button. A pop-up window appears asking for account's +password. Click 'Ok' when done. + +Now wait for the account connection. When 'Connected' appears, your buddy +list gets updated. + +3. You are now connected! Select a buddy from buddy list, write a message on +the command entry and click 'Send'. Your message appears in the text box. +If your buddy replies, his/her message also gets shown in the text box. diff --git a/nullclient-ecore.py b/nullclient-ecore.py index 4691910..1f7d844 100644 --- a/nullclient-ecore.py +++ b/nullclient-ecore.py @@ -1,269 +1,402 @@ -#!/usr/bin/env python +# +# Copyright (c) 2008 INdT - Instituto Nokia de Tecnologia +# +# This file is part of python-purple. +# +# python-purple is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# python-purple is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# import etk import ecore import purple -#from xml.dom import minidom -class MainWindow: - def __init__(self, quit_cb): - self.bt_cbs = {} - self.new_acc_bt_cbs = {} - self.send_cbs = {} - self.quit_cb = quit_cb +# The information below is needed by libpurple +__NAME__ = "nullclient-ecore" +__VERSION__ = "0.1" +__WEBSITE__ = "N/A" +__DEV_WEBSITE__ = "N/A" - def init_window(self): - # Main vbox - vbox = etk.VBox(homogeneous=False) +class MainWindow(object): + def __init__(self): + # Connect button callback + self.__connect_button_cb = None - hbox_cmd = etk.HBox(homogeneous=False) - self.cmd_entry = etk.Entry() - self.lcmd = etk.Label(text="Type your message: ") - hbox_cmd.append(self.lcmd, etk.HBox.START, etk.HBox.START, 0) - hbox_cmd.append(self.cmd_entry, etk.HBox.START, etk.HBox.EXPAND_FILL, 0) + # Send button callback + self.__send_button_cb = None - vbox_accs = etk.VBox() - self.accslistmodel = etk.ListModel() - self.accslist = etk.List(model=self.accslistmodel,\ - columns=[(10, etk.TextRenderer(slot=0),\ - False)], selectable=True,\ - animated_changes=True) - vbox_accs.append(self.accslist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) - - hbox_buttons = etk.HBox(homogeneous=False) - send_bt = etk.Button(label="Send") - send_bt.on_clicked(self._send_bt_cb) - conn_bt = etk.Button(label="Connect") - conn_bt.on_clicked(self.login_window) - new_account_bt = etk.Button(label="New Account") - new_account_bt.on_clicked(self._new_account) - hbox_buttons.append(send_bt, etk.HBox.START, etk.HBox.NONE, 0) - hbox_buttons.append(conn_bt, etk.HBox.START, etk.HBox.NONE, 0) - hbox_buttons.append(new_account_bt, etk.HBox.START, etk.HBox.NONE, 0) - - hbox_panel = etk.HBox() - - vbox_buddies = etk.VBox() - self.blistmodel = etk.ListModel() - self.blist = etk.List(model=self.blistmodel,\ - columns=[(10, etk.TextRenderer(slot=0), False)],\ - selectable=True, animated_changes=True) - vbox_buddies.append(self.blist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + # New account callback + self.__new_account_cb = None - vbox_txt_area = etk.VBox() - self.txt_area = etk.Label() - self.txt_area.text = "
" + # Exit callback + self.__exit_cb = None - vbox_txt_area.append(self.txt_area, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + def __login_window_cb(self, pointer): + # Password entry + self.login_password = etk.Entry() - hbox_panel.append(vbox_txt_area, etk.HBox.START, etk.HBox.EXPAND_FILL, 0) - hbox_panel.append(vbox_buddies, etk.HBox.END, etk.HBox.EXPAND_FILL, 0) - hbox_panel.append(vbox_accs, etk.HBox.END, etk.HBox.EXPAND_FILL, 0) + # Confirm login button + confirm_login_bt = etk.Button(label='Ok') + confirm_login_bt.on_clicked(self.__connect_button_clicked) - self.lstatus = etk.Label(text="Connection status") + # Login VBox + vbox = etk.VBox() + vbox.append(self.login_password, etk.VBox.START, etk.VBox.FILL, 0) + vbox.append(confirm_login_bt, etk.VBox.END, etk.VBox.NONE, 0) - vbox.append(hbox_panel, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) - vbox.append(hbox_cmd, etk.VBox.END, etk.VBox.FILL, 0) - vbox.append(hbox_buttons, etk.VBox.END, etk.VBox.NONE, 5) - vbox.append(self.lstatus, etk.VBox.END, etk.VBox.FILL, 0) + # Login window + self.login_window = etk.Window(title='Password', \ + size_request=(190, 80), child=vbox) + self.login_window.show_all() - self._window = etk.Window(title="NullClient-Etk", size_request=(600, 600), child=vbox) - self._window.on_destroyed(self.quit_cb) - self._window.show_all() + def __connect_button_clicked(self, pointer): + # Call connection button callback + if self.__connect_button_cb: + self.__connect_button_cb(self.login_password.text) + self.login_window.destroy() - def login_window(self, pointer): - self.login_password = etk.Entry() - confirm_login_bt = etk.Button(label="Ok") - confirm_login_bt.on_clicked(self._conn_bt_cb) - vbox_login = etk.VBox() - vbox_login.append(self.login_password, etk.VBox.START, etk.VBox.FILL, 0) - vbox_login.append(confirm_login_bt, etk.VBox.END, etk.VBox.NONE, 0) - self.login_win = etk.Window(title="Password", size_request=(190, 80), - child=vbox_login) - self.login_win.show_all() - - def _conn_bt_cb(self, pointer): - if self.bt_cbs.has_key("on_clicked"): - self.bt_cbs["on_clicked"](self.login_password.text) - self.login_win.destroy() - - def _send_bt_cb(self, pointer): + def __send_button_clicked(self, pointer): + # Get selected buddy name from buddy list bname = self.blist.selected_rows[0][0] + + # Get message from command entry msg = self.cmd_entry.text - if bname and msg != "": - if self.send_cbs.has_key("on_clicked"): - self.send_cbs["on_clicked"](bname, msg) - else: - print "Buddy not selected!" - self.cmd_entry.text = "" - - def selected_accs(self): + + if bname and msg != '': + # Call send button callback + if self.__send_button_cb: + self.__send_button_cb(bname, msg) + + # Clear text from command entry + self.cmd_entry.text = '' + + def __new_account_button_clicked(self, pointer): + # Username entry + self.login_username = etk.Entry() + + # Confirm username button + confirm_username_bt = etk.Button(label='Ok') + confirm_username_bt.on_clicked(self.add_account) + + # Username VBox + vbox = etk.VBox() + vbox.append(self.login_username, etk.VBox.START, etk.VBox.FILL, 0) + vbox.append(confirm_username_bt, etk.VBox.END, etk.VBox.NONE, 0) + + # Username window + self.username_window = etk.Window(title='Username', \ + size_request=(190, 80), child=vbox) + self.username_window.show_all() + + def __create_accounts_list(self): + # Accounts list + self.accslistmodel = etk.ListModel() + self.accslist = etk.List(model=self.accslistmodel, \ + columns=[(10, etk.TextRenderer(slot=0), False)], \ + selectable=True, animated_changes=True) + + #Appending accounts list to VBox + vbox = etk.VBox() + vbox.append(self.accslist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + return vbox + + def __create_buddies_list(self): + # Buddies list + self.blistmodel = etk.ListModel() + self.blist = etk.List(model=self.blistmodel, \ + columns=[(10, etk.TextRenderer(slot=0), False)], \ + selectable=True, animated_changes=True) + + # Appending buddies list to VBox + vbox = etk.VBox() + vbox.append(self.blist, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + return vbox + + def __create_buttons_bar(self): + # Send button + send_button = etk.Button(label='Send') + send_button.on_clicked(self.__send_button_clicked) + + # Connect button + conn_button = etk.Button(label='Connect') + conn_button.on_clicked(self.__login_window_cb) + + # New account button + new_acc_button = etk.Button(label='New Account') + new_acc_button.on_clicked(self.__new_account_button_clicked) + + # Appending all buttons to HBox + hbox = etk.HBox(homogeneous=False) + hbox.append(send_button, etk.HBox.START, etk.HBox.NONE, 0) + hbox.append(conn_button, etk.HBox.START, etk.HBox.NONE, 0) + hbox.append(new_acc_button, etk.HBox.START, etk.HBox.NONE, 0) + return hbox + + def __create_command_entry_box(self): + # Command entry box + self.cmd_entry = etk.Entry() + self.cmd_label = etk.Label(text='Type your message: ') + + # appending command entry and label to HBox + hbox = etk.HBox(homogeneous=False) + hbox.append(self.cmd_label, etk.HBox.START, \ + etk.HBox.START, 0) + hbox.append(self.cmd_entry, etk.HBox.START, \ + etk.HBox.EXPAND_FILL, 0) + return hbox + + def __create_text_area(self): + # Text area (shows buddy messages) + self.txt_area = etk.Label() + self.txt_area.text = '
Nullclient-Ecore
' + + # Appending text area to VBox + vbox = etk.VBox() + vbox.append(self.txt_area, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + return vbox + + def __create_main_panel(self): + # Text box + txt_vbox = self.__create_text_area() + + # Buddies list + bdd_vbox = self.__create_buddies_list() + + # Accounts list + acc_vbox = self.__create_accounts_list() + + # Appending text area, buddies list and accounts list to HBox + hbox = etk.HBox() + hbox.append(txt_vbox, etk.HBox.START, etk.HBox.EXPAND_FILL, 0) + hbox.append(bdd_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0) + hbox.append(acc_vbox, etk.HBox.END, etk.HBox.EXPAND_FILL, 0) + return hbox + + def __create_main_box(self): + # Main panel + panel_hbox = self.__create_main_panel() + + # Command entry + cmd_hbox = self.__create_command_entry_box() + + # Buttons Bar + btn_hbox = self.__create_buttons_bar() + + # Connection status + self.status = etk.Label(text='Connection status') + + # Main VBox + vbox = etk.VBox(homogeneous=False) + vbox.append(panel_hbox, etk.VBox.START, etk.VBox.EXPAND_FILL, 0) + vbox.append(cmd_hbox, etk.VBox.END, etk.VBox.FILL, 0) + vbox.append(btn_hbox, etk.VBox.END, etk.VBox.NONE, 5) + vbox.append(self.status, etk.VBox.END, etk.VBox.FILL, 0) + return vbox + + def get_selected_account(self): + # Catch selected account from accounts list try: - acc = self.accslist.selected_rows[0][0] - if acc: - return acc + account = self.accslist.selected_rows[0][0] + if account: + return account else: return None except: return None - def _new_account(self, pointer): - if self.new_acc_bt_cbs.has_key("on_clicked"): - self.new_acc_bt_cbs["on_clicked"]() - - - def new_buddy(self, b): - if [b] not in self.blistmodel.elements: - self.blistmodel.append([b]) - - def remove_buddy(self, bname): - self.blistmodel.remove([bname]) + def add_buddy(self, name): + # Adds a new buddy into buddy list + if [name] not in self.blistmodel.elements: + self.blistmodel.append([name]) - def new_account(self, a): - if [a] not in self.accslistmodel.elements: - self.accslistmodel.append([a]) + def remove_buddy(self, name): + # Removes a buddy from buddy list + self.blistmodel.remove([name]) - def set_panel_text(self, txt): - self.txt_area = txt + def add_account(self, pointer): + # Adds a new account into accounts list + if [self.login_username.text] not in self.accslistmodel.elements: + self.accslistmodel.append([self.login_username.text]) + self.username_window.destroy() + self.window.show_all() - def add_bt_conn_cb(self, cb): + def add_connection_button_cb(self, cb): if callable(cb): - self.bt_cbs["on_clicked"] = cb + self.__connect_button_cb = cb - def add_account_cb(self, cb): + def add_new_account_cb(self, cb): if callable(cb): - self.new_acc_bt_cbs["on_clicked"] = cb + self.__new_account_cb = cb - def add_send_cb(self, cb): + def add_send_button_cb(self, cb): if callable(cb): - self.send_cbs["on_clicked"] = cb + self.__send_button_cb = cb - def add_quit_cb(self, cb): + def add_exit_cb(self, cb): if callable(cb): - self.quit_cb = cb + self.__exit_cb = cb + + def init_window(self): + # Main box + main_box = self.__create_main_box() + + # Main Window + self.window = etk.Window(title='Nullclient-Ecore', \ + size_request=(600, 600), child=main_box) + self.window.on_destroyed(self.__exit_cb) + self.window.show_all() def show(self): - if self._window: - self._window.show_all() + if self.window: + self.window.show_all() -class NullClientPurple(object): +class NullClient(object): def __init__(self): - self.purple = purple.Purple(debug_enabled=False) - self.window = MainWindow(self.quit) - self.buddies = {} #all buddies - self.conversations = {} - self.protocol_id = "prpl-jabber" + # Sets initial parameters + self.core = purple.Purple(__NAME__, __VERSION__, __WEBSITE__, \ + __DEV_WEBSITE__, debug_enabled=True, default_path='/tmp') self.account = None + self.buddies = {} + self.conversations = {} + self.protocol = purple.Protocol('prpl-jabber') + self.window = MainWindow() + + # Adds libpurple core callbacks + + # Updates buddy list + self.core.add_callback('blist', 'update', \ + self.__update_blist_cb) + + # Updates connection progress + self.core.add_callback('connection', 'connect-progress', \ + self.__connection_progress_cb) + + # Activates when an account is connected + self.core.add_callback('connection', 'connected', \ + self.__connected_cb) + + # Activates when an account is disconnected + self.core.add_callback('connection', 'disconnected', \ + self.__disconected_cb) + + # Activates when a message is sent or received from conversation + self.core.add_callback('conversation', 'write-im', \ + self.__write_im_cb) - self.purple.add_callback("blist", "update", self.__purple_update_blist_cb) - self.purple.add_callback("connection", "connect-progress", self.__purple_conn_progress_cb) - self.purple.add_callback("connection", "connected", self.__purple_connected_cb) - self.purple.add_callback("connection", "disconnected", self.__purple_disconnected_cb) - self.purple.add_callback("conversation", "write-im", self.__purple_write_im_cb) + # Signal when account signed on + self.core.signal_connect('signed-on', self.__signed_on_cb) - self.purple.purple_init() + # Signal when account signed off + self.core.signal_connect('signed-off', self.__signed_off_cb) - #Initializing UI - self.window.add_bt_conn_cb(self.connect) - self.window.add_send_cb(self.send_msg) - self.window.add_account_cb(self.add_account) + # Signal when buddy signed on + self.core.signal_connect('buddy-signed-on', self.__buddy_signed_on_cb) + + # Signed when buddy signed off + self.core.signal_connect('buddy-signed-off', self.__buddy_signed_off_cb) + + # Adds UI callbacks + self.window.add_connection_button_cb(self.connect) + self.window.add_send_button_cb(self.send_message) + self.window.add_exit_cb(self.exit) + + # Initializes libpurple + self.core.purple_init() + + # Initializes UI self.window.init_window() - def __purple_update_blist_cb(self, type, name=None, alias=None, \ - totalsize=None, currentsize=None, \ - online=None): - if self.account and name != None and type == 2: + def __update_blist_cb(self, type, name=None, alias=None): + if self.account and name and type == 2: if not self.buddies.has_key(name): - b = purple.Buddy() - b.new_buddy(self.account, name, alias) - self.buddies[name] = b - elif self.buddies[name].online: - self.window.new_buddy(name) + self.buddies[name] = purple.Buddy(name, self.account) + if self.buddies[name].online: + self.window.add_buddy(name) - def __purple_conn_progress_cb(self, text, step, step_count): + def __connection_progress_cb(self, text, step, step_count): if self.window: - self.window.lstatus.text = text + self.window.status.text = text - def __purple_connected_cb(self, *data): + def __connected_cb(self, *data): if self.window: - self.window.lstatus.text = "Connected" + self.window.status.text = 'Connected' - def __purple_disconnected_cb(self, *data): + def __disconected_cb(): if self.window: - self.window.lstatus.text = "Disconnected" + self.window.status.text = 'Disconnected' - def __purple_write_im_cb(self, username, name, alias, message): + def __write_im_cb(self, username, name, alias, message, flags): if self.window: - if alias: + if 'SEND' == flags: + self.window.txt_area.text += username + ": " + message + "
" + elif alias: self.window.txt_area.text += alias + ": " + message + "
" else: self.window.txt_area.text += name + ": " + message + "
" self.window.show() - def __purple_signal_signed_on_cb(self, username, protocol_id): - print "[DEBUG] Signed on: %s %s" % (username, protocol_id) + def __signed_on_cb(self, username, protocol_id): + if self.window: + self.window.txt_area += 'Signed on: %s (%s)' % (username, protocol_id) + self.window.show() - def __purple_signal_signed_off_cb(self, username, protocol_id): - print "[DEBUG] Signed off: %s %s" % (username, protocol_id) + def __signed_off_cb(self, username, protocol_id): + if self.window: + self.window.txt_area += 'Signed off: %s (%s)' % (username, protocol_id) + self.window.show() - def __purple_signal_buddy_signed_on_cb(self, name, alias): - print "[DEBUG]: Buddy signed on: %s %s" % (name, alias) + def __buddy_signed_on_cb(self, name, alias): + if self.window: + self.window.txt_area += 'Buddy signed on: %s (%s)' % (name, alias) + self.window.show() - def __purple_signal_buddy_signed_off_cb(self, name, alias): + def __buddy_signed_off_cb(self, name, alias): if self.buddies.has_key(name): - self.buddies[name] = None - self.buddies.pop(name) - print "[DEBUG]: Buddy signed off: %s %s" % (name, alias) - self.window.remove_buddy(name) - - """ - def __purple_signal_jabber_receiving_xmlnode_cb(self, message): - xml = minidom.parse(message) - for msg in xml.getElementsByTagName("message"): - who = msg.getAttribute("from") - for geoloc in msg.getElementsByTagNameNS("http://jabber.org/protocol/geoloc", "geoloc"): - lat = geoloc.getElementsByTagName("lat")[0].childNodes[0].nodeValue - lon = geoloc.getElementsByTagName("lon")[0].childNodes[0].nodeValue - print "who: %s lat: %s lon: %s" % (who, lat, lon) - """ - - def add_account(self): - username = "carmanplugintest@gmail.com" - host = "172.18.216.211" - port = 8080 - self.purple.account_add(username, self.protocol_id, host, port) - for account in self.purple.accounts.keys(): - self.window.new_account(account) + del self.buddies[name] + + if self.window: + self.window.txt_area += 'Buddy signed off: %s (%s)' % (name, alias) + self.window.remove_buddy(name) + self.window.show() def connect(self, password): - username_acc = self.window.selected_accs() - if username_acc: - self.account = self.purple.account_verify(username_acc) - self.account.get_protocol_options() - self.account.set_enabled("carman-purple-python", True) - self.account.password = password - self.purple.signal_connect("signed-on", self.__purple_signal_signed_on_cb) - self.purple.signal_connect("signed-off", self.__purple_signal_signed_off_cb) - self.purple.signal_connect("buddy-signed-on", self.__purple_signal_buddy_signed_on_cb) - self.purple.signal_connect("buddy-signed-off", self.__purple_signal_buddy_signed_off_cb) - #self.purple.signal_connect("jabber-receiving-xmlnode", self.__purple_signal_jabber_receiving_xmlnode_cb) - - def send_msg(self, name, msg): + username = self.window.get_selected_account() + if username and password: + self.account = purple.Account(username, self.protocol, self.core) + if not self.account.exists: + self.account.new() + info = {} + info['connect_server'] = 'talk.google.com' + info['port'] = '443' + info['old_ssl'] = True + self.account.set_protocol_options(info) + + self.account.set_password(password) + self.account.set_enabled(True) + + def send_message(self, name, message): + print name, message if not self.conversations.has_key(name): - conv = purple.Conversation() - conv.initialize(self.account, "IM", name) - self.conversations[name] = conv - self.conversations[name].write(msg) - - def quit(self, o): - print "[DEBUG]: quitting" - for i in self.conversations: - self.conversations[i].destroy() - self.conversations[i] = None - self.conversations = None - self.purple.destroy() + self.conversations[name] = purple.Conversation('IM', self.account, name) + self.conversations[name].new() + + self.conversations[name].im_send(message) + + def exit(self, pointer): ecore.main_loop_quit() if __name__ == '__main__': - nullpurple = NullClientPurple() + client = NullClient() + + # Initializes ecore mainloop ecore.main_loop_begin()