summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Estienne <sebastien.estienne@gmail.com>2005-09-06 16:09:43 +0000
committerSebastien Estienne <sebastien.estienne@gmail.com>2005-09-06 16:09:43 +0000
commit193aa246dd77d553a77052d8db168f8c65d1c246 (patch)
tree2c04e36ed32eccd84d332f0f921223cbca34b23c
parentcc47eb76e4ab296367f4e200e769c2a0f2efb5e8 (diff)
* added a configuration ui
* rewrote a lot things git-svn-id: file:///home/lennart/svn/public/service-discovery-applet/trunk@8 3be567f1-68ff-0310-b24a-ad7cc433fd2f
-rw-r--r--configure.ac4
-rw-r--r--servers/GNOME_ServiceDiscoveryApplet.server.in2
-rw-r--r--src/Makefile.am21
-rwxr-xr-xsrc/service-discovery-applet.in186
-rw-r--r--src/service-discovery-config.glade373
-rwxr-xr-xsrc/service-discovery-config.in201
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">&lt;b&gt;Service type that will be browsed.&lt;/b&gt;</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">&lt;b&gt;Advanced options :&lt;/b&gt;</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()
+
+