[d-feet/pygi] Port to pygi and gdbus



commit cf4b5a71a1e1fff59b07be4b458f928fb83190c4
Author: Thomas Bechtold <thomasbechtold jpberlin de>
Date:   Sat Aug 4 13:38:50 2012 +0200

    Port to pygi and gdbus
    
    * Port from pygtk to pygi
    * Port from python-dbus to gdbus
    * restructure code
    * add (still simple) testsuite
    
    https://bugzilla.gnome.org/show_bug.cgi?id=681093

 .gitignore                       |    2 +
 AUTHORS                          |    2 +
 README                           |    8 +-
 TODO                             |   10 +
 d-feet                           |    2 -
 d-feet.doap                      |   11 +-
 dfeet/DFeetApp.py                |  283 ++++++----------
 dfeet/_introspect_parser.py      |  150 ---------
 dfeet/_ui/__init__.py            |    2 +-
 dfeet/_ui/addconnectiondialog.py |   64 +++--
 dfeet/_ui/busbox.py              |   95 ------
 dfeet/_ui/busnamebox.py          |   65 ----
 dfeet/_ui/busnameinfobox.py      |    4 +-
 dfeet/_ui/busnameview.py         |  162 ---------
 dfeet/_ui/executemethoddialog.py |  158 +++++----
 dfeet/_ui/uiloader.py            |   38 ++-
 dfeet/_ui/wnck_utils.py          |    2 +-
 dfeet/_util.py                   |   32 --
 dfeet/bus_watch.py               |  215 ++++++++++++
 dfeet/dbus_introspector.py       |  477 ---------------------------
 dfeet/dbus_utils.py              |    1 +
 dfeet/introspect_data.py         |  678 --------------------------------------
 dfeet/introspection.py           |  229 +++++++++++++
 dfeet/introspection_helper.py    |  218 ++++++++++++
 tests/tests.py                   |  106 ++++++
 tests/tests.py~                  |   79 +++++
 tests/uifile_tests.py            |   33 --
 ui/addconnectiondialog.ui        |   63 +++--
 ui/buswatch.ui                   |  210 ++++++++++++
 ui/default-actiongroup.ui        |   99 ------
 ui/executedialog.ui              |  430 ++++++++++++++++++++----
 ui/introspection.ui              |  165 +++++++++
 ui/introspectview.ui             |  118 -------
 ui/mainwindow.ui                 |  189 ++++++++---
 34 files changed, 2064 insertions(+), 2336 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 0d20b64..a888202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
 *.pyc
+*~
+\#*#
diff --git a/AUTHORS b/AUTHORS
index ba0eae5..71965fc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,6 +2,8 @@ John (J5) Palmieri <johnp redhat com>
 Ray Strode <rstrode redhat com>
 Marcel Holtmann <marcel holtmann org>
 Johan Dahlin <johan gnome org>
+Thomas Bechtold <thomasbechtold jpberlin de>
+
 
 Some code taken and modified from the D-Bus Python project http://dbus.freedesktop.org
 Some code taken and modified from the Jokosher Project http://jokosher.org
diff --git a/README b/README
index 8c3bedc..a582bec 100644
--- a/README
+++ b/README
@@ -2,10 +2,10 @@ Welcome to D-Feet (http://live.gnome.org/d-feet)
 
 Requirements:
 
-D-Bus > 1.0
-D-Bus Python > 0.82.3
-PyGtk
-Python 2.5
+python >= 2.7
+glib >= 2.34
+gobject-introspection
+python-gi
 
 Optional Requriements:
 
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..86e5a12
--- /dev/null
+++ b/TODO
@@ -0,0 +1,10 @@
+* reimplement the bustab list save/restore stuff
+* Add checkbox in addconnectiondialog.ui to be able to start a
+   peer-to-peer connection
+* Add filter for introspector treeview. Should be possible to filter
+   methods, properties and interfaces
+* Add menu entry to start a service by name
+   (org.freedesktop.DBus.StartServiceByName)
+* Add a list with activateable services
+   (org.freedesktop.DBus.ListActivatableNames)
+
diff --git a/d-feet b/d-feet
index 8e85c5e..cc15057 100755
--- a/d-feet
+++ b/d-feet
@@ -29,8 +29,6 @@ if options.use_local_dirs:
                  "DFEET_LOCALE_PATH" : "locale/",
                  "DFEET_HELP_PATH" : "/usr/share/gnome/dfeet/"
                 }
