[d-feet/pygi] Port to pygi and gdbus
- From: Thomas Bechtold <toabctl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [d-feet/pygi] Port to pygi and gdbus
- Date: Mon, 15 Oct 2012 15:45:26 +0000 (UTC)
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"><b>Bus Address: </b></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"><b>Method name:</b></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"><b>Object Path:</b></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"><b>Interface:</b></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"><b>Method input</b></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"><b>Method output</b></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"><b>Method execution</b></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"><b>Unique name:</b></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"><b>Name:</b></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"><b>Address:</b></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]