2010-09-07 20:42:33 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2019-04-13 13:00:22 +00:00
|
|
|
##########################################################################
|
|
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
|
|
# ---------------------------------------------------------------------- #
|
2022-02-06 09:10:17 +00:00
|
|
|
# Copyright (c) 2008-2022 OpenLP Developers #
|
2019-04-13 13:00:22 +00:00
|
|
|
# ---------------------------------------------------------------------- #
|
|
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
|
|
# it under the terms of the GNU General Public License as published by #
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
|
|
# (at your option) any later version. #
|
|
|
|
# #
|
|
|
|
# This program is distributed in the hope that it will be useful, #
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
|
|
# GNU General Public License for more details. #
|
|
|
|
# #
|
|
|
|
# You should have received a copy of the GNU General Public License #
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
|
|
##########################################################################
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
The actual exception dialog form.
|
|
|
|
"""
|
2010-12-21 19:39:35 +00:00
|
|
|
import logging
|
2010-12-10 20:42:20 +00:00
|
|
|
import os
|
2010-12-11 00:26:41 +00:00
|
|
|
import platform
|
2016-04-04 19:53:54 +00:00
|
|
|
import re
|
2013-07-19 20:56:31 +00:00
|
|
|
|
2018-12-01 05:52:49 +00:00
|
|
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
2011-12-12 22:10:37 +00:00
|
|
|
|
2017-10-07 07:05:07 +00:00
|
|
|
from openlp.core.common import is_linux
|
|
|
|
from openlp.core.common.i18n import UiStrings, translate
|
2017-10-23 22:09:57 +00:00
|
|
|
from openlp.core.common.mixins import RegistryProperties
|
2017-10-07 07:05:07 +00:00
|
|
|
from openlp.core.ui.exceptiondialog import Ui_ExceptionDialog
|
2018-10-02 04:39:42 +00:00
|
|
|
from openlp.core.version import get_library_versions, get_version
|
2017-10-23 22:09:57 +00:00
|
|
|
from openlp.core.widgets.dialogs import FileDialog
|
2010-09-07 20:42:33 +00:00
|
|
|
|
|
|
|
|
2010-12-21 19:39:35 +00:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2013-02-01 19:58:18 +00:00
|
|
|
|
2015-11-07 00:49:40 +00:00
|
|
|
class ExceptionForm(QtWidgets.QDialog, Ui_ExceptionDialog, RegistryProperties):
|
2010-09-07 20:42:33 +00:00
|
|
|
"""
|
|
|
|
The exception dialog
|
|
|
|
"""
|
2013-07-19 20:56:31 +00:00
|
|
|
def __init__(self):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
Constructor.
|
|
|
|
"""
|
2016-01-09 16:26:14 +00:00
|
|
|
super(ExceptionForm, self).__init__(None, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
|
2018-09-12 05:43:27 +00:00
|
|
|
self.setup_ui(self)
|
2013-08-31 18:17:38 +00:00
|
|
|
self.settings_section = 'crashreport'
|
2015-08-26 08:20:55 +00:00
|
|
|
self.report_text = '**OpenLP Bug Report**\n' \
|
2016-06-04 00:15:19 +00:00
|
|
|
'Version: {version}\n\n' \
|
|
|
|
'--- Details of the Exception. ---\n\n{description}\n\n ' \
|
|
|
|
'--- Exception Traceback ---\n{traceback}\n' \
|
|
|
|
'--- System information ---\n{system}\n' \
|
|
|
|
'--- Library Versions ---\n{libs}\n'
|
2010-12-10 20:42:20 +00:00
|
|
|
|
2015-11-07 00:49:40 +00:00
|
|
|
def exec(self):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
Show the dialog.
|
|
|
|
"""
|
2013-08-31 18:17:38 +00:00
|
|
|
self.description_text_edit.setPlainText('')
|
2013-03-05 14:05:19 +00:00
|
|
|
self.on_description_updated()
|
|
|
|
self.file_attachment = None
|
2015-11-07 00:49:40 +00:00
|
|
|
return QtWidgets.QDialog.exec(self)
|
2011-02-03 17:11:20 +00:00
|
|
|
|
2013-03-05 14:14:37 +00:00
|
|
|
def _create_report(self):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
Create an exception report.
|
|
|
|
"""
|
2017-09-09 05:19:22 +00:00
|
|
|
openlp_version = get_version()
|
2013-03-05 14:02:56 +00:00
|
|
|
description = self.description_text_edit.toPlainText()
|
|
|
|
traceback = self.exception_text_edit.toPlainText()
|
2016-05-20 16:22:06 +00:00
|
|
|
system = translate('OpenLP.ExceptionForm', 'Platform: {platform}\n').format(platform=platform.platform())
|
2018-12-01 05:52:49 +00:00
|
|
|
library_versions = get_library_versions()
|
|
|
|
library_versions['PyUNO'] = self._get_pyuno_version()
|
|
|
|
libraries = '\n'.join(['{}: {}'.format(library, version) for library, version in library_versions.items()])
|
2016-05-20 16:22:06 +00:00
|
|
|
|
2014-08-27 23:18:06 +00:00
|
|
|
if is_linux():
|
2013-08-31 18:17:38 +00:00
|
|
|
if os.environ.get('KDE_FULL_SESSION') == 'true':
|
|
|
|
system += 'Desktop: KDE SC\n'
|
|
|
|
elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
|
|
|
|
system += 'Desktop: GNOME\n'
|
|
|
|
elif os.environ.get('DESKTOP_SESSION') == 'xfce':
|
|
|
|
system += 'Desktop: Xfce\n'
|
2016-06-24 12:39:47 +00:00
|
|
|
# NOTE: Keys match the expected input for self.report_text.format()
|
|
|
|
return {'version': openlp_version, 'description': description, 'traceback': traceback,
|
|
|
|
'system': system, 'libs': libraries}
|
2010-12-13 14:24:16 +00:00
|
|
|
|
2013-03-05 14:14:37 +00:00
|
|
|
def on_save_report_button_clicked(self):
|
2010-12-10 20:42:20 +00:00
|
|
|
"""
|
2012-12-29 09:35:24 +00:00
|
|
|
Saving exception log and system information to a file.
|
2010-12-10 20:42:20 +00:00
|
|
|
"""
|
2019-03-03 09:49:01 +00:00
|
|
|
while True:
|
|
|
|
file_path, filter_used = FileDialog.getSaveFileName(
|
|
|
|
self,
|
|
|
|
translate('OpenLP.ExceptionForm', 'Save Crash Report'),
|
2020-02-09 20:24:05 +00:00
|
|
|
self.settings.value(self.settings_section + '/last directory'),
|
2019-03-03 09:49:01 +00:00
|
|
|
translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)'))
|
|
|
|
if file_path is None:
|
|
|
|
break
|
2020-02-09 20:24:05 +00:00
|
|
|
self.settings.setValue(self.settings_section + '/last directory', file_path.parent)
|
2016-06-24 12:39:47 +00:00
|
|
|
opts = self._create_report()
|
|
|
|
report_text = self.report_text.format(version=opts['version'], description=opts['description'],
|
2016-06-25 11:39:57 +00:00
|
|
|
traceback=opts['traceback'], libs=opts['libs'], system=opts['system'])
|
2010-12-10 20:42:20 +00:00
|
|
|
try:
|
2017-09-24 08:39:54 +00:00
|
|
|
with file_path.open('w') as report_file:
|
2011-06-01 05:42:56 +00:00
|
|
|
report_file.write(report_text)
|
2019-03-03 09:49:01 +00:00
|
|
|
break
|
|
|
|
except OSError as e:
|
2013-08-31 18:17:38 +00:00
|
|
|
log.exception('Failed to write crash report')
|
2019-03-03 09:49:01 +00:00
|
|
|
QtWidgets.QMessageBox.warning(
|
|
|
|
self, translate('OpenLP.ExceptionDialog', 'Failed to Save Report'),
|
2019-11-15 16:26:08 +00:00
|
|
|
translate('OpenLP.ExceptionDialog', 'The following error occurred when saving the report.\n\n'
|
2019-03-03 09:49:01 +00:00
|
|
|
'{exception}').format(file_name=file_path, exception=e))
|
2010-12-10 20:42:20 +00:00
|
|
|
|
2013-03-05 14:14:37 +00:00
|
|
|
def on_send_report_button_clicked(self):
|
2010-12-10 20:42:20 +00:00
|
|
|
"""
|
2013-03-14 10:46:19 +00:00
|
|
|
Opening systems default email client and inserting exception log and system information.
|
2010-12-10 20:42:20 +00:00
|
|
|
"""
|
2013-03-05 14:14:37 +00:00
|
|
|
content = self._create_report()
|
2013-08-31 18:17:38 +00:00
|
|
|
source = ''
|
|
|
|
exception = ''
|
2016-06-24 12:39:47 +00:00
|
|
|
for line in content['traceback'].split('\n'):
|
2010-12-11 15:39:12 +00:00
|
|
|
if re.search(r'[/\\]openlp[/\\]', line):
|
|
|
|
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
|
2013-08-31 18:17:38 +00:00
|
|
|
if ':' in line:
|
|
|
|
exception = line.split('\n')[-1].split(':')[0]
|
2016-05-20 16:22:06 +00:00
|
|
|
subject = 'Bug report: {error} in {source}'.format(error=exception, source=source)
|
2016-03-12 21:22:21 +00:00
|
|
|
mail_urlquery = QtCore.QUrlQuery()
|
|
|
|
mail_urlquery.addQueryItem('subject', subject)
|
2016-06-24 12:39:47 +00:00
|
|
|
mail_urlquery.addQueryItem('body', self.report_text.format(version=content['version'],
|
|
|
|
description=content['description'],
|
|
|
|
traceback=content['traceback'],
|
|
|
|
system=content['system'],
|
|
|
|
libs=content['libs']))
|
2013-03-05 14:05:19 +00:00
|
|
|
if self.file_attachment:
|
2016-03-12 21:22:21 +00:00
|
|
|
mail_urlquery.addQueryItem('attach', self.file_attachment)
|
2020-01-06 21:15:11 +00:00
|
|
|
mail_to_url = QtCore.QUrl('mailto:bugs3@openlp.org')
|
2016-03-12 21:22:21 +00:00
|
|
|
mail_to_url.setQuery(mail_urlquery)
|
2013-12-24 11:32:38 +00:00
|
|
|
QtGui.QDesktopServices.openUrl(mail_to_url)
|
2011-02-03 17:11:20 +00:00
|
|
|
|
2013-03-05 14:05:19 +00:00
|
|
|
def on_description_updated(self):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
Update the minimum number of characters needed in the description.
|
|
|
|
"""
|
2013-03-05 14:02:56 +00:00
|
|
|
count = int(20 - len(self.description_text_edit.toPlainText()))
|
2011-02-03 17:11:20 +00:00
|
|
|
if count < 0:
|
2013-03-05 14:14:37 +00:00
|
|
|
self.__button_state(True)
|
2016-08-03 21:19:14 +00:00
|
|
|
self.description_word_count.setText(
|
|
|
|
translate('OpenLP.ExceptionDialog', '<strong>Thank you for your description!</strong>'))
|
|
|
|
elif count == 20:
|
|
|
|
self.__button_state(False)
|
|
|
|
self.description_word_count.setText(
|
|
|
|
translate('OpenLP.ExceptionDialog', '<strong>Tell us what you were doing when this happened.</strong>'))
|
2011-02-03 19:07:27 +00:00
|
|
|
else:
|
2013-03-05 14:14:37 +00:00
|
|
|
self.__button_state(False)
|
2016-08-03 21:19:14 +00:00
|
|
|
self.description_word_count.setText(
|
|
|
|
translate('OpenLP.ExceptionDialog', '<strong>Please enter a more detailed description of the situation'
|
2016-08-25 19:24:59 +00:00
|
|
|
'</strong>'))
|
2011-02-03 17:11:20 +00:00
|
|
|
|
2013-03-05 14:14:37 +00:00
|
|
|
def on_attach_file_button_clicked(self):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
2017-08-26 15:06:11 +00:00
|
|
|
Attach files to the bug report e-mail.
|
|
|
|
"""
|
|
|
|
file_path, filter_used = \
|
|
|
|
FileDialog.getOpenFileName(self,
|
|
|
|
translate('ImagePlugin.ExceptionDialog', 'Select Attachment'),
|
2020-02-09 20:24:05 +00:00
|
|
|
self.settings.value(self.settings_section + '/last directory'),
|
2017-08-26 15:06:11 +00:00
|
|
|
'{text} (*)'.format(text=UiStrings().AllFiles))
|
2017-09-24 08:39:54 +00:00
|
|
|
log.info('New files {file_path}'.format(file_path=file_path))
|
2017-08-26 15:06:11 +00:00
|
|
|
if file_path:
|
|
|
|
self.file_attachment = str(file_path)
|
2011-02-03 19:07:27 +00:00
|
|
|
|
2013-03-05 14:14:37 +00:00
|
|
|
def __button_state(self, state):
|
2013-02-01 19:58:18 +00:00
|
|
|
"""
|
|
|
|
Toggle the button state.
|
|
|
|
"""
|
2013-03-05 14:02:56 +00:00
|
|
|
self.save_report_button.setEnabled(state)
|
|
|
|
self.send_report_button.setEnabled(state)
|
2013-07-19 20:56:31 +00:00
|
|
|
|
2017-11-09 06:10:29 +00:00
|
|
|
def _get_pyuno_version(self):
|
2013-07-21 14:10:21 +00:00
|
|
|
"""
|
|
|
|
Added here to define only when the form is actioned. The uno interface spits out lots of exception messages
|
|
|
|
if the import is at a file level. If uno import is changed this could be reverted.
|
|
|
|
This happens in other classes but there it is localised here it is across the whole system and hides real
|
|
|
|
errors.
|
|
|
|
"""
|
2013-07-19 20:56:31 +00:00
|
|
|
try:
|
|
|
|
import uno
|
2013-08-31 18:17:38 +00:00
|
|
|
arg = uno.createUnoStruct('com.sun.star.beans.PropertyValue')
|
|
|
|
arg.Name = 'nodepath'
|
|
|
|
arg.Value = '/org.openoffice.Setup/Product'
|
2013-07-19 20:56:31 +00:00
|
|
|
context = uno.getComponentContext()
|
2013-08-31 18:17:38 +00:00
|
|
|
provider = context.ServiceManager.createInstance('com.sun.star.configuration.ConfigurationProvider')
|
|
|
|
node = provider.createInstanceWithArguments('com.sun.star.configuration.ConfigurationAccess', (arg,))
|
|
|
|
return node.getByName('ooSetupVersion')
|
2013-07-19 20:56:31 +00:00
|
|
|
except ImportError:
|
2013-08-31 18:17:38 +00:00
|
|
|
return '-'
|
2018-10-27 01:40:20 +00:00
|
|
|
except Exception:
|
2013-08-31 18:17:38 +00:00
|
|
|
return '- (Possible non-standard UNO installation)'
|