summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2009-08-11 15:36:23 +0200
committerJiri Moskovcak <jmoskovc@redhat.com>2009-08-11 15:36:23 +0200
commitde7ae6b763e48607f7d1da8f4f98bd7386cccba8 (patch)
tree60b61555cba7712e850fbecb7a37a1dca26b7a23
parent13329d88e147fac7cafcdebcafd1859a74a27aa9 (diff)
downloadabrt-de7ae6b763e48607f7d1da8f4f98bd7386cccba8.tar.gz
abrt-de7ae6b763e48607f7d1da8f4f98bd7386cccba8.tar.xz
abrt-de7ae6b763e48607f7d1da8f4f98bd7386cccba8.zip
GUI: Added option to disable/enable plugins (config preview)
-rw-r--r--lib/Plugins/Bugzilla.GTKBuilder17
-rw-r--r--lib/Plugins/KerneloopsReporter.GTKBuilder10
-rw-r--r--lib/Plugins/Logger.GTKBuilder10
-rw-r--r--lib/Plugins/Mailx.GTKBuilder10
-rw-r--r--src/Gui/ABRTPlugin.py52
-rw-r--r--src/Gui/CCDBusBackend.py43
-rw-r--r--src/Gui/CCDump.py2
-rw-r--r--src/Gui/CCMainWindow.py7
-rw-r--r--src/Gui/Makefile.am7
-rw-r--r--src/Gui/PluginList.py51
-rw-r--r--src/Gui/PluginSettingsUI.py57
-rw-r--r--src/Gui/SettingsDialog.py133
-rw-r--r--src/Gui/ccgui.glade19
-rw-r--r--src/Gui/settings.GtkBuilder215
14 files changed, 579 insertions, 54 deletions
diff --git a/lib/Plugins/Bugzilla.GTKBuilder b/lib/Plugins/Bugzilla.GTKBuilder
index 6d3bb4c3..2c2d63ca 100644
--- a/lib/Plugins/Bugzilla.GTKBuilder
+++ b/lib/Plugins/Bugzilla.GTKBuilder
@@ -1,13 +1,13 @@
<?xml version="1.0"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
+ <requires lib="gtk+" version="2.14"/>
<!-- interface-naming-policy project-wide -->
- <object class="GtkDialog" id="dialog1">
+ <object class="GtkDialog" id="PluginDialog">
<property name="border_width">5</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
+ <object class="GtkVBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
@@ -19,10 +19,6 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Bugzilla plugin configuration</property>
- <attributes>
- <attribute name="weight">bold</attribute>
- <attribute name="scale">1.300000</attribute>
- </attributes>
</object>
<packing>
<property name="position">0</property>
@@ -60,7 +56,7 @@
</packing>
</child>
<child>
- <object class="GtkEntry" id="conf_Bugzilla URL">
+ <object class="GtkEntry" id="conf_BugzillaURL">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
@@ -124,7 +120,7 @@
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
- <object class="GtkButton" id="button1">
+ <object class="GtkButton" id="bApply">
<property name="label" translatable="yes">gtk-apply</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -161,8 +157,9 @@
</object>
</child>
<action-widgets>
- <action-widget response="-10">button1</action-widget>
+ <action-widget response="-10">bApply</action-widget>
<action-widget response="-6">button2</action-widget>
</action-widgets>
</object>
+ <object class="GtkAction" id="action1"/>
</interface>
diff --git a/lib/Plugins/KerneloopsReporter.GTKBuilder b/lib/Plugins/KerneloopsReporter.GTKBuilder
index 69400f19..74cb36b9 100644
--- a/lib/Plugins/KerneloopsReporter.GTKBuilder
+++ b/lib/Plugins/KerneloopsReporter.GTKBuilder
@@ -1,13 +1,13 @@
<?xml version="1.0"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
+ <requires lib="gtk+" version="2.14"/>
<!-- interface-naming-policy project-wide -->
- <object class="GtkDialog" id="dialog1">
+ <object class="GtkDialog" id="PluginDialog">
<property name="border_width">5</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
+ <object class="GtkVBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
@@ -19,10 +19,6 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Kerneloops Reporter plugin configuration</property>
- <attributes>
- <attribute name="weight">bold</attribute>
- <attribute name="scale">1.300000</attribute>
- </attributes>
</object>
<packing>
<property name="position">0</property>
diff --git a/lib/Plugins/Logger.GTKBuilder b/lib/Plugins/Logger.GTKBuilder
index b64d40ae..a6b82c00 100644
--- a/lib/Plugins/Logger.GTKBuilder
+++ b/lib/Plugins/Logger.GTKBuilder
@@ -1,13 +1,13 @@
<?xml version="1.0"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
+ <requires lib="gtk+" version="2.14"/>
<!-- interface-naming-policy project-wide -->
- <object class="GtkDialog" id="dialog1">
+ <object class="GtkDialog" id="PluginDialog">
<property name="border_width">5</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
+ <object class="GtkVBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
@@ -19,10 +19,6 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Logger plugin configuration</property>
- <attributes>
- <attribute name="weight">bold</attribute>
- <attribute name="scale">1.300000</attribute>
- </attributes>
</object>
<packing>
<property name="position">0</property>
diff --git a/lib/Plugins/Mailx.GTKBuilder b/lib/Plugins/Mailx.GTKBuilder
index 62cc0d4b..df359734 100644
--- a/lib/Plugins/Mailx.GTKBuilder
+++ b/lib/Plugins/Mailx.GTKBuilder
@@ -1,13 +1,13 @@
<?xml version="1.0"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
+ <requires lib="gtk+" version="2.14"/>
<!-- interface-naming-policy project-wide -->
- <object class="GtkDialog" id="dialog1">
+ <object class="GtkDialog" id="PluginDialog">
<property name="border_width">5</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
+ <object class="GtkVBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
@@ -19,10 +19,6 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Mailx plugin configuration</property>
- <attributes>
- <attribute name="weight">bold</attribute>
- <attribute name="scale">1.300000</attribute>
- </attributes>
</object>
<packing>
<property name="position">0</property>
diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py
new file mode 100644
index 00000000..ff6478be
--- /dev/null
+++ b/src/Gui/ABRTPlugin.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+""" PluginInfo keys:
+WWW
+Name
+Enabled
+GTKBuilder
+Version
+Type
+Email
+Description
+"""
+
+
+class PluginSettings(dict):
+ def __init__(self):
+ print "Init plugin settings"
+
+ def __init__(self, settings_dict):
+ for key in settings_dict.keys():
+ self[key] = settings_dict[key]
+
+"""Class to represent common plugin info"""
+class PluginInfo():
+ keys = ["WWW", "Name", "Enabled",
+ "GTKBuilder", "Version",
+ "Type", "Email", "Description"]
+
+ def __init__(self):
+ #print "Init PluginInfo"
+ self.WWW = None
+ self.Name = None
+ self.Enabled = None
+ self.GTKBuilder = None
+ self.Version = None
+ self.Type = None
+ self.Email = None
+ self.Description = None
+ self.Settings = None
+
+ def getName(self):
+ return self.Name
+
+ def getDescription(self):
+ return self.Description
+
+ def getGUI(self):
+ return self.GTKBuilder
+
+ def __str__(self):
+ return self.Name
+
diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py
index 52e7bdaa..6fe13576 100644
--- a/src/Gui/CCDBusBackend.py
+++ b/src/Gui/CCDBusBackend.py
@@ -35,28 +35,20 @@ class DBusManager(gobject.GObject):
try:
session = dbus.SessionBus()
except Exception, e:
- print e
-
- try:
- app_proxy = session.get_object(APP_NAME,APP_PATH)
- app_iface = dbus.Interface(app_proxy, dbus_interface=APP_IFACE)
- # app is running, so make it show it self
- app_iface.show()
- raise ABRTExceptions.IsRunning()
- except DBusException, e:
- # cannot create proxy or call the method => gui is not running
+ # probably run after "$ su"
pass
- """
- try:
- session = dbus.SessionBus()
- except:
- # FIXME: root doesn't have SessionBus
- pass
if session:
- if session.request_name(APP_NAME, dbus.bus.NAME_FLAG_DO_NOT_QUEUE) != dbus.bus.REQUEST_NAME_REPLY_PRIMARY_OWNER:
- raise Exception("Name %s is taken,\nanother instance is already running." % APP_NAME)
- """
+ try:
+ app_proxy = session.get_object(APP_NAME,APP_PATH)
+ app_iface = dbus.Interface(app_proxy, dbus_interface=APP_IFACE)
+ # app is running, so make it show it self
+ app_iface.show()
+ raise ABRTExceptions.IsRunning()
+ except DBusException, e:
+ # cannot create proxy or call the method => gui is not running
+ pass
+
gobject.GObject.__init__(self)
# signal emited when new crash is detected
gobject.signal_new ("crash", self ,gobject.SIGNAL_RUN_FIRST,gobject.TYPE_NONE,())
@@ -189,3 +181,16 @@ class DBusManager(gobject.GObject):
row_dict[column] = row[column]
rows.append(row_dict);
return rows
+
+ def getPluginsInfo(self):
+ return self.cc.GetPluginsInfo()
+
+ def getPluginSettings(self, plugin_name):
+ return self.cc.GetPluginSettings(plugin_name)
+
+ def registerPlugin(self, plugin_name):
+ return self.cc.RegisterPlugin(plugin_name)
+
+ def unRegisterPlugin(self, plugin_name):
+ return self.cc.UnRegisterPlugin(plugin_name)
+
diff --git a/src/Gui/CCDump.py b/src/Gui/CCDump.py
index 04bca621..0c7b29c0 100644
--- a/src/Gui/CCDump.py
+++ b/src/Gui/CCDump.py
@@ -6,7 +6,7 @@ EDITABLE = 1
CONTENT = 2
class Dump():
- """Class for mapping the debug dump to pyhon object"""
+ """Class for mapping the debug dump to python object"""
def __init__(self):
self.UUID = None
self.UID = None
diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py
index 8ddaa517..4b5fed2a 100644
--- a/src/Gui/CCMainWindow.py
+++ b/src/Gui/CCMainWindow.py
@@ -11,6 +11,7 @@ import CCDBusBackend
from CC_gui_functions import *
from CCDumpList import getDumpList, DumpList
from CCReporterDialog import ReporterDialog
+from SettingsDialog import SettingsDialog
from CCReport import Report
from exception import installExceptionHandler, handleMyException
import ABRTExceptions
@@ -100,6 +101,7 @@ class MainWindow():
self.wTree.get_widget("bReport").connect("clicked", self.on_bReport_clicked)
self.wTree.get_widget("miQuit").connect("activate", self.on_bQuit_clicked)
self.wTree.get_widget("miAbout").connect("activate", self.on_miAbout_clicked)
+ self.wTree.get_widget("miPreferences").connect("activate", self.on_miPreferences_clicked)
# connect handlers for daemon signals
self.ccdaemon.connect("crash", self.on_data_changed_cb, None)
self.ccdaemon.connect("analyze-complete", self.on_analyze_complete_cb, self.pBarWindow)
@@ -121,6 +123,11 @@ class MainWindow():
dialog = self.wTree.get_widget("about")
result = dialog.run()
dialog.hide()
+
+ def on_miPreferences_clicked(self, widget):
+ dialog = SettingsDialog(self.window,self.ccdaemon)
+ dialog.hydrate()
+ dialog.show()
def error_cb(self, daemon, message=None):
# try to hide the progressbar, we dont really care if it was visible ..
diff --git a/src/Gui/Makefile.am b/src/Gui/Makefile.am
index 1715588a..ca8a790f 100644
--- a/src/Gui/Makefile.am
+++ b/src/Gui/Makefile.am
@@ -3,10 +3,11 @@
bin_SCRIPTS = abrt-gui
PYTHON_FILES = CCDBusBackend.py CCDumpList.py CCDump.py CC_gui_functions.py \
- ccgui.glade report.glade CCReporterDialog.py CCReport.py \
- CCMainWindow.py exception.py CellRenderers.py ABRTExceptions.py
+ CCReporterDialog.py CCReport.py \
+ CCMainWindow.py exception.py CellRenderers.py ABRTExceptions.py \
+ SettingsDialog.py ABRTPlugin.py PluginList.py PluginSettingsUI.py
-GLADE_FILES = ccgui.glade report.glade
+GLADE_FILES = ccgui.glade report.glade settings.GtkBuilder
EXTRA_DIST = $(PYTHON_FILES) $(GLADE_FILES) abrt-gui abrt.desktop
diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py
new file mode 100644
index 00000000..b315eb95
--- /dev/null
+++ b/src/Gui/PluginList.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+import CCDBusBackend
+from ABRTPlugin import PluginInfo, PluginSettings
+
+class PluginInfoList(list):
+ """Class to store list of PluginInfos"""
+ def __init__(self,dbus_manager=None):
+ self.dm = dbus_manager
+ self.ddict = {}
+
+ def load(self):
+ if self.dm:
+ #print "loading PluginList"
+ try:
+ rows = self.dm.getPluginsInfo()
+ #print rows
+ for row in rows:
+ entry = PluginInfo()
+ for column in row:
+ #print "PluginInfoList adding %s:%s" % (column,row[column])
+ entry.__dict__[column] = row[column]
+ if entry.Enabled == "yes":
+ #print ">>%s<<" % entry
+ entry.Settings = PluginSettings(self.dm.getPluginSettings(str(entry)))
+ #for i in entry.Settings.keys():
+ # print "%s: %s" % (i, entry.Settings[i])
+ #else:
+ # print "%s is disabled" % entry
+ self.append(entry)
+ self.ddict[entry.getName()] = entry
+ except Exception, e:
+ print e
+ return
+ else:
+ print "db == None!"
+
+
+__PFList = None
+__PFList_dbmanager = None
+
+def getPluginInfoList(dbmanager,refresh=None):
+ global __PFList
+ global __PFList_dbmanager
+
+ if __PFList == None or refresh or __PFList_dbmanager != dbmanager:
+ __PFList = PluginInfoList(dbus_manager=dbmanager)
+ __PFList.load()
+ __PFList_dbmanager = dbmanager
+ return __PFList
+
+__PFList = None
diff --git a/src/Gui/PluginSettingsUI.py b/src/Gui/PluginSettingsUI.py
new file mode 100644
index 00000000..55174d6e
--- /dev/null
+++ b/src/Gui/PluginSettingsUI.py
@@ -0,0 +1,57 @@
+import gtk
+
+class PluginSettingsUI(gtk.Dialog):
+ def __init__(self, pluginfo):
+ #print "Init PluginSettingsUI"
+ gtk.Dialog.__init__(self)
+ self.plugin_name = pluginfo.Name
+ self.Settings = pluginfo.Settings
+ self.pluginfo = pluginfo
+ self.plugin_gui = None
+
+ if pluginfo.getGUI():
+ self.plugin_gui = gtk.Builder()
+ self.plugin_gui.add_from_file(pluginfo.getGUI())
+ self.dialog = self.plugin_gui.get_object("PluginDialog")
+ if not self.dialog:
+ raise Exception("Can't find PluginDialog widget in UI description!")
+ self.dialog.set_title("%s" % pluginfo.getName())
+ else:
+ # we shouldn't get here, but just to be safe
+ no_ui_label = gtk.Label("No UI for plugin %s" % pluginfo)
+ self.add(no_ui_label)
+ no_ui_label.show()
+
+ def hydrate(self):
+ if self.plugin_gui:
+ if self.pluginfo.Enabled == "yes":
+ if self.Settings:
+ #print "Hydrating %s" % self.plugin_name
+ for key,value in self.Settings.iteritems():
+ #print "%s:%s" % (key,value)
+ widget = self.plugin_gui.get_object("conf_%s" % key)
+ if type(widget) == gtk.Entry:
+ widget.set_text(value)
+ elif type(widget) == gtk.CheckButton:
+ widget.set_active(value == "yes")
+ elif type(widget) == gtk.ComboBox:
+ print "combo box is not implemented"
+ else:
+ #print "Plugin %s has no configuration." % self.plugin_name
+ pass
+ else:
+ #print "Plugin %s is disabled." % self.plugin_name
+ pass
+
+ else:
+ print "Nothing to hydrate!"
+
+ def dehydrate(self):
+ #print "dehydrating %s" % self.pluginfo.getName()
+ pass
+
+ def destroy(self):
+ self.dialog.destroy()
+
+ def run(self):
+ return self.dialog.run()
diff --git a/src/Gui/SettingsDialog.py b/src/Gui/SettingsDialog.py
new file mode 100644
index 00000000..bd87a30c
--- /dev/null
+++ b/src/Gui/SettingsDialog.py
@@ -0,0 +1,133 @@
+import sys
+import gtk
+from PluginList import getPluginInfoList, PluginInfoList
+from CC_gui_functions import *
+from PluginSettingsUI import PluginSettingsUI
+from ABRTPlugin import PluginSettings
+
+class SettingsDialog:
+ def __init__(self, parent, daemon):
+ #print "Settings dialog init"
+ self.ccdaemon = daemon
+ self.builder = gtk.Builder()
+ builderfile = "%s%ssettings.GtkBuilder" % (sys.path[0],"/")
+ #print builderfile
+ try:
+ self.builder.add_from_file(builderfile)
+ except Exception, e:
+ print e
+ self.window = self.builder.get_object("wSettings")
+ if not self.window:
+ raise Exception("Can't load gui description for SettingsDialog!")
+ #self.window.set_parent(parent)
+
+ self.pluginlist = self.builder.get_object("tvSettings")
+ self.pluginsListStore = gtk.ListStore(str, bool, object)
+ # set filter
+ self.modelfilter = self.pluginsListStore.filter_new()
+ self.modelfilter.set_visible_func(self.filter_plugins, None)
+ self.pluginlist.set_model(self.modelfilter)
+ # ===============================================
+ columns = [None]*1
+ columns[0] = gtk.TreeViewColumn('Plugins')
+
+ # create list
+ for column in columns:
+ n = self.pluginlist.append_column(column)
+ column.cell = gtk.CellRendererText()
+ column.pack_start(column.cell, False)
+ column.set_attributes(column.cell, text=(n-1))
+ column.set_resizable(True)
+
+ # toggle
+ toggle_renderer = gtk.CellRendererToggle()
+ toggle_renderer.set_property('activatable', True)
+ toggle_renderer.connect( 'toggled', self.on_enabled_toggled, self.pluginsListStore )
+ column = gtk.TreeViewColumn('Enabled', toggle_renderer)
+ column.add_attribute( toggle_renderer, "active", 1)
+ self.pluginlist.insert_column(column, 0)
+
+ #connect signals
+ self.pluginlist.connect("cursor-changed", self.on_tvDumps_cursor_changed)
+ self.builder.get_object("bConfigurePlugin").connect("clicked", self.on_bConfigurePlugin_clicked, self.pluginlist)
+ self.builder.get_object("bClose").connect("clicked", self.on_bClose_clicked)
+
+ def on_enabled_toggled(self,cell, path, model):
+ plugin = model[path][model.get_n_columns()-1]
+ if model[path][1]:
+ #print "self.ccdaemon.UnRegisterPlugin(%s)" % (plugin.getName())
+ self.ccdaemon.unRegisterPlugin(plugin.getName())
+ # FIXME: create class plugin and move this into method Plugin.Enable()
+ plugin.Enabled = "no"
+ plugin.Settings = None
+ else:
+ #print "self.ccdaemon.RegisterPlugin(%s)" % (model[path][model.get_n_columns()-1])
+ self.ccdaemon.registerPlugin(plugin.getName())
+ # FIXME: create class plugin and move this into method Plugin.Enable()
+ plugin.Enabled = "yes"
+ plugin.Settings = PluginSettings(self.ccdaemon.getPluginSettings(plugin.getName()))
+ model[path][1] = not model[path][1]
+
+ def filter_plugins(self, model, miter, data):
+ return True
+ def hydrate(self):
+ #print "settings hydrate"
+ self.pluginsListStore.clear()
+ try:
+ pluginlist = getPluginInfoList(self.ccdaemon, refresh=True)
+ except Exception, e:
+ print e
+ #gui_error_message("Error while loading plugins info, please check if abrt daemon is running\n %s" % e)
+ for entry in pluginlist:
+ n = self.pluginsListStore.append(["%s\n%s" % (entry.getName(), entry.Description), entry.Enabled == "yes", entry])
+
+ def dehydrate(self):
+ # we have nothing to save, plugin's does the work
+ pass
+
+ def show(self):
+ self.window.show()
+ #if result == gtk.RESPONSE_APPLY:
+ # self.dehydrate()
+ #self.window.destroy()
+ #return result
+
+ def on_bConfigurePlugin_clicked(self, button, pluginview):
+ pluginsListStore, path = pluginview.get_selection().get_selected_rows()
+ if not path:
+ self.builder.get_object("lDescription").set_label("ARGH...")
+ return
+ # this should work until we keep the row object in the last position
+ pluginfo = pluginsListStore.get_value(pluginsListStore.get_iter(path[0]), pluginsListStore.get_n_columns()-1)
+ try:
+ ui = PluginSettingsUI(pluginfo)
+ except Exception, e:
+ gui_error_message("Error while opening plugin settings UI: \n\n%s" % e)
+ return
+ ui.hydrate()
+ response = ui.run()
+ if response == gtk.RESPONSE_APPLY:
+ ui.dehydrate()
+ elif response == gtk.RESPONSE_CANCEL:
+ pass
+ else:
+ print "unknown response from settings dialog"
+ ui.destroy()
+
+ def on_bClose_clicked(self, button):
+ self.window.destroy()
+
+ def on_tvDumps_cursor_changed(self, treeview):
+ pluginsListStore, path = treeview.get_selection().get_selected_rows()
+ if not path:
+ self.builder.get_object("lDescription").set_label("ARGH...")
+ return
+ # this should work until we keep the row object in the last position
+ pluginfo = pluginsListStore.get_value(pluginsListStore.get_iter(path[0]), pluginsListStore.get_n_columns()-1)
+ self.builder.get_object("lPluginAuthor").set_text(pluginfo.Email)
+ self.builder.get_object("lPluginVersion").set_text(pluginfo.Version)
+ self.builder.get_object("lPluginWebSite").set_text(pluginfo.WWW)
+ self.builder.get_object("lPluginName").set_text(pluginfo.Name)
+ self.builder.get_object("lPluginDescription").set_text(pluginfo.Description)
+# print (pluginfo.Enabled == "yes" and pluginfo.GTKBuilder != "")
+ self.builder.get_object("bConfigurePlugin").set_sensitive(pluginfo.Enabled == "yes" and pluginfo.GTKBuilder != "")
diff --git a/src/Gui/ccgui.glade b/src/Gui/ccgui.glade
index 53da45b6..958af5d9 100644
--- a/src/Gui/ccgui.glade
+++ b/src/Gui/ccgui.glade
@@ -32,6 +32,25 @@
</widget>
</child>
<child>
+ <widget class="GtkMenuItem" id="edit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkImageMenuItem" id="miPreferences">
+ <property name="label">gtk-preferences</property>
+ <property name="visible">True</property>
+ <property name="use_stock">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
<widget class="GtkMenuItem" id="menuitem8">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
diff --git a/src/Gui/settings.GtkBuilder b/src/Gui/settings.GtkBuilder
new file mode 100644
index 00000000..422b6231
--- /dev/null
+++ b/src/Gui/settings.GtkBuilder
@@ -0,0 +1,215 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.14"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkWindow" id="wSettings">
+ <property name="title" translatable="yes">Settings</property>
+ <property name="modal">True</property>
+ <property name="default_width">450</property>
+ <property name="default_height">400</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="tvSettings">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="exPluginDetails">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="lPluginName">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lPluginDescription">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">Web Site:</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">Author:</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">Version:</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lPluginVersion">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lPluginAuthor">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lPluginWebSite">
+ <property name="visible">True</property>
+ <property name="xalign">0.05000000074505806</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Plugin Details</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">11</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bConfigurePlugin">
+ <property name="label" translatable="yes">C_onfigure plugin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bClose">
+ <property name="label" translatable="yes">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStatusbar" id="statusbar1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>