summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2009-02-23 16:37:25 +0100
committerJiri Moskovcak <jmoskovc@redhat.com>2009-02-23 16:37:25 +0100
commitd740acb4e7c11eaf5deb94b35f33f0bfb7ee99be (patch)
tree3232e0a7820ea3963c75975a98c1f2eebc061fad /src
parent79833fc32cf10ef409b2be63fa58b4f8dfbe1e06 (diff)
downloadabrt-d740acb4e7c11eaf5deb94b35f33f0bfb7ee99be.tar.gz
abrt-d740acb4e7c11eaf5deb94b35f33f0bfb7ee99be.tar.xz
abrt-d740acb4e7c11eaf5deb94b35f33f0bfb7ee99be.zip
Added more functionality to gui
Diffstat (limited to 'src')
-rw-r--r--src/Gui/CCDBusBackend.py (renamed from src/Gui/CCGuiDbusBackend.py)19
-rw-r--r--src/Gui/CCDump.py35
-rw-r--r--src/Gui/CCDumpList.py41
-rw-r--r--src/Gui/CCReporterDialog.py56
-rw-r--r--src/Gui/CC_gui_functions.py39
-rw-r--r--src/Gui/ccgui.glade108
-rwxr-xr-xsrc/Gui/mainwindow.py84
7 files changed, 296 insertions, 86 deletions
diff --git a/src/Gui/CCGuiDbusBackend.py b/src/Gui/CCDBusBackend.py
index 406c1bf..ad3e82c 100644
--- a/src/Gui/CCGuiDbusBackend.py
+++ b/src/Gui/CCDBusBackend.py
@@ -14,10 +14,12 @@ class DBusManager(gobject.GObject):
# and later with policyKit
def __init__(self):
gobject.GObject.__init__(self)
+ # signal emited when new crash is detected
+ gobject.signal_new ("crash", self ,gobject.SIGNAL_RUN_FIRST,gobject.TYPE_NONE,())
# binds the dbus to glib mainloop
DBusGMainLoop(set_as_default=True)
self.proxy = None
- self.connect()
+ self.connect_to_daemon()
if self.proxy:
self.cc = dbus.Interface(self.proxy, dbus_interface=CC_IFACE)
#intr = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Introspectable')
@@ -30,29 +32,28 @@ class DBusManager(gobject.GObject):
print "disconnect"
def crash_cb(self,*args):
- print "got another crash while in gui!"
- for arg in args:
- print arg
+ #FIXME "got another crash, gui should reload!"
+ #for arg in args:
+ # print arg
#emit a signal
+ #print "crash"
+ self.emit("crash")
- def connect(self):
+ def connect_to_daemon(self):
bus = dbus.SystemBus()
if not bus:
raise Exception("Can't connect to dbus")
try:
self.proxy = bus.get_object(CC_IFACE, CC_PATH)
except Exception, e:
- print "Error while creating the proxy"
- print e
+ raise Exception(e.message + "\nPlease check if crash-catcher daemon is running.")
def getDumps(self):
row_dict = None
rows = []
for row in self.cc.GetCrashInfosMap(""):
-# print row
row_dict = {}
for column in row:
row_dict[column] = row[column]
- # print "%s:%s" % (column, row[column])
rows.append(row_dict);
return rows
diff --git a/src/Gui/CCDump.py b/src/Gui/CCDump.py
new file mode 100644
index 0000000..87474e9
--- /dev/null
+++ b/src/Gui/CCDump.py
@@ -0,0 +1,35 @@
+from datetime import datetime
+
+class Dump():
+ """Class for mapping the debug dump to pyhon object"""
+ def __init__(self):
+ self.UUID = None
+ self.UID = None
+ self.Count = None
+ self.Executable = None
+ self.Package = None
+ self.Time = None
+
+ def getUUID(self):
+ return self.UUID
+
+ def getUID(self):
+ return self.UID
+
+ def getCount(self):
+ return self.Count
+
+ def getExecutable(self):
+ return self.Executable
+
+ def getPackage(self):
+ return self.Package
+
+ def getTime(self,format):
+ #print format
+ if format:
+ try:
+ return datetime.fromtimestamp(int(self.Time)).strftime(format)
+ except Exception, e:
+ print e
+ return int(self.Time)
diff --git a/src/Gui/CCDumpList.py b/src/Gui/CCDumpList.py
new file mode 100644
index 0000000..25e12af
--- /dev/null
+++ b/src/Gui/CCDumpList.py
@@ -0,0 +1,41 @@
+import CCDBusBackend
+from CCDump import Dump
+
+class DumpList(list):
+ """Class to store list of debug dumps"""
+ def __init__(self,dbus_manager=None):
+ self.dm = dbus_manager
+
+ def load(self):
+ if self.dm:
+ print "loading DumpList"
+ try:
+ rows = self.dm.getDumps()
+ #print rows
+ for row in rows:
+ entry = Dump()
+ for column in row:
+ #print "DumpList adding %s:%s" % (column,row[column])
+ entry.__dict__[column] = row[column]
+ self.append(entry)
+ except Exception, e:
+ print e
+ return
+ else:
+ print "db == None!"
+
+
+__PFList = None
+__PFList_dbmanager = None
+
+def getDumpList(dbmanager,refresh=None):
+ global __PFList
+ global __PFList_dbmanager
+
+ if __PFList == None or refresh or __PFList_dbmanager != dbmanager:
+ __PFList = DumpList(dbus_manager=dbmanager)
+ __PFList.load()
+ __PFList_dbmanager = dbmanager
+ return __PFList
+
+__PFList = None
diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py
new file mode 100644
index 0000000..c801de3
--- /dev/null
+++ b/src/Gui/CCReporterDialog.py
@@ -0,0 +1,56 @@
+import pygtk
+pygtk.require("2.0")
+import gtk
+import gtk.glade
+import sys
+from CC_gui_functions import *
+from CCDumpList import getDumpList, DumpList
+
+class ReporterDialog():
+ """Reporter window"""
+ def __init__(self, dump):
+ self.dump = dump
+ #Set the Glade file
+ self.gladefile = "ccgui.glade"
+ self.wTree = gtk.glade.XML(self.gladefile)
+ #Get the Main Window, and connect the "destroy" event
+ self.window = self.wTree.get_widget("reporter_dialog")
+
+ #init the dumps treeview
+ self.tvReport = self.wTree.get_widget("tvReport")
+ columns = [None]*2
+ columns[0] = gtk.TreeViewColumn('Item')
+ columns[1] = gtk.TreeViewColumn('Value')
+
+ self.reportListStore = gtk.ListStore(str, str, bool)
+ # set filter
+ #self.modelfilter = self.reportListStore.filter_new()
+ #self.modelfilter.set_visible_func(self.filter_dumps, None)
+ self.tvReport.set_model(self.reportListStore)
+ renderer = gtk.CellRendererText()
+ column = gtk.TreeViewColumn('Item', renderer, text=0)
+ self.tvReport.append_column(column)
+
+ renderer = gtk.CellRendererText()
+ column = gtk.TreeViewColumn('Value', renderer, text=1, editable=2)
+ self.tvReport.append_column(column)
+
+
+ # connect the signals
+ self.wTree.get_widget("bApply").connect("clicked", self.on_apply_clicked, self.tvReport)
+
+ self.hydrate()
+
+ def on_apply_clicked(self, button, treeview):
+ #print treeview
+ self.window.hide()
+
+ def hydrate(self):
+ for item in self.dump.__dict__:
+ self.reportListStore.append([item, self.dump.__dict__[item], False])
+ self.reportListStore.append(["Comment","", True])
+
+ def run(self):
+ self.window.show()
+
+
diff --git a/src/Gui/CC_gui_functions.py b/src/Gui/CC_gui_functions.py
new file mode 100644
index 0000000..5ac8e8c
--- /dev/null
+++ b/src/Gui/CC_gui_functions.py
@@ -0,0 +1,39 @@
+import gtk
+
+def gui_error_message ( message, parent_dialog=None,
+ message_type=gtk.MESSAGE_ERROR,
+ widget=None, page=0, broken_widget=None ):
+
+ dialog = gtk.MessageDialog( parent_dialog,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ message_type, gtk.BUTTONS_OK,
+ message )
+
+ if parent_dialog:
+ dialog.set_position (gtk.WIN_POS_CENTER_ON_PARENT)
+ dialog.set_transient_for(parent_dialog)
+ else:
+ dialog.set_position (gtk.WIN_POS_CENTER)
+
+ ret = dialog.run ()
+ dialog.destroy()
+ return ret
+
+def gui_info_dialog ( message, parent_dialog=None,
+ message_type=gtk.MESSAGE_INFO,
+ widget=None, page=0, broken_widget=None ):
+
+ dialog = gtk.MessageDialog( parent_dialog,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ message_type, gtk.BUTTONS_YES_NO,
+ message )
+
+ if parent_dialog:
+ dialog.set_position (gtk.WIN_POS_CENTER_ON_PARENT)
+ dialog.set_transient_for(parent_dialog)
+ else:
+ dialog.set_position (gtk.WIN_POS_CENTER)
+
+ ret = dialog.run ()
+ dialog.destroy()
+ return ret
diff --git a/src/Gui/ccgui.glade b/src/Gui/ccgui.glade
index 3623c15..61c2981 100644
--- a/src/Gui/ccgui.glade
+++ b/src/Gui/ccgui.glade
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Fri Feb 20 16:42:05 2009 -->
+<!--Generated with glade3 3.4.5 on Mon Feb 23 15:20:47 2009 -->
<glade-interface>
<widget class="GtkWindow" id="main_window">
<property name="default_width">640</property>
@@ -336,7 +336,7 @@
</packing>
</child>
<child>
- <widget class="GtkStatusbar" id="statusbar1">
+ <widget class="GtkStatusbar" id="appBar">
<property name="visible">True</property>
<property name="spacing">2</property>
</widget>
@@ -348,7 +348,7 @@
</widget>
</child>
</widget>
- <widget class="GtkDialog" id="dialog1">
+ <widget class="GtkDialog" id="reporter_dialog">
<property name="border_width">5</property>
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
<property name="default_width">400</property>
@@ -365,14 +365,14 @@
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
- <property name="label" translatable="yes">label</property>
+ <property name="label" translatable="yes">Report</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
- <widget class="GtkTreeView" id="treeview1">
+ <widget class="GtkTreeView" id="tvReport">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
@@ -390,7 +390,7 @@
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
- <widget class="GtkButton" id="button4">
+ <widget class="GtkButton" id="bApply">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -400,7 +400,7 @@
</widget>
</child>
<child>
- <widget class="GtkButton" id="button5">
+ <widget class="GtkButton" id="bCancel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -459,53 +459,6 @@
<placeholder/>
</child>
<child>
- <widget class="GtkLabel" id="label14">
- <property name="visible">True</property>
- <property name="label" translatable="yes">BlackList</property>
- </widget>
- </child>
- <child>
- <widget class="GtkEntry" id="entry1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label15">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Database Plugin</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkComboBox" id="combobox1">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label16">
- <property name="visible">True</property>
- <property name="label" translatable="yes">OpenPGP Public Keys</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
<widget class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<child>
@@ -553,6 +506,53 @@
<property name="bottom_attach">3</property>
</packing>
</child>
+ <child>
+ <widget class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">OpenPGP Public Keys</property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkComboBox" id="combobox1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Database Plugin</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">BlackList</property>
+ </widget>
+ </child>
</widget>
</child>
<child>
diff --git a/src/Gui/mainwindow.py b/src/Gui/mainwindow.py
index 81d7385..b333379 100755
--- a/src/Gui/mainwindow.py
+++ b/src/Gui/mainwindow.py
@@ -5,17 +5,26 @@ import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
-import CCGuiDbusBackend
-from datetime import datetime
+import CCDBusBackend
+import sys
+from CC_gui_functions import *
+from CCDumpList import getDumpList, DumpList
+from CCReporterDialog import ReporterDialog
def cb(self, *args):
pass
-class CCMainWindow():
+class MainWindow():
"""This is an Hello World GTK application"""
def __init__(self):
- self.ccdaemon = CCGuiDbusBackend.DBusManager()
+ try:
+ self.ccdaemon = CCDBusBackend.DBusManager()
+ except Exception, e:
+ # show error message if connection fails
+ # FIXME add an option to start the daemon
+ gui_error_message(e.message)
+ sys.exit()
#Set the Glade file
self.gladefile = "ccgui.glade"
self.wTree = gtk.glade.XML(self.gladefile)
@@ -26,13 +35,15 @@ class CCMainWindow():
if (self.window):
self.window.connect("destroy", gtk.main_quit)
+ self.appBar = self.wTree.get_widget("appBar")
+
#init the dumps treeview
self.dlist = self.wTree.get_widget("tvDumps")
columns = [None]*2
columns[0] = gtk.TreeViewColumn('Date')
- columns[1] = gtk.TreeViewColumn('package')
+ columns[1] = gtk.TreeViewColumn('Package')
# create list
- self.dumpsListStore = gtk.ListStore(str, str, int)
+ self.dumpsListStore = gtk.ListStore(str, str, object)
# set filter
self.modelfilter = self.dumpsListStore.filter_new()
self.modelfilter.set_visible_func(self.filter_dumps, None)
@@ -49,7 +60,29 @@ class CCMainWindow():
self.wTree.get_widget("bDelete").connect("clicked", self.on_bDelete_clicked)
self.wTree.get_widget("bNext").connect("clicked", self.on_bNext_clicked)
self.wTree.get_widget("bQuit").connect("clicked", self.on_bQuit_clicked)
+ self.ccdaemon.connect("crash", self.on_data_changed_cb, None)
+ # load data
+ self.load()
+
+ def load(self):
+ self.appBar.push(0,"Loading dumps...")
+ self.loadDumpList()
+ self.appBar.pop(0)
+
+ def loadDumpList(self):
+ #dumplist = getDumpList(dbmanager=self.ccdaemon)
+ pass
+
+ def on_data_changed_cb(self, *args):
+ ret = gui_info_dialog("Another crash detected, do you want to refresh the data?",self.window)
+ if ret == gtk.RESPONSE_YES:
+ self.hydrate()
+ else:
+ pass
+ #print "got another crash, refresh gui?"
+
+
def filter_dumps(self, model, miter, data):
# this could be use for filtering the dumps
return True
@@ -58,45 +91,50 @@ class CCMainWindow():
self.window.show()
def hydrate(self):
- self.rows = self.ccdaemon.getDumps()
- row_c = 0
- for row in self.rows:
- self.dumpsListStore.append([row["Time"], row["Package"], row_c])
- row_c += 1
+ self.dumpsListStore.clear()
+ dumplist = getDumpList(self.ccdaemon, refresh=True)
+ #self.rows = self.ccdaemon.getDumps()
+ #row_c = 0
+ for entry in dumplist:
+ self.dumpsListStore.append([entry.getTime("%Y:%m:%d"),entry.getPackage(),entry])
+ #row_c += 1
def on_tvDumps_cursor_changed(self,treeview):
dumpsListStore, path = self.dlist.get_selection().get_selected_rows()
if not path:
return
- # rewrite this OO
- #DumpList class
- row = self.rows[dumpsListStore.get_value(dumpsListStore.get_iter(path[0]), 2)]
+ # this should work until we keep the row object in the last position
+ dump = dumpsListStore.get_value(dumpsListStore.get_iter(path[0]), len(dumpsListStore))
lDate = self.wTree.get_widget("lDate")
#move this to Dump class
- t = datetime.fromtimestamp(int(row["Time"]))
- date = t.strftime("%Y-%m-%d %H:%M:%S")
- lDate.set_label(date)
+ lDate.set_label(dump.getTime("%Y.%m.%d %H:%M:%S"))
lPackage = self.wTree.get_widget("lPackage")
- lPackage.set_label(row["Package"])
- self.wTree.get_widget("lExecutable").set_label(row["Executable"])
- self.wTree.get_widget("lCRate").set_label(row["Count"])
+ lPackage.set_label(dump.getPackage())
+ self.wTree.get_widget("lExecutable").set_label(dump.getExecutable())
+ self.wTree.get_widget("lCRate").set_label(dump.getCount())
#print self.rows[row]
def on_bDelete_clicked(self, button):
print "Delete"
def on_bNext_clicked(self, button):
- print "Next"
+ # FIXME don't duplicate the code, move to function
+ dumpsListStore, path = self.dlist.get_selection().get_selected_rows()
+ if not path:
+ return
+ dump = dumpsListStore.get_value(dumpsListStore.get_iter(path[0]), len(dumpsListStore))
+ # show the report window with selected dump
+ report_dialog = ReporterDialog(dump)
+ report_dialog.run()
def on_bQuit_clicked(self, button):
- print "Quit"
gtk.main_quit()
if __name__ == "__main__":
- cc = CCMainWindow()
+ cc = MainWindow()
cc.hydrate()
cc.show()
gtk.main()