class BugTool(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.ui = Ui_bugtoolUI() self.ui.setupUi(self) self.screens = availableScreens self.screenData = None self.moveInc = 1 self.menuText = "" self.createWidgets(self.screens) self.shared_data = {} self.screenId = [] for each in self.screens: title = each.Widget().windowTitle() self.screenId.append(title) if self.screens.index(each) == 0: self.menuText += self.putBold(title) else: self.menuText += self.putBr(title) self.ui.labelMenu.setText(self.menuText) QtCore.QObject.connect(self.ui.buttonNext, QtCore.SIGNAL("clicked()"), self.slotNext) QtCore.QObject.connect(self.ui.buttonBack, QtCore.SIGNAL("clicked()"), self.slotBack) QtCore.QObject.connect(self.ui.buttonFinish, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()")) QtCore.QObject.connect(self.ui.buttonCancel, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()")) # returns the id of current stack def getCur(self, d): new = self.ui.mainStack.currentIndex() + d total = self.ui.mainStack.count() if new < 0: new = 0 if new > total: new = total return new # move to id numbered step def setCurrent(self, id=None): if id: self.stackMove(id) # execute next step def slotNext(self, dryRun=False): _w = self.ui.mainStack.currentWidget() ret = _w.execute() if not ret: return self.stackMove(self.getCur(self.moveInc)) self.moveInc = 1 self.menuText = "" curIndex = self.ui.mainStack.currentIndex() for each in self.screenId: i = self.screenId.index(each) if curIndex < len(self.screenId): if i == curIndex: self.menuText += self.putBold(self.screenId[i]) else: self.menuText += self.putBr(self.screenId[i]) self.ui.labelMenu.setText(self.menuText) # execute previous step def slotBack(self): self.menuText = "" curIndex = self.ui.mainStack.currentIndex() for each in self.screenId: i = self.screenId.index(each) if i <= len(self.screenId) and not i == 0: if i == curIndex: self.menuText += self.putBold(self.screenId[i - 1]) else: self.menuText += self.putBr(self.screenId[i - 1]) self.menuText += self.putBr(self.screenId[-1]) self.ui.labelMenu.setText(self.menuText) _w = self.ui.mainStack.currentWidget() _w.backCheck() self.stackMove(self.getCur(self.moveInc * -1)) self.moveInc = 1 def putBr(self, item): return unicode(u"» ") + item + "<br>" def putBold(self, item): return "<b>" + unicode(u"» ") + item + "</b><br>" # move to id numbered stack def stackMove(self, wid): if wid != self.ui.mainStack.currentIndex() or wid == 0: self.ui.mainStack.setCurrentIndex(wid) _w = self.ui.mainStack.currentWidget() _w.update() _w.shown() if self.ui.mainStack.currentIndex() == len(self.screens) - 1: self.ui.buttonNext.hide() self.ui.buttonFinish.show() else: self.ui.buttonNext.show() self.ui.buttonFinish.hide() if self.ui.mainStack.currentIndex() == 0: self.ui.buttonBack.hide() else: self.ui.buttonBack.show() # create all widgets and add inside stack def createWidgets(self, screens=[]): self.ui.mainStack.removeWidget(self.ui.page) for screen in screens: _scr = screen.Widget() self.ui.mainStack.addWidget(_scr) self.stackMove(0) def disableNext(self): self.ui.buttonNext.setEnabled(False) def disableBack(self): self.ui.buttonBack.setEnabled(False) def enableNext(self): self.ui.buttonNext.setEnabled(True) def enableBack(self): self.ui.buttonBack.setEnabled(True) def isNextEnabled(self): return self.ui.buttonNext.isEnabled() def isBackEnabled(self): return self.ui.buttonBack.isEnabled()
class PApport(QtGui.QWidget, apport.ui.UserInterface): def __init__(self, app, parent=None): apport.ui.UserInterface.__init__(self) QtGui.QWidget.__init__(self, parent) self.ui = Ui_bugtoolUI() self.ui.setupUi(self) self.active_widgets = [] self.screenData = None self.moveInc = 1 self.app = app self.app.setQuitOnLastWindowClosed(True) self.running = True self.is_active = False self.waitNextClick = QtCore.QWaitCondition() self.mutex = QtCore.QMutex() QtCore.QObject.connect(self.ui.buttonNext, QtCore.SIGNAL("clicked()"), self.slotNext) QtCore.QObject.connect(self.ui.buttonCancel, QtCore.SIGNAL("clicked()"), self.closeEvent) # Forcing show() on __init__() since run_argv() may block the UI self.show() rect = QtGui.QDesktopWidget().screenGeometry() self.move(rect.width()/2 - self.width()/2, rect.height()/2 -\ self.height()/2) #self.app.exec_() self.run_argv() def slotNext(self): if not self.is_active: sys.exit(0) if hasattr(self.current, 'execute') and self.current.execute(): self.is_active = False self.waitNextClick.wakeAll() def closeEvent(self, event=None): sys.exit(0) def _updateMenu(self): self.menuText = "" current = self.ui.mainStack.currentIndex() - 1 for index, each in enumerate(self.active_widgets): title = each.windowTitle() if index == current: self.menuText += self.putBold(title) else: self.menuText += self.putBr(title) self.ui.labelMenu.setText(self.menuText) def getCur(self, d): new = self.ui.mainStack.currentIndex() + d total = self.ui.mainStack.count() if new < 0: new = 0 if new > total: new = total return new def setCurrent(self, wid=None): if wid: self.stackMove(wid) def appendScreen(self, screen): widget = screen.Widget() self.is_active = True self.active_widgets.append(widget) self.ui.mainStack.addWidget(widget) self.ui.mainStack.setCurrentWidget(widget) self._updateMenu() def set_current_title(self, title): self.current.setWindowTitle(title) self._updateMenu() def putBr(self, item): return unicode(u"» ") + item + "<br>" def putBold(self, item): return "<b>" + unicode(u"» ") + item + "</b><br>" def wait_for_next_click(self): self.waitNextClick.wait(self.mutex) def wait_user_input(self): self.during_progress = False t = Thread(target=self.wait_for_next_click) t.start() while t.is_alive(): self.app.processEvents() @property def current(self): return self.ui.mainStack.currentWidget() # Apport interface def ui_present_crash(self, desktop_entry): self.appendScreen(errorScreen) if desktop_entry: name = desktop_entry.getName() heading = 'Sorry, %s closed unexpectedly' % name elif self.report.has_key('ExecutablePath'): name = os.path.basename(self.report['ExecutablePath']) heading = 'Sorry, the program "%s" closed unexpectedly.' % name else: name = self.cur_package heading = 'Sorry, %s closed unexpectedly.' % name self.set_current_title("Program Crash") self.current.ui.heading.setText(heading) self.current.ui.text.setText('If you were not doing anything ' 'confidential (entering passwords or ' 'other private information), you can help' 'to improve the application by reporting' 'the problem.') self.current.setCheckBox('&Ignore future crashes of this program' ' version') self.wait_user_input() blacklist = self.current.ui.checkBox.isChecked() return {'action': 'report', 'blacklist': blacklist} def ui_present_kernel_error(self): self.appendScreen(errorScreen) message = 'Your system encountered a serious kernel problem.' annotate = '' if self.report.has_key('Annotation'): annotate = self.report['Annotation'] + '\n\n' annotate += ('You can help the developers to fix the problem by ' 'reporting it.') self.set_current_title('Kernel Problem') self.current.ui.heading.setText(message) self.current.ui.text.setText(annotate) self.wait_user_input() return 'report' def ui_persent_package_error(self): self.appendScreen(errorScreen) name = self.report['Package'] heading = 'Sorry, the package "%s" failed to install or upgrade.' % name text = ('You can help the developers to fix the package by reporting'\ ' the problem') self.set_current_title('Package Error') self.current.ui.heading.setText(heading) self.current.ui.text.setText(text) self.wait_user_input() return 'report' def ui_present_report_details(self): self.appendScreen(reportScreen) name = self.report.get('Package') if name is not None: name = name.split()[0] else: name = 'Generic Error' heading = 'Send problem report to the developers?' text = ('You may check below the data that will be sent to the ' 'developers as well as choose whether you want to send a ' 'complete report or a reduced one.') self.set_current_title('%s Details' % name) self.current.ui.heading.setText(heading) self.current.ui.text.setText(text) # complete/reduce radio buttons if self.report.has_key('CoreDump') and \ self.report.has_useful_stacktrace(): complete_size = self.format_filesize(self.get_complete_size()) reduced_size = self.format_filesize(self.get_reduced_size()) self.current.ui.complete.setText('Complete report (recommended; ' '%s)' % complete_size) self.current.ui.reduced.setText('Reduced report (slow Internet ' 'connection; %s)' % reduced_size) else: self.current.ui.options.hide() self.current.load_report(self.report) self.wait_user_input() if self.current.ui.reduced.isChecked(): return 'reduced' else: return 'full' def ui_info_message(self, title, text): self.appendScreen(messageScreen) self.set_current_title('Information') self.current.ui.heading.setText(title) self.current.ui.text.setText(text) self.wait_user_input() def ui_error_message(self, title, text): self.appendScreen(messageScreen) self.set_current_title('Error!') self.current.ui.heading.setText(title) self.current.ui.text.setText(text) self.wait_user_input() def ui_question_yesno(self, text): # TODO: check if this would be better when stacked in the wizard response = kdeui.KMessageBox.questionYesNoCancel( None, text, QtCore.QString(), kdeui.KStandardGuiItem.yes(), kdeui.KStandardGuiItem.no(), kdeui.KStandardGuiItem.cancel()) if response == kdeui.KMessageBox.Yes: return True if response == kdeui.KMessageBox.No: return False return None def ui_question_file(self, text): # TODO: check if this would be better when stacked in the wizard response = QtGui.QFileDialog.getOpenFileName(None, text) if response.length() == 0: return None return str(response) def ui_question_choice(self, text, options, multiple): ''' Show a question with predefined choices. @options is a list of strings to present. @multiple - if True, choices should be QCheckBoxes, if False then should be QRadioButtons. Return list of selected option indexes, or None if the user cancelled. If multiple is False, the list will always have one element. ''' self.appendScreen(choicesScreen) self.set_current_title('Apport Choices') self.current.ui.text.setText(text) for option in options: self.current.add_choice(option, multiple) self.wait_user_input() return self.current.get_response() def ui_question_userpass(self, text): '''Show a Username/Password dialog. Return a tuple (user, pass) or None if cancelled. ''' self.appendScreen(userpassScreen) # Forcing this because this method may be called any time. self.ui.buttonNext.setEnabled(True) self.set_current_title('Credentials') self.current.ui.text.setText(text) self.wait_user_input() return self.current.get_userpass() def ui_start_info_collection_progress(self): self.appendScreen(progressScreen) self.set_current_title('Collecting data') self.current.ui.heading.setText('Collecting Problem Information') self.current.ui.text.setText('The collected information can be sent ' 'to the developers to improve the ' 'application. This might take a few ' 'minutes.') self.current.set_progress() self.ui.buttonNext.setEnabled(False) self.during_progress = True self.app.processEvents() def ui_pulse_info_collection_progress(self): if not self.during_progress: self.ui_start_info_collection_progress() self.current.set_progress() self.app.processEvents() def ui_stop_info_collection_progress(self): self.ui.buttonNext.setEnabled(True) self.during_progress = False self.app.processEvents() def ui_start_upload_progress(self): self.appendScreen(progressScreen) self.set_current_title('Uploading Report') self.current.ui.heading.setText('Uploading Problem Information') self.current.ui.text.setText('The collected information is being sent' ' to the bug tracking system. This might' ' take a few minutes.') self.ui.buttonNext.setEnabled(False) self.during_progress = True self.app.processEvents() def ui_set_upload_progress(self, progress): if not self.during_progress: self.ui_start_upload_progress() self.current.set_progress(progress) self.app.processEvents() def ui_stop_upload_progress(self): self.ui.buttonNext.setEnabled(True) self.during_progress = False self.app.processEvents()
class PApport(QtGui.QWidget, apport.ui.UserInterface): def __init__(self, app, parent=None): apport.ui.UserInterface.__init__(self) QtGui.QWidget.__init__(self, parent) self.ui = Ui_bugtoolUI() self.ui.setupUi(self) self.active_widgets = [] self.screenData = None self.moveInc = 1 self.app = app self.app.setQuitOnLastWindowClosed(True) self.running = True self.is_active = False self.waitNextClick = QtCore.QWaitCondition() self.mutex = QtCore.QMutex() QtCore.QObject.connect(self.ui.buttonNext, QtCore.SIGNAL("clicked()"), self.slotNext) QtCore.QObject.connect(self.ui.buttonCancel, QtCore.SIGNAL("clicked()"), self.closeEvent) # Forcing show() on __init__() since run_argv() may block the UI self.show() rect = QtGui.QDesktopWidget().screenGeometry() self.move(rect.width()/2 - self.width()/2, rect.height()/2 -\ self.height()/2) #self.app.exec_() self.run_argv() def slotNext(self): if not self.is_active: sys.exit(0) if hasattr(self.current, 'execute') and self.current.execute(): self.is_active = False self.waitNextClick.wakeAll() def closeEvent(self, event=None): sys.exit(0) def _updateMenu(self): self.menuText = "" current = self.ui.mainStack.currentIndex() - 1 for index, each in enumerate(self.active_widgets): title = each.windowTitle() if index == current: self.menuText += self.putBold(title) else: self.menuText += self.putBr(title) self.ui.labelMenu.setText(self.menuText) def getCur(self, d): new = self.ui.mainStack.currentIndex() + d total = self.ui.mainStack.count() if new < 0: new = 0 if new > total: new = total return new def setCurrent(self, wid=None): if wid: self.stackMove(wid) def appendScreen(self, screen): widget = screen.Widget() self.is_active = True self.active_widgets.append(widget) self.ui.mainStack.addWidget(widget) self.ui.mainStack.setCurrentWidget(widget) self._updateMenu() def set_current_title(self, title): self.current.setWindowTitle(title) self._updateMenu() def putBr(self, item): return unicode(u"» ") + item + "<br>" def putBold(self, item): return "<b>" + unicode(u"» ") + item + "</b><br>" def wait_for_next_click(self): self.waitNextClick.wait(self.mutex) def wait_user_input(self): self.during_progress = False t = Thread(target=self.wait_for_next_click) t.start() while t.is_alive(): self.app.processEvents() @property def current(self): return self.ui.mainStack.currentWidget() # Apport interface def ui_present_crash(self, desktop_entry): self.appendScreen(errorScreen) if desktop_entry: name = desktop_entry.getName() heading = 'Sorry, %s closed unexpectedly' % name elif self.report.has_key('ExecutablePath'): name = os.path.basename(self.report['ExecutablePath']) heading = 'Sorry, the program "%s" closed unexpectedly.' % name else: name = self.cur_package heading = 'Sorry, %s closed unexpectedly.' % name self.set_current_title("Program Crash") self.current.ui.heading.setText(heading) self.current.ui.text.setText('If you were not doing anything ' 'confidential (entering passwords or ' 'other private information), you can help' 'to improve the application by reporting' 'the problem.') self.current.setCheckBox('&Ignore future crashes of this program' ' version') self.wait_user_input() blacklist = self.current.ui.checkBox.isChecked() return {'action': 'report', 'blacklist': blacklist} def ui_present_kernel_error(self): self.appendScreen(errorScreen) message = 'Your system encountered a serious kernel problem.' annotate = '' if self.report.has_key('Annotation'): annotate = self.report['Annotation'] + '\n\n' annotate += ('You can help the developers to fix the problem by ' 'reporting it.') self.set_current_title('Kernel Problem') self.current.ui.heading.setText(message) self.current.ui.text.setText(annotate) self.wait_user_input() return 'report' def ui_persent_package_error(self): self.appendScreen(errorScreen) name = self.report['Package'] heading = 'Sorry, the package "%s" failed to install or upgrade.' % name text = ('You can help the developers to fix the package by reporting'\ ' the problem') self.set_current_title('Package Error') self.current.ui.heading.setText(heading) self.current.ui.text.setText(text) self.wait_user_input() return 'report' def ui_present_report_details(self): self.appendScreen(reportScreen) name = self.report.get('Package') if name is not None: name = name.split()[0] else: name = 'Generic Error' heading = 'Send problem report to the developers?' text = ('You may check below the data that will be sent to the ' 'developers as well as choose whether you want to send a ' 'complete report or a reduced one.') self.set_current_title('%s Details' % name) self.current.ui.heading.setText(heading) self.current.ui.text.setText(text) # complete/reduce radio buttons if self.report.has_key('CoreDump') and \ self.report.has_useful_stacktrace(): complete_size = self.format_filesize(self.get_complete_size()) reduced_size = self.format_filesize(self.get_reduced_size()) self.current.ui.complete.setText('Complete report (recommended; ' '%s)' % complete_size) self.current.ui.reduced.setText('Reduced report (slow Internet ' 'connection; %s)' % reduced_size) else: self.current.ui.options.hide() self.current.load_report(self.report) self.wait_user_input() if self.current.ui.reduced.isChecked(): return 'reduced' else: return 'full' def ui_info_message(self, title, text): self.appendScreen(messageScreen) self.set_current_title('Information') self.current.ui.heading.setText(title) self.current.ui.text.setText(text) self.wait_user_input() def ui_error_message(self, title, text): self.appendScreen(messageScreen) self.set_current_title('Error!') self.current.ui.heading.setText(title) self.current.ui.text.setText(text) self.wait_user_input() def ui_question_yesno(self, text): # TODO: check if this would be better when stacked in the wizard response = kdeui.KMessageBox.questionYesNoCancel(None, text, QtCore.QString(), kdeui.KStandardGuiItem.yes(), kdeui.KStandardGuiItem.no(), kdeui.KStandardGuiItem.cancel()) if response == kdeui.KMessageBox.Yes: return True if response == kdeui.KMessageBox.No: return False return None def ui_question_file(self, text): # TODO: check if this would be better when stacked in the wizard response = QtGui.QFileDialog.getOpenFileName(None, text) if response.length() == 0: return None return str(response) def ui_question_choice(self, text, options, multiple): ''' Show a question with predefined choices. @options is a list of strings to present. @multiple - if True, choices should be QCheckBoxes, if False then should be QRadioButtons. Return list of selected option indexes, or None if the user cancelled. If multiple is False, the list will always have one element. ''' self.appendScreen(choicesScreen) self.set_current_title('Apport Choices') self.current.ui.text.setText(text) for option in options: self.current.add_choice(option, multiple) self.wait_user_input() return self.current.get_response() def ui_question_userpass(self, text): '''Show a Username/Password dialog. Return a tuple (user, pass) or None if cancelled. ''' self.appendScreen(userpassScreen) # Forcing this because this method may be called any time. self.ui.buttonNext.setEnabled(True) self.set_current_title('Credentials') self.current.ui.text.setText(text) self.wait_user_input() return self.current.get_userpass() def ui_start_info_collection_progress(self): self.appendScreen(progressScreen) self.set_current_title('Collecting data') self.current.ui.heading.setText('Collecting Problem Information') self.current.ui.text.setText('The collected information can be sent ' 'to the developers to improve the ' 'application. This might take a few ' 'minutes.') self.current.set_progress() self.ui.buttonNext.setEnabled(False) self.during_progress = True self.app.processEvents() def ui_pulse_info_collection_progress(self): if not self.during_progress: self.ui_start_info_collection_progress() self.current.set_progress() self.app.processEvents() def ui_stop_info_collection_progress(self): self.ui.buttonNext.setEnabled(True) self.during_progress = False self.app.processEvents() def ui_start_upload_progress(self): self.appendScreen(progressScreen) self.set_current_title('Uploading Report') self.current.ui.heading.setText('Uploading Problem Information') self.current.ui.text.setText('The collected information is being sent' ' to the bug tracking system. This might' ' take a few minutes.') self.ui.buttonNext.setEnabled(False) self.during_progress = True self.app.processEvents() def ui_set_upload_progress(self, progress): if not self.during_progress: self.ui_start_upload_progress() self.current.set_progress(progress) self.app.processEvents() def ui_stop_upload_progress(self): self.ui.buttonNext.setEnabled(True) self.during_progress = False self.app.processEvents()