diff options
| author | Karel Klic <kklic@redhat.com> | 2010-01-18 13:19:54 +0100 |
|---|---|---|
| committer | Karel Klic <kklic@redhat.com> | 2010-01-18 13:19:54 +0100 |
| commit | 4267cbcc29781ddcac00e259dfe05f3a26fbc2ec (patch) | |
| tree | 213e47138967f1e7af4ee9ff9a3f2ed861cb5815 /src/Gui | |
| parent | b2d1bd9e4f387c5a014d3002d741f25421c37aac (diff) | |
| parent | b41833ed61f7b579d2a46b26d261616c21a6ae32 (diff) | |
| download | abrt-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.py | 2 | ||||
| -rw-r--r-- | src/Gui/ABRTPlugin.py | 49 | ||||
| -rw-r--r-- | src/Gui/CCDBusBackend.py | 40 | ||||
| -rw-r--r-- | src/Gui/CCDumpList.py | 2 | ||||
| -rw-r--r-- | src/Gui/CCMainWindow.py | 61 | ||||
| -rw-r--r-- | src/Gui/CCReporterDialog.py | 4 | ||||
| -rw-r--r-- | src/Gui/CC_gui_functions.py | 20 | ||||
| -rw-r--r-- | src/Gui/ConfBackend.py | 171 | ||||
| -rw-r--r-- | src/Gui/PluginList.py | 22 | ||||
| -rw-r--r-- | src/Gui/PluginSettingsUI.py | 2 | ||||
| -rw-r--r-- | src/Gui/PluginsSettingsDialog.py | 122 | ||||
| -rw-r--r-- | src/Gui/SettingsDialog.py | 2 | ||||
| -rw-r--r-- | src/Gui/abrt_utils.py | 43 |
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)) |
