[Reportbug-commits] r645 - in trunk (3 files)
morph-guest at users.alioth.debian.org
morph-guest at users.alioth.debian.org
Thu Sep 4 17:35:49 UTC 2008
Date: Thursday, September 4, 2008 @ 17:35:47
Author: morph-guest
Revision: 645
applied Luca's patches for gtk+ ui
Modified:
trunk/debian/changelog
trunk/reportbug/debianbts.py
trunk/reportbug/ui/gtk2_ui.py
Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog 2008-09-03 17:24:02 UTC (rev 644)
+++ trunk/debian/changelog 2008-09-04 17:35:47 UTC (rev 645)
@@ -45,7 +45,7 @@
* reportbug/debianbts.py
- added buildd.emdebian.org and debian-i18n pseudo-packages
- -- Sandro Tosi <matrixhasu at gmail.com> Wed, 03 Sep 2008 19:22:59 +0200
+ -- Sandro Tosi <matrixhasu at gmail.com> Thu, 04 Sep 2008 19:26:24 +0200
reportbug (3.45) unstable; urgency=low
Modified: trunk/reportbug/debianbts.py
===================================================================
--- trunk/reportbug/debianbts.py 2008-09-03 17:24:02 UTC (rev 644)
+++ trunk/reportbug/debianbts.py 2008-09-04 17:35:47 UTC (rev 645)
@@ -162,7 +162,7 @@
# 'boot-floppy' : '(Obsolete, please use boot-floppies instead.)',
# 'boot-floppies' : 'Bugs in the woody installation subsystem',
'bugs.debian.org' : 'The bug tracking system, @bugs.debian.org',
- 'buildd.emdebian.org' : 'Problems related to building packages for Emdebian'
+ 'buildd.emdebian.org' : 'Problems related to building packages for Emdebian',
'cdimage.debian.org' : 'CD Image issues',
'cdrom' : 'Problems with installation from CD-ROMs',
# dpkg-iwj -- The dpkg branch maintained by Ian Jackson
Modified: trunk/reportbug/ui/gtk2_ui.py
===================================================================
--- trunk/reportbug/ui/gtk2_ui.py 2008-09-03 17:24:02 UTC (rev 644)
+++ trunk/reportbug/ui/gtk2_ui.py 2008-09-04 17:35:47 UTC (rev 645)
@@ -78,30 +78,13 @@
dialog.set_title ('Reportbug')
dialog.show_all ()
-class ExceptionDialog (gtk.Dialog):
- # Register an exception hook to display an error when the GUI breaks
- @classmethod
- def create_excepthook (cls, oldhook):
- def excepthook (exctype, value, tb):
- if oldhook:
- oldhook (exctype, value, tb)
- application.run_once_in_main_thread (cls.start_dialog,
- ''.join (traceback.format_exception (exctype, value, tb)))
- return excepthook
-
- @classmethod
- def start_dialog (cls, tb):
- try:
- dialog = cls (tb)
- dialog.show_all ()
- except:
- sys.exit (1)
-
- def __init__ (self, tb):
- gtk.Dialog.__init__ (self, "Reportbug: exception", assistant,
+class CustomDialog (gtk.Dialog):
+ def __init__ (self, stock_image, message, buttons, *args, **kwargs):
+ gtk.Dialog.__init__ (self, "Reportbug", assistant,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+ buttons)
# Try following the HIG
+ self.set_default_response (buttons[-1]) # this is the response of the last button
self.set_border_width (5)
vbox = gtk.VBox (spacing=10)
@@ -115,14 +98,52 @@
align = gtk.Alignment (0.5, 0.5, 1.0, 1.0)
hbox.pack_start (align, expand=False)
- image = gtk.image_new_from_stock (gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
+ image = gtk.image_new_from_stock (stock_image, gtk.ICON_SIZE_DIALOG)
hbox.pack_start (image)
- label = gtk.Label ("An error has occurred while doing an operation in Reportbug.\nPlease report the bug.")
+ label = gtk.Label (message)
label.set_line_wrap (True)
label.set_justify (gtk.JUSTIFY_FILL)
hbox.pack_start (label, expand=False)
+ self.setup_dialog (vbox, *args, **kwargs)
+
+class InputStringDialog (CustomDialog):
+ def __init__ (self, message):
+ CustomDialog.__init__ (self, gtk.STOCK_DIALOG_INFO, message,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+
+ def setup_dialog (self, vbox):
+ self.entry = gtk.Entry ()
+ vbox.pack_start (self.entry, expand=False)
+
+ def get_value (self):
+ return self.entry.get_text ()
+
+class ExceptionDialog (CustomDialog):
+ # Register an exception hook to display an error when the GUI breaks
+ @classmethod
+ def create_excepthook (cls, oldhook):
+ def excepthook (exctype, value, tb):
+ if oldhook:
+ oldhook (exctype, value, tb)
+ application.run_once_in_main_thread (cls.start_dialog,
+ ''.join (traceback.format_exception (exctype, value, tb)))
+ return excepthook
+
+ @classmethod
+ def start_dialog (cls, tb):
+ try:
+ dialog = cls (tb)
+ dialog.show_all ()
+ except:
+ sys.exit (1)
+
+ def __init__ (self, tb):
+ CustomDialog.__init__ (self, gtk.STOCK_DIALOG_ERROR, "An error has occurred while doing an operation in Reportbug.\nPlease report the bug.", (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), tb)
+
+ def setup_dialog (self, vbox, tb):
# The traceback
expander = gtk.Expander ("More details")
vbox.pack_start (expander)
@@ -400,7 +421,7 @@
class SyncReturn (RuntimeError):
def __init__ (self, result):
- RuntimeError.__init__ (result)
+ RuntimeError.__init__ (self, result)
self.result = result
class ReportbugConnector (object):
@@ -429,7 +450,6 @@
self.widget.set_border_width (6)
self.widget.show_all ()
self.page_num = Page.next_page_num
- Page.next_page_num += 1
def execute_operation (self, *args, **kwargs):
self.switch_in ()
@@ -452,6 +472,7 @@
# The user will see this as next page
def switch_in (self):
+ Page.next_page_num += 1
self.assistant.insert_page (self.widget, self.page_num)
self.set_page_complete (self.default_complete)
self.set_page_type (self.page_type)
@@ -469,7 +490,7 @@
def validate (self, *args, **kwargs):
value = self.get_value ()
if self.is_valid (value):
- self.assistant.application.set_next_value (value)
+ self.application.set_next_value (value)
self.set_page_complete (True)
else:
self.set_page_complete (False)
@@ -501,8 +522,44 @@
def execute (self, prompt, options=None, force_prompt=False, default=''):
self.label.set_text (prompt)
- self.entry.grab_focus ()
+ self.entry.set_text (default)
+class GetMultilinePage (Page):
+ def create_widget (self):
+ vbox = gtk.VBox (spacing=12)
+ self.label = gtk.Label ()
+ vbox.pack_start (self.label, expand=False)
+
+ view = gtk.TextView ()
+ self.buffer = view.get_buffer ()
+ scrolled = create_scrollable (view)
+ vbox.pack_start (scrolled)
+ return vbox
+
+ def connect_signals (self):
+ self.buffer.connect ('changed', self.validate)
+
+ def is_valid (self, value):
+ if self.empty_ok:
+ return True
+ else:
+ return bool (value)
+
+ def get_value (self):
+ text = self.buffer.get_text (self.buffer.get_start_iter (), self.buffer.get_end_iter ())
+ lines = text.split ('\n')
+ # Remove the trailing empty line at the end
+ if len (lines) > 0 and not lines[-1].strip ():
+ del lines[-1]
+ return text.split ('\n')
+
+ def execute (self, prompt, empty_ok=True):
+ # The result must be iterable for reportbug even if it's empty and not modified
+ self.empty_ok = empty_ok
+ self.label.set_text (prompt)
+ self.buffer.set_text ("")
+ self.buffer.emit ('changed')
+
class TreePage (Page):
value_column = None
@@ -525,6 +582,79 @@
return result[0]
return result
+class GetListPage (TreePage):
+ value_column = 0
+
+ def create_widget (self):
+ vbox = gtk.VBox (spacing=12)
+ self.label = gtk.Label ()
+ vbox.pack_start (self.label, expand=False)
+
+ hbox = gtk.HBox (spacing=6)
+
+ self.view = gtk.TreeView ()
+ self.view.set_rules_hint (True)
+ self.view.get_selection().set_mode (gtk.SELECTION_MULTIPLE)
+ scrolled = create_scrollable (self.view)
+ hbox.pack_start (scrolled)
+
+ bbox = gtk.VButtonBox ()
+ bbox.set_spacing (6)
+ bbox.set_layout (gtk.BUTTONBOX_START)
+ button = gtk.Button (stock=gtk.STOCK_ADD)
+ button.connect ('clicked', self.on_add)
+ bbox.pack_start (button, expand=False)
+ button = gtk.Button (stock=gtk.STOCK_REMOVE)
+ button.connect ('clicked', self.on_remove)
+ bbox.pack_start (button, expand=False)
+ hbox.pack_start (bbox, expand=False)
+
+ vbox.pack_start (hbox)
+ return vbox
+
+ def get_value (self):
+ values = []
+ for row in self.model:
+ values.append (row[self.value_column])
+ return values
+
+ def is_valid (self, value):
+ if self.empty_ok:
+ return True
+ else:
+ return bool (value)
+
+ def on_add (self, button):
+ dialog = InputStringDialog ("Add a new item to the list")
+ dialog.show_all ()
+ dialog.connect ('response', self.on_add_dialog_response)
+
+ def on_add_dialog_response (self, dialog, res):
+ if res == gtk.RESPONSE_ACCEPT:
+ self.model.append ([dialog.get_value ()])
+ dialog.destroy ()
+
+ def on_remove (self, button):
+ model, paths = self.selection.get_selected_rows ()
+ # We need to transform them to iters, since paths change when removing rows
+ iters = []
+ for path in paths:
+ iters.append (self.model.get_iter (path))
+ for iter in iters:
+ self.model.remove (iter)
+
+ def execute (self, prompt, empty_ok=True):
+ self.empty_ok = empty_ok
+ self.label.set_text (prompt)
+
+ self.model = gtk.ListStore (str)
+ self.model.connect ('row-changed', self.validate)
+ self.view.set_model (self.model)
+
+ self.selection.set_mode (gtk.SELECTION_MULTIPLE)
+
+ self.view.append_column (gtk.TreeViewColumn ('Item', gtk.CellRendererText (), text=0))
+
class MenuPage (TreePage):
value_column = 0
@@ -605,7 +735,6 @@
self.application.run_once_in_main_thread (self.assistant.set_progress_label, progress_label)
- result = None
try:
(count, sectitle, hierarchy) = debianbts.get_reports (
package, bts, mirrors=mirrors, version=version,
@@ -637,19 +766,31 @@
error_dialog ('No record of this package found.')
raise NoPackage
- if result and result < 0:
- raise NoReport
+ raise SyncReturn (None)
- raise SyncReturn (result)
-
def create_widget (self):
- vbox = gtk.VBox (spacing=12)
+ vbox = gtk.VBox (spacing=6)
self.label = gtk.Label ("List of bugs. Select a bug to retrieve and submit more information.")
- vbox.pack_start (self.label, expand=False)
+ vbox.pack_start (self.label, expand=False, padding=6)
+ hbox = gtk.HBox (spacing=6)
+ label = gtk.Label ("Filter:")
+ hbox.pack_start (label, expand=False)
+ self.entry = gtk.Entry ()
+ hbox.pack_start (self.entry)
+ button = gtk.Button ()
+ button.set_image (gtk.image_new_from_stock (gtk.STOCK_CLEAR, gtk.ICON_SIZE_BUTTON))
+ button.connect ('clicked', self.on_filter_clear)
+ hbox.pack_start (button, expand=False)
+ vbox.pack_start (hbox, expand=False)
+
self.view = gtk.TreeView ()
self.view.set_rules_hint (True)
scrolled = create_scrollable (self.view)
+ self.columns = ['ID', 'Tag', 'Package', 'Description', 'Reporter', 'Date', 'Severity', 'Version',
+ 'Filed date', 'Modified date']
+ for col in zip (self.columns, range (len (self.columns))):
+ self.view.append_column (gtk.TreeViewColumn (col[0], gtk.CellRendererText (), text=col[1]))
vbox.pack_start (scrolled)
button = gtk.Button ("Retrieve and submit bug information")
@@ -661,7 +802,15 @@
def connect_signals (self):
TreePage.connect_signals (self)
self.view.connect ('row-activated', self.on_retrieve_info)
+ self.entry.connect ('changed', self.on_filter_changed)
+ def on_filter_clear (self, button):
+ self.entry.set_text ("")
+
+ def on_filter_changed (self, entry):
+ self.model.filter_text = entry.get_text().lower ()
+ self.filter.refilter ()
+
def on_retrieve_info (self, *args):
bug_ids = TreePage.get_value (self)
if not bug_ids:
@@ -680,20 +829,40 @@
# The value returned to reportbug doesn't depend by a selection, but by the dialog of a bug
return None
- def execute (self, buglist, sectitle):
- self.label.set_text ("%s. Double-click a bug to retrieve and submit more information." % sectitle)
+ def match_filter (self, iter):
+ # Flatten the columns into a single string
+ text = ""
+ for col in range (len (self.columns)):
+ value = self.model.get_value (iter, col)
+ if value:
+ text += self.model.get_value (iter, col) + " "
- columns = ['ID', 'Tag', 'Package', 'Description', 'Reporter', 'Date', 'Severity', 'Version',
- 'Filed date', 'Modified date']
+ text = text.lower ()
+ # Tokens shouldn't be adjacent by default
+ for token in self.model.filter_text.split (' '):
+ if token in text:
+ return True
+ return False
- self.model = gtk.TreeStore (*([str] * len (columns)))
- self.view.set_model (self.model)
+ def filter_visible_func (self, model, iter):
+ matches = self.match_filter (iter)
+ if not self.model.iter_parent (iter) and not matches:
+ # If no children are visible, hide it
+ it = model.iter_children (iter)
+ while it:
+ if self.match_filter (it):
+ return True
+ it = model.iter_next (it)
+ return False
- for col in zip (columns, range (len (columns))):
- self.view.append_column (gtk.TreeViewColumn (col[0], gtk.CellRendererText (), text=col[1]))
+ return matches
+ def execute (self, buglist, sectitle):
+ self.label.set_text ("%s. Double-click a bug to retrieve and submit more information." % sectitle)
+
+ self.model = gtk.TreeStore (*([str] * len (self.columns)))
for category in buglist:
- row = [None] * len (columns)
+ row = [None] * len (self.columns)
row[3] = category[0]
iter = self.model.append (None, row)
for bug in category[1]:
@@ -701,6 +870,11 @@
self.selection.set_mode (gtk.SELECTION_MULTIPLE)
+ self.model.filter_text = ""
+ self.filter = self.model.filter_new ()
+ self.filter.set_visible_func (self.filter_visible_func)
+ self.view.set_model (self.filter)
+
class DisplayReportPage (Page):
default_complete = True
@@ -718,6 +892,8 @@
def create_widget (self):
self.label = gtk.Label ()
+ self.label.set_line_wrap (True)
+ self.label.set_justify (gtk.JUSTIFY_FILL)
eb = gtk.EventBox ()
eb.add (self.label)
return eb
@@ -738,32 +914,6 @@
LongMessagePage.execute (self, *args, **kwargs)
self.set_page_title ("Thanks for your report")
-class GetMultilinePage (Page):
- default_complete = True
-
- def create_widget (self):
- vbox = gtk.VBox (spacing=12)
- self.label = gtk.Label ()
- vbox.pack_start (self.label, expand=False)
-
- view = gtk.TextView ()
- self.buffer = view.get_buffer ()
- scrolled = create_scrollable (view)
- vbox.pack_start (scrolled)
- return vbox
-
- def is_valid (self, value):
- return True
-
- def connect_signals (self):
- self.buffer.connect ('changed', self.validate)
-
- def get_value (self):
- return self.buffer.get_text (self.buffer.get_start_iter (), self.buffer.get_end_iter ())
-
- def execute (self, prompt):
- self.label.set_text (prompt)
-
class EditorPage (Page):
def create_widget (self):
vbox = gtk.VBox (spacing=6)
@@ -833,7 +983,7 @@
self.info_buffer.set_text (info)
class SelectOptionsPage (Page):
- default_complete = True
+ default_complete = False
def create_widget (self):
self.label = gtk.Label ()
@@ -856,7 +1006,7 @@
if 'Change editor' in desc:
continue
button = gtk.Button (options[menuopt.lower ()])
- button.connect ('clicked', self.on_clicked, menuopt)
+ button.connect ('clicked', self.on_clicked, menuopt.lower ())
if menuopt.isupper ():
default = button
buttons.insert (0, gtk.HSeparator ())
@@ -951,11 +1101,11 @@
# We insert pages between the intro and the progress, so that we give the user the feedback
# that the applications is still running when he presses the "Forward" button
self.showing_page = IntroPage (self)
+ self.showing_page.switch_in ()
self.progress_page = ProgressPage (self)
- Page.next_page_num = 1
- self.showing_page.switch_in ()
self.progress_page.switch_in ()
self.set_current_page (0)
+ Page.next_page_num = 1
assistant = ReportbugAssistant (application)
@@ -1021,6 +1171,13 @@
kwargs['empty_ok'] = True
return menu (*args, **kwargs)
+def get_multiline (prompt, *args, **kwargs):
+ if 'ENTER' in prompt:
+ # This is a list, let's handle it the best way
+ return get_list (prompt, *args, **kwargs)
+ else:
+ return get_multiline (prompt, *args, **kwargs)
+
pages = { 'get_string': GetStringPage,
'menu': MenuPage,
'handle_bts_query': HandleBTSQueryPage,
@@ -1028,7 +1185,8 @@
'display_report': DisplayReportPage,
'final_message': FinalMessagePage,
'spawn_editor': EditorPage,
- 'select_options': SelectOptionsPage }
+ 'select_options': SelectOptionsPage,
+ 'get_list': GetListPage }
dialogs = { 'yes_no': YesNoDialog,
'get_filename': GetFilenameDialog,
'display_failure': DisplayFailureDialog, }
@@ -1057,7 +1215,9 @@
def test ():
# Write some tests here
- asd ()
+ page = HandleBTSQueryPage (assistant)
+ application.run_once_in_main_thread (page.execute_operation, [('asd', (Bug ('#123 [asd] [we] we we Reported by: asd;' ), Bug ('#123 [asd] [we] we we Reported by: asd;')))], 'asd')
+ return application.get_last_value ()
if __name__ == '__main__':
test ()
More information about the Reportbug-commits
mailing list