3
'''QT4 Apport user interface.
5
Copyright (C) 2007 Michael Hofmann <mh21@piware.de>
7
This program is free software; you can redistribute it and/or modify it
8
under the terms of the GNU General Public License as published by the
9
Free Software Foundation; either version 2 of the License, or (at your
10
option) any later version. See http://www.gnu.org/copyleft/gpl.html for
11
the full text of the license.
14
# FIXME: taskbar entry, header for problem details treewidget, binary data
16
import os.path, sys, subprocess
17
from PyQt4.QtCore import *
18
from PyQt4.QtGui import *
20
from gettext import gettext as _
23
class QT4Dialog(QDialog):
24
'''QT4 dialog wrapper.'''
26
def __init__(self, ui, title, heading, text):
27
QDialog.__init__(self)
29
dialog = uic.loadUi(os.path.join(os.path.dirname(sys.argv[0]), ui), self)
31
self.setWindowTitle (title)
32
self.findChild(QLabel, 'heading').setText('<h2>%s</h2>' % heading)
33
self.findChild(QLabel, 'text').setText(text)
35
def on_buttons_clicked(self, button):
36
self.actionButton = button
37
if self.sender().buttonRole(button) == QDialogButtonBox.ActionRole:
38
button.window().done (2)
40
def addbutton(self, button):
41
return self.findChild(QDialogButtonBox, 'buttons').addButton(
42
button, QDialogButtonBox.ActionRole)
44
class QT4ErrorDialog(QT4Dialog):
45
'''QT4 Error dialog wrapper.'''
47
def __init__(self, title, heading, text, checker = None):
48
QT4Dialog.__init__(self, 'error.ui', title, heading, text)
50
self.setMaximumSize(1, 1)
51
self.findChild(QLabel, 'icon').setPixmap(QMessageBox.standardIcon
52
(QMessageBox.Critical))
54
self.checker = self.findChild(QCheckBox, 'checker')
56
self.checker.setText(checker)
61
return self.checker.isChecked()
63
class QT4ProgressDialog(QT4Dialog):
64
'''QT4 Progress dialog wrapper.'''
66
def __init__(self, title, heading, text):
67
QT4Dialog.__init__(self, 'progress.ui', title, heading, text)
69
self.setMaximumSize(1, 1)
71
def on_buttons_clicked(self, button):
72
QT4Dialog.on_buttons_clicked(self, button)
73
if self.sender().buttonRole(button) == QDialogButtonBox.RejectRole:
76
def set(self, value = None):
77
progress = self.findChild(QProgressBar, 'progress')
79
progress.setRange(0, 0)
82
progress.setRange(0, 1000)
83
progress.setValue(value * 1000)
85
class QT4UserInterface(apport.ui.UserInterface):
86
'''QT4 UserInterface.'''
89
'''Shortcut for getting a widget.'''
91
return self.widgets.get_widget(widget)
94
apport.ui.UserInterface.__init__(self)
96
self.app = QApplication([])
99
# ui_* implementation of abstract UserInterface classes
102
def ui_present_crash(self, desktop_entry):
103
# adapt dialog heading and label appropriately
105
name = desktop_entry.getName()
106
heading = _('Sorry, %s closed unexpectedly.') % name
107
elif self.report.has_key('ExecutablePath'):
108
name = os.path.basename(self.report['ExecutablePath'])
109
heading = _('Sorry, the program "%s" closed unexpectedly.') % name
111
name = self.cur_package
112
heading = _('Sorry, %s closed unexpectedly.') % name
114
dialog = QT4ErrorDialog (name, heading,
115
_('If you were not doing anything confidential (entering '
116
'passwords or other private information), you can help to '
117
'improve the application by reporting the problem.'),
118
_('&Ignore future crashes of this program version'))
120
reportbutton = dialog.addbutton(_('&Report Problem...'))
122
if desktop_entry and self.report.has_key('ExecutablePath') and \
123
os.path.dirname(self.report['ExecutablePath']) in \
124
os.environ['PATH'].split(':') and \
125
subprocess.call(['pgrep', '-x',
126
os.path.basename(self.report['ExecutablePath']),
127
'-u', str(os.geteuid())], stdout=subprocess.PIPE) != 0:
128
restartButton = dialog.addbutton(_('Restart &Program'))
130
# show crash notification dialog
131
response = dialog.exec_()
132
blacklist = dialog.checked()
134
if response == QDialog.Rejected:
135
return {'action': 'cancel', 'blacklist': blacklist}
136
if dialog.actionButton == reportbutton:
137
return {'action': 'report', 'blacklist': blacklist}
138
if dialog.actionButton == restartbutton:
139
return {'action': 'restart', 'blacklist': blacklist}
141
return {'action': 'cancel', 'blacklist': blacklist}
143
def ui_present_package_error(self):
144
dialog = QT4ErrorDialog (self.report['Package'],
145
_('Sorry, the package "%s" failed to install or upgrade.') %
147
_('You can help the developers to fix the package by '
148
'reporting the problem.'))
150
reportbutton = dialog.addbutton(_('&Report Problem...'))
152
response = dialog.exec_()
154
if response == QDialog.Rejected:
156
if dialog.actionButton == reportbutton:
161
def ui_present_kernel_error(self):
162
dialog = QT4ErrorDialog (_('Kernel Error'),
163
_('Sorry, the kernel encountered a serious problem'),
164
_('Your system might become unstable now and might need to be '
165
'restarted.\n\nYou can help the developers to fix the '
166
'problem by reporting it.'))
168
reportbutton = dialog.addbutton(_('&Report Problem...'))
170
response = dialog.exec_()
172
if response == QDialog.Rejected:
174
if dialog.actionButton == reportbutton:
179
def ui_present_report_details(self):
180
# Let's get the dialog and modify it to our needs
181
dialog = QT4Dialog ('bugreport.ui',
182
self.report.get('Package', 'Ubuntu').split()[0],
183
_('Send problem report to the developers?'),
184
_('After the problem report has been sent, please fill out '
185
'the form in the automatically opening web browser.'))
187
sendbutton = dialog.addbutton(_('&Send'))
189
# report contents in expander
190
details = dialog.findChild (QTreeWidget, 'details')
191
for key in self.report:
192
keyitem = QTreeWidgetItem([key]);
193
details.addTopLevelItem (keyitem)
196
lines = self.report[key].splitlines()
198
QTreeWidgetItem(keyitem, [line])
200
keyitem.setExpanded(True)
202
QTreeWidgetItem (keyitem, _('(binary data)'))
204
# complete/reduced radio buttons
205
if self.report.has_key('CoreDump'):
206
dialog.findChild(QRadioButton, 'complete').setText(
207
_('Complete report (recommended; %s)') %
208
self.format_filesize(self.get_complete_size()))
209
dialog.findChild(QRadioButton, 'reduced').setText(
210
_('Reduced report (slow Internet connection; %s)') %
211
self.format_filesize(self.get_reduced_size()))
213
dialog.findChild(QFrame, 'options').hide()
215
response = dialog.exec_()
217
if response == QDialog.Rejected:
220
if dialog.actionButton != sendbutton:
222
if dialog.findChild(QRadioButton, 'reduced').isChecked():
224
if dialog.findChild(QRadioButton, 'complete').isChecked():
229
def ui_info_message(self, title, text):
230
QMessageBox.information (None, title, text,
231
QMessageBox.Close, QMessageBox.Close)
233
def ui_error_message(self, title, text):
234
QMessageBox.critical (None, title, text,
235
QMessageBox.Close, QMessageBox.Close)
237
def ui_start_info_collection_progress(self):
238
self.progress = QT4ProgressDialog (
239
_('Collecting Problem Information'),
240
_('Collecting problem information'),
241
_('The collected information can be send to the developers to '
242
'improve the application. This might take some minutes.'))
246
def ui_pulse_info_collection_progress(self):
248
QCoreApplication.processEvents()
250
def ui_stop_info_collection_progress(self):
253
def ui_start_upload_progress(self):
254
'''Open a window with an definite progress bar, telling the user to
255
wait while debug information is being uploaded.'''
257
self.progress = QT4ProgressDialog (
258
_('Uploading Problem Information'),
259
_('Uploading problem information'),
260
_('The collected information is sent to the bug tracking '
261
'system. This might take some minutes.'))
264
def ui_set_upload_progress(self, progress):
265
'''Set the progress bar in the debug data upload progress
266
window to the given ratio (between 0 and 1, or None for indefinite
269
This function is called every 100 ms.'''
272
self.progress.set(progress)
275
QCoreApplication.processEvents()
277
def ui_stop_upload_progress(self):
278
'''Close debug data upload progress window.'''
282
if __name__ == '__main__':
283
app = QT4UserInterface()