-    
-
 else:
     ENV_PATHS = {"DFEET_DATA_PATH" : "/usr/share/dfeet/",
                  "DFEET_IMAGE_PATH" : "/usr/share/dfeet/pixmaps/",
diff --git a/d-feet.doap b/d-feet.doap
index 3252439..1827172 100644
--- a/d-feet.doap
+++ b/d-feet.doap
@@ -7,7 +7,9 @@
   <name xml:lang="en">D-Feet</name>
   <shortdesc xml:lang="en">D-Bus Debugger</shortdesc>
   <homepage rdf:resource="http://live.gnome.org/DFeet"; />
-
+  <download-page rdf:resource="http://download.gnome.org/sources/d-feet/"; />
+  <bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=d-feet"; />
+  
   <maintainer>
     <foaf:Person>
       <foaf:name>John (J5) Palmieri</foaf:name>
@@ -15,4 +17,11 @@
       <gnome:userid>johnp</gnome:userid>
     </foaf:Person>
   </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Thomas Bechtold</foaf:name>
+      <foaf:mbox rdf:resource="mailto:thomasbechtold jpberlin de" />
+      <gnome:userid>toabctl</gnome:userid>
+    </foaf:Person>
+  </maintainer>
 </Project>
diff --git a/dfeet/DFeetApp.py b/dfeet/DFeetApp.py
index 6463592..ef407c7 100644
--- a/dfeet/DFeetApp.py
+++ b/dfeet/DFeetApp.py
@@ -1,209 +1,141 @@
+# -*- coding: utf-8 -*-
 import os
 import sys
-from gi.repository import Gtk
-import _ui
-import _util
 
-import dbus_introspector
-import introspect_data
+from gi.repository import Gtk, Gio, GObject
 
-from dbus_introspector import BusWatch
+
+from bus_watch import BusWatch
+from introspection import AddressInfo
 from settings import Settings
 from _ui.uiloader import UILoader
 from _ui.addconnectiondialog import AddConnectionDialog
 from _ui.executemethoddialog import ExecuteMethodDialog
 
 
+class NotebookTabLabel(Gtk.Box):
+    __gsignals__ = {
+        "close-clicked": (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
+    }
+    def __init__(self, label_text):
+        Gtk.Box.__init__(self)
+        self.set_orientation(Gtk.Orientation.HORIZONTAL)
+        self.set_spacing(5)
+        # label 
+        label = Gtk.Label(label_text)
+        self.pack_start(label, True, True, 0)
+        # close button
+        button = Gtk.Button()
+        button.set_relief(Gtk.ReliefStyle.NONE)
+        button.set_focus_on_click(False)
+        button.add(Gtk.Image.new_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU))
+        button.connect("clicked", self.__button_clicked)
+        self.pack_end(button, False, False, 0)
+        self.show_all()
+    
+    def __button_clicked(self, button, data=None):
+        self.emit("close-clicked")
+
+
 class DFeetApp:
 
     HISTORY_MAX_SIZE = 10
 
     def __init__(self):
-        signal_dict = {'add_session_bus': self.add_session_bus_cb,
-                       'add_system_bus': self.add_system_bus_cb,
-                       'add_bus_address': self.add_bus_address_cb,
-                       'reconnect_current_bus': self.reconnect_current_bus_cb,
-                       'execute_method': self.execute_current_method_cb,
-                       'quit': self.quit_cb}
-
-        self.ICON_SIZE_CLOSE_BUTTON = Gtk.icon_size_register('ICON_SIZE_CLOSE_BUTTON', 14, 14)
+        signal_dict = {
+            'action_systembus_connect_activate_cb': self.__systembus_connect_cb,
+            'action_sessionbus_connect_activate_cb': self.__sessionbus_connect_cb,
+            'action_otherbus_connect_activate_cb': self.__otherbus_connect_cb,
+            'action_close_activate_cb': self.__close_cb,
+            }
 
         settings = Settings.get_instance()
 
         ui = UILoader(UILoader.UI_MAINWINDOW) 
-
         self.main_window = ui.get_root_widget()
-        self.main_window.set_icon_name('dfeet-icon')
-        self.main_window.connect('delete-event', self._quit_dfeet)
+        self.main_window.connect('delete-event', self.__quit_dfeet)
+        self.main_window.set_default_size(int(settings.general['windowwidth']), 
+                                          int(settings.general['windowheight']))
 
         self.notebook = ui.get_widget('display_notebook')
         self.notebook.show_all()
+        self.notebook_page_widget = ui.get_widget('box_notebook_page')
 
-        self.execute_method_action = ui.get_widget('execute_method')
-        self.reconnect_current_bus_action = ui.get_widget('reconnect_current_bus')
+        #create bus history list and load entries from settings
+        self.__bus_history = []
+        for bus in settings.general['addbus_list']:
+            if bus != '':
+                self.__bus_history.append(bus)
 
-        self.notebook.connect('switch-page', self.switch_tab_cb)
+        ui.connect_signals(signal_dict)
+        self.main_window.show()
 
-        self.main_window.set_default_size(int(settings.general['windowwidth']), 
-                                 int(settings.general['windowheight']))
 
-        self._load_tabs(settings)
-        self._load_addbus_history(settings)
+    @property
+    def bus_history(self):
+        return self.__bus_history
 
-        self.main_window.show()
 
-        ui.connect_signals(signal_dict)
+    def __systembus_connect_cb(self, action):
+        """ connect to system bus """
+        bw = BusWatch(Gio.BusType.SYSTEM)
+        self.__notebook_append_page(bw.paned_buswatch, "System Bus")
 
-    def _load_tabs(self, settings):
-        for bus_name in settings.general['bustabs_list']:
-            if bus_name == 'Session Bus':
-                self.add_bus(dbus_introspector.SESSION_BUS)
-            elif bus_name == 'System Bus':
-                self.add_bus(dbus_introspector.SYSTEM_BUS)
-            else:
-                self.add_bus(address = bus_name)
-
-    def _load_addbus_history(self, settings):
-        self.add_bus_history = []
-        self.combo_addbus_history_model = Gtk.ListStore(str)
-        for bus_add in settings.general['addbus_list']:
-            if bus_add != '':
-                self.add_bus_history.append(bus_add)
-
-    def _add_bus_tab(self, bus_watch, position=None):
-        name = bus_watch.get_bus_name()
-        bus_paned = _ui.BusBox(bus_watch)
-        bus_paned.connect('introspectnode-selected', 
-                          self.introspect_node_selected_cb)
-        bus_paned.show_all()
-        hbox = Gtk.HBox()
-        hbox.pack_start(Gtk.Label(name), True, True, 0)
-        close_btn = Gtk.Button()
-        img = Gtk.Image()
-        img.set_from_stock(Gtk.STOCK_CLOSE, self.ICON_SIZE_CLOSE_BUTTON)
-        img.show()
-        close_btn.set_image(img)
-        close_btn.set_relief(Gtk.ReliefStyle.NONE)
-        close_btn.connect('clicked', self.close_tab_cb, bus_paned)
-        hbox.pack_start(close_btn, False, False, 0)
-        hbox.show_all()
-
-        if position:
-            self.notebook.insert_page(bus_paned, hbox, position)
-            self.notebook.set_current_page(position)
-            self.notebook.set_tab_reorderable(bus_paned, True)
-        else:
-            p = self.notebook.append_page(bus_paned, hbox)
-            self.notebook.set_current_page(p)
-            self.notebook.set_tab_reorderable(bus_paned, True)
-
-    def introspect_node_selected_cb(self, widget, node):
-        if isinstance(node, introspect_data.Method):
-            self.execute_method_action.set_sensitive(True)
-        else:
-            self.execute_method_action.set_sensitive(False)
-            
-    def execute_current_method_cb(self, action):
-        page = self.notebook.get_current_page()
-        if page >= 0:
-            busbox = self.notebook.get_nth_page(page)
-            node = busbox.get_selected_introspect_node()
-            busname = busbox.get_selected_busname()
-            dialog = ExecuteMethodDialog(busname, node)
-            dialog.run()
-
-    def close_tab_cb(self, button, child):
-        n = self.notebook.page_num(child)
-        if child.get_bus_watch().get_bus_name() not in [u'Session Bus', u'System Bus']:
-            child.get_bus_watch().close_bus()
-        self.notebook.remove_page(n)
-        if self.notebook.get_n_pages() <= 0:
-            self.reconnect_current_bus_action.set_sensitive(False)
-
-    def switch_tab_cb(self, notebook, page, page_num):
-        child = self.notebook.get_nth_page(page_num)
-        if child.get_bus_watch().get_bus_name() not in [u'Session Bus', u'System Bus']:
-            self.reconnect_current_bus_action.set_sensitive(True)
-        else:
-            self.reconnect_current_bus_action.set_sensitive(False)
-
-    def select_or_add_bus(self, address):
-        for i in range(self.notebook.get_n_pages()):
-            page = self.notebook.get_nth_page(i)
-            tab_label = self.notebook.get_tab_label(page)
-            if tab_label.get_children()[0].get_text() == address:
-                self.notebook.set_current_page(i)
-                break
-        else:
-            self.add_bus(address=address)
-
-    def add_bus(self, bus_type=None, address=None):
-        if bus_type == dbus_introspector.SESSION_BUS or bus_type == dbus_introspector.SYSTEM_BUS:
-            bus_watch = BusWatch(bus_type)
-            self._add_bus_tab(bus_watch)
-        else:
-            try:
-                bus_watch = BusWatch(None, address=address)
-                self._add_bus_tab(bus_watch)
-            except Exception, e:
-                print e
-
-    def add_session_bus_cb(self, action):
-        self.add_bus(dbus_introspector.SESSION_BUS)
-
-    def add_system_bus_cb(self, action):
-        self.add_bus(dbus_introspector.SYSTEM_BUS)
-
-    def add_bus_address_cb(self, action):
-        dialog = AddConnectionDialog(self.main_window)
-        self.combo_addbus_history_model.clear()
-        # Load combo box history
-        for el in self.add_bus_history:
-            self.combo_addbus_history_model.append([el])
-        dialog.set_model(self.combo_addbus_history_model)
-        result = dialog.run()
-        if result == 1:
-            bus_address = dialog.get_address()
-            if bus_address == 'Session Bus':
-                self.add_bus(dbus_introspector.SESSION_BUS)
-            elif bus_address == 'System Bus':
-                self.add_bus(dbus_introspector.SYSTEM_BUS)
-            else:
-                self.add_bus(address = bus_address)
-                # Fill history
-                if bus_address in self.add_bus_history:
-                    self.add_bus_history.remove(bus_address)
-                self.add_bus_history.insert(0, bus_address)
-                # Truncating history
-                if (len(self.add_bus_history) > self.HISTORY_MAX_SIZE):
-                    self.add_bus_history = self.add_bus_history[0:self.HISTORY_MAX_SIZE]
 
-        dialog.destroy()
-
-    def reconnect_current_bus_cb(self, action):
-        page = self.notebook.get_current_page()
-        if page >= 0:
-            child = self.notebook.get_nth_page(page)
-            bus_watch = child.get_bus_watch()
+    def __sessionbus_connect_cb(self, action):
+        """ connect to session bus """
+        bw = BusWatch(Gio.BusType.SESSION)
+        self.__notebook_append_page(bw.paned_buswatch, "Session Bus")
 
-            bus_type = bus_watch.get_bus_type()
-            bus_address = bus_watch.get_bus_address()
 
-            if bus_type == dbus_introspector.SESSION_BUS or bus_type == dbus_introspector.SYSTEM_BUS:
-                pass
+    def __otherbus_connect_cb(self, action):
+        """ connect to other bus """
+        dialog = AddConnectionDialog(self.main_window, self.bus_history)
+        result = dialog.run()
+        if result == Gtk.ResponseType.OK:
+            address = dialog.address
+            if address == 'Session Bus':
+                self.__sessionbus_connect_cb(None)
+                return
+            elif address == 'System Bus':
+                self.__systembus_connect_cb(None)
+                return
             else:
-                bus_watch.close_bus()
-                self.notebook.remove_page(page)
                 try:
-                    new_bus_watch = BusWatch(None, address=bus_address)
-                    self._add_bus_tab(new_bus_watch, page)
+                    bw = BusWatch(address)
+                    self.__notebook_append_page(bw.paned_buswatch, address)
+                    # Fill history
+                    if address in self.bus_history:
+                        self.bus_history.remove(address)
+                    self.bus_history.insert(0, address)
+                    # Truncating history
+                    if (len(self.bus_history) > self.HISTORY_MAX_SIZE):
+                        self.bus_history = self.bus_history[0:self.HISTORY_MAX_SIZE]
                 except Exception, e:
-                    print e
+                    print "can not connect to '%s': %s" % (address, str(e))
+        dialog.destroy()
+
+
+    def __notebook_append_page(self, widget, text):
+        """ add a page to the notebook """
+        ntl = NotebookTabLabel(text)
+        page_nbr = self.notebook.append_page(widget, ntl)
+        ntl.connect("close-clicked", self.__notebook_page_close_clicked_cb, widget)
+
 
-    def quit_cb(self, action):
+    def __notebook_page_close_clicked_cb(self, button, widget):
+        """ remove a page from the notebook """
+        nbr = self.notebook.page_num(widget)
+        self.notebook.remove_page(nbr)
+
+
+    def __close_cb(self, action):
+        """ quit program """
         self._quit_dfeet(self.main_window, None)
 
-    def _quit_dfeet(self, main_window, event):
+
+    def __quit_dfeet(self, main_window, event):
+        """ quit d-feet application and store some settings """
         settings = Settings.get_instance()
         size = main_window.get_size()
         pos = main_window.get_position() 
@@ -211,24 +143,17 @@ class DFeetApp:
         settings.general['windowwidth'] = size[0]
         settings.general['windowheight'] = size[1]
 
-        n = self.notebook.get_n_pages()
-        tab_list = []
-        for i in xrange(n):
-            child = self.notebook.get_nth_page(i)
-            bus_watch = child.get_bus_watch()
-            tab_list.append(bus_watch.get_bus_name())
-
-        self.add_bus_history = self.add_bus_history[0:self.HISTORY_MAX_SIZE]
+        self.bus_history = self.bus_history[0:self.HISTORY_MAX_SIZE]
 
-        settings.general['bustabs_list'] = tab_list
-        settings.general['addbus_list'] = self.add_bus_history
-         
+        settings.general['addbus_list'] = self.bus_history
         settings.write()
-
         Gtk.main_quit()
 
+
     def run(self):
+        """ start the application """
         Gtk.main()
 
+
 if __name__ == "__main__":
     DFeetApp().run()
diff --git a/dfeet/_ui/__init__.py b/dfeet/_ui/__init__.py
index 5c8eacb..d7b0c3c 100644
--- a/dfeet/_ui/__init__.py
+++ b/dfeet/_ui/__init__.py
@@ -1,2 +1,2 @@
-from busbox import BusBox
+#from busbox import BusBox
 
diff --git a/dfeet/_ui/addconnectiondialog.py b/dfeet/_ui/addconnectiondialog.py
index 4cecaf0..643d2d0 100644
--- a/dfeet/_ui/addconnectiondialog.py
+++ b/dfeet/_ui/addconnectiondialog.py
@@ -1,34 +1,56 @@
-from gi.repository import Gtk
+from gi.repository import Gtk, Gio
 from uiloader import UILoader
 
 class AddConnectionDialog:
-    RESPONSE_CANCEL = -1
-    RESPONSE_CONNECT = 1
 
-    def __init__(self, parent):
-        ui = UILoader(UILoader.UI_ADDCONNECTIONDIALOG) 
+    def __init__(self, parent, address_bus_history=[]):
+        ui = UILoader(UILoader.UI_ADDCONNECTIONDIALOG)
 
         self.dialog = ui.get_root_widget()
-        self.combo_entry = ui.get_widget('address_comboentry1')
-        
-        self.combo_entry.get_child().connect('activate', self.activate_combo)
-        self.dialog.add_button('gtk-cancel', self.RESPONSE_CANCEL)
-        self.dialog.add_button('gtk-connect', self.RESPONSE_CONNECT)
 
-    def get_address(self):
-        return self.combo_entry.get_active_text()
+        #get the hbox and add address combo box with model
+        hbox1 = ui.get_widget('hbox1')
+        self.address_combo_box_store = Gtk.ListStore(str)
+        self.address_combo_box = Gtk.ComboBox.new_with_model_and_entry(self.address_combo_box_store)
+        self.address_combo_box.set_entry_text_column(0)
+        self.label_status = ui.get_widget('label_status')
+
+        hbox1.pack_start(self.address_combo_box, True, True, 0)
+        hbox1.show_all()
+
+        #add history to model
+        for el in address_bus_history:
+            self.address_combo_box_store.append([el])
+
+        self.dialog.add_button('gtk-cancel', Gtk.ResponseType.CANCEL)
+        self.dialog.add_button('gtk-connect', Gtk.ResponseType.OK)
+
+    
+    @property
+    def address(self):
+        tree_iter = self.address_combo_box.get_active_iter()
+        if tree_iter != None:
+            model = self.address_combo_box.get_model()
+            return model[tree_iter][0]
+        else:
+            entry = self.address_combo_box.get_child()
+            return entry.get_text()
 
     def run(self):
-        return self.dialog.run()
+        response = self.dialog.run()
+        if response == Gtk.ResponseType.CANCEL:
+            return response
+        elif response == Gtk.ResponseType.OK:
+            #check if given address is valid
+            try:
+                is_supported = Gio.dbus_is_supported_address(self.address)
+            except Exception, e:
+                self.label_status.set_text(str(e))
+                self.run()
+            else:
+                return Gtk.ResponseType.OK
+
 
     def destroy(self):
         self.dialog.destroy()
 
-    def activate_combo(self, user_data):
-        self.dialog.response(self.RESPONSE_CONNECT)
-        return True
-
-    def set_model(self, model):
-        self.combo_entry.set_model(model)
-        self.combo_entry.set_text_column(0)
-
diff --git a/dfeet/_ui/busnameinfobox.py b/dfeet/_ui/busnameinfobox.py
index c84f274..05d1d6f 100644
--- a/dfeet/_ui/busnameinfobox.py
+++ b/dfeet/_ui/busnameinfobox.py
@@ -1,6 +1,6 @@
-import gobject 
+from gi.repository import GObject as gobject 
 from gi.repository import Gtk
-import pango 
+from gi.repository import Pango as pango 
 
 from dfeet import _util
 from dfeet.introspect_data import IntrospectData, Method, Signal
diff --git a/dfeet/_ui/executemethoddialog.py b/dfeet/_ui/executemethoddialog.py
index 7a542ae..564303f 100644
--- a/dfeet/_ui/executemethoddialog.py
+++ b/dfeet/_ui/executemethoddialog.py
@@ -1,33 +1,13 @@
-from gi.repository import Gtk
-import dbus
-
-from dfeet import _util
-
-from uiloader import UILoader
-
+# -*- coding: utf-8 -*-
+import time
 from pprint import pformat
+from gi.repository import Gtk, GLib, Gio
 
-def unwrap(x):
-    """Hack to unwrap D-Bus values, so that they're easier to read when
-    printed."""
-
-    if isinstance(x, list):
-        return map(unwrap, x)
-
-    if isinstance(x, tuple):
-        return tuple(map(unwrap, x))
-
-    if isinstance(x, dict):
-        return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()])
-
-    for t in [unicode, str, long, int, float, bool]:
-        if isinstance(x, t):
-            return t(x)
+from uiloader import UILoader
 
