diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | servers/GNOME_ServiceDiscoveryApplet.server.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 21 | ||||
-rwxr-xr-x | src/service-discovery-applet.in | 186 | ||||
-rw-r--r-- | src/service-discovery-config.glade | 373 | ||||
-rwxr-xr-x | src/service-discovery-config.in | 201 |
6 files changed, 731 insertions, 56 deletions
diff --git a/configure.ac b/configure.ac index f55e52c..5f293d7 100644 --- a/configure.ac +++ b/configure.ac @@ -16,9 +16,13 @@ AM_CHECK_PYMOD(gnomeapplet,,,[AC_MSG_ERROR(Could not find Python module gnomeapp SCRIPTSDIR="${datadir}/${PACKAGE}/scripts/" AC_SUBST(SCRIPTSDIR) + ICONSDIR="${datadir}/${PACKAGE}/icons/" AC_SUBST(ICONSDIR) +INTERFACESDIR="${datadir}/${PACKAGE}/interfaces/" +AC_SUBST(INTERFACESDIR) + AC_CONFIG_FILES([ Makefile common/Makefile diff --git a/servers/GNOME_ServiceDiscoveryApplet.server.in b/servers/GNOME_ServiceDiscoveryApplet.server.in index 5db309a..ec947b4 100644 --- a/servers/GNOME_ServiceDiscoveryApplet.server.in +++ b/servers/GNOME_ServiceDiscoveryApplet.server.in @@ -24,7 +24,7 @@ <oaf_attribute name="name" type="string" value="Zeroconf service discovery applet"/> <oaf_attribute name="description" type="string" value="This applet allow you to quickly access the zeroconf services available on your network."/> <oaf_attribute name="panel:category" type="string" value="Internet"/> - <oaf_attribute name="panel:icon" type="string" value="@iconsdir@/service-discovery-applet.png"/> + <oaf_attribute name="panel:icon" type="string" value="@iconsdir@/48x48/service-discovery-applet.png"/> </oaf_server> </oaf_info> diff --git a/src/Makefile.am b/src/Makefile.am index 8885425..01c41b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,15 @@ +interfacesdir = $(INTERFACESDIR) + +interfaces_DATA = service-discovery-config.glade + pythonscripts = \ - service-discovery-applet + service-discovery-applet \ + service-discovery-config EXTRA_DIST = \ - service-discovery-applet.in + service-discovery-applet.in \ + service-discovery-config.in \ + $(interfaces_DATA) bin_SCRIPTS = $(pythonscripts) @@ -15,4 +22,14 @@ service-discovery-applet: service-discovery-applet.in $< > $@ chmod +x $@ +service-discovery-config: service-discovery-config.in + sed \ + -e 's,@PYTHON\@,$(PYTHON),g' \ + -e 's,@version\@,$(VERSION),g' \ + -e 's,@iconsdir\@,$(ICONSDIR),g' \ + -e 's,@interfacesdir\@,$(INTERFACESDIR),g' \ + -e 's,@scriptsdir\@,$(SCRIPTSDIR),g' \ + $< > $@ + chmod +x $@ + CLEANFILES = $(pythonscripts) diff --git a/src/service-discovery-applet.in b/src/service-discovery-applet.in index d773bfe..7a9845c 100755 --- a/src/service-discovery-applet.in +++ b/src/service-discovery-applet.in @@ -1,5 +1,5 @@ #!@PYTHON@ - +# -*-python-*- # This file is part of service-discovery-applet (sd-applet). # # sd-applet is free software; you can redistribute it and/or modify it @@ -20,7 +20,6 @@ # $id$ # # todo -# * memleaks ? # * dict([el.split('=',1) for el in l ]) import os @@ -43,12 +42,20 @@ import gtk import gnomeapplet import gnome import gnome.ui +import gconf + +# Gconf Paths +gc_options = "/apps/service-discovery-applet/options" +gc_services = "/apps/service-discovery-applet/services" + #from gettext import gettext as _ -domain = None +#type_browsed = ('_ssh._tcp', '_http._tcp','_ftp._tcp') -type_browsed = ('_ssh._tcp', '_http._tcp','_ftp._tcp') +show_local_services = False +show_notifications = False +show_applet_name = False service_browsers = {} service_menu = gtk.Menu() @@ -90,7 +97,7 @@ def menuitem_response(widget, interface, protocol, name, type, domain): server.ResolveService(interface, protocol, name, type, domain, avahi.PROTO_UNSPEC, reply_handler=service_resolved, error_handler=print_error) def new_service(interface, protocol, name, type, domain): - global server, service_menu, zc_types, zc_pretty_name, zc_services, notif + global server, service_menu, zc_types, zc_pretty_name, zc_services, notif, show_notifications print "Found service '%s' of type '%s' in domain '%s' on %s.%i." % (name, type, domain, siocgifname(interface), protocol) @@ -119,17 +126,18 @@ def new_service(interface, protocol, name, type, domain): iconfile = "@iconsdir@/48x48/%s.png" % (type) message = "<b>Name :</b> %s\n<b>Type : </b> %s <i>(%s)</i>" % (name,zc_pretty_name[type], type) try: - notif.Notify("Service Discovery Applet", - iconfile, dbus.UInt32(0),"",dbus.Byte(0), - "New Service found",message, - [iconfile],[""],[""],True,dbus.UInt32(3)) + if show_notifications == True: + notif.Notify("Service Discovery Applet", + iconfile, dbus.UInt32(0),"",dbus.Byte(0), + "New Service found",message, + [iconfile],[""],[""],True,dbus.UInt32(3)) except: print "can't use notification daemon" pass def remove_service(interface, protocol, name, type, domain): - global zc_services,notif + global zc_services, notif, show_notifications print "Service '%s' of type '%s' in domain '%s' on %s.%i disappeared." % (name, type, domain, siocgifname(interface), protocol) @@ -139,18 +147,20 @@ def remove_service(interface, protocol, name, type, domain): service_menu.remove(zc_types[type].get_attach_widget()) del zc_types[type] + # check that iconfil exist iconfile = "@iconsdir@/48x48/%s.png" % (type) message = "<b>Name :</b> %s\n<b>Type : </b> %s <i>(%s)</i>" % (name,zc_pretty_name[type], type) try: - notif.Notify("Service Discovery Applet", - iconfile, dbus.UInt32(0),"",dbus.Byte(0), - "Service disappeared",message, - [iconfile],[""],[""],True,dbus.UInt32(3)) + if show_notifications == True: + notif.Notify("Service Discovery Applet", + iconfile, dbus.UInt32(0),"",dbus.Byte(0), + "Service disappeared",message, + [iconfile],[""],[""],True,dbus.UInt32(3)) except: print "can't use notification daemon" pass -def new_service_type(interface, protocol, type, domain): +def add_service_type(interface, protocol, type, domain): global server, service_browsers, system_bus # Are we already browsing this domain for this type? @@ -159,23 +169,26 @@ def new_service_type(interface, protocol, type, domain): print "Browsing for services of type '%s' in domain '%s' on %s.%i ..." % (type, domain, siocgifname(interface), protocol) - b = dbus.Interface(system_bus.get_object(avahi.DBUS_NAME, server.ServiceBrowserNew(interface, protocol, type, domain)), avahi.DBUS_INTERFACE_SERVICE_BROWSER) + b = dbus.Interface(system_bus.get_object(avahi.DBUS_NAME, + server.ServiceBrowserNew(interface, protocol, type, domain)) + , avahi.DBUS_INTERFACE_SERVICE_BROWSER) b.connect_to_signal('ItemNew', new_service) b.connect_to_signal('ItemRemove', remove_service) service_browsers[(interface, protocol, type, domain)] = b -def browse_domain(interface, protocol, domain): - global server +def del_service_type(interface, protocol, type, domain): - # Are we already browsing this domain? - for type in type_browsed: - new_service_type(interface, protocol, type, domain) - -def new_domain(interface, protocol, domain): - # We browse for .local anyway... - if domain != "local": - browse_domain(interface, protocol, domain) + service = (interface, protocol, type, domain) + if not service_browsers.has_key(service): + return + sb = service_browsers[service] + sb.Free() + del service_browsers[service] + # delete the sub menu of service_type + if zc_types.has_key(type): + service_menu.remove(zc_types[type].get_attach_widget()) + del zc_types[type] def on_menubar_click(widget, event): @@ -188,7 +201,7 @@ def on_menubar_click(widget, event): def on_about(component, verb, applet): icon = gtk.Image() - icon.set_from_file("@iconsdir@/service-discovery-applet.png") + icon.set_from_file("@iconsdir@/48x48/service-discovery-applet.png") fullname = "Service Discovery Applet" copyright = "Copyright (C) 2005 Sebastien Estienne" @@ -199,8 +212,85 @@ def on_about(component, verb, applet): about.set_icon(icon.get_pixbuf()) about.show() +def on_config(component, verb, applet): + os.system("service-discovery-config") + +#FIXME replace with gconf key +def start_service_discovery(component, verb, applet): + global system_bus, server, db , gc_client, domain, interface, protocol + + if len(domain) != 0: + return + + try: + domain = server.GetDomainName() + except: + print "Check that Avahi daemon is running!" + return + + interface = avahi.IF_UNSPEC + protocol = avahi.PROTO_UNSPEC + + gc_entries = gc_client.all_entries(gc_services) + for gc_entry in gc_entries: + if gc_client.get_bool(gc_entry.key) == True: + service_type = os.path.basename(gc_entry.key) + add_service_type(interface, protocol, service_type, domain) + print "start" + +def stop_service_discovery(component, verb, applet): + global domain + + if len(domain) == 0: + return + + for service in service_browsers.copy(): + del_service_type(service[0],service[1],service[2],service[3]) + domain = "" + print "stop" + +# Callback called when a service is added/removed/enabled/disabled in gconf +def gc_services_cb (client, cnxn_id, gc_entry, data): + global interface, domain, protocol + + service_type = os.path.basename(gc_entry.key) + # FIXME unset key + if client.get_bool(gc_entry.key) == True: + # Browse for a new service + print "browse %s" % (service_type) + add_service_type(interface, protocol, service_type, domain) + else: + # Stop browsing for a service + print "remove %s" % (service_type) + del_service_type(interface, protocol, service_type, domain) + +def gc_options_cb (client, cnxn_id, gc_entry, data): + global show_notifications, show_applet_name, show_local_services + + key = os.path.basename(gc_entry.key) + if key == "show_applet_name": + show_applet_name = client.get_bool(gc_entry.key) + if key == "show_notifications": + show_notifications = client.get_bool(gc_entry.key) + if key == "show_local_services": + show_local_services = client.get_bool(gc_entry.key) + def ServiceDiscoveryApplet_factory(applet, iid): - global menuZC, system_bus, server, session_bus, domain, notif + global menuZC, session_bus, notif, show_notifications, gc_client, server, system_bus, domain + + # Gconf + gc_client = gconf.client_get_default () + + gc_client.add_dir (gc_options, gconf.CLIENT_PRELOAD_NONE) + + show_local_services = gc_client.get_bool ("%s/%s" % (gc_options,"show_local_services")) + show_notifications = gc_client.get_bool ("%s/%s" % (gc_options,"show_notifications")) + show_applet_name = gc_client.get_bool ("%s/%s" % (gc_options,"show_applet_name")) + + gc_client.notify_add (gc_options, gc_options_cb, None) + + gc_client.add_dir (gc_services, gconf.CLIENT_PRELOAD_NONE) + gc_client.notify_add (gc_services, gc_services_cb,None) print "Creating new applet instance" menubar = gtk.MenuBar() @@ -223,39 +313,29 @@ def ServiceDiscoveryApplet_factory(applet, iid): # funky right-click menu menuXml = """ <popup name="button3"> - <menuitem name="Service Discovery Applet About Item" verb="SDA About" _label="_About" pixtype="stock" pixname="gnome-stock-about"/> + <menuitem name="Service Discovery Applet About Item" verb="SDA About" _label="_About" pixtype="stock" pixname="gtk-about"/> <menuitem name="Service Discovery Applet Configuration Item" verb="SDA Config" _label="_Config" pixtype="stock" pixname="gtk-preferences"/> + <menuitem name="Service Discovery Applet Start Item" verb="SDA Start" _label="_Start" pixtype="stock" pixname="gtk-media-play"/> + <menuitem name="Service Discovery Applet Stop Item" verb="SDA Stop" _label="_Stop" pixtype="stock" pixname="gtk-media-stop"/> </popup> """ - applet.setup_menu(menuXml, [("SDA About", on_about)], applet) - applet.setup_menu(menuXml, [("SDA Config", on_about)], applet) - + applet.setup_menu(menuXml, [ + ("SDA About", on_about), + ("SDA Config", on_config), + ("SDA Start", start_service_discovery), + ("SDA Stop", stop_service_discovery) + ], applet) + popup = applet.get_popup_component() +# popup.set_prop ("/button3/Service Discovery Applet Start Item", "_label", "prout") + + #Start Service Discovery + domain = "" system_bus = dbus.SystemBus() server = dbus.Interface(system_bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER) - if domain is None: - # Explicitly browse .local - try: - browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local") - except: - print "Can't connect to Avahi." - sys.exit(0) - - # Browse for other browsable domains - sdb = server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE) - obj = system_bus.get_object(avahi.DBUS_NAME, sdb) - db = dbus.Interface(obj, avahi.DBUS_INTERFACE_DOMAIN_BROWSER) - db.connect_to_signal('ItemNew', new_domain) - - else: - # Just browse the domain the user wants us to browse - try: - browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain) - except: - print "Can't connect to Avahi." - sys.exit(0) + start_service_discovery(None, None, None) session_bus = dbus.SessionBus() obj = session_bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications") diff --git a/src/service-discovery-config.glade b/src/service-discovery-config.glade new file mode 100644 index 0000000..3724490 --- /dev/null +++ b/src/service-discovery-config.glade @@ -0,0 +1,373 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkDialog" id="sda-prefs-dialog"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Service Discovery Applet Preferences</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="has_separator">True</property> + <signal name="destroy" handler="gtk_main_quit"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog1-vbox"> + <property name="width_request">350</property> + <property name="height_request">450</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog1-action_area"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">0</property> + <signal name="clicked" handler="gtk_main_quit" last_modification_time="Tue, 06 Sep 2005 14:25:40 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + + <child> + <widget class="GtkVBox" id="vbox_services"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkImage" id="image_services"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_services"> + <property name="visible">True</property> + <property name="label"><b>Service type that will be browsed.</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTreeView" id="treeview_services"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_service_info"> + <property name="label">services informations</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="button_add_service"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_del_service"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-remove</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_services"> + <property name="visible">True</property> + <property name="label" translatable="yes">Services</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table_advanced"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">5</property> + + <child> + <widget class="GtkCheckButton" id="checkbutton_notifications"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">Display notifications.</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbutton_local"> + <property name="can_focus">True</property> + <property name="label">Browse for my own services.</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Advanced options :</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbutton_applet_name"> + <property name="can_focus">True</property> + <property name="label">Display applet name in the panel.</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_advanced"> + <property name="visible">True</property> + <property name="label" translatable="yes">Advanced</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/src/service-discovery-config.in b/src/service-discovery-config.in new file mode 100755 index 0000000..420ec7e --- /dev/null +++ b/src/service-discovery-config.in @@ -0,0 +1,201 @@ +#!@PYTHON@ +# -*-python-*- +# This file is part of service-discovery-applet (sd-applet). +# +# sd-applet 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. +# +# sd-applet 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 sd-applet; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# $id$ +# + +import os +import avahi, gtk, gobject +import gconf + +from avahi.SimpleGladeApp import SimpleGladeApp + +( + COLUMN_ENABLED, + COLUMN_SERVICE, + COLUMN_NAME, + COLUMN_ACTION, + COLUMN_EDITABLE +) = range(5) + +glade_dir = "@interfacesdir@" + +gc_options = "/apps/service-discovery-applet/options" +gc_services = "/apps/service-discovery-applet/services" + +class Config_window(SimpleGladeApp): + def __init__(self, path="service-discovery-config.glade", root="sda-prefs-dialog", domain=None, **kwargs): + path = os.path.join(glade_dir, path) + SimpleGladeApp.__init__(self, path, root, domain, **kwargs) + + def __create_model(self): + lstore = gtk.ListStore( + gobject.TYPE_BOOLEAN, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_BOOLEAN, + gobject.TYPE_BOOLEAN) + + gc_entries = self.gc_client.all_entries(gc_services) + for gc_entry in gc_entries: + svc_enabled = self.gc_client.get_bool(gc_entry.key) + svc_type = os.path.basename(gc_entry.key) + + iter = lstore.append() + lstore.set(iter, + COLUMN_ENABLED, svc_enabled, + COLUMN_SERVICE, svc_type, + COLUMN_NAME, None, + COLUMN_ACTION, False, + COLUMN_EDITABLE, True) + return lstore + + def __add_columns(self, treeview): + model = treeview.get_model() + + # column for enabled toggles + renderer = gtk.CellRendererToggle() + renderer.connect('toggled', self.enabled_toggled, model) + + column = gtk.TreeViewColumn('Enabled', renderer, active=COLUMN_ENABLED) + + # set this column to a fixed sizing(of 50 pixels) + #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + #column.set_fixed_width(50) + column.set_sort_column_id(COLUMN_ENABLED) + treeview.append_column(column) + + # column for service type + + renderer = gtk.CellRendererText() + renderer.connect("edited", self.on_cell_edited, model) + renderer.set_data("column", COLUMN_SERVICE) + + column = gtk.TreeViewColumn('Service type', renderer, + text=COLUMN_SERVICE, editable=COLUMN_EDITABLE) + treeview.append_column(column) + + # columns for service name +# column = gtk.TreeViewColumn('Service Name', gtk.CellRendererText(), +# text=COLUMN_NAME) +# column.set_sort_column_id(COLUMN_NAME) +# treeview.append_column(column) + + # column for action scripts +# renderer = gtk.CellRendererToggle() +# column = gtk.TreeViewColumn('Action', renderer, active=COLUMN_ACTION) +# column.set_sort_column_id(COLUMN_ACTION) +# treeview.append_column(column) + + def on_cell_edited(self, cell, path_string, service_type, model): + + iter = model.get_iter_from_string(path_string) + path = model.get_path(iter)[0] + column = cell.get_data("column") + + if column == COLUMN_SERVICE: + old_service_type = model.get_value(iter, column) + old_service_enabled= model.get_value(iter, COLUMN_ENABLED) + self.gc_client.unset("%s/%s" % (gc_services, old_service_type)) + model.set(iter, column, service_type) + self.gc_client.set_bool("%s/%s" % (gc_services, service_type), old_service_enabled) + + def on_add_service_clicked(self, button, model): + iter = model.append() + model.set (iter, + COLUMN_ENABLED, False, + COLUMN_SERVICE, "_service._protocol", + COLUMN_NAME, None, + COLUMN_ACTION, False, + COLUMN_EDITABLE, True) + + def on_del_service_clicked(self, button, treeview): + + selection = treeview.get_selection() + model, iter = selection.get_selected() + + if iter: + path = model.get_path(iter)[0] + service_type = model.get_value(iter,COLUMN_SERVICE) + self.gc_client.unset("%s/%s" % (gc_services, service_type)) + model.remove(iter) + #FIXME remove entry from gconf + + def enabled_toggled(self, cell, path, model): + # get toggled iter + iter = model.get_iter((int(path),)) + enabled = model.get_value(iter, COLUMN_ENABLED) + service_type = model.get_value(iter, COLUMN_SERVICE) + # do something with the value + enabled = not enabled + + # set new value + model.set(iter, COLUMN_ENABLED, enabled) + + self.gc_client.set_bool("%s/%s" % (gc_services, service_type), enabled) + + def cb_local_toggled(self,cb,client): + client.set_bool ("%s/%s" % (gc_options,"show_local_services"), cb.get_active()) + + def cb_notifications_toggled(self,cb,client): + client.set_bool ("%s/%s" % (gc_options,"show_notifications"), cb.get_active()) + + def cb_applet_name_toggled(self,cb,client): + client.set_bool ("%s/%s" % (gc_options,"show_applet_name"), cb.get_active()) + + def new(self): + print "A new main_window has been created" + + # Gconf + self.gc_client = gconf.client_get_default () + self.gc_client.add_dir (gc_options, gconf.CLIENT_PRELOAD_NONE) + + # images + self.image_services.set_from_file("@iconsdir@/48x48/service-discovery-applet.png") + + # connect advanced checkbuttons + self.checkbutton_local.set_active(self.gc_client.get_bool ("%s/%s" % (gc_options,"show_local_services"))) + self.checkbutton_local.connect('toggled',self.cb_local_toggled,self.gc_client) + + self.checkbutton_notifications.set_active(self.gc_client.get_bool ("%s/%s" % (gc_options,"show_notifications"))) + self.checkbutton_notifications.connect('toggled',self.cb_notifications_toggled,self.gc_client) + + self.checkbutton_applet_name.set_active(self.gc_client.get_bool ("%s/%s" % (gc_options,"show_applet_name"))) + self.checkbutton_applet_name.connect('toggled',self.cb_applet_name_toggled,self.gc_client) + + # The services treeview + model = self.__create_model() + + self.treeview_services.set_model(model) + self.__add_columns(self.treeview_services) + + # connect add/remove service buttons + self.button_add_service.connect("clicked", self.on_add_service_clicked, model) + self.button_del_service.connect("clicked", self.on_del_service_clicked, self.treeview_services) + + +def main(): + config_window = Config_window() + + config_window.run() + +if __name__ == "__main__": + main() + + |