diff --git a/chat/BuddyList.py b/chat/BuddyList.py index 9bc63bad..7bf2e4ec 100644 --- a/chat/BuddyList.py +++ b/chat/BuddyList.py @@ -53,6 +53,8 @@ class BuddyList(object): self._buddies = {} self._pdiscovery = presence.PresenceDiscovery() self._pdiscovery.add_service_listener(self._on_service_change) + + def start(self): self._pdiscovery.start() def add_buddy_listener(self, listener): diff --git a/chat/SimpleGladeApp.py b/chat/SimpleGladeApp.py deleted file mode 100644 index 90c598cc..00000000 --- a/chat/SimpleGladeApp.py +++ /dev/null @@ -1,341 +0,0 @@ -""" - SimpleGladeApp.py - Module that provides an object oriented abstraction to pygtk and libglade. - Copyright (C) 2004 Sandino Flores Moreno -""" - -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -import os -import sys -import re - -import tokenize -import gtk -import gtk.glade -import weakref -import inspect - -__version__ = "1.0" -__author__ = 'Sandino "tigrux" Flores-Moreno' - -def bindtextdomain(app_name, locale_dir=None): - """ - Bind the domain represented by app_name to the locale directory locale_dir. - It has the effect of loading translations, enabling applications for different - languages. - - app_name: - a domain to look for translations, tipically the name of an application. - - locale_dir: - a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo - If omitted or None, then the current binding for app_name is used. - """ - try: - import locale - import gettext - locale.setlocale(locale.LC_ALL, "") - gtk.glade.bindtextdomain(app_name, locale_dir) - gettext.install(app_name, locale_dir, unicode=1) - except (IOError,locale.Error), e: - print "Warning", app_name, e - __builtins__.__dict__["_"] = lambda x : x - - -class SimpleGladeApp: - - def __init__(self, path, root=None, domain=None, **kwargs): - """ - Load a glade file specified by glade_filename, using root as - root widget and domain as the domain for translations. - - If it receives extra named arguments (argname=value), then they are used - as attributes of the instance. - - path: - path to a glade filename. - If glade_filename cannot be found, then it will be searched in the - same directory of the program (sys.argv[0]) - - root: - the name of the widget that is the root of the user interface, - usually a window or dialog (a top level widget). - If None or ommited, the full user interface is loaded. - - domain: - A domain to use for loading translations. - If None or ommited, no translation is loaded. - - **kwargs: - a dictionary representing the named extra arguments. - It is useful to set attributes of new instances, for example: - glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value") - sets two attributes (foo and bar) to glade_app. - """ - if os.path.isfile(path): - self.glade_path = path - else: - glade_dir = os.path.dirname( sys.argv[0] ) - self.glade_path = os.path.join(glade_dir, path) - for key, value in kwargs.items(): - try: - setattr(self, key, weakref.proxy(value) ) - except TypeError: - setattr(self, key, value) - self.glade = None - self.install_custom_handler(self.custom_handler) - self.glade = self.create_glade(self.glade_path, root, domain) - if root: - self.main_widget = self.get_widget(root) - else: - self.main_widget = None - self.normalize_names() - self.add_callbacks(self) - self.new() - - def __repr__(self): - class_name = self.__class__.__name__ - if self.main_widget: - root = gtk.Widget.get_name(self.main_widget) - repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root) - else: - repr = '%s(path="%s")' % (class_name, self.glade_path) - return repr - - def new(self): - """ - Method called when the user interface is loaded and ready to be used. - At this moment, the widgets are loaded and can be refered as self.widget_name - """ - pass - - def add_callbacks(self, callbacks_proxy): - """ - It uses the methods of callbacks_proxy as callbacks. - The callbacks are specified by using: - Properties window -> Signals tab - in glade-2 (or any other gui designer like gazpacho). - - Methods of classes inheriting from SimpleGladeApp are used as - callbacks automatically. - - callbacks_proxy: - an instance with methods as code of callbacks. - It means it has methods like on_button1_clicked, on_entry1_activate, etc. - """ - self.glade.signal_autoconnect(callbacks_proxy) - - def normalize_names(self): - """ - It is internally used to normalize the name of the widgets. - It means a widget named foo:vbox-dialog in glade - is refered self.vbox_dialog in the code. - - It also sets a data "prefixes" with the list of - prefixes a widget has for each widget. - """ - for widget in self.get_widgets(): - widget_name = gtk.Widget.get_name(widget) - prefixes_name_l = widget_name.split(":") - prefixes = prefixes_name_l[ : -1] - widget_api_name = prefixes_name_l[-1] - widget_api_name = "_".join( re.findall(tokenize.Name, widget_api_name) ) - gtk.Widget.set_name(widget, widget_api_name) - if hasattr(self, widget_api_name): - raise AttributeError("instance %s already has an attribute %s" % (self,widget_api_name)) - else: - setattr(self, widget_api_name, widget) - if prefixes: - gtk.Widget.set_data(widget, "prefixes", prefixes) - - def add_prefix_actions(self, prefix_actions_proxy): - """ - By using a gui designer (glade-2, gazpacho, etc) - widgets can have a prefix in theirs names - like foo:entry1 or foo:label3 - It means entry1 and label3 has a prefix action named foo. - - Then, prefix_actions_proxy must have a method named prefix_foo which - is called everytime a widget with prefix foo is found, using the found widget - as argument. - - prefix_actions_proxy: - An instance with methods as prefix actions. - It means it has methods like prefix_foo, prefix_bar, etc. - """ - prefix_s = "prefix_" - prefix_pos = len(prefix_s) - - is_method = lambda t : callable( t[1] ) - is_prefix_action = lambda t : t[0].startswith(prefix_s) - drop_prefix = lambda (k,w): (k[prefix_pos:],w) - - members_t = inspect.getmembers(prefix_actions_proxy) - methods_t = filter(is_method, members_t) - prefix_actions_t = filter(is_prefix_action, methods_t) - prefix_actions_d = dict( map(drop_prefix, prefix_actions_t) ) - - for widget in self.get_widgets(): - prefixes = gtk.Widget.get_data(widget, "prefixes") - if prefixes: - for prefix in prefixes: - if prefix in prefix_actions_d: - prefix_action = prefix_actions_d[prefix] - prefix_action(widget) - - def custom_handler(self, - glade, function_name, widget_name, - str1, str2, int1, int2): - """ - Generic handler for creating custom widgets, internally used to - enable custom widgets (custom widgets of glade). - - The custom widgets have a creation function specified in design time. - Those creation functions are always called with str1,str2,int1,int2 as - arguments, that are values specified in design time. - - Methods of classes inheriting from SimpleGladeApp are used as - creation functions automatically. - - If a custom widget has create_foo as creation function, then the - method named create_foo is called with str1,str2,int1,int2 as arguments. - """ - try: - handler = getattr(self, function_name) - return handler(str1, str2, int1, int2) - except AttributeError: - return None - - def gtk_widget_show(self, widget, *args): - """ - Predefined callback. - The widget is showed. - Equivalent to widget.show() - """ - widget.show() - - def gtk_widget_hide(self, widget, *args): - """ - Predefined callback. - The widget is hidden. - Equivalent to widget.hide() - """ - widget.hide() - - def gtk_widget_grab_focus(self, widget, *args): - """ - Predefined callback. - The widget grabs the focus. - Equivalent to widget.grab_focus() - """ - widget.grab_focus() - - def gtk_widget_destroy(self, widget, *args): - """ - Predefined callback. - The widget is destroyed. - Equivalent to widget.destroy() - """ - widget.destroy() - - def gtk_window_activate_default(self, window, *args): - """ - Predefined callback. - The default widget of the window is activated. - Equivalent to window.activate_default() - """ - widget.activate_default() - - def gtk_true(self, *args): - """ - Predefined callback. - Equivalent to return True in a callback. - Useful for stopping propagation of signals. - """ - return True - - def gtk_false(self, *args): - """ - Predefined callback. - Equivalent to return False in a callback. - """ - return False - - def gtk_main_quit(self, *args): - """ - Predefined callback. - Equivalent to self.quit() - """ - self.quit() - - def main(self): - """ - Starts the main loop of processing events. - The default implementation calls gtk.main() - - Useful for applications that needs a non gtk main loop. - For example, applications based on gstreamer needs to override - this method with gst.main() - - Do not directly call this method in your programs. - Use the method run() instead. - """ - gtk.main() - - def quit(self): - """ - Quit processing events. - The default implementation calls gtk.main_quit() - - Useful for applications that needs a non gtk main loop. - For example, applications based on gstreamer needs to override - this method with gst.main_quit() - """ - gtk.main_quit() - - def run(self): - """ - Starts the main loop of processing events checking for Control-C. - - The default implementation checks wheter a Control-C is pressed, - then calls on_keyboard_interrupt(). - - Use this method for starting programs. - """ - try: - self.main() - except KeyboardInterrupt: - self.on_keyboard_interrupt() - - def on_keyboard_interrupt(self): - """ - This method is called by the default implementation of run() - after a program is finished by pressing Control-C. - """ - pass - - def install_custom_handler(self, custom_handler): - gtk.glade.set_custom_handler(custom_handler) - - def create_glade(self, glade_path, root, domain): - return gtk.glade.XML(self.glade_path, root, domain) - - def get_widget(self, widget_name): - return self.glade.get_widget(widget_name) - - def get_widgets(self): - return self.glade.get_widget_prefix("") diff --git a/chat/chat.glade b/chat/chat.glade index 1058c232..eda4612b 100644 --- a/chat/chat.glade +++ b/chat/chat.glade @@ -22,7 +22,7 @@ False - + True 2 2 diff --git a/chat/main.py b/chat/chat.py similarity index 54% rename from chat/main.py rename to chat/chat.py index e22a13af..b014ee26 100755 --- a/chat/main.py +++ b/chat/chat.py @@ -1,18 +1,27 @@ #!/usr/bin/python -t # -*- tab-width: 4; indent-tabs-mode: t -*- -import os, sys, pwd -sys.path.append(os.getcwd()) +import dbus +import dbus.service +import dbus.glib + +import pygtk +pygtk.require('2.0') import gtk, gobject +import gtk.glade + +import sys +import os +import pwd +import gc + +sys.path.append(os.getcwd()) +sys.path.append('../shell/example-activity/') +import activity -from SimpleGladeApp import SimpleGladeApp import presence -import network -import avahi import BuddyList - -glade_dir = os.getcwd() - +import network class Chat(object): def __init__(self, view, label): @@ -29,7 +38,6 @@ class Chat(object): self._buffer.insert(aniter, buddy.nick() + ": " + msg + "\n") - class GroupChat(Chat): def __init__(self, parent, view, label): Chat.__init__(self, view, label) @@ -50,18 +58,71 @@ class GroupChat(Chat): if buddy: self.recv_message(buddy, msg['data']) - -class ChatApp(SimpleGladeApp): - def __init__(self, glade_file="chat.glade", root="mainWindow", domain=None, **kwargs): +class ChatActivity(activity.Activity): + def __init__(self): + activity.Activity.__init__(self) + self._act_name = "Chat" self._pannounce = presence.PresenceAnnounce() self._buddy_list = BuddyList.BuddyList() self._buddy_list.add_buddy_listener(self._on_buddy_presence_event) (self._nick, self._realname) = self._get_name() - path = os.path.join(glade_dir, glade_file) - gtk.window_set_default_icon_name("config-users") - SimpleGladeApp.__init__(self, path, root, domain, **kwargs) + self._glade = gtk.glade.XML("chat.glade", "mainTable", None) + + def _ui_setup(self, plug): + self._buddy_list_model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + self._buddy_list_view = self._glade.get_widget("buddyListView") + self._buddy_list_view.set_model(self._buddy_list_model) + self._buddy_list_view.connect("cursor-changed", self._on_buddyList_buddy_selected) + self._buddy_list_view.connect("row-activated", self._on_buddyList_buddy_double_clicked) + + self._entry = self._glade.get_widget("entry") + self._entry.connect("activate", self._send_chat_message) + + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn("", renderer, text=0) + column.set_resizable(True) + column.set_sizing("GTK_TREE_VIEW_COLUMN_GROW_ONLY"); + column.set_expand(True); + self._buddy_list_view.append_column(column) + + self._chat_view = self._glade.get_widget("chatView") + self._chat_label = self._glade.get_widget("chatLabel") + self._group_chat = GroupChat(self, self._chat_view, self._chat_label) + aniter = self._buddy_list_model.append(None) + self._buddy_list_model.set(aniter, 0, "Group", 1, None) + self._group_chat.activate() + plug.add(self._glade.get_widget("mainTable")) + + def _start(self): + self._buddy_list.start() + self._pannounce.register_service(self._realname, 6666, presence.OLPC_CHAT_SERVICE, + name = self._nick, realname = self._realname) + + def activity_on_connected_to_shell(self): + print "act %d: in activity_on_connected_to_shell" % self.activity_get_id() + self.activity_set_tab_text(self._act_name) + self._plug = self.activity_get_gtk_plug() + self._ui_setup(self._plug) + self._plug.show_all() + self._start() + + def activity_on_disconnected_from_shell(self): + print "act %d: in activity_on_disconnected_from_shell"%self.activity_get_id() + print "act %d: Shell disappeared..."%self.activity_get_id() + + gc.collect() + + def activity_on_close_from_user(self): + print "act %d: in activity_on_close_from_user"%self.activity_get_id() + self.activity_shutdown() + + def activity_on_lost_focus(self): + print "act %d: in activity_on_lost_focus"%self.activity_get_id() + + def activity_on_got_focus(self): + print "act %d: in activity_on_got_focus"%self.activity_get_id() def _get_name(self): ent = pwd.getpwuid(os.getuid()) @@ -75,14 +136,14 @@ class ChatApp(SimpleGladeApp): def _on_buddyList_buddy_selected(self, widget, *args): (model, aniter) = widget.get_selection().get_selected() - name = self.treemodel.get(aniter,0) + name = self._buddy_list_model.get(aniter,0) print "Selected %s" % name def _on_buddyList_buddy_double_clicked(self, widget, *args): """ Select the chat for this buddy or group """ (model, aniter) = widget.get_selection().get_selected() chat = None - buddy = self.treemodel.get_value(aniter, 1) + buddy = self._buddy_list_model.get_value(aniter, 1) if not buddy: chat = self._group_chat else: @@ -96,12 +157,12 @@ class ChatApp(SimpleGladeApp): def _on_buddy_presence_event(self, action, buddy): if action == BuddyList.ACTION_BUDDY_ADDED: - aniter = self.treemodel.append(None) - self.treemodel.set(aniter, 0, buddy.nick(), 1, buddy) + aniter = self._buddy_list_model.append(None) + self._buddy_list_model.set(aniter, 0, buddy.nick(), 1, buddy) elif action == BuddyList.ACCTION_BUDDY_REMOVED: - aniter = self.treemodel.get_iter(buddy.nick()) + aniter = self._buddy_list_model.get_iter(buddy.nick()) if aniter: - self.treemodel.remove(iter) + self._buddy_list_model.remove(iter) def find_buddy_by_address(self, address): return self._buddy_list.find_buddy_by_address(address) @@ -110,7 +171,7 @@ class ChatApp(SimpleGladeApp): self.quit() def _get_current_chat(self): - selection = self.buddyListView.get_selection() + selection = self._buddy_list_view.get_selection() (model, aniter) = selection.get_selected() buddy = model.get_value(aniter, 1) if not buddy: @@ -123,36 +184,13 @@ class ChatApp(SimpleGladeApp): chat.send_message(text) widget.set_text("") - def new(self): - self.treemodel = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) - self.buddyListView.set_model(self.treemodel) - self.buddyListView.connect("cursor-changed", self._on_buddyList_buddy_selected) - self.buddyListView.connect("row-activated", self._on_buddyList_buddy_double_clicked) - self.mainWindow.connect("delete-event", self._on_main_window_delete) - self.entry.connect("activate", self._send_chat_message) - - renderer = gtk.CellRendererText() - column = gtk.TreeViewColumn("", renderer, text=0) - column.set_resizable(True) - column.set_sizing("GTK_TREE_VIEW_COLUMN_GROW_ONLY"); - column.set_expand(True); - self.buddyListView.append_column(column) - - self._group_chat = GroupChat(self, self.chatView, self.chatLabel) - aniter = self.treemodel.append(None) - self.treemodel.set(aniter, 0, "Group", 1, None) - self._group_chat.activate() - - self._pannounce.register_service(self._realname, 6666, presence.OLPC_CHAT_SERVICE, - name = self._nick, realname = self._realname) - - def cleanup(self): - pass + def run(self): + gtk.main() def main(): - app = ChatApp() + app = ChatActivity() + app.activity_connect_to_shell() app.run() - app.cleanup() if __name__ == "__main__": main()