]> git.meshlink.io Git - catta/commitdiff
Move SimpleGladeApp.py into avahi-discover, so that avahi-python doesn't need to...
authorSjoerd Simons <sjoerd@debian.org>
Sun, 23 Sep 2007 18:47:13 +0000 (18:47 +0000)
committerSjoerd Simons <sjoerd@debian.org>
Sun, 23 Sep 2007 18:47:13 +0000 (18:47 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@1539 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

avahi-python/Makefile.am
avahi-python/avahi-discover.desktop.in [deleted file]
avahi-python/avahi-discover.in [deleted file]
avahi-python/avahi-discover/Makefile.am [new file with mode: 0644]
avahi-python/avahi-discover/SimpleGladeApp.py [new file with mode: 0644]
avahi-python/avahi-discover/__init__.py [new file with mode: 0755]
avahi-python/avahi-discover/avahi-discover.desktop.in [new file with mode: 0644]
avahi-python/avahi-discover/avahi-discover.in [new file with mode: 0755]
avahi-python/avahi/Makefile.am
avahi-python/avahi/SimpleGladeApp.py [deleted file]
configure.ac

index d59b19f310e9df4a6fcd18dba62d3984a7f7ab51..09ad6de6f736a274b16a1a5f9c13ab767289e9c6 100644 (file)
@@ -23,11 +23,9 @@ AM_CFLAGS=-I$(top_srcdir)
 AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
 
 EXTRA_DIST = \
-       avahi-bookmarks.in \
-       avahi-discover.in \
-       avahi-discover.desktop.in
+       avahi-bookmarks.in
 
-SUBDIRS=avahi
+SUBDIRS=avahi avahi-discover
 
 if HAVE_PYTHON
 if HAVE_PYTHON_DBUS
@@ -36,35 +34,12 @@ if HAVE_PYGTK
 pythonscripts = \
        avahi-bookmarks
 
-desktopdir = $(datadir)/applications
-desktop_DATA = 
-
-if HAVE_GDBM
-pythonscripts += \
-       avahi-discover
-desktop_DATA += avahi-discover.desktop
-endif
-
-if HAVE_DBM
-pythonscripts += \
-       avahi-discover
-desktop_DATA += avahi-discover.desktop
-endif
-
-avahi-discover.desktop: avahi-discover.desktop.in
-       sed -e 's,@bindir\@,$(bindir),g' $< > $@
-
-avahi-discover: avahi-discover.in
-       sed -e 's,@PYTHON\@,$(PYTHON),g' \
-               -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
-       chmod +x $@
-
 avahi-bookmarks: avahi-bookmarks.in
        sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
        chmod +x $@
 
 bin_SCRIPTS = $(pythonscripts)
-CLEANFILES = $(pythonscripts) $(desktop_DATA)
+CLEANFILES = $(pythonscripts)
 
 endif
 endif
diff --git a/avahi-python/avahi-discover.desktop.in b/avahi-python/avahi-discover.desktop.in
deleted file mode 100644 (file)
index e896192..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[Desktop Entry]
-Version=1.0
-Encoding=UTF-8
-Name=Avahi Zeroconf Browser
-Comment=Browse for Zeroconf services available on your network
-Exec=@bindir@/avahi-discover
-Terminal=false
-Type=Application
-Icon=network-wired
-Categories=GNOME;Application;System;
-StartupNotify=false
-GenericName=
diff --git a/avahi-python/avahi-discover.in b/avahi-python/avahi-discover.in
deleted file mode 100755 (executable)
index 23dee80..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi 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 of the
-# License, or (at your option) any later version.
-#
-# avahi 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 Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import os, sys
-
-try:
-    import avahi, gtk, gobject, dbus, avahi.ServiceTypeDatabase
-    from avahi.SimpleGladeApp import SimpleGladeApp
-except ImportError, e:
-    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus.\n Error: %s" % e
-    sys.exit(1)
-
-
-## !!NOTE!! ##
-# It's really important to do this, else you won't see any events
-##
-try:
-    from dbus import DBusException
-    import dbus.glib
-except ImportError, e:
-    pass
-
-service_type_browsers = {}
-service_browsers = {}
-
-def error_msg(msg):
-    d = gtk.MessageDialog(parent=None, flags=gtk.DIALOG_MODAL,
-                          type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK)
-    d.set_markup(msg)
-    d.show_all()
-    d.run()
-    d.destroy()
-
-glade_dir = "@interfacesdir@"
-
-service_type_db = avahi.ServiceTypeDatabase.ServiceTypeDatabase()
-
-class Main_window(SimpleGladeApp):
-    def __init__(self, path="avahi-discover.glade", root="main_window", domain=None, **kwargs):
-        path = os.path.join(glade_dir, path)
-        gtk.window_set_default_icon_name("network-wired")
-        SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
-
-    def on_tree_view_cursor_changed(self, widget, *args):
-        (model, iter) = widget.get_selection().get_selected()
-        (name,interface,protocol,stype,domain) = self.treemodel.get(iter,1,2,3,4,5)
-        if stype == None:
-            self.info_label.set_markup("<i>No service currently selected.</i>")
-            return
-        #Asynchronous resolving
-        self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved, error_handler=self.print_error)
-
-    def protoname(self,protocol):
-        if protocol == avahi.PROTO_INET:
-            return "IPv4"
-        if protocol == avahi.PROTO_INET6:
-            return "IPv6"
-        return "n/a"
-            
-    def siocgifname(self, interface):
-        if interface <= 0:
-            return "n/a"
-        else:
-            return self.server.GetNetworkInterfaceNameByIndex(interface)
-
-    def get_interface_name(self, interface, protocol):
-        if interface == avahi.IF_UNSPEC and protocol == avahi.PROTO_UNSPEC:
-            return "Wide Area"
-        else:
-            return str(self.siocgifname(interface)) + " " + str(self.protoname(protocol))
-                        
-    def service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
-        print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, stype, domain, interface, protocol)
-
-        print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
-
-        self.update_label(interface, protocol, name, stype, domain, host, aprotocol, address, port, avahi.txt_array_to_string_array(txt))
-        
-    def print_error(self, err):
-        error_label = "<b>Error:</b> %s" % (err)
-        self.info_label.set_markup(error_label)
-        print "Error:", str(err)
-
-    def lookup_type(self, stype):
-        global service_type_db
-
-        try:
-            return service_type_db[stype]
-        except KeyError:
-            return stype
-            
-    def new_service(self, interface, protocol, name, stype, domain, flags):
-        print "Found service '%s' of type '%s' in domain '%s' on %i.%i." % (name, stype, domain, interface, protocol)
-        if self.zc_ifaces.has_key((interface,protocol)) == False:
-
-            ifn = self.get_interface_name(interface, protocol)
-            
-            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn, None,interface,protocol,None,domain)
-        if self.zc_domains.has_key((interface,protocol,domain)) == False:
-            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
-        if self.zc_types.has_key((interface,protocol,stype,domain)) == False:
-            thisDomain = self.zc_domains[(interface,protocol,domain)]
-            self.zc_types[(interface,protocol,stype,domain)] = self.insert_row(self.treemodel, thisDomain, self.lookup_type(stype), name, interface,None,None,None)
-        treeiter = self.insert_row(self.treemodel,self.zc_types[(interface,protocol,stype,domain)], name, name, interface,protocol,stype,domain)
-        self.services_browsed[(interface, protocol, name, stype, domain)] = treeiter
-        # expand the tree of this path
-        self.tree_view.expand_to_path(self.treemodel.get_path(treeiter))
-
-    def remove_service(self, interface, protocol, name, stype, domain, flags):
-        print "Service '%s' of type '%s' in domain '%s' on %i.%i disappeared." % (name, stype, domain, interface, protocol)
-        self.info_label.set_markup("")
-        treeiter=self.services_browsed[(interface, protocol, name, stype, domain)]
-        parent = self.treemodel.iter_parent(treeiter)
-        self.treemodel.remove(treeiter)
-        del self.services_browsed[(interface, protocol, name, stype, domain)]
-        if self.treemodel.iter_has_child(parent) == False:
-            treeiter=self.zc_types[(interface,protocol,stype,domain)]
-            parent = self.treemodel.iter_parent(treeiter)
-            self.treemodel.remove(treeiter)
-            del self.zc_types[(interface,protocol,stype,domain)]
-            if self.treemodel.iter_has_child(parent) == False:
-                treeiter=self.zc_domains[(interface,protocol,domain)]
-                parent = self.treemodel.iter_parent(treeiter)
-                self.treemodel.remove(treeiter)
-                del self.zc_domains[(interface,protocol,domain)]
-                if self.treemodel.iter_has_child(parent) == False:
-                    treeiter=self.zc_ifaces[(interface,protocol)]
-                    parent = self.treemodel.iter_parent(treeiter)
-                    self.treemodel.remove(treeiter)
-                    del self.zc_ifaces[(interface,protocol)]
-    def new_service_type(self, interface, protocol, stype, domain, flags):
-        global service_browsers
-
-        # Are we already browsing this domain for this type? 
-        if service_browsers.has_key((interface, protocol, stype, domain)):
-            return
-        
-        print "Browsing for services of type '%s' in domain '%s' on %i.%i ..." % (stype, domain, interface, protocol)
-        
-        b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(interface, protocol, stype, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_BROWSER)
-        b.connect_to_signal('ItemNew', self.new_service)
-        b.connect_to_signal('ItemRemove', self.remove_service)
-
-        service_browsers[(interface, protocol, stype, domain)] = b
-
-    def browse_domain(self, interface, protocol, domain):
-        global service_type_browsers
-
-        # Are we already browsing this domain?
-        if service_type_browsers.has_key((interface, protocol, domain)):
-            return
-
-        if self.stype is None:
-            print "Browsing domain '%s' on %i.%i ..." % (domain, interface, protocol)
-
-            try:
-                b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceTypeBrowserNew(interface, protocol, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_TYPE_BROWSER)
-            except DBusException, e:
-                print e
-                error_msg("You should check that the avahi daemon is running.\n\nError : %s" % e)
-                sys.exit(0)
-                
-            b.connect_to_signal('ItemNew', self.new_service_type)
-
-            service_type_browsers[(interface, protocol, domain)] = b
-        else:
-            new_service_type(interface, protocol, stype, domain)
-
-    def new_domain(self,interface, protocol, domain, flags):
-        if self.zc_ifaces.has_key((interface,protocol)) == False:
-            ifn = self.get_interface_name(interface, protocol)
-            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn,None,interface,protocol,None,domain)
-        if self.zc_domains.has_key((interface,protocol,domain)) == False:
-            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
-        if domain != "local":
-            self.browse_domain(interface, protocol, domain)
-
-    def pair_to_dict(self, l):
-        res = dict()
-        for el in l:
-            if "=" not in el:
-                res[el]=''
-            else:
-                tmp = el.split('=',1)
-                if len(tmp[0]) > 0:
-                    res[tmp[0]] = tmp[1]
-        return res
-                                                                            
-
-    def update_label(self,interface, protocol, name, stype, domain, host, aprotocol, address, port, txt):
-        if len(txt) != 0:
-            txts = ""
-            txtd = self.pair_to_dict(txt)
-            for k,v in txtd.items():
-                txts+="<b>TXT <i>%s</i></b> = %s\n" % (k,v)
-        else:
-            txts = "<b>TXT Data:</b> <i>empty</i>"
-
-        infos = "<b>Service Type:</b> %s\n<b>Service Name:</b> %s\n<b>Domain Name:</b> %s\n<b>Interface:</b> %s %s\n<b>Address:</b> %s/%s:%i\n%s" % (stype, name, domain, self.siocgifname(interface), self.protoname(protocol), host, address, port, txts.strip())
-        self.info_label.set_markup(infos)
-
-    def insert_row(self, model,parent,
-                   content, name, interface,protocol,stype,domain):
-        myiter=model.insert_after(parent,None)
-        model.set(myiter,0,content,1,name,2,interface,3,protocol,4,stype,5,domain)
-        return myiter
-
-    def new(self):
-        print "A new main_window has been created"
-        self.treemodel=gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
-        self.tree_view.set_model(self.treemodel)
-
-        #creating the columns headers
-        self.tree_view.set_headers_visible(False)
-        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.tree_view.append_column(column)
-
-        self.domain = None
-        self.stype = None
-        self.zc_ifaces = {}
-        self.zc_domains = {}
-        self.zc_types = {}
-        self.services_browsed = {}
-        
-        self.bus = dbus.SystemBus()
-        self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-
-        if self.domain is None:
-            # Explicitly browse .local
-            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
-                        
-            # Browse for other browsable domains
-            db = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE, dbus.UInt32(0))), avahi.DBUS_INTERFACE_DOMAIN_BROWSER)
-            db.connect_to_signal('ItemNew', self.new_domain)
-        else:
-            # Just browse the domain the user wants us to browse
-            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
-
-        
-def main():
-    main_window = Main_window()
-
-    main_window.run()
-    
-if __name__ == "__main__":
-    main()
-
-                                            
diff --git a/avahi-python/avahi-discover/Makefile.am b/avahi-python/avahi-discover/Makefile.am
new file mode 100644 (file)
index 0000000..c1d6cab
--- /dev/null
@@ -0,0 +1,67 @@
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi 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 of the
+# License, or (at your option) any later version.
+#
+# avahi 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 Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+AM_CFLAGS=-I$(top_srcdir)
+
+EXTRA_DIST = \
+       __init__.py \
+       SimpleGladeApp.py \
+       avahi-discover.in \
+       avahi-discover.desktop.in
+
+if HAVE_PYTHON
+if HAVE_PYTHON_DBUS
+if HAVE_PYGTK
+
+pythonscripts =
+
+desktopdir = $(datadir)/applications
+desktop_DATA = 
+
+avahi_discoverdir = $(pythondir)/avahi_discover
+avahi_discover_PYTHON =
+
+if HAVE_GDBM
+pythonscripts += \
+       avahi-discover
+desktop_DATA += avahi-discover.desktop
+avahi_discover_PYTHON += __init__.py SimpleGladeApp.py
+endif
+
+if HAVE_DBM
+pythonscripts += \
+       avahi-discover
+desktop_DATA += avahi-discover.desktop
+avahi_discover_PYTHON += __init__.py SimpleGladeApp.py
+endif
+
+avahi-discover.desktop: avahi-discover.desktop.in
+       sed -e 's,@bindir\@,$(bindir),g' $< > $@
+
+avahi-discover: avahi-discover.in
+       sed -e 's,@PYTHON\@,$(PYTHON),g' \
+               -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
+       chmod +x $@
+
+bin_SCRIPTS = $(pythonscripts)
+CLEANFILES = $(pythonscripts) $(desktop_DATA) *.pyc *.pyo
+
+endif
+endif
+endif
diff --git a/avahi-python/avahi-discover/SimpleGladeApp.py b/avahi-python/avahi-discover/SimpleGladeApp.py
new file mode 100644 (file)
index 0000000..90c598c
--- /dev/null
@@ -0,0 +1,341 @@
+"""
+ 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/avahi-python/avahi-discover/__init__.py b/avahi-python/avahi-discover/__init__.py
new file mode 100755 (executable)
index 0000000..b2cd7d8
--- /dev/null
@@ -0,0 +1,20 @@
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi 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 of the
+# License, or (at your option) any later version.
+#
+# avahi 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 Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
diff --git a/avahi-python/avahi-discover/avahi-discover.desktop.in b/avahi-python/avahi-discover/avahi-discover.desktop.in
new file mode 100644 (file)
index 0000000..e896192
--- /dev/null
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Version=1.0
+Encoding=UTF-8
+Name=Avahi Zeroconf Browser
+Comment=Browse for Zeroconf services available on your network
+Exec=@bindir@/avahi-discover
+Terminal=false
+Type=Application
+Icon=network-wired
+Categories=GNOME;Application;System;
+StartupNotify=false
+GenericName=
diff --git a/avahi-python/avahi-discover/avahi-discover.in b/avahi-python/avahi-discover/avahi-discover.in
new file mode 100755 (executable)
index 0000000..229c7bd
--- /dev/null
@@ -0,0 +1,271 @@
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi 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 of the
+# License, or (at your option) any later version.
+#
+# avahi 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 Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import os, sys
+
+try:
+    import avahi, gtk, gobject, dbus, avahi.ServiceTypeDatabase
+    from avahi_discover.SimpleGladeApp import SimpleGladeApp
+except ImportError, e:
+    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus.\n Error: %s" % e
+    sys.exit(1)
+
+
+## !!NOTE!! ##
+# It's really important to do this, else you won't see any events
+##
+try:
+    from dbus import DBusException
+    import dbus.glib
+except ImportError, e:
+    pass
+
+service_type_browsers = {}
+service_browsers = {}
+
+def error_msg(msg):
+    d = gtk.MessageDialog(parent=None, flags=gtk.DIALOG_MODAL,
+                          type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK)
+    d.set_markup(msg)
+    d.show_all()
+    d.run()
+    d.destroy()
+
+glade_dir = "@interfacesdir@"
+
+service_type_db = avahi.ServiceTypeDatabase.ServiceTypeDatabase()
+
+class Main_window(SimpleGladeApp):
+    def __init__(self, path="avahi-discover.glade", root="main_window", domain=None, **kwargs):
+        path = os.path.join(glade_dir, path)
+        gtk.window_set_default_icon_name("network-wired")
+        SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
+
+    def on_tree_view_cursor_changed(self, widget, *args):
+        (model, iter) = widget.get_selection().get_selected()
+        (name,interface,protocol,stype,domain) = self.treemodel.get(iter,1,2,3,4,5)
+        if stype == None:
+            self.info_label.set_markup("<i>No service currently selected.</i>")
+            return
+        #Asynchronous resolving
+        self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved, error_handler=self.print_error)
+
+    def protoname(self,protocol):
+        if protocol == avahi.PROTO_INET:
+            return "IPv4"
+        if protocol == avahi.PROTO_INET6:
+            return "IPv6"
+        return "n/a"
+            
+    def siocgifname(self, interface):
+        if interface <= 0:
+            return "n/a"
+        else:
+            return self.server.GetNetworkInterfaceNameByIndex(interface)
+
+    def get_interface_name(self, interface, protocol):
+        if interface == avahi.IF_UNSPEC and protocol == avahi.PROTO_UNSPEC:
+            return "Wide Area"
+        else:
+            return str(self.siocgifname(interface)) + " " + str(self.protoname(protocol))
+                        
+    def service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
+        print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, stype, domain, interface, protocol)
+
+        print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
+
+        self.update_label(interface, protocol, name, stype, domain, host, aprotocol, address, port, avahi.txt_array_to_string_array(txt))
+        
+    def print_error(self, err):
+        error_label = "<b>Error:</b> %s" % (err)
+        self.info_label.set_markup(error_label)
+        print "Error:", str(err)
+
+    def lookup_type(self, stype):
+        global service_type_db
+
+        try:
+            return service_type_db[stype]
+        except KeyError:
+            return stype
+            
+    def new_service(self, interface, protocol, name, stype, domain, flags):
+        print "Found service '%s' of type '%s' in domain '%s' on %i.%i." % (name, stype, domain, interface, protocol)
+        if self.zc_ifaces.has_key((interface,protocol)) == False:
+
+            ifn = self.get_interface_name(interface, protocol)
+            
+            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn, None,interface,protocol,None,domain)
+        if self.zc_domains.has_key((interface,protocol,domain)) == False:
+            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
+        if self.zc_types.has_key((interface,protocol,stype,domain)) == False:
+            thisDomain = self.zc_domains[(interface,protocol,domain)]
+            self.zc_types[(interface,protocol,stype,domain)] = self.insert_row(self.treemodel, thisDomain, self.lookup_type(stype), name, interface,None,None,None)
+        treeiter = self.insert_row(self.treemodel,self.zc_types[(interface,protocol,stype,domain)], name, name, interface,protocol,stype,domain)
+        self.services_browsed[(interface, protocol, name, stype, domain)] = treeiter
+        # expand the tree of this path
+        self.tree_view.expand_to_path(self.treemodel.get_path(treeiter))
+
+    def remove_service(self, interface, protocol, name, stype, domain, flags):
+        print "Service '%s' of type '%s' in domain '%s' on %i.%i disappeared." % (name, stype, domain, interface, protocol)
+        self.info_label.set_markup("")
+        treeiter=self.services_browsed[(interface, protocol, name, stype, domain)]
+        parent = self.treemodel.iter_parent(treeiter)
+        self.treemodel.remove(treeiter)
+        del self.services_browsed[(interface, protocol, name, stype, domain)]
+        if self.treemodel.iter_has_child(parent) == False:
+            treeiter=self.zc_types[(interface,protocol,stype,domain)]
+            parent = self.treemodel.iter_parent(treeiter)
+            self.treemodel.remove(treeiter)
+            del self.zc_types[(interface,protocol,stype,domain)]
+            if self.treemodel.iter_has_child(parent) == False:
+                treeiter=self.zc_domains[(interface,protocol,domain)]
+                parent = self.treemodel.iter_parent(treeiter)
+                self.treemodel.remove(treeiter)
+                del self.zc_domains[(interface,protocol,domain)]
+                if self.treemodel.iter_has_child(parent) == False:
+                    treeiter=self.zc_ifaces[(interface,protocol)]
+                    parent = self.treemodel.iter_parent(treeiter)
+                    self.treemodel.remove(treeiter)
+                    del self.zc_ifaces[(interface,protocol)]
+    def new_service_type(self, interface, protocol, stype, domain, flags):
+        global service_browsers
+
+        # Are we already browsing this domain for this type? 
+        if service_browsers.has_key((interface, protocol, stype, domain)):
+            return
+        
+        print "Browsing for services of type '%s' in domain '%s' on %i.%i ..." % (stype, domain, interface, protocol)
+        
+        b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(interface, protocol, stype, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+        b.connect_to_signal('ItemNew', self.new_service)
+        b.connect_to_signal('ItemRemove', self.remove_service)
+
+        service_browsers[(interface, protocol, stype, domain)] = b
+
+    def browse_domain(self, interface, protocol, domain):
+        global service_type_browsers
+
+        # Are we already browsing this domain?
+        if service_type_browsers.has_key((interface, protocol, domain)):
+            return
+
+        if self.stype is None:
+            print "Browsing domain '%s' on %i.%i ..." % (domain, interface, protocol)
+
+            try:
+                b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceTypeBrowserNew(interface, protocol, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_TYPE_BROWSER)
+            except DBusException, e:
+                print e
+                error_msg("You should check that the avahi daemon is running.\n\nError : %s" % e)
+                sys.exit(0)
+                
+            b.connect_to_signal('ItemNew', self.new_service_type)
+
+            service_type_browsers[(interface, protocol, domain)] = b
+        else:
+            new_service_type(interface, protocol, stype, domain)
+
+    def new_domain(self,interface, protocol, domain, flags):
+        if self.zc_ifaces.has_key((interface,protocol)) == False:
+            ifn = self.get_interface_name(interface, protocol)
+            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn,None,interface,protocol,None,domain)
+        if self.zc_domains.has_key((interface,protocol,domain)) == False:
+            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
+        if domain != "local":
+            self.browse_domain(interface, protocol, domain)
+
+    def pair_to_dict(self, l):
+        res = dict()
+        for el in l:
+            if "=" not in el:
+                res[el]=''
+            else:
+                tmp = el.split('=',1)
+                if len(tmp[0]) > 0:
+                    res[tmp[0]] = tmp[1]
+        return res
+                                                                            
+
+    def update_label(self,interface, protocol, name, stype, domain, host, aprotocol, address, port, txt):
+        if len(txt) != 0:
+            txts = ""
+            txtd = self.pair_to_dict(txt)
+            for k,v in txtd.items():
+                txts+="<b>TXT <i>%s</i></b> = %s\n" % (k,v)
+        else:
+            txts = "<b>TXT Data:</b> <i>empty</i>"
+
+        infos = "<b>Service Type:</b> %s\n<b>Service Name:</b> %s\n<b>Domain Name:</b> %s\n<b>Interface:</b> %s %s\n<b>Address:</b> %s/%s:%i\n%s" % (stype, name, domain, self.siocgifname(interface), self.protoname(protocol), host, address, port, txts.strip())
+        self.info_label.set_markup(infos)
+
+    def insert_row(self, model,parent,
+                   content, name, interface,protocol,stype,domain):
+        myiter=model.insert_after(parent,None)
+        model.set(myiter,0,content,1,name,2,interface,3,protocol,4,stype,5,domain)
+        return myiter
+
+    def new(self):
+        print "A new main_window has been created"
+        self.treemodel=gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+        self.tree_view.set_model(self.treemodel)
+
+        #creating the columns headers
+        self.tree_view.set_headers_visible(False)
+        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.tree_view.append_column(column)
+
+        self.domain = None
+        self.stype = None
+        self.zc_ifaces = {}
+        self.zc_domains = {}
+        self.zc_types = {}
+        self.services_browsed = {}
+        
+        self.bus = dbus.SystemBus()
+        self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+        if self.domain is None:
+            # Explicitly browse .local
+            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
+                        
+            # Browse for other browsable domains
+            db = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE, dbus.UInt32(0))), avahi.DBUS_INTERFACE_DOMAIN_BROWSER)
+            db.connect_to_signal('ItemNew', self.new_domain)
+        else:
+            # Just browse the domain the user wants us to browse
+            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
+
+        
+def main():
+    main_window = Main_window()
+
+    main_window.run()
+    
+if __name__ == "__main__":
+    main()
+
+                                            
index c974171980beb57b123ee019253383fe10283b4d..2fff2189f3bb66e19cc3b0fd649842f77823e7fd 100644 (file)
@@ -17,7 +17,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA.
 
-EXTRA_DIST = __init__.py SimpleGladeApp.py ServiceTypeDatabase.py.in
+EXTRA_DIST = __init__.py ServiceTypeDatabase.py.in
 
 if HAVE_PYTHON
 
@@ -55,7 +55,7 @@ avahi_PYTHON = $(avahi_SCRIPTS)
 if HAVE_PYGTK
 if HAVE_PYTHON_DBUS
 
-avahi_PYTHON += __init__.py SimpleGladeApp.py 
+avahi_PYTHON += __init__.py
 
 endif
 endif
diff --git a/avahi-python/avahi/SimpleGladeApp.py b/avahi-python/avahi/SimpleGladeApp.py
deleted file mode 100644 (file)
index 90c598c..0000000
+++ /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("")        
index 463f205761373ca6129ec51181f0d0e3ea138701..7126678954076277f34a8e276b93681367e20191 100644 (file)
@@ -997,6 +997,7 @@ avahi-dnsconfd/Makefile
 avahi-utils/Makefile
 avahi-python/Makefile
 avahi-python/avahi/Makefile
+avahi-python/avahi-discover/Makefile
 examples/Makefile
 common/Makefile
 man/Makefile