summaryrefslogtreecommitdiffstats
path: root/src/Gui
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2010-01-18 13:19:54 +0100
committerKarel Klic <kklic@redhat.com>2010-01-18 13:19:54 +0100
commit4267cbcc29781ddcac00e259dfe05f3a26fbc2ec (patch)
tree213e47138967f1e7af4ee9ff9a3f2ed861cb5815 /src/Gui
parentb2d1bd9e4f387c5a014d3002d741f25421c37aac (diff)
parentb41833ed61f7b579d2a46b26d261616c21a6ae32 (diff)
downloadabrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.tar.gz
abrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.tar.xz
abrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.zip
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'src/Gui')
-rw-r--r--src/Gui/ABRTExceptions.py2
-rw-r--r--src/Gui/ABRTPlugin.py49
-rw-r--r--src/Gui/CCDBusBackend.py40
-rw-r--r--src/Gui/CCDumpList.py2
-rw-r--r--src/Gui/CCMainWindow.py61
-rw-r--r--src/Gui/CCReporterDialog.py4
-rw-r--r--src/Gui/CC_gui_functions.py20
-rw-r--r--src/Gui/ConfBackend.py171
-rw-r--r--src/Gui/PluginList.py22
-rw-r--r--src/Gui/PluginSettingsUI.py2
-rw-r--r--src/Gui/PluginsSettingsDialog.py122
-rw-r--r--src/Gui/SettingsDialog.py2
-rw-r--r--src/Gui/abrt_utils.py43
13 files changed, 356 insertions, 184 deletions
diff --git a/src/Gui/ABRTExceptions.py b/src/Gui/ABRTExceptions.py
index c4d6b59..c857f71 100644
--- a/src/Gui/ABRTExceptions.py
+++ b/src/Gui/ABRTExceptions.py
@@ -1,4 +1,4 @@
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
class IsRunning(Exception):
def __init__(self):
diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py
index ea90b87..320c81c 100644
--- a/src/Gui/ABRTPlugin.py
+++ b/src/Gui/ABRTPlugin.py
@@ -10,49 +10,51 @@ Type
Email
Description
"""
-from abrt_utils import _
-from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError
+from abrt_utils import _, log, log1, log2
+from ConfBackend import getCurrentConfBackend, ConfBackendInitError
class PluginSettings(dict):
def __init__(self):
dict.__init__(self)
- self.conf = None
+ self.client_side_conf = None
try:
- self.conf = ConfBackendGnomeKeyring()
+ self.client_side_conf = getCurrentConfBackend()
except ConfBackendInitError, e:
print e
pass
def check(self):
+ # if present, these should be non-empty
for key in ["Password", "Login"]:
if key in self.keys():
- # some of the required keys is missing
if not self[key]:
+ # some of the required keys are missing
return False
# settings are OK
return True
- def load(self, name, default_settings):
+ def load_daemon_settings(self, name, daemon_settings):
# load settings from daemon
- for key in default_settings.keys():
- self[str(key)] = str(default_settings[key])
+ for key in daemon_settings.keys():
+ self[str(key)] = str(daemon_settings[key])
- if self.conf:
- settings = self.conf.load(name)
- # overwrite defaluts with user setting
+ if self.client_side_conf:
+ settings = self.client_side_conf.load(name)
+ # overwrite daemon data with user setting
for key in settings.keys():
- # only rewrite keys needed by the plugin
- # e.g we don't want a pass field for logger
- if key in default_settings.keys():
+ # only rewrite keys which exist in plugin's keys.
+ # e.g. we don't want a password field for logger plugin
+ if key in daemon_settings.keys():
self[str(key)] = str(settings[key])
- def save(self, name):
- if self.conf:
- self.conf.save(name, self)
+ def save_on_client_side(self, name):
+ if self.client_side_conf:
+ self.client_side_conf.save(name, self)
class PluginInfo():
"""Class to represent common plugin info"""
- types = {"Analyzer":_("Analyzer plugins"),
+ types = {"":_("Not loaded plugins"),
+ "Analyzer":_("Analyzer plugins"),
"Action":_("Action plugins"),
"Reporter":_("Reporter plugins"),
"Database":_("Database plugins")}
@@ -61,7 +63,6 @@ class PluginInfo():
"Type", "Email", "Description"]
def __init__(self):
- #print "Init PluginInfo"
self.WWW = None
self.Name = None
self.Enabled = None
@@ -90,11 +91,11 @@ class PluginInfo():
def __getitem__(self, item):
return self.__dict__[item]
- def load_settings(self, default_settings):
+ def load_daemon_settings(self, daemon_settings):
if self.Name:
- self.Settings.load(self.Name, default_settings)
+ self.Settings.load_daemon_settings(self.Name, daemon_settings)
else:
- print _("Plugin name is not set, can't load its settings")
+ log("Plugin name is not set, can't load its settings")
- def save_settings(self):
- self.Settings.save(str(self.Name))
+ def save_settings_on_client_side(self):
+ self.Settings.save_on_client_side(str(self.Name))
diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py
index 85987e8..f4ef104 100644
--- a/src/Gui/CCDBusBackend.py
+++ b/src/Gui/CCDBusBackend.py
@@ -6,7 +6,7 @@ from dbus.mainloop.glib import DBusGMainLoop
import gtk
from dbus.exceptions import *
import ABRTExceptions
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
CC_NAME = 'com.redhat.abrt'
CC_IFACE = 'com.redhat.abrt'
@@ -40,7 +40,7 @@ class DBusManager(gobject.GObject):
if session:
try:
- app_proxy = session.get_object(APP_NAME,APP_PATH)
+ 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()
@@ -111,13 +111,13 @@ class DBusManager(gobject.GObject):
# def disconnected(self, *args):
# print "disconnect"
- def error_handler_cb(self,error):
- self.emit("abrt-error",error)
+ def error_handler_cb(self, error):
+ self.emit("abrt-error", error)
- def warning_handler_cb(self,arg):
- self.emit("warning",arg)
+ def warning_handler_cb(self, arg):
+ self.emit("warning", arg)
- def error_handler(self,arg):
+ def error_handler(self, arg):
# used to silently ingore dbus timeouts
pass
@@ -134,11 +134,11 @@ class DBusManager(gobject.GObject):
self.emit("crash")
def update_cb(self, message, job_id=0):
- print "Update >>%s<<" % message
+ log1("Update:%s", message)
self.emit("update", message)
def warning_cb(self, message, job_id=0):
- print "Warning >>%s<<" % message
+ log1("Warning:%s", message)
self.emit("warning", message)
def owner_changed_cb(self,name, old_owner, new_owner):
@@ -151,7 +151,7 @@ class DBusManager(gobject.GObject):
def jobdone_cb(self, dest, uuid):
# TODO: check that it is indeed OUR job:
# remember uuid in getReport and compare here
- print "Our job for UUID %s is done." % uuid
+ log1("Our job for UUID %s is done", uuid)
dump = self.daemon().CreateReport(uuid)
if dump:
self.emit("analyze-complete", dump)
@@ -167,7 +167,10 @@ class DBusManager(gobject.GObject):
def Report(self, report, reporters_settings = None):
# map < Plguin_name vec <status, message> >
- self.daemon().Report(report, reporters_settings, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60)
+ if reporters_settings:
+ self.daemon().Report(report, reporters_settings, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60)
+ else:
+ self.daemon().Report(report, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60)
def DeleteDebugDump(self,UUID):
return self.daemon().DeleteDebugDump(UUID)
@@ -188,15 +191,14 @@ class DBusManager(gobject.GObject):
def getPluginSettings(self, plugin_name):
settings = self.daemon().GetPluginSettings(plugin_name)
- #for i in settings.keys():
- # print i
return settings
- def registerPlugin(self, plugin_name):
- return self.daemon().RegisterPlugin(plugin_name)
-
- def unRegisterPlugin(self, plugin_name):
- return self.daemon().UnRegisterPlugin(plugin_name)
+# "Enable" toggling in GUI is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD
+# def registerPlugin(self, plugin_name):
+# return self.daemon().RegisterPlugin(plugin_name)
+#
+# def unRegisterPlugin(self, plugin_name):
+# return self.daemon().UnRegisterPlugin(plugin_name)
def setPluginSettings(self, plugin_name, plugin_settings):
return self.daemon().SetPluginSettings(plugin_name, plugin_settings)
@@ -206,6 +208,6 @@ class DBusManager(gobject.GObject):
def setSettings(self, settings):
# FIXME: STUB!!!!
- print "setSettings stub"
+ log1("setSettings stub")
retval = self.daemon().SetSettings(self.daemon().GetSettings())
print ">>>", retval
diff --git a/src/Gui/CCDumpList.py b/src/Gui/CCDumpList.py
index 09191f5..a8657e0 100644
--- a/src/Gui/CCDumpList.py
+++ b/src/Gui/CCDumpList.py
@@ -6,7 +6,6 @@ class DumpList(list):
"""Class to store list of debug dumps"""
def __init__(self,dbus_manager=None):
self.dm = dbus_manager
- self.ddict = {}
def load(self):
if self.dm:
@@ -21,7 +20,6 @@ class DumpList(list):
# print "DumpList adding %s:%s" % (column,row[column])
entry.__dict__[column] = row[column]
self.append(entry)
- self.ddict[entry.getUUID()] = entry
except Exception, e:
# FIXME handle exception better
# this is just temporary workaround for rhbz#543725
diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py
index 77ce3d3..5ffc027 100644
--- a/src/Gui/CCMainWindow.py
+++ b/src/Gui/CCMainWindow.py
@@ -2,6 +2,7 @@
import sys
import os
import pwd
+import getopt
import pygtk
pygtk.require("2.0")
import gobject
@@ -12,6 +13,12 @@ except RuntimeError,e:
print e
os.exit()
import gtk.glade
+try:
+ import rpm
+except Exception, ex:
+ rpm = None
+
+from ConfBackend import getCurrentConfBackend, ConfBackendInitError
import CCDBusBackend
from CC_gui_functions import *
from CCDumpList import getDumpList, DumpList
@@ -21,12 +28,7 @@ from SettingsDialog import SettingsDialog
from CCReport import Report
from PluginList import getPluginInfoList
import ABRTExceptions
-from abrt_utils import _
-
-try:
- import rpm
-except Exception, ex:
- rpm = None
+from abrt_utils import _, init_logging, log, log1, log2
class MainWindow():
@@ -41,11 +43,10 @@ class MainWindow():
sys.exit()
except Exception, e:
# show error message if connection fails
- # FIXME add an option to start the daemon
gui_error_message("%s" % e)
sys.exit()
#Set the Glade file
- self.gladefile = "%s%sccgui.glade" % (sys.path[0],"/")
+ self.gladefile = "%s/ccgui.glade" % sys.path[0]
self.wTree = gtk.glade.XML(self.gladefile)
#Get the Main Window, and connect the "destroy" event
@@ -69,9 +70,9 @@ class MainWindow():
#icon, package_name, application, date, crash_rate, user, is_reported, ?object?
self.dumpsListStore = gtk.ListStore(gtk.gdk.Pixbuf, str,str,str,str,str,bool, object)
# set filter
- self.modelfilter = self.dumpsListStore.filter_new()
- self.modelfilter.set_visible_func(self.filter_dumps, None)
- self.dlist.set_model(self.modelfilter)
+ modelfilter = self.dumpsListStore.filter_new()
+ modelfilter.set_visible_func(self.filter_dumps, None)
+ self.dlist.set_model(modelfilter)
# add pixbuff separatelly
icon_column = gtk.TreeViewColumn(_("Icon"))
icon_column.cell = gtk.CellRendererPixbuf()
@@ -233,9 +234,11 @@ class MainWindow():
# it is not informative (no URL to the report)
for message in dump.getMessage().split('\n'):
if message:
- if "http" in message[0:5] or "file:///"[0:8] in message:
- message = "<a href=\"%s\">%s</a>" % (message, message)
+ #Doesn't work (far too easy to make it worse, not better):
+ #if "http" in message[0:5] or "file:///"[0:8] in message:
+ # message = "<a href=\"%s\">%s</a>" % (message, message)
report_label += "%s\n" % message
+ log2("setting markup '%s'", report_label)
self.wTree.get_widget("lReported").set_markup(report_label)
else:
self.wTree.get_widget("lReported").set_markup(_("<b>Not reported!</b>"))
@@ -297,13 +300,20 @@ class MainWindow():
try:
self.pBarWindow.show_all()
self.timer = gobject.timeout_add(100, self.progress_update_cb)
- reporters_settings = {}
- # self.pluginlist = getPluginInfoList(self.ccdaemon, refresh=True)
- # don't force refresh!
- self.pluginlist = getPluginInfoList(self.ccdaemon)
- for plugin in self.pluginlist.getReporterPlugins():
- reporters_settings[str(plugin)] = plugin.Settings
+ # Old way: it needs to talk to daemon
+ #reporters_settings = {}
+ ## self.pluginlist = getPluginInfoList(self.ccdaemon, refresh=True)
+ ## don't force refresh!
+ #self.pluginlist = getPluginInfoList(self.ccdaemon)
+ #for plugin in self.pluginlist.getReporterPlugins():
+ # reporters_settings[str(plugin)] = plugin.Settings
+ reporters_settings = getCurrentConfBackend().load_all()
+ log2("Report(result,settings):")
+ log2(" result:%s", str(result))
+ # Careful, this will print reporters_settings["Password"] too
+ log2(" settings:%s", str(reporters_settings))
self.ccdaemon.Report(result, reporters_settings)
+ log2("Report() returned")
#self.hydrate()
except Exception, e:
gui_error_message(_("Reporting failed!\n%s" % e))
@@ -381,8 +391,19 @@ class MainWindow():
self.window.present()
if __name__ == "__main__":
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "v")
+ except getopt.GetoptError, err:
+ print str(err) # prints something like "option -a not recognized"
+ sys.exit(2)
+ verbose = 0
+ for opt, arg in opts:
+ if opt == "-v":
+ verbose += 1
+ init_logging("abrt-gui", verbose)
+ log1("log level:%d", verbose)
+
cc = MainWindow()
cc.hydrate()
cc.show()
gtk.main()
-
diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py
index 09a9c91..ab6ad0f 100644
--- a/src/Gui/CCReporterDialog.py
+++ b/src/Gui/CCReporterDialog.py
@@ -12,7 +12,7 @@ from ABRTPlugin import PluginInfo
from PluginSettingsUI import PluginSettingsUI
from PluginList import getPluginInfoList
#from CCDumpList import getDumpList, DumpList
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
# FIXME - create method or smth that returns type|editable|content
CD_TYPE = 0
@@ -131,7 +131,7 @@ class ReporterDialog():
ui.dehydrate()
if plugin.Settings.check():
try:
- plugin.save_settings()
+ plugin.save_settings_on_client_side()
except Exception, e:
gui_error_message(_("Can't save plugin settings:\n %s" % e))
box = image.get_parent()
diff --git a/src/Gui/CC_gui_functions.py b/src/Gui/CC_gui_functions.py
index 0532ab7..0379f20 100644
--- a/src/Gui/CC_gui_functions.py
+++ b/src/Gui/CC_gui_functions.py
@@ -15,13 +15,15 @@ try:
import rpm
except:
rpm = None
+from abrt_utils import _, log, log1, log2
+
def on_url_clicked(label, url):
import gnomevfs
file_mimetype = gnomevfs.get_mime_type(url)
default_app = gnomevfs.mime_get_default_application(file_mimetype)
if default_app:
- #print "Default Application:", default_app[2]
+ log2("default application:%s", default_app[2])
subprocess.Popen([default_app[2], url])
def gui_report_dialog ( report_status_dict, parent_dialog,
@@ -160,8 +162,8 @@ def gui_question_dialog ( message, parent_dialog=None,
dialog.destroy()
return ret
-def get_icon_for_package(theme,package):
- #print package
+def get_icon_for_package(theme, package):
+ log2("get_icon_for_package('%s')", package)
try:
return theme.load_icon(package, 22, gtk.ICON_LOOKUP_USE_BUILTIN)
except:
@@ -169,7 +171,7 @@ def get_icon_for_package(theme,package):
if not rpm:
return None
ts = rpm.TransactionSet()
- mi = ts.dbMatch( 'name', package )
+ mi = ts.dbMatch('name', package)
possible_icons = []
icon_filename = ""
filenames = ""
@@ -180,19 +182,19 @@ def get_icon_for_package(theme,package):
if filename.rfind(".png") != -1:
possible_icons.append(filename)
if filename.rfind(".desktop") != -1:
- #print filename
+ log2("desktop file:'%s'", filename)
desktop_file = open(filename, 'r')
lines = desktop_file.readlines()
for line in lines:
if line.find("Icon=") != -1:
- #print line[5:-1]
+ log2("Icon='%s'", line[5:-1])
icon_filename = line[5:-1]
break
desktop_file.close()
# .dektop file found
for filename in h['filenames']:
if filename.rfind("%s.png" % icon_filename) != -1:
- #print filename
+ log2("png file:'%s'", filename)
icon_filename = filename
break
#we didn't find the .desktop file
@@ -205,8 +207,8 @@ def get_icon_for_package(theme,package):
if icon_filename:
break
if icon_filename:
- #print "icon created form %s" % icon_filename
- return gtk.gdk.pixbuf_new_from_file_at_size(icon_filename,22,22)
+ log1("icon created from %s", icon_filename)
+ return gtk.gdk.pixbuf_new_from_file_at_size(icon_filename, 22, 22)
else:
return None
diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py
index 5e26f3e..0d47760 100644
--- a/src/Gui/ConfBackend.py
+++ b/src/Gui/ConfBackend.py
@@ -1,6 +1,8 @@
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
-#FIXME: add some backend factory
+# Doc on Gnome keyring API:
+# http://library.gnome.org/devel/gnome-keyring/stable/
+# Python bindings are in gnome-python2-desktop package
try:
import gnomekeyring as gkey
@@ -38,63 +40,182 @@ class ConfBackend(object):
raise NotImplementedError
+# We use Gnome keyring in the following way:
+# we store passwords for each plugin in a key named "abrt:<plugin_name>".
+# The value of the key becomes the value of "Password" setting.
+# Other settings (if plugin has them) are stored as attributes of this key.
+#
+# Example: Key "abrt:Bugzilla" with bugzilla password as value, and with attributes:
+#
+# Application: abrt
+# AbrtPluginInfo: Bugzilla
+# NoSSLVerify: yes
+# Login: user@host.com
+# BugzillaURL: https://host.with.bz.com/
+#
+# Attributes "Application" and "AbrtPluginInfo" are special, they are used
+# for efficient key retrieval via keyring API find_items_sync() function.
+
+g_default_key_ring = None
+
class ConfBackendGnomeKeyring(ConfBackend):
def __init__(self):
+ global g_default_key_ring
+
ConfBackend.__init__(self)
- if not gkey.is_available():
+ if g_default_key_ring:
+ return
+ if not gkey or not gkey.is_available():
raise ConfBackendInitError(_("Can't connect to Gnome Keyring daemon"))
try:
- self.default_key_ring = gkey.get_default_keyring_sync()
+ g_default_key_ring = gkey.get_default_keyring_sync()
except:
# could happen if keyring daemon is running, but we run gui under
- # user who is not owner is the running session - using su
+ # user who is not the owner of the running session - using su
raise ConfBackendInitError(_("Can't get default keyring"))
def save(self, name, settings):
settings_tmp = settings.copy()
+ settings_tmp["Application"] = "abrt"
settings_tmp["AbrtPluginInfo"] = name
- password = ""
- item_list = []
+ # delete all keyring items containg "AbrtPluginInfo":"<plugin_name>",
+ # so we always have only 1 item per plugin
try:
- item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)})
+ item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, { "AbrtPluginInfo": str(name) })
+ for item in item_list:
+ log2("found old keyring item: ring:'%s' item_id:%s attrs:%s", item.keyring, item.item_id, str(item.attributes))
+ log2("deleting it from keyring '%s'", g_default_key_ring)
+ gkey.item_delete_sync(g_default_key_ring, item.item_id)
except gkey.NoMatchError:
# nothing found
pass
except gkey.DeniedError:
- raise ConfBackendSaveError(_("Acces to gnome-keyring has been denied, plugins settings won't be saved."))
-
- # delete all items containg "AbrtPluginInfo":<plugin_name>, so we always have only 1 item per plugin
- for item in item_list:
- gkey.item_delete_sync(self.default_key_ring, item.item_id)
-
+ raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved."))
+ # if plugin has a "Password" setting, we handle it specially: in keyring,
+ # it is stored as item.secret, not as one of attributes
+ password = ""
if "Password" in settings_tmp:
password = settings_tmp["Password"]
del settings_tmp["Password"]
+ # store new settings for this plugin as one keyring item
try:
- gkey.item_create_sync(self.default_key_ring,
+ gkey.item_create_sync(g_default_key_ring,
gkey.ITEM_GENERIC_SECRET,
- "abrt:%s" % name,
- settings_tmp,
- password,
+ "abrt:%s" % name, # display_name
+ settings_tmp, # attrs
+ password, # secret
True)
except gkey.DeniedError, e:
- raise ConfBackendSaveError(_("Acces to gnome-keyring has been denied, plugins settings won't be saved."))
+ raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved."))
def load(self, name):
item_list = None
try:
+ log2("looking for keyring items with 'AbrtPluginInfo:%s' attr", str(name))
item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)})
+ for item in item_list:
+ # gnome keyring is weeeeird. why display_name, type, mtime, ctime
+ # aren't available in find_items_sync() results? why we need to
+ # get them via additional call, item_get_info_sync()?
+ # internally, item has GNOME_KEYRING_TYPE_FOUND type,
+ # and info has GNOME_KEYRING_TYPE_ITEM_INFO type.
+ # why not use the same type for both?
+ #
+ # and worst of all, this information took four hours of googling...
+ #
+ #info = gkey.item_get_info_sync(item.keyring, item.item_id)
+ log2("found keyring item: ring:'%s' item_id:%s attrs:%s", # "secret:'%s' display_name:'%s'"
+ item.keyring, item.item_id, str(item.attributes) #, item.secret, info.get_display_name()
+ )
except gkey.NoMatchError:
# nothing found
pass
-
if item_list:
retval = item_list[0].attributes.copy()
retval["Password"] = item_list[0].secret
return retval
- else:
- return {}
- #for i in item_list:
- # for attr in i.attributes:
- # print attr, i.attributes[attr]
+ return {}
+
+ # This routine loads setting for all plugins. It doesn't need plugin name.
+ # Thus we can avoid talking to abrtd just in order to get plugin names.
+ def load_all(self):
+ retval = {}
+ item_list = {}
+
+ # UGLY compat cludge for users who has saved items without "Application" attr
+ # (abrt <= 1.0.3 was saving those)
+ item_ids = gkey.list_item_ids_sync(g_default_key_ring)
+ log2("all keyring item ids:%s", item_ids)
+ for item_id in item_ids:
+ info = gkey.item_get_info_sync(g_default_key_ring, item_id)
+ attrs = gkey.item_get_attributes_sync(g_default_key_ring, item_id)
+ log2("keyring item %s: attrs:%s", item_id, str(attrs))
+ if "AbrtPluginInfo" in attrs:
+ if not "Application" in attrs:
+ log2("updating old-style keyring item")
+ attrs["Application"] = "abrt"
+ try:
+ gkey.item_set_attributes_sync(g_default_key_ring, item_id, attrs)
+ except:
+ log2("error updating old-style keyring item")
+ plugin_name = attrs["AbrtPluginInfo"]
+ # If plugin has a "Password" setting, we handle it specially: in keyring,
+ # it is stored as item.secret, not as one of attributes
+ if info.get_secret():
+ attrs["Password"] = info.get_secret()
+ # avoiding sending useless duplicate info over dbus...
+ del attrs["AbrtPluginInfo"]
+ try:
+ del attrs["Application"]
+ except:
+ pass
+ retval[plugin_name] = attrs;
+ # end of UGLY compat cludge
+
+ try:
+ log2("looking for keyring items with 'Application:abrt' attr")
+ item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, { "Application": "abrt" })
+ except gkey.NoMatchError:
+ # nothing found
+ pass
+ for item in item_list:
+ # gnome keyring is weeeeird. why display_name, type, mtime, ctime
+ # aren't available in find_items_sync() results? why we need to
+ # get them via additional call, item_get_info_sync()?
+ # internally, item has GNOME_KEYRING_TYPE_FOUND type,
+ # and info has GNOME_KEYRING_TYPE_ITEM_INFO type.
+ # why not use the same type for both?
+ #
+ # and worst of all, this information took four hours of googling...
+ #
+ #info = gkey.item_get_info_sync(item.keyring, item.item_id)
+ log2("found keyring item: ring:%s item_id:%s attrs:%s", # "secret:%s display_name:'%s'"
+ item.keyring, item.item_id, str(item.attributes) #, item.secret, info.get_display_name()
+ )
+ attrs = item.attributes.copy()
+ if "AbrtPluginInfo" in attrs:
+ plugin_name = attrs["AbrtPluginInfo"]
+ # If plugin has a "Password" setting, we handle it specially: in keyring,
+ # it is stored as item.secret, not as one of attributes
+ if item.secret:
+ attrs["Password"] = item.secret
+ # avoiding sending useless duplicate info over dbus...
+ del attrs["AbrtPluginInfo"]
+ try:
+ del attrs["Application"]
+ except:
+ pass
+ retval[plugin_name] = attrs;
+ return retval
+
+
+# Rudimentary backend factory
+
+currentConfBackend = None
+
+def getCurrentConfBackend():
+ global currentConfBackend
+ if not currentConfBackend:
+ currentConfBackend = ConfBackendGnomeKeyring()
+ return currentConfBackend
diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py
index e57040d..d2232bb 100644
--- a/src/Gui/PluginList.py
+++ b/src/Gui/PluginList.py
@@ -1,31 +1,27 @@
# -*- coding: utf-8 -*-
import CCDBusBackend
from ABRTPlugin import PluginInfo, PluginSettings
+from abrt_utils import _, log, log1, log2
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"
rows = self.dm.getPluginsInfo()
- #print rows
- for row in rows:
+ for plugin_name in rows:
+ row = rows[plugin_name]
entry = PluginInfo()
- for column in row:
- #print "PluginInfoList adding %s:%s" % (column,row[column])
- entry.__dict__[column] = row[column]
- if entry.Enabled == "yes":
- #entry.Settings = PluginSettings(self.dm.getPluginSettings(str(entry)))
- default_settings = self.dm.getPluginSettings(str(entry))
- entry.load_settings(default_settings)
+ for attr_name in row:
+ log2("PluginInfoList: adding %s[%s]:%s", plugin_name, attr_name, row[attr_name])
+ entry.__dict__[attr_name] = row[attr_name]
+ daemon_settings = self.dm.getPluginSettings(plugin_name)
+ entry.load_daemon_settings(daemon_settings)
self.append(entry)
- self.ddict[entry.getName()] = entry
else:
- print "db == None!"
+ log("PluginInfoList: db == None")
def getEnabledPlugins(self):
return [x for x in self if x["Enabled"] == 'yes']
diff --git a/src/Gui/PluginSettingsUI.py b/src/Gui/PluginSettingsUI.py
index a26f87f..c324b31 100644
--- a/src/Gui/PluginSettingsUI.py
+++ b/src/Gui/PluginSettingsUI.py
@@ -1,5 +1,5 @@
import gtk
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
class PluginSettingsUI(gtk.Dialog):
def __init__(self, pluginfo, parent=None):
diff --git a/src/Gui/PluginsSettingsDialog.py b/src/Gui/PluginsSettingsDialog.py
index 8453385..611a8c5 100644
--- a/src/Gui/PluginsSettingsDialog.py
+++ b/src/Gui/PluginsSettingsDialog.py
@@ -4,14 +4,16 @@ from PluginList import getPluginInfoList, PluginInfoList
from CC_gui_functions import *
from PluginSettingsUI import PluginSettingsUI
from ABRTPlugin import PluginSettings, PluginInfo
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
+
class PluginsSettingsDialog:
def __init__(self, parent, daemon):
#print "Settings dialog init"
self.ccdaemon = daemon
+
self.builder = gtk.Builder()
- builderfile = "%s%ssettings.glade" % (sys.path[0],"/")
+ builderfile = "%s%ssettings.glade" % (sys.path[0], "/")
#print builderfile
try:
self.builder.add_from_file(builderfile)
@@ -22,42 +24,41 @@ class PluginsSettingsDialog:
raise Exception(_("Can't load gui description for SettingsDialog!"))
#self.window.set_parent(parent)
- self.pluginlist = self.builder.get_object("tvSettings")
+ self.pluginlist = self.builder.get_object("tvSettings") # a TreeView
# cell_text, toggle_active, toggle_visible, group_name_visible, color, plugin
self.pluginsListStore = gtk.TreeStore(str, bool, bool, bool, str, 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(_("Name"))
+ modelfilter = self.pluginsListStore.filter_new()
+ modelfilter.set_visible_func(self.filter_plugins, None)
+ self.pluginlist.set_model(modelfilter)
- # create list
- for column in columns:
- n = self.pluginlist.append_column(column)
- column.cell = gtk.CellRendererText()
- column.gray_background = gtk.CellRendererText()
- column.pack_start(column.cell, True)
- column.pack_start(column.gray_background, True)
- column.set_attributes(column.cell, markup=(n-1), visible=2)
- column.set_attributes(column.gray_background, visible=3, cell_background=4)
- column.set_resizable(True)
+ # Create/configure columns and add them to pluginlist
+ # column "name" has two kind of cells:
+ column = gtk.TreeViewColumn(_("Name"))
+ # cells for individual plugins (white)
+ cell_name = gtk.CellRendererText()
+ column.pack_start(cell_name, True)
+ column.set_attributes(cell_name, markup=0, visible=2) # show 0th field (plugin name) from data items if 2th field is true
+ # cells for plugin types (gray)
+ cell_plugin_type = gtk.CellRendererText()
+ column.pack_start(cell_plugin_type, True)
+ column.add_attribute(cell_plugin_type, "visible", 3)
+ column.add_attribute(cell_plugin_type, "markup", 0)
+ column.add_attribute(cell_plugin_type, "cell_background", 4)
+ # column "name" is ready, insert
+ column.set_resizable(True)
+ self.pluginlist.append_column(column)
- # toggle
- group_name_renderer = gtk.CellRendererText()
- toggle_renderer = gtk.CellRendererToggle()
- toggle_renderer.set_property('activatable', True)
- toggle_renderer.connect( 'toggled', self.on_enabled_toggled, self.pluginsListStore )
- column = gtk.TreeViewColumn(_('Enabled'))
- column.pack_start(toggle_renderer, True)
- column.pack_start(group_name_renderer, True)
- column.add_attribute( toggle_renderer, "active", 1)
- column.add_attribute( toggle_renderer, "visible", 2)
- column.add_attribute( group_name_renderer, "visible", 3)
- column.add_attribute( group_name_renderer, "markup", 0)
- column.add_attribute( group_name_renderer, "cell_background", 4)
- self.pluginlist.insert_column(column, 0)
+# "Enable" toggle column is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD
+# column = gtk.TreeViewColumn(_("Enabled"))
+# # column "enabled" has one kind of cells:
+# cell_toggle_enable = gtk.CellRendererToggle()
+# cell_toggle_enable.set_property("activatable", True)
+# cell_toggle_enable.connect("toggled", self.on_enabled_toggled, self.pluginsListStore)
+# column.pack_start(cell_toggle_enable, True)
+# column.add_attribute(cell_toggle_enable, "active", 1)
+# column.add_attribute(cell_toggle_enable, "visible", 2)
+# self.pluginlist.append_column(column)
#connect signals
self.pluginlist.connect("cursor-changed", self.on_tvDumps_cursor_changed)
@@ -65,27 +66,29 @@ class PluginsSettingsDialog:
self.builder.get_object("bClose").connect("clicked", self.on_bClose_clicked)
self.builder.get_object("bConfigurePlugin").set_sensitive(False)
- def on_enabled_toggled(self,cell, path, model):
- plugin = model[path][model.get_n_columns()-1]
- if plugin:
- 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"
- default_settings = self.ccdaemon.getPluginSettings(plugin.getName())
- plugin.Settings = PluginSettings()
- plugin.Settings.load(plugin.getName(), default_settings)
- model[path][1] = not model[path][1]
+# "Enable" toggle column is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD
+# def on_enabled_toggled(self,cell, path, model):
+# plugin = model[path][model.get_n_columns()-1]
+# if plugin:
+# 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"
+# default_settings = self.ccdaemon.getPluginSettings(plugin.getName())
+# plugin.Settings = PluginSettings()
+# plugin.Settings.load(plugin.getName(), default_settings)
+# 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()
@@ -96,15 +99,22 @@ class PluginsSettingsDialog:
except Exception, e:
print e
#gui_error_message("Error while loading plugins info, please check if abrt daemon is running\n %s" % e)
+ return
plugin_rows = {}
for plugin_type in PluginInfo.types.keys():
- it = self.pluginsListStore.append(None, ["<b>%s</b>" % (PluginInfo.types[plugin_type]),0 , 0, 1,"gray", None])
+ it = self.pluginsListStore.append(None,
+ ["<b>%s</b>" % PluginInfo.types[plugin_type], 0, 0, 1, "gray", None])
plugin_rows[plugin_type] = it
for entry in pluginlist:
- n = self.pluginsListStore.append(plugin_rows[entry.getType()],["<b>%s</b>\n%s" % (entry.getName(), entry.Description), entry.Enabled == "yes", 1, 0, "white", entry])
+ if entry.Description:
+ text = "<b>%s</b>\n%s" % (entry.getName(), entry.Description)
+ else:
+ # non-loaded plugins have empty description
+ text = "<b>%s</b>" % entry.getName()
+ self.pluginsListStore.append(plugin_rows[entry.getType()],
+ [text, entry.Enabled == "yes", 1, 0, "white", entry])
self.pluginlist.expand_all()
-
def dehydrate(self):
# we have nothing to save, plugin's does the work
pass
@@ -135,7 +145,7 @@ class PluginsSettingsDialog:
ui.dehydrate()
if pluginfo.Settings:
try:
- pluginfo.save_settings()
+ pluginfo.save_settings_on_client_side()
# FIXME: do we need to call this? all reporters set their settings
# when Report() is called
self.ccdaemon.setPluginSettings(pluginfo.getName(), pluginfo.Settings)
@@ -146,7 +156,7 @@ class PluginsSettingsDialog:
elif response == gtk.RESPONSE_CANCEL:
pass
else:
- print _("unknown response from settings dialog")
+ log("unknown response from settings dialog:%d", response)
ui.destroy()
def on_bClose_clicked(self, button):
diff --git a/src/Gui/SettingsDialog.py b/src/Gui/SettingsDialog.py
index c2b292f..893c23f 100644
--- a/src/Gui/SettingsDialog.py
+++ b/src/Gui/SettingsDialog.py
@@ -3,7 +3,7 @@ import gtk
from PluginList import getPluginInfoList
from CC_gui_functions import *
#from PluginSettingsUI import PluginSettingsUI
-from abrt_utils import _
+from abrt_utils import _, log, log1, log2
#FIXME: create a better struct, to automatize hydrate/dehydrate process
diff --git a/src/Gui/abrt_utils.py b/src/Gui/abrt_utils.py
index 6122b9c..2fabb54 100644
--- a/src/Gui/abrt_utils.py
+++ b/src/Gui/abrt_utils.py
@@ -1,16 +1,37 @@
+import sys
import gtk.glade
+
PROGNAME = "abrt"
+g_verbose = 0
+
import locale
-try:
- locale.setlocale (locale.LC_ALL, "")
-except locale.Error, e:
- import os
- os.environ['LC_ALL'] = 'C'
- locale.setlocale (locale.LC_ALL, "")
import gettext
-gettext.bind_textdomain_codeset(PROGNAME,locale.nl_langinfo(locale.CODESET))
-gettext.bindtextdomain(PROGNAME, '/usr/share/locale')
-gtk.glade.bindtextdomain(PROGNAME, '/usr/share/locale')
-gtk.glade.textdomain(PROGNAME)
-gettext.textdomain(PROGNAME)
+
_ = lambda x: gettext.lgettext(x)
+
+def init_logging(progname, v):
+ global PROGNAME, g_verbose
+ PROGNAME = progname
+ g_verbose = v
+ try:
+ locale.setlocale(locale.LC_ALL, "")
+ except locale.Error, e:
+ import os
+ os.environ['LC_ALL'] = 'C'
+ locale.setlocale(locale.LC_ALL, "")
+ gettext.bind_textdomain_codeset(PROGNAME, locale.nl_langinfo(locale.CODESET))
+ gettext.bindtextdomain(PROGNAME, '/usr/share/locale')
+ gtk.glade.bindtextdomain(PROGNAME, '/usr/share/locale')
+ gtk.glade.textdomain(PROGNAME)
+ gettext.textdomain(PROGNAME)
+
+def log(fmt, *args):
+ sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args))
+
+def log1(fmt, *args):
+ if g_verbose >= 1:
+ sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args))
+
+def log2(fmt, *args):
+ if g_verbose >= 2:
+ sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args))