-    return x
 
 class ExecuteMethodDialog:
-    def __init__(self, busname, method):
+    def __init__(self, connection, connection_is_bus, bus_name, method_obj):
         signal_dict = { 
                         'execute_dbus_method_cb' : self.execute_cb,
                         'execute_dialog_close_cb': self.close_cb
@@ -35,62 +15,102 @@ class ExecuteMethodDialog:
 
         ui = UILoader(UILoader.UI_EXECUTEDIALOG)
         self.dialog = ui.get_root_widget()
-        self.command_label = ui.get_widget('commandlabel1')
+        self.label_method_name = ui.get_widget('label_method_name')
+        self.label_object_path = ui.get_widget('label_object_path')
+        self.label_interface = ui.get_widget('label_interface')
         self.notebook = ui.get_widget('notebook1')
         self.parameter_textview = ui.get_widget('parametertextview1')
         self.source_textview = ui.get_widget('sourcetextview1')
-        self.notebook.set_tab_label_text(self.source_textview.get_parent(), 
-                                         'Source')
         self.prettyprint_textview = ui.get_widget('prettyprinttextview1')
-        self.notebook.set_tab_label_text(self.prettyprint_textview.get_parent(), 
-                                         'Pretty Print')
+        self.method_execution_count_spinbutton = ui.get_widget('method_exec_count_spinbutton')
+        self.label_avg = ui.get_widget('label_avg')
+        self.label_min = ui.get_widget('label_min')
+        self.label_max = ui.get_widget('label_max')
         ui.connect_signals(signal_dict)
 
-        self.busname = busname
-        self.method = method
+        self.connection = connection
+        self.connection_is_bus = connection_is_bus
+        self.bus_name = bus_name
+        self.method_obj = method_obj
 
-        # FIXME: get the interface and object path
-        text = 'Execute ' + str(self.method) 
-        self.command_label.set_text(text)
+        self.label_method_name.set_markup("%s" % (self.method_obj.markup_str))
+        self.label_object_path.set_markup("%s" % (self.method_obj.object_path))
+        self.label_interface.set_markup("%s" % (self.method_obj.iface_info.name))
 
     def execute_cb(self, widget):
-        # TODO: make call async, time it and add spinner to dialog 
+        #get given parameters
+        buf = self.parameter_textview.get_buffer()
+        params = buf.get_text(buf.get_start_iter(), 
+                              buf.get_end_iter(), False)
+
+        #reset the statistics stuff
+        self.label_avg.set_text("")
+        self.label_min.set_text("")
+        self.label_max.set_text("")
+        user_data = {
+            'avg': 0,
+            'count': 0,
+            }
+        
         try:
-            args = ()
-            buf = self.parameter_textview.get_buffer()
-            params = buf.get_text(buf.get_start_iter(), 
-                                  buf.get_end_iter())
+            #build a GVariant
             if params:
                 params = '(' + params + ',)'
-                args = eval(params, {'Boolean':dbus.Boolean,
-                                     'Byte':dbus.Byte,
-                                     'Int16':dbus.Int16,
-                                     'Int32':dbus.Int32,
-                                     'Int64':dbus.Int64,
-                                     'UInt16':dbus.UInt16,
-                                     'UInt32':dbus.UInt32,
-                                     'UInt64':dbus.UInt64,
-                                     'Double':dbus.Double,
-                                     'ObjectPath':dbus.ObjectPath,
-                                     'Signature':dbus.Signature,
-                                     'String':dbus.String,
-                                     'UTF8String':dbus.UTF8String})
-
-            result = self.method.dbus_call(self.busname.get_bus(), 
-                              self.busname.get_display_name(),
-                              *args)
-        except Exception, e: # FIXME: treat D-Bus errors differently
-                             #        from parameter errors?
-            result = str(e) 
-
-        if result is None:
-            result = 'This method did not return anything'
-
-        prettified = pformat(unwrap(result))
-        self.prettyprint_textview.get_buffer().set_text(prettified)
-
-        self.source_textview.get_buffer().set_text(str(result))
-
+                params_gvariant = GLib.Variant.parse(None, params, None, None)
+            else:
+                params_gvariant = None
+            
+            if self.connection_is_bus:
+                proxy = Gio.DBusProxy.new_sync(self.connection,
+                                               Gio.DBusProxyFlags.NONE, 
+                                               None, 
+                                               self.bus_name,
+                                               self.method_obj.object_path,
+                                               self.method_obj.iface_info.name,
+                                               None)
+                #call the function
+                for i in range(0, self.method_execution_count_spinbutton.get_value_as_int()):
+                    user_data['method_call_time_start'] = time.time()
+                    proxy.call(self.method_obj.method_info.name, params_gvariant, Gio.DBusCallFlags.NONE, -1, None, self.method_connection_bus_cb, user_data)
+            else:
+                #FIXME: implement p2p connection execution
+                raise Exception("Function execution on p2p connections not yet implemented")
+                #self.connection.call(None, object_path, self.method_obj.iface_obj.iface_info.name, self.method_obj.method_info.name, params_gvariant, GLib.VariantType.new("(s)"), Gio.DBusCallFlags.NONE, -1, None)
+
+            
+        except Exception, e:
+            #output the exception
+            self.source_textview.get_buffer().set_text(str(e))
+            self.prettyprint_textview.get_buffer().set_text(pformat(str(e)))
+
+
+    def method_connection_bus_cb(self, proxy, res_async, user_data):
+        """ async callback for executed method """
+        try:
+            #get the result from the dbus method call
+            result = proxy.call_finish(res_async)
+            #remember the needed time for the method call
+            method_call_time_end = time.time()
+            method_call_time_needed = method_call_time_end - user_data['method_call_time_start']
+            
+            #update avg, min, max
+            user_data['avg'] += method_call_time_needed
+            user_data['count'] += 1
+            self.label_avg.set_text("%.4f" % (float(user_data['avg'] / user_data['count'])))
+            self.label_min.set_text("%.4f" % min(float(self.label_min.get_text() or "999"), method_call_time_needed))
+            self.label_max.set_text("%.4f" % max(float(self.label_max.get_text() or "0"), method_call_time_needed))
+
+            #output result
+            if result:
+                self.source_textview.get_buffer().set_text(str(result))
+                self.prettyprint_textview.get_buffer().set_text(str(result.unpack()[0]))
+            else:
+                self.prettyprint_textview.get_buffer().set_text('This method did not return anything')
+        except Exception, e:
+            #output the exception
+            self.source_textview.get_buffer().set_text(str(e))
+            self.prettyprint_textview.get_buffer().set_text(pformat(str(e)))
+                
     def run(self):
         self.dialog.run()
 
diff --git a/dfeet/_ui/uiloader.py b/dfeet/_ui/uiloader.py
index a25ead1..2a38875 100644
--- a/dfeet/_ui/uiloader.py
+++ b/dfeet/_ui/uiloader.py
@@ -1,41 +1,40 @@
+# -*- coding: utf-8 -*-
+import os
 from gi.repository import Gtk
 
-from dfeet import _util
 
 class UILoader:
     instance = None
     
-    UI_COUNT = 5 
+    UI_COUNT = 5
 
     (UI_MAINWINDOW,
-     UI_FILTERBOX,
-     UI_INTROSPECTVIEW,
+     UI_INTROSPECTION,
+     UI_BUSWATCH,
      UI_EXECUTEDIALOG,
      UI_ADDCONNECTIONDIALOG
     ) = range(UI_COUNT)
 
     # {ui_id: ((files,...), root widget)}
-    _ui_map = {UI_MAINWINDOW     : (('default-actiongroup.ui','mainwindow.ui'), 
-                                    'appwindow1'),
-               UI_FILTERBOX      : (('filterbox.ui',),
-                                    'filterbox_table1'),
-               UI_INTROSPECTVIEW : (('introspectview.ui',),
-                                    'introspectview_table1'),
-               UI_EXECUTEDIALOG  : (('executedialog.ui',),
-                                    'executedialog1'),
+    _ui_map = {UI_MAINWINDOW           : (('mainwindow.ui',), 
+                                          'appwindow1'),
+               UI_INTROSPECTION        : (('introspection.ui',),
+                                          'box_introspectview'),
+               UI_BUSWATCH             : (('buswatch.ui',),
+                                          'paned_buswatch'),
+               UI_EXECUTEDIALOG        : (('executedialog.ui',),
+                                          'executedialog1'),
                UI_ADDCONNECTIONDIALOG  : (('addconnectiondialog.ui',),
                                           'add_connection_dialog1')
               }
 
     def __init__(self, ui):
-        ui_dir = _util.get_ui_dir()
-       
         ui_info = self._ui_map[ui]
         self.ui = Gtk.Builder()
 
         #load ui files
         for file in ui_info[0]:
-            self.ui.add_from_file(ui_dir + '/' + file)
+            self.ui.add_from_file(self.ui_dir + '/' + file)
 
         self.root_widget_name = ui_info[1]
 
@@ -48,3 +47,12 @@ class UILoader:
     def connect_signals(self, obj_or_map):
         self.ui.connect_signals(obj_or_map)
 
+    @property
+    def ui_dir(self):
+        try:
+            ui_dir = os.environ['DFEET_DATA_PATH']
+        except:
+            ui_dir = "../ui"
+            
+        return ui_dir 
+
diff --git a/dfeet/_ui/wnck_utils.py b/dfeet/_ui/wnck_utils.py
index a5f1e21..3b77e9a 100644
--- a/dfeet/_ui/wnck_utils.py
+++ b/dfeet/_ui/wnck_utils.py
@@ -2,7 +2,7 @@
 # icon information. If the wnck module is not installed we fallback to default
 # behvior
 
-import gobject
+from gi.repository import GObject as gobject
 from gi.repository import Gtk
 
 try:
diff --git a/dfeet/bus_watch.py b/dfeet/bus_watch.py
new file mode 100644
index 0000000..f3db940
--- /dev/null
+++ b/dfeet/bus_watch.py
@@ -0,0 +1,215 @@
+# -*- coding: utf-8 -*-
+
+import os
+from gi.repository import GObject, GdkPixbuf, Gtk, Gio, GLib
+from _ui.uiloader import UILoader
+from introspection import AddressInfo
+
+
+class DBusBusName(GObject.GObject):
+    """ class to represent a name on the bus """
+    def __init__(self, bus_name_unique):
+        super(DBusBusName, self).__init__()
+        self.__bus_name_unique = bus_name_unique
+        self.__pid = 0
+        self.__cmdline = ''
+
+    def __repr__(self):
+        return u"%s (pid: %s)" % (self.bus_name_unique, self.pid)
+
+    def __update_cmdline(self):
+        if self.pid > 0:
+            procpath = '/proc/' + str(self.pid) + '/cmdline'
+            with open(procpath, 'r') as f:
+                self.__cmdline = " ".join(f.readline().split('\0'))
+        else:
+            self.__cmdline = ''
+
+    @property
+    def bus_name_unique(self):
+        return self.__bus_name_unique
+
+    @property
+    def pid(self):
+        return self.__pid
+    
+    @pid.setter
+    def pid(self, pid_new):
+        self.__pid = pid_new
+        try:
+            self.__update_cmdline()
+        except Exception, e:
+            self.__cmdline = ''
+
+    @property
+    def cmdline(self):
+        return self.__cmdline
+
+
+class BusWatch:
+    """ watch for a given bus """
+    def __init__(self, address):
+        self.address = address
+        #setup UI
+        ui = UILoader(UILoader.UI_BUSWATCH)
+        self.paned_buswatch = ui.get_root_widget()
+        self.liststore_model = ui.get_widget('liststore_buswatch')
+        self.treeview = ui.get_widget('treeview_buswatch')
+        self.entry_filter = ui.get_widget('entry_filter')
+        self.grid_bus_name_selected_info = ui.get_widget('grid_bus_name_info')
+        self.label_bus_name_selected_name = ui.get_widget('label_bus_name_selected_name')
+        self.label_bus_name_selected_pid = ui.get_widget('label_bus_name_selected_pid')
+        self.label_bus_name_selected_cmdline = ui.get_widget('label_bus_name_selected_cmdline')
+        self.addr_info = None # hold the currently selected AddressInfo object
+        
+        self.treeview.connect('cursor-changed',
+                               self.__tree_view_cursor_changed_cb)
+
+
+        #setup the conection
+        if self.address == Gio.BusType.SYSTEM or self.address == Gio.BusType.SESSION:
+            self.connection = Gio.bus_get_sync(self.address, None)
+        elif Gio.dbus_is_supported_address(self.address) == True:
+            self.connection = Gio.DBusConnection.new_for_address_sync(self.address,
+                                                                      Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT | Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION,
+                                                                      None, None)
+
+        #setup signals
+        self.connection.signal_subscribe(None, "org.freedesktop.DBus", "NameOwnerChanged",
+                                         None, None, 0, self.__name_owner_changed_cb, None)
+
+        self.bus_proxy = Gio.DBusProxy.new_sync(self.connection,
+                                                Gio.DBusProxyFlags.NONE, 
+                                                None, 
+                                                'org.freedesktop.DBus',
+                                                '/org/freedesktop/DBus',
+                                                'org.freedesktop.DBus', None)
+
+        #list all names
+        self.bus_proxy.ListNames('()',
+                                 result_handler=self.__list_names_handler,
+                                 error_handler=self.__list_names_error_handler)
+
+    def __tree_view_cursor_changed_cb(self, treeview):
+        """ do something when a row is selected """
+        selection = self.treeview.get_selection()
+        if selection:
+            model, iter = selection.get_selected()
+            if not iter:
+                return
+        
+            bus_name_obj = model.get(iter, 0)[0]
+            #remove current child
+            c2 = self.paned_buswatch.get_child2()
+            if c2:
+                c2.destroy()
+            try:
+                del(self.addr_info)
+            except:
+                pass
+
+            #add Introspection to paned
+            self.addr_info = AddressInfo(self.address, bus_name_obj.bus_name_unique, connection_is_bus=True)
+            self.paned_buswatch.add2(self.addr_info.introspect_box)
+            
+            #update info about selected bus name
+            self.label_bus_name_selected_name.set_text(bus_name_obj.bus_name_unique)
+            self.label_bus_name_selected_pid.set_text("%s" % bus_name_obj.pid)
+            self.label_bus_name_selected_cmdline.set_text(bus_name_obj.cmdline)
+            self.grid_bus_name_selected_info.set_visible(True)
+            
+
+    def __liststore_model_add(self, bus_name_obj):
+        """ add a DBusBusName object to the liststore model """
+        #update bus info stuff
+        self.bus_proxy.GetConnectionUnixProcessID('(s)', bus_name_obj.bus_name_unique, 
+                                                  result_handler = self.__get_unix_process_id_cb,
+                                                  error_handler =  self.__get_unix_process_id_error_cb,
+                                                  user_data=bus_name_obj)
+        #add bus to liststore
+        return self.liststore_model.append([bus_name_obj, 0, u"%s" % (bus_name_obj.bus_name_unique), bus_name_obj.cmdline])
+
+
+    def __liststore_model_remove(self, bus_name_obj):
+        """ remove a DBusBusName object to the liststore model """
+        for n, obj in enumerate(self.liststore_model):
+            if obj[2] == bus_name_obj.bus_name_unique:
+                del(self.liststore_model[n])
+                break
+    
+    def __liststore_model_get(self, bus_name_obj):
+        """ get a object from the liststore """
+        for n, obj in enumerate(self.liststore_model):
+            if obj[2] == bus_name_obj.bus_name_unique:
+                return obj
+        raise Exception("bus name object '%s' not found in liststore" % (bus_name_obj))
+
+
+    def __name_owner_changed_cb(self, connection, sender_name, object_path, interface_name, signal_name, parameters, user_data):
+        """ bus name added or removed """
+        bus_name = parameters[0]
+        old_owner = parameters[1]
+        new_owner = parameters[2]
+
+        bus_name_obj = DBusBusName(bus_name)
+
+        if bus_name[0] == ':':
+            if not old_owner:
+                self.__liststore_model_add(bus_name_obj)
+            else:
+                self.__liststore_model_remove(bus_name_obj)
+        else :
+            if new_owner:
+                self.__liststore_model_add(bus_name_obj)
+            if old_owner:
+                self.__liststore_model_remove(bus_name_obj)
+
+
+    def __list_names_handler(self, obj, names, userdata):
+        for n in names:
+            bus_name_obj = DBusBusName(n)
+            self.__liststore_model_add(bus_name_obj)
+
+
+    def __list_names_error_handler(self, obj, error, userdata):
+        print "error getting bus names: %s" % str(error)
+
+
+    def __get_unix_process_id_cb(self, obj, pid, bus_name_obj):
+        bus_name_obj.pid = pid
+
+
+    def __get_unix_process_id_error_cb(self, obj, error, bus_name_obj):
+        print "error getting unix process id for %s: %s" % (bus_name_obj.bus_name_unique, str(error))
+        bus_name_obj.pid = 0
+
+
+if __name__ == "__main__":
+    """ for debugging """
+    import sys
+    import argparse
+
+    parser = argparse.ArgumentParser(description='show a given bus address')
+    parser.add_argument('addr')
+    p = parser.parse_args()
+
+    if p.addr.lower() == 'system':
+        addr = Gio.BusType.SYSTEM
+    elif p.addr.lower() == 'session':
+        addr = Gio.BusType.SESSION
+    else:
+        addr = p.addr
+
+    bw = BusWatch(addr)
+
+    win = Gtk.Window()
+    win.connect("delete-event", Gtk.main_quit)
+    win.set_default_size(1024, 768)
+    win.add(bw.paned_buswatch)
+    win.show_all()
+    try:
+        Gtk.main()
+    except (KeyboardInterrupt, SystemExit):
+        Gtk.main_quit()
+
+        
diff --git a/dfeet/dbus_utils.py b/dfeet/dbus_utils.py
index 10554bf..fa38ba5 100644
--- a/dfeet/dbus_utils.py
+++ b/dfeet/dbus_utils.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 def convert_complex_type(subsig):
     result = None
     len_consumed = 0
diff --git a/dfeet/introspection.py b/dfeet/introspection.py
new file mode 100644
index 0000000..a37a811
--- /dev/null
+++ b/dfeet/introspection.py
@@ -0,0 +1,229 @@
+# -*- coding: utf-8 -*-
+
+from gi.repository import GObject, Gdk, GdkPixbuf, Gtk, Gio, Pango, GLib
+import dbus_utils
+from _ui.executemethoddialog import ExecuteMethodDialog
+import time
+
+from _ui.uiloader import UILoader
+
+from introspection_helper import DBusNode, DBusInterface, DBusProperty, DBusSignal, DBusMethod
+
+
+class AddressInfo():
+    """
+    class to handle information about a name (eg "org.freedesktop.NetworkManager")
+    on a given address (eg Gio.BusType.SYSTEM or unix:path=/var/run/dbus/system_bus_socket)
+    """
+    def __init__(self, address, name, connection_is_bus=True):
+        self.address = address # can be Gio.BusType.SYSTEM or Gio.BusType.SYSTEM or an other address
+        self.name = name
+        self.connection_is_bus = connection_is_bus # is it a bus or a p2p connection?
+        self.introspect_time = -1 # time needed to introspect the given bus name (in seconds)
+
+        #setup UI
+        ui = UILoader(UILoader.UI_INTROSPECTION)
+        self.introspect_box = ui.get_root_widget()
+        self.tree_model = ui.get_widget('treestore')
+        self.treeview = ui.get_widget('treeview')
+        button_reload = ui.get_widget('button_reload')
+        self.label_name = ui.get_widget('label_name')
+        self.label_unique_name = ui.get_widget('label_unique_name')
+        self.label_address = ui.get_widget('label_address')
+        cr_name = Gtk.CellRendererText()
+        col_name = Gtk.TreeViewColumn()
+        col_name.pack_start(cr_name, True)
+        col_name.add_attribute(cr_name, 'markup', 0)
+        self.treeview.append_column(col_name)
+
+        #connect signals
+        button_reload.connect("clicked", self.__on_button_reload_clicked, self)
+        self.treeview.connect('cursor-changed',
+                               self.tree_view_cursor_changed_cb)
+        self.treeview.connect('row-activated', 
+                               self.tree_view_row_activated_cb)
+
+        if self.connection_is_bus:
+            #we expect a bus connection
+            if self.address == Gio.BusType.SYSTEM or self.address == Gio.BusType.SESSION:
+                self.connection = Gio.bus_get_sync(self.address, None)
+                self.label_address.set_text(Gio.dbus_address_get_for_bus_sync(self.address, None))
+            elif Gio.dbus_is_supported_address(self.address) == True:
+                self.connection = Gio.DBusConnection.new_for_address_sync(self.address,
+                                                                          Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT | Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION,
+                                                                          None, None)
+                self.label_address.set_text(self.address)
+            else:
+                self.connection = None
+                raise Exception("Invalid bus address '%'" % (self.address))
+        else:
+            #we have a peer-to-peer connection
+            if Gio.dbus_is_supported_address(self.address) == True:
+                self.connection = Gio.DBusConnection.new_for_address_sync(self.address,
+                                                                          Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
+                                                                          None, None)
+                self.label_address.set_text(self.address)
+            else:
+                self.connection = None
+                raise Exception("Invalid p2p address '%'" % (self.address))
+            
+        #start processing data
+        self.introspect()
+        self.treeview.expand_all() #FIXME: only good for testing!
+    
+    def tree_view_cursor_changed_cb(self, treeview):
+        """ do something when a row is selected """
+        selection = self.treeview.get_selection()
+        if selection:
+            model, iter = selection.get_selected()
+            if not iter:
+                return
+        
+            node_obj = model.get(iter, 1)[0]
+            #print "NODE: %s" % (node_obj)
+
+    def tree_view_row_activated_cb(self, treeview, path, view_column):
+        model = treeview.get_model() 
+        iter = model.get_iter(path)
+
+        obj = model.get_value(iter, 1)
+
+        if isinstance(obj, DBusMethod):
+            #execute the selected method
+            dialog = ExecuteMethodDialog(self.connection, self.connection_is_bus, self.name, obj)
+            dialog.run()
+        elif isinstance(obj, DBusProperty):
+            #update the selected property (TODO: do this async)
+            proxy = Gio.DBusProxy.new_sync(self.connection,
+                                           Gio.DBusProxyFlags.NONE, 
+                                           None, 
+                                           self.name,
+                                           obj.object_path,
+                                           "org.freedesktop.DBus.Properties", None)
+            args = GLib.Variant('(ss)', (obj.iface_info.name, obj.property_info.name))
+            result = proxy.call_sync("Get", args, 0, -1, None)
+            #update the object value so markup string is calculated correct
+            obj.value = result[0]
+            #set new markup string
+            model[iter][0] = obj.markup_str
+        else:
+            if treeview.row_expanded(path):
+                treeview.collapse_row(path)
+            else:
+                treeview.expand_row(path, False)
+
+
+    def introspect(self):
+        """ introspect the given bus name and update the tree model """
+        #cleanup current tree model
+        self.tree_model.clear()
+        #start introspection and measure introspection time
+        introspect_start = time.time()
+        self.__dbus_node_introspect(self.name, "/")
+        self.introspect_time = time.time() - introspect_start
+        #update name, unique name, ...
+        self.label_name.set_text(self.name)
+        try:
+            self.label_unique_name.set_text(self.connection.get_unique_name())
+        except:
+            pass
+
+
+    def __on_button_reload_clicked(self, widget, address_info):
+        """ reload the introspection data """
+        address_info.introspect()
+        print "needed %.3f s to introspect name '%s'" % (address_info.introspect_time, address_info.name)
+
+
+    def __dbus_node_introspect(self, name, object_path):
+        """ iterate over the given object_path and introspect the path recursive """
+        tree_iter = None
+        if self.connection_is_bus:
+            proxy = Gio.DBusProxy.new_sync(self.connection,
+                                           Gio.DBusProxyFlags.NONE, 
+                                           None, 
+                                           name,
+                                           object_path,
+                                           'org.freedesktop.DBus.Introspectable', None)
+            node_info = Gio.DBusNodeInfo.new_for_xml(proxy.Introspect())
+        else:
+            res = self.connection.call_sync(None, object_path, 'org.freedesktop.DBus.Introspectable', 'Introspect', None, GLib.VariantType.new("(s)"), Gio.DBusCallFlags.NONE, -1, None)
+            node_info = Gio.DBusNodeInfo.new_for_xml(res[0])
+
+        #create a GObject node and add to tree-model
+        if len(node_info.interfaces) > 0:
+            node_obj = DBusNode(name, object_path, node_info)
+            tree_iter = self.tree_model.append(tree_iter, ["%s" % object_path, node_obj])
+            #tree_iter = self.tree_model.append(tree_iter, ["Hallo", None])
+
+            #append interfaces to tree model
+            if len(node_info.interfaces) > 0:
+                name_iter = self.tree_model.append(tree_iter, ["<b>Interfaces</b>", None])
+                for iface in node_info.interfaces:
+                    iface_obj = DBusInterface(node_obj, iface)
+                    iface_iter = self.tree_model.append(name_iter, ["%s" % iface.name, iface_obj])
+                    #interface methods
+                    if len(iface.methods) > 0:
+                        iface_methods_iter = self.tree_model.append(iface_iter, ["<b>Methods</b>", None])
+                        for iface_method in iface.methods:
+                            method_obj = DBusMethod(iface_obj, iface_method)
+                            self.tree_model.append(iface_methods_iter, ["%s" % method_obj.markup_str, method_obj])
+                    #interface signals
+                    if len(iface.signals) > 0:
+                        iface_signals_iter = self.tree_model.append(iface_iter, ["<b>Signals</b>", None])
+                        for iface_signal in iface.signals:
+                            signal_obj = DBusSignal(iface_obj, iface_signal)
+                            self.tree_model.append(iface_signals_iter, ["%s" % signal_obj.markup_str, signal_obj])
+                    #interface properties
+                    if len(iface.properties) > 0:
+                        iface_properties_iter = self.tree_model.append(iface_iter, ["<b>Properties</b>", None])
+                        for iface_property in iface.properties:
+                            property_obj = DBusProperty(iface_obj, iface_property)
+                            self.tree_model.append(iface_properties_iter, ["%s" % property_obj.markup_str, property_obj])
+                    #interface annotations #FIXME: add Annotation object!!!
+                    if len(iface.annotations) > 0:
+                        iface_annotations_iter = self.tree_model.append(iface_iter, ["<b>Annotations</b>", None])
+                        for iface_annotation in iface.annotations:
+                            self.tree_model.append(iface_annotations_iter, ["%s" % iface_annotation.name, iface_annotation])
+                    
+
+        for node in node_info.nodes:
+            #node_iter = self.tree_model.append(tree_iter, [node.path, node])
+            if object_path == "/":
+                object_path = ""
+            object_path_new = object_path + "/" + node.path
+            self.__dbus_node_introspect(name, object_path_new)
+
+
+
+if __name__ == "__main__":
+    """ for debugging """
+    import sys
+    import argparse
+
+    parser = argparse.ArgumentParser(description='introspect a given dbus address and name')
+    parser.add_argument('-p', '--p2p', action='store_true', default=False)
+    parser.add_argument('addr')
+    parser.add_argument('name')
+    p = parser.parse_args()
+
+    if p.addr.lower() == 'system':
+        addr = Gio.BusType.SYSTEM
+    elif p.addr.lower() == 'session':
+        addr = Gio.BusType.SESSION
+    else:
+        addr = p.addr
+
+    
+    name = p.name
+    ai = AddressInfo(addr, name, not p.p2p)
+
+    win = Gtk.Window()
+    win.connect("delete-event", Gtk.main_quit)
+    win.set_default_size(1024, 768)
+    win.add(ai.introspect_box)
+    win.show_all()
+    try:
+        Gtk.main()
+    except (KeyboardInterrupt, SystemExit):
+        Gtk.main_quit()
diff --git a/dfeet/introspection_helper.py b/dfeet/introspection_helper.py
new file mode 100644
index 0000000..d7214eb
--- /dev/null
+++ b/dfeet/introspection_helper.py
@@ -0,0 +1,218 @@
+# -*- coding: utf-8 -*-
+
+from gi.repository import GObject, Gio, GLib
+import dbus_utils
+
+
+def args_signature_markup(arg_signature):
+    return '<small><span foreground="#2E8B57">%s</span></small>' % (arg_signature)
+
+def args_name_markup(arg_name):
+    return '<small><span foreground="#000000">%s</span></small>' % (arg_name)
+
+
+
+class DBusNode(GObject.GObject):
+    """ object to represent a DBus Node (object path) """
+    def __init__(self, name, object_path, node_info):
+        GObject.GObject.__init__(self)
+        self.__name = name
+        self.__object_path = object_path
+        self.__node_info = node_info # Gio.GDBusNodeInfo object
+
+    def __repr__(self):
+        return u"Name: %s ; ObjPath: %s ; NodeInfo: %s" % (self.name, self.object_path, self.node_info)
+
+    @property
+    def name(self):
+        return self.__name
+
+    @property
+    def object_path(self):
+        return self.__object_path
+
+    @property
+    def node_info(self):
+        return self.__node_info
+
+
+class DBusInterface(DBusNode):
+    """ object to represent a DBus Interface """
+    def __init__(self, dbus_node_obj, iface_info):
+        DBusNode.__init__(self, dbus_node_obj.name, dbus_node_obj.object_path, dbus_node_obj.node_info)
+        self.__iface_info = iface_info # Gio.GDBusInterfaceInfo object
+
+    def __repr__(self):
+        return u"iface '%s' on node '%s'" % (self.iface_info.name, self.node_info.path)
+
+    @property
+    def iface_info(self):
+        return self.__iface_info
+
+
+class DBusProperty(DBusInterface):
+    """ object to represent a DBus Property """
+    def __init__(self, dbus_iface_obj, property_info):
+        DBusInterface.__init__(self, dbus_iface_obj, dbus_iface_obj.iface_info)
+        self.__property_info = property_info # Gio.GDBusPropertyInfo object
+        self.__value = None #the value
+
+    def __repr__(self):
+        sig = dbus_utils.sig_to_string(self.property_info.signature)
+        return u"%s %s (%s)" % (sig, self.property_info.name, self.property_info.flags)
+
+    @property
+    def property_info(self):
+        return self.__property_info
+
+    @property
+    def value(self):
+        return self.__value
+
+    @value.setter
+    def value(self, new_val):
+        self.__value = new_val
+
+
+    @property
+    def markup_str(self):
+        sig = dbus_utils.sig_to_string(self.property_info.signature)
+        readwrite = list()
+        if self.readable:
+            readwrite.append("read")
+        if self.writable:
+            readwrite.append("write")
+        s = "%s %s <small>(%s)</small>" % (args_signature_markup(sig), args_name_markup(self.property_info.name), " / ".join(readwrite))
+        if self.value:
+            s += " = %s" % (self.value)
+        return s
+
+    @property
+    def readable(self):
+        if int(self.property_info.flags) == int(Gio.DBusPropertyInfoFlags.READABLE) or int(self.property_info.flags) == (int(Gio.DBusPropertyInfoFlags.WRITABLE | Gio.DBusPropertyInfoFlags.READABLE)):
+            return True
+        else:
+            return False
+
+    @property
+    def writable(self):
+        if int(self.property_info.flags) == int(Gio.DBusPropertyInfoFlags.WRITABLE) or int(self.property_info.flags) == (int(Gio.DBusPropertyInfoFlags.WRITABLE | Gio.DBusPropertyInfoFlags.READABLE)):
+            return True
+        else:
+            return False
+
+
+class DBusSignal(DBusInterface):
+    """ object to represent a DBus Signal """
+    def __init__(self, dbus_iface_obj, signal_info):
+        DBusInterface.__init__(self, dbus_iface_obj, dbus_iface_obj.iface_info)
+        self.__signal_info = signal_info #Gio.GDBusSignalInfo object
+
+    def __repr__(self):
+        return u"%s" % (self.signal_info.name)
+    
+    @property
+    def signal_info(self):
+        return self.__signal_info
+
+    @property
+    def args(self):
+        args = list()
+        for arg in self.signal_info.args:
+            sig = dbus_utils.sig_to_string(arg.signature)
+            args.append({'signature': sig, 'name': arg.name})
+        return args
+
+    @property
+    def args_markup_str(self):
+        result = ''
+        result += '<span foreground="#FF00FF">(</span>'
+        result += ', '.join('%s' % (args_signature_markup(arg['signature'])) for arg in self.args)
+        result += '<span foreground="#FF00FF">)</span>'
+        return result
+
+    @property
+    def markup_str(self):
+        return "%s %s" % (self.signal_info.name, self.args_markup_str)
+
+
+class DBusMethod(DBusInterface):
+    """ object to represent a DBus Method """
+    def __init__(self, dbus_iface_obj, method_info):
+        DBusInterface.__init__(self, dbus_iface_obj, dbus_iface_obj.iface_info)
+        self.__method_info = method_info #Gio.GDBusMethodInfo object
+
+    def __repr__(self):
+        return u"%s(%s) â %s (%s)" % (self.method_info.name, self.in_args_str, self.out_args_str, DBusInterface.__repr__(self))
+
+    @property
+    def method_info(self):
+        return self.__method_info
+
+    @property
+    def iface_info(self):
+        return super(DBusMethod, self).iface_info
+
+    @property
+    def name(self):
+        return super(DBusMethod, self).name
+
+    @property
+    def object_path(self):
+        return super(DBusMethod, self).object_path
+
+    @property
+    def node_info(self):
+        return super(DBusMethod, self).node_info
+
+    @property
+    def markup_str(self):
+        return u"%s %s <b>â</b> %s" % (self.method_info.name, self.in_args_markup_str, self.out_args_markup_str)
+
+    @property
+    def in_args(self):
+        in_args = list()
+        for in_arg in self.method_info.in_args:
+            sig = dbus_utils.sig_to_string(in_arg.signature)
+            in_args.append({'signature': sig, 'name': in_arg.name})
+        return in_args
+
+    @property
+    def out_args(self):
+        out_args = list()
+        for out_arg in self.method_info.out_args:
+            sig = dbus_utils.sig_to_string(out_arg.signature)
+            out_args.append({'signature': sig, 'name': out_arg.name})
+        return out_args
+    
+    @property
+    def in_args_str(self):
+        result = u''
+        for arg in self.in_args:
+            result += "%s %s, " % (arg['signature'], arg['name'])
+        
+        return result[0:-2]
+
+    @property
+    def out_args_str(self):
+        result = u''
+        for arg in self.out_args:
+            result += "%s %s, " % (arg['signature'], arg['name'])
+        
+        return result[0:-2]
+
+    def __args_markup_str(self, args):
+        """ markup a given list of args """
+        result = ''
+        result += '<span foreground="#FF00FF">(</span>'
+        result += ', '.join('%s %s' % (args_signature_markup(arg['signature']), args_name_markup(arg['name'])) for arg in args)
+        result += '<span foreground="#FF00FF">)</span>'
+        return result
+
+    @property
+    def in_args_markup_str(self):
+        return self.__args_markup_str(self.in_args)
+    
+    @property
+    def out_args_markup_str(self):
+        return self.__args_markup_str(self.out_args)
diff --git a/tests/tests.py b/tests/tests.py
new file mode 100755
index 0000000..bb58ffd
--- /dev/null
+++ b/tests/tests.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+import sys, os
+sys.path.insert(0, os.path.abspath(os.path.join(__file__, "../../")))
+
+from gi.repository import Gtk, Gio, GLib
+from dfeet.introspection import AddressInfo
+from dfeet.introspection_helper import DBusNode, DBusInterface, DBusProperty, DBusSignal, DBusMethod
+import unittest
+import time
+
+XML = """
+<node>
+  <interface name='org.gnome.d-feet.TestInterface'>
+    <method name='HelloWorld'>
+      <arg type='s' name='greeting' direction='in'/>
+      <arg type='s' name='response' direction='out'/>
+    </method>
+    <property name="TestString" type="s" access="readwrite"/>
+    <property name="TestBool" type="b" access="read"/>
+    <signal name="TestSignal">
+      <arg name="SigString" type="s"/>
+      <arg name="SigBool" type="b"/>
+    </signal>
+  </interface>
+</node>
+"""
+
+class IntrospectionHelperTest(unittest.TestCase):
+    """ tests for the introspection helper classes """
+    def setUp(self):
+        self.name = "org.gnome.d-feet"
+        self.object_path = "/org/gnome/d-feet"
+        self.node_info = Gio.DBusNodeInfo.new_for_xml(XML)
+
+    def test_dbus_node_info(self):
+        """ test DBusNode class """
+        obj_node = DBusNode(self.name, self.object_path, self.node_info)
+        self.assertEqual(obj_node.name, self.name)
+        self.assertEqual(obj_node.object_path, self.object_path)
+        self.assertEqual(len(obj_node.node_info.interfaces), 1)
+
+    def test_dbus_interface(self):
+        """ test DBusInterface class """
+        obj_node = DBusNode(self.name, self.object_path, self.node_info)
+        obj_iface = DBusInterface(obj_node, obj_node.node_info.interfaces[0])
+        self.assertEqual(obj_iface.name, self.name)
+        self.assertEqual(obj_iface.object_path, self.object_path)
+        self.assertEqual(len(obj_iface.iface_info.methods), 1)
+        self.assertEqual(len(obj_iface.iface_info.properties), 2)
+        self.assertEqual(len(obj_iface.iface_info.signals), 1)
+
+    def test_dbus_property(self):
+        """ test DBusProperty class """
+        obj_node = DBusNode(self.name, self.object_path, self.node_info)
+        obj_iface = DBusInterface(obj_node, obj_node.node_info.interfaces[0])
+        obj_prop = DBusProperty(obj_iface, obj_iface.iface_info.properties[0])
+        self.assertEqual(obj_prop.name, self.name)
+        self.assertEqual(obj_prop.object_path, self.object_path)
+
+    def test_dbus_signal(self):
+        """ test DBusSignal class """
+        obj_node = DBusNode(self.name, self.object_path, self.node_info)
+        obj_iface = DBusInterface(obj_node, obj_node.node_info.interfaces[0])
+        obj_sig = DBusSignal(obj_iface, obj_iface.iface_info.signals[0])
+        self.assertEqual(obj_sig.name, self.name)
+        self.assertEqual(obj_sig.object_path, self.object_path)
+
+
+class AddressInfoTest(unittest.TestCase):
+    """ tests for the AddressInfo class and the introspection stuff """
+
+    def test_system_bus(self):
+        """ introspect a name on the system bus """
+        ai = AddressInfo(Gio.BusType.SYSTEM, "org.freedesktop.DBus")
+
+    def test_session_bus(self):
+        """ introspect a name on the session bus """
+        return
+        ai = AddressInfo(Gio.BusType.SESSION, "org.freedesktop.DBus")
+
+    def test_other_bus(self):
+        """ test another bus """
+        return 
+        sysbus_addr = os.getenv("DBUS_SYSTEM_BUS_ADDRESS")
+        ai = AddressInfo(sysbus_addr, "org.freedesktop.DBus")
+        #TODO: create another bus and test with the other bus
+    
+    @unittest.skip("TODO:peer to peer test not implemented")
+    def test_peer_to_peer(self):
+        """ test a p2p connection """
+        #TODO: setup a gdbus server and test a peer to peer connection
+        #(see http://developer.gnome.org/gio/unstable/GDBusServer.html#gdbus-peer-to-peer)
+        pass
+
+if __name__ == "__main__":
+    #FIXME: this is copied from the file "f-deet"
+    ENV_PATHS = {"DFEET_DATA_PATH" : "ui/",
+                 "DFEET_IMAGE_PATH" : "ui/",
+                 "DFEET_LOCALE_PATH" : "locale/",
+                 "DFEET_HELP_PATH" : "/usr/share/gnome/dfeet/"
+                 }
+    for var, path in ENV_PATHS.iteritems():
+        os.environ.setdefault(var, path)
+
+    #run tests
+    unittest.main()
diff --git a/tests/tests.py~ b/tests/tests.py~
new file mode 100755
index 0000000..9a49ded
--- /dev/null
+++ b/tests/tests.py~
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import sys, os
+sys.path.insert(0, os.path.abspath(os.path.join(__file__, "../../")))
+
+from gi.repository import Gtk, Gio, GLib
+from dfeet.gdbus_introspector import BusNameInfo
+import threading
+import unittest
+import time
+
+
+class DBusServer:
+    """ a dbus server for testing. Sever runs inside a thread """
+    XML = '''
+<node>
+  <interface name='de.toabctl.Demo.Hello'>
+    <method name='hello'>
+      <arg type='s' name='ping' direction='in'/>
+      <arg type='s' name='pong' direction='out'/>
+    </method>
+  </interface>
+</node>'''
+    def __init__(self, addr):
+        self.addr = addr
+        self.server = Gio.DBusServer.new_sync(self.addr,
+                                              Gio.DBusServerFlags.AUTHENTICATION_ALLOW_ANONYMOUS,
+                                              Gio.dbus_generate_guid(),
+                                              None, None)
+        self.server.start()
+        self.server.connect("new-connection", self.new_connection_cb, self)
+        self.loop = GLib.MainLoop()
+        self.vtable = Gio.DBusInterfaceVTable()
+        self.vtable.method_call(self.handle_method_call_cb)
+        self.vtable.get_property(None)
+        self.vtable.set_property(None)
+    
+    def handle_method_call_cb(self, connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
+        print "method call"
+        if method_name == "hello":
+            ret = GLib.Variant(("s"), ("Adios"))  
+            involcation.return_value(ret)
+
+    def new_connection_cb(self, server, connection, user_data):
+        print "new connection"
+        connection.register_object("/de/toabctl/Demo/", DBusServer.XML,
+                                   self.vtable, None, None)
+
+    def start(self):
+        self.loop.run()
+
+    def quit(self):
+        self.server.stop()
+        self.loop.quit()
+
+class Introspector(unittest.TestCase):
+    """ tests for gdbus_introspector.py """
+
+    def test_system_bus(self):
+        return
+        bni = BusNameInfo(Gio.BusType.SYSTEM, "org.freedesktop.DBus")
+
+    def test_session_bus(self):
+        return 
+        bni = BusNameInfo(Gio.BusType.SESSION, "org.freedesktop.DBus")
+
+if __name__ == '__main__':
+    #FIXME: this is copied from the file "f-deet"
+    ENV_PATHS = {"DFEET_DATA_PATH" : "ui/",
+                 "DFEET_IMAGE_PATH" : "ui/",
+                 "DFEET_LOCALE_PATH" : "locale/",
+                 "DFEET_HELP_PATH" : "/usr/share/gnome/dfeet/"
+                 }
+    for var, path in ENV_PATHS.iteritems():
+        os.environ.setdefault(var, path)
+
+    #run tests
+    #unittest.main()
+    s = DBusServer("unix:abstract=myaddr")
+    s.start()    
diff --git a/ui/addconnectiondialog.ui b/ui/addconnectiondialog.ui
index f1096dd..4806dcb 100644
--- a/ui/addconnectiondialog.ui
+++ b/ui/addconnectiondialog.ui
@@ -1,58 +1,77 @@
-<?xml version="1.0" standalone="no"?>
-<!--*- mode: xml -*-->
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
+  <!-- interface-requires gtk+ 3.0 -->
   <object class="GtkDialog" id="add_connection_dialog1">
+    <property name="can_focus">False</property>
     <property name="border_width">5</property>
-    <property name="default_height">50</property>
+    <property name="title" translatable="yes" context="yes">Add a Connection</property>
     <property name="default_width">480</property>
+    <property name="default_height">50</property>
     <property name="destroy_with_parent">True</property>
-    <property name="has_separator">False</property>
-    <property name="title" context="yes" translatable="yes">Add a Connection</property>
     <property name="type_hint">normal</property>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog1-vbox">
-        <property name="border_width">2</property>
+      <object class="GtkBox" id="dialog1-vbox">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkHBox" id="hbox1">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <child>
               <object class="GtkLabel" id="label1">
-                <property name="label" context="yes" translatable="yes">&lt;b&gt;Bus Address: &lt;/b&gt;</property>
-                <property name="use_markup">True</property>
                 <property name="visible">True</property>
-                <property name="xalign">0.0</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">See http://dbus.freedesktop.org/doc/dbus-specification.html#addresses</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes" context="yes">Address:</property>
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkComboBoxEntry" id="address_comboentry1">
-                <property name="items">Session Bus</property>
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
+              <placeholder/>
             </child>
           </object>
           <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
             <property name="padding">5</property>
-            <property name="position">1</property>
+            <property name="position">0</property>
           </packing>
         </child>
         <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog1-action_area">
-            <property name="border_width">5</property>
+          <object class="GtkButtonBox" id="dialog1-action_area">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="layout_style">end</property>
-            <property name="spacing">6</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_status">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">True</property>
             <property name="pack_type">end</property>
+            <property name="position">2</property>
           </packing>
         </child>
       </object>
diff --git a/ui/buswatch.ui b/ui/buswatch.ui
new file mode 100644
index 0000000..fdba11a
--- /dev/null
+++ b/ui/buswatch.ui
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="liststore_buswatch">
+    <columns>
+      <!-- column-name bus_name_obj -->
+      <column type="GObject"/>
+      <!-- column-name bus_name_pid -->
+      <column type="guint"/>
+      <!-- column-name bus_name_unique -->
+      <column type="gchararray"/>
+      <!-- column-name bus_name_cmdline -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkPaned" id="paned_buswatch">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Filter:</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="entry_filter">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">â</property>
+                <property name="invisible_char_set">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="treeview_buswatch">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="has_tooltip">True</property>
+                <property name="halign">start</property>
+                <property name="valign">start</property>
+                <property name="model">liststore_buswatch</property>
+                <property name="search_column">2</property>
+                <property name="tooltip_column">2</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection"/>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="treeviewcolumn_unique_bus_name">
+                    <property name="title" translatable="yes">unique bus name</property>
+                    <property name="clickable">True</property>
+                    <property name="sort_indicator">True</property>
+                    <property name="sort_column_id">2</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext_unique_bus_name"/>
+                      <attributes>
+                        <attribute name="text">2</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid_bus_name_info">
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Command line:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_bus_name_selected_cmdline">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="wrap_mode">char</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Process ID:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_bus_name_selected_pid">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0.52999997138977051</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Name:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_bus_name_selected_name">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="resize">False</property>
+        <property name="shrink">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkImage" id="image1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="pixbuf">dfeet-icon.png</property>
+      </object>
+      <packing>
+        <property name="resize">True</property>
+        <property name="shrink">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/ui/executedialog.ui b/ui/executedialog.ui
index 92b8c0c..06c3a89 100644
--- a/ui/executedialog.ui
+++ b/ui/executedialog.ui
@@ -1,146 +1,446 @@
-<?xml version="1.0"?>
-
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkAdjustment" id="adjustment1">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">1</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkDialog" id="executedialog1">
-    <property name="allow_shrink">True</property>
-    <property name="default_height">400</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes" context="yes">Execute D-Bus Method</property>
     <property name="default_width">320</property>
+    <property name="default_height">400</property>
     <property name="destroy_with_parent">True</property>
-    <property name="title" context="yes" translatable="yes">Execute D-Bus Method</property>
-    <!--<property name="type_hint">normal</property>-->
-    <signal handler="execute_dialog_close_cb" name="close"/>
+    <property name="type_hint">normal</property>
+    <signal name="close" handler="execute_dialog_close_cb" swapped="no"/>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog1-vbox">
-        <property name="border_width">2</property>
+      <object class="GtkBox" id="dialog1-vbox">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog1-action_area">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="closebutton1">
+                <property name="label" context="yes">gtk-close</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="execute_dialog_close_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="executebutton1">
+                <property name="label" translatable="yes" context="yes">_Execute</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="is_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_underline">True</property>
+                <signal name="clicked" handler="execute_dbus_method_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkVBox" id="vbox3">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkLabel" id="label_method_name">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="ypad">5</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label8">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Method name:&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label10">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Object Path:&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label11">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Interface:&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_object_path">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_interface">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
             <child>
-              <object class="GtkLabel" id="commandlabel1">
-                <property name="label" context="yes" translatable="yes">Execute i.c on object path o</property>
+              <object class="GtkLabel" id="label4">
                 <property name="visible">True</property>
-                <property name="xalign">0.0</property>
-                <property name="ypad">5</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="margin_top">10</property>
+                <property name="label" translatable="yes">&lt;b&gt;Method input&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
+                <property name="position">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="label" context="yes" translatable="yes">Parameters (in python syntax)</property>
-                <property name="shadow">none</property>
-                <property name="shadow_type">none</property>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
                 <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="shadow_type">in</property>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
-                    <property name="hscrollbar_policy">never</property>
-                    <property name="shadow_type">in</property>
+                  <object class="GtkTextView" id="parametertextview1">
                     <property name="visible">True</property>
-                    <property name="vscrollbar_policy">automatic</property>
-                    <child>
-                      <object class="GtkTextView" id="parametertextview1">
-                        <property name="is_focus">True</property>
-                        <property name="visible">True</property>
-                        <property name="wrap_mode">word</property>
-                      </object>
-                    </child>
+                    <property name="can_focus">True</property>
                   </object>
                 </child>
               </object>
               <packing>
-                <property name="position">1</property>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="margin_top">10</property>
+                <property name="yalign">0.49000000953674316</property>
+                <property name="xpad">1</property>
+                <property name="label" translatable="yes">&lt;b&gt;Method output&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">3</property>
               </packing>
             </child>
             <child>
               <object class="GtkFrame" id="frame2">
-                <property name="label" context="yes" translatable="yes">Output</property>
-                <property name="shadow">none</property>
-                <property name="shadow_type">none</property>
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
                 <child>
                   <object class="GtkNotebook" id="notebook1">
-                    <property name="tab_pos">bottom</property>
                     <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tab_pos">bottom</property>
                     <child>
                       <object class="GtkScrolledWindow" id="scrolledwindow2">
-                        <property name="hscrollbar_policy">never</property>
                         <property name="visible">True</property>
-                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="can_focus">True</property>
+                        <property name="shadow_type">in</property>
                         <child>
                           <object class="GtkTextView" id="prettyprinttextview1">
-                            <property name="editable">False</property>
                             <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="editable">False</property>
                             <property name="wrap_mode">word</property>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <child type="tab">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Pretty print</property>
+                      </object>
+                      <packing>
+                        <property name="tab_fill">False</property>
+                      </packing>
+                    </child>
                     <child>
                       <object class="GtkScrolledWindow" id="scrolledwindow3">
-                        <property name="hscrollbar_policy">never</property>
                         <property name="visible">True</property>
-                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="can_focus">True</property>
+                        <property name="shadow_type">in</property>
                         <child>
                           <object class="GtkTextView" id="sourcetextview1">
-                            <property name="editable">False</property>
                             <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="editable">False</property>
                             <property name="wrap_mode">word</property>
                           </object>
                         </child>
                       </object>
                       <packing>
                         <property name="position">1</property>
-                        <property name="tab_label" context="yes" translatable="yes">Page 2</property>
+                      </packing>
+                    </child>
+                    <child type="tab">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Source</property>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                        <property name="tab_fill">False</property>
                       </packing>
                     </child>
                   </object>
                 </child>
               </object>
               <packing>
-                <property name="position">2</property>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">4</property>
               </packing>
             </child>
-          </object>
-          <packing>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog1-action_area">
-            <property name="border_width">5</property>
-            <property name="layout_style">end</property>
-            <property name="spacing">6</property>
-            <property name="visible">True</property>
             <child>
-              <object class="GtkButton" id="closebutton1">
-                <property name="label" context="yes" translatable="yes">gtk-close</property>
-	        <property name="use_stock">True</property>
+              <object class="GtkBox" id="box2">
                 <property name="visible">True</property>
-                <signal handler="execute_dialog_close_cb" name="clicked"/>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkLabel" id="label6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="yalign">0.49000000953674316</property>
+                    <property name="xpad">1</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Method execution&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="method_exec_count_spinbutton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="has_tooltip">True</property>
+                    <property name="tooltip_markup" translatable="yes">Number of method executions</property>
+                    <property name="tooltip_text" translatable="yes">Number of method executions</property>
+                    <property name="invisible_char">â</property>
+                    <property name="invisible_char_set">True</property>
+                    <property name="adjustment">adjustment1</property>
+                    <property name="climb_rate">1</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="pack_type">end</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">5</property>
+              </packing>
             </child>
             <child>
-              <object class="GtkButton" id="executebutton1">
-                <property name="is_focus">True</property>
-                <property name="use_underline">True</property>
-                <property name="label" context="yes" translatable="yes">_Execute</property>
+              <object class="GtkBox" id="box_output_stats">
                 <property name="visible">True</property>
-                <signal handler="execute_dbus_method_cb" name="clicked"/>
+                <property name="can_focus">False</property>
+                <property name="homogeneous">True</property>
+                <child>
+                  <object class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Ã:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_avg">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="has_tooltip">True</property>
+                    <property name="tooltip_markup" translatable="yes">Average method execution time in seconds</property>
+                    <property name="tooltip_text" translatable="yes">Average method execution time in seconds</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Min:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_min">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="has_tooltip">True</property>
+                    <property name="tooltip_markup" translatable="yes">Minimal method execution time in seconds</property>
+                    <property name="tooltip_text" translatable="yes">Minimal method execution time in seconds</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label9">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Max:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_max">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="has_tooltip">True</property>
+                    <property name="tooltip_markup" translatable="yes">Maximal method execution time in seconds</property>
+                    <property name="tooltip_text" translatable="yes">Maximal method execution time in seconds</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
               </object>
               <packing>
-                <property name="position">1</property>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">6</property>
               </packing>
             </child>
-         </object>
+          </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
           </packing>
         </child>
       </object>
     </child>
+    <action-widgets>
+      <action-widget response="0">closebutton1</action-widget>
+      <action-widget response="0">executebutton1</action-widget>
+    </action-widgets>
   </object>
 </interface>
diff --git a/ui/introspection.ui b/ui/introspection.ui
new file mode 100644
index 0000000..4185fcd
--- /dev/null
+++ b/ui/introspection.ui
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkBox" id="box_introspectview">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes">&lt;b&gt;Unique name:&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes">&lt;b&gt;Name:&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_unique_name">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_name">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes">&lt;b&gt;Address:&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_address">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selectable">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="button_reload">
+            <property name="label">gtk-refresh</property>
+            <property name="use_action_appearance">False</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_action_appearance">False</property>
+            <property name="use_stock">True</property>
+            <signal name="clicked" handler="on_button_reload_clicked" swapped="no"/>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkTreeView" id="treeview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="model">treestore</property>
+            <property name="search_column">0</property>
+            <child internal-child="selection">
+              <object class="GtkTreeSelection" id="treeview-selection1"/>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkTreeStore" id="treestore">
+    <columns>
+      <!-- column-name gchararray1 -->
+      <column type="gchararray"/>
+      <!-- column-name GObject1 -->
+      <column type="GObject"/>
+    </columns>
+  </object>
+</interface>
diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui
index c1093c2..fdef12d 100644
--- a/ui/mainwindow.ui
+++ b/ui/mainwindow.ui
@@ -1,45 +1,102 @@
-<?xml version="1.0" standalone="no"?>
-
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkAction" id="action_close">
+    <property name="label" translatable="yes">Close</property>
+    <property name="stock_id">gtk-close</property>
+    <signal name="activate" handler="action_close_activate_cb" swapped="no"/>
+  </object>
+  <object class="GtkActionGroup" id="actiongroup_connect">
+    <child>
+      <object class="GtkAction" id="action_systembus_connect">
+        <property name="label" translatable="yes">Connect to System Bus</property>
+        <property name="short_label" translatable="yes">Connect to System Bus</property>
+        <property name="tooltip" translatable="yes">Connect to System Bus</property>
+        <property name="stock_id">gtk-connect</property>
+        <signal name="activate" handler="action_systembus_connect_activate_cb" swapped="no"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkAction" id="action_sessionbus_connect">
+        <property name="label" translatable="yes">Connect to Session Bus</property>
+        <property name="short_label" translatable="yes">Connect to Session Bus</property>
+        <property name="tooltip" translatable="yes">Connect to Session Bus</property>
+        <property name="stock_id">gtk-connect</property>
+        <signal name="activate" handler="action_sessionbus_connect_activate_cb" swapped="no"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkAction" id="action_otherbus_connect">
+        <property name="label" translatable="yes">Connect to other Bus</property>
+        <property name="short_label" translatable="yes">Connect to other Bus</property>
+        <property name="tooltip" translatable="yes">Connect to other Bus</property>
+        <property name="stock_id">gtk-connect</property>
+        <signal name="activate" handler="action_otherbus_connect_activate_cb" swapped="no"/>
+      </object>
+    </child>
+  </object>
   <object class="GtkWindow" id="appwindow1">
-    <property name="default_height">480</property>
-    <property name="default_width">640</property>
-    <property name="height_request">200</property>
-    <property name="title" context="yes" translatable="yes">D-Feet D-Bus debugger</property>
-    <property name="visible">False</property>
     <property name="width_request">300</property>
+    <property name="height_request">200</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes" context="yes">D-Feet D-Bus debugger</property>
+    <property name="default_width">640</property>
+    <property name="default_height">480</property>
+    <property name="icon_name">dfeet-icon</property>
     <child>
-      <object class="GtkVBox" id="main_vbox">
+      <object class="GtkVBox" id="vbox1">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
         <child>
-          <object class="GtkFrame" id="frame1">
-            <property name="visible">True</property>
+          <object class="GtkMenuBar" id="menubar1">
+            <property name="can_focus">False</property>
             <child>
-              <object class="GtkVBox" id="vbox1">
+              <object class="GtkMenuItem" id="menuitem_file">
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
-                <child>
-                  <object class="GtkMenuBar" id="menubar1" constructor="default-uiman" />
-                  <packing>
-                    <property name="expand">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object constructor="default-uiman" class="GtkToolbar" id="toolbar1">
-                    <property name="toolbar_style">both-horiz</property>
-                    <property name="visible">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkNotebook" id="display_notebook">
-                    <property name="enable_popup">True</property>
-                    <property name="is_focus">True</property>
-                    <property name="scrollable">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">File</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu1">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <child>
-                      <placeholder/>
+                      <object class="GtkMenuItem" id="menuitem_systembus">
+                        <property name="related_action">action_systembus_connect</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="menuitem_sessionbus">
+                        <property name="related_action">action_sessionbus_connect</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuItem" id="menuitem_otherbus">
+                        <property name="related_action">action_otherbus_connect</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem" id="menuitem1">
+                        <property name="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="menuitem_close">
+                        <property name="related_action">action_close</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
                     </child>
                   </object>
                 </child>
@@ -47,35 +104,77 @@
             </child>
           </object>
           <packing>
-              <property name="expand">True</property>
-            </packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
         </child>
         <child>
-          <object class="GtkFrame" id="frame2">
+          <object class="GtkToolbar" id="toolbar1">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <child>
-              <object class="GtkNotebook" id="console_notebook">
-                <property name="enable_popup">True</property>
-                <property name="is_focus">True</property>
-                <property name="scrollable">True</property>
+              <object class="GtkToolButton" id="toolbutton_systembus_connect">
+                <property name="related_action">action_systembus_connect</property>
                 <property name="visible">True</property>
-                <child>
-                  <placeholder/>
-                </child>
+                <property name="can_focus">False</property>
+                <property name="related_action">action_systembus_connect</property>
+                <property name="label" translatable="yes">toolbutton1</property>
+                <property name="use_underline">True</property>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="toolbutton_sessionbus_connect">
+                <property name="related_action">action_sessionbus_connect</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="related_action">action_sessionbus_connect</property>
+                <property name="label" translatable="yes">toolbutton1</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="toolbutton_otherbus_connect">
+                <property name="related_action">action_otherbus_connect</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="related_action">action_otherbus_connect</property>
+                <property name="label" translatable="yes">toolbutton1</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
-          <object class="GtkStatusbar" id="statusbar1">
+          <object class="GtkNotebook" id="display_notebook">
             <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="scrollable">True</property>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
           </packing>
         </child>
       </object>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]