File indexing completed on 2024-12-22 04:14:03

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "kbugreport.h"
0008 
0009 #include <QProcess>
0010 #include <QCoreApplication>
0011 #include <QDialogButtonBox>
0012 #include <QPushButton>
0013 #include <QLayout>
0014 #include <QRadioButton>
0015 #include <QGroupBox>
0016 #include <QLocale>
0017 #include <QCloseEvent>
0018 #include <QLabel>
0019 #include <QUrl>
0020 #include <QUrlQuery>
0021 #include <QStandardPaths>
0022 #include <QComboBox>
0023 #include <QLineEdit>
0024 #include <QDebug>
0025 #include <QTextEdit>
0026 #include <QDesktopServices>
0027 #include <QStandardPaths>
0028 #include <QClipboard>
0029 #include <QGuiApplication>
0030 
0031 #include <kaboutdata.h>
0032 #include <kconfig.h>
0033 #include <kconfiggroup.h>
0034 #include <kemailsettings.h>
0035 #include <klocalizedstring.h>
0036 #include <kmessagebox.h>
0037 
0038 #include <ktitlewidget.h>
0039 #include <kwidgetsaddons_version.h>
0040 #include <kstandardguiitem.h>
0041 
0042 #include "systeminformation_p.h"
0043 
0044 #include "config-xmlgui.h"
0045 
0046 #include <kis_icon_utils.h>
0047 
0048 class KisKBugReportPrivate
0049 {
0050 public:
0051     KisKBugReportPrivate(KisKBugReport *q): q(q), m_aboutData(KAboutData::applicationData()) {}
0052 
0053     void _k_updateUrl();
0054 
0055     KisKBugReport *q {nullptr};
0056     QProcess *m_process {nullptr};
0057     KAboutData m_aboutData;
0058 
0059     QTextEdit *m_lineedit {nullptr};
0060     QLineEdit *m_subject {nullptr};
0061     QLabel *m_version {nullptr};
0062     QString m_strVersion;
0063     QGroupBox *m_bgSeverity {nullptr};
0064 
0065     QLabel *lblApplicationName {nullptr};
0066     QString lastError;
0067     QString appname;
0068     QString os;
0069     QUrl url;
0070     QList<QRadioButton *> severityButtons;
0071     int currentSeverity()
0072     {
0073         for (int i = 0; i < severityButtons.count(); i++)
0074             if (severityButtons[i]->isChecked()) {
0075                 return i;
0076             }
0077         return -1;
0078     }
0079 };
0080 
0081 KisKBugReport::KisKBugReport(const KAboutData &aboutData, QWidget *_parent)
0082     : QDialog(_parent), d(new KisKBugReportPrivate(this))
0083 {
0084     setWindowTitle(i18n("Submit Bug Report"));
0085 
0086     QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
0087     buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0088     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
0089     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
0090     connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
0091     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0092 
0093     d->m_aboutData = aboutData;
0094     d->m_process = 0;
0095     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::close());
0096 
0097     QLabel *tmpLabel;
0098     QVBoxLayout *lay = new QVBoxLayout(this);
0099 
0100     KTitleWidget *title = new KTitleWidget(this);
0101     title->setText(i18n("Submit Bug Report"));
0102 
0103 #if KWIDGETSADDONS_VERSION_MAJOR > 5 || (KWIDGETSADDONS_VERSION_MAJOR == 5 && KWIDGETSADDONS_VERSION_MINOR >= 72)
0104     title->setIcon(KisIconUtils::loadIcon(QStringLiteral("tools-report-bug")));
0105 #else
0106     title->setPixmap(KisIconUtils::loadIcon(QStringLiteral("tools-report-bug")).pixmap(32));
0107 #endif
0108 
0109     lay->addWidget(title);
0110 
0111     QGridLayout *glay = new QGridLayout();
0112     lay->addLayout(glay);
0113 
0114     int row = 0;
0115 
0116     // Program name
0117     QString qwtstr = i18n("The application for which you wish to submit a bug report - if incorrect, please use the Report Bug menu item of the correct application");
0118     tmpLabel = new QLabel(i18n("Application: "), this);
0119     glay->addWidget(tmpLabel, row, 0);
0120     tmpLabel->setWhatsThis(qwtstr);
0121     d->lblApplicationName = new QLabel(this);
0122     d->lblApplicationName->setWhatsThis(qwtstr);
0123 
0124     d->appname = d->m_aboutData.productName();
0125     d->lblApplicationName->setText(d->appname);
0126 
0127     glay->addWidget(d->lblApplicationName, row, 1);
0128 
0129     tmpLabel->setWhatsThis(qwtstr);
0130 
0131     // Version
0132     qwtstr = i18n("The version of this application - please make sure that no newer version is available before sending a bug report");
0133     tmpLabel = new QLabel(i18n("Version:"), this);
0134     glay->addWidget(tmpLabel, ++row, 0);
0135     tmpLabel->setWhatsThis(qwtstr);
0136     d->m_strVersion = d->m_aboutData.version();
0137     if (d->m_strVersion.isEmpty()) {
0138         d->m_strVersion = i18n("no version set (programmer error)");
0139     }
0140     d->m_version = new QLabel(d->m_strVersion, this);
0141     d->m_version->setTextInteractionFlags(Qt::TextBrowserInteraction);
0142     //glay->addWidget( d->m_version, row, 1 );
0143     glay->addWidget(d->m_version, row, 1, 1, 2);
0144     d->m_version->setWhatsThis(qwtstr);
0145 
0146     tmpLabel = new QLabel(i18n("OS:"), this);
0147     glay->addWidget(tmpLabel, ++row, 0);
0148     d->os = SystemInformation::operatingSystemVersion();
0149 
0150     tmpLabel = new QLabel(d->os, this);
0151     tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
0152     glay->addWidget(tmpLabel, row, 1, 1, 2);
0153 
0154     // Point to the web form
0155 
0156     lay->addSpacing(10);
0157     QString text = i18n("<qt>"
0158                         "<p>Please read <b><a href=\"https://docs.krita.org/en/untranslatable_pages/reporting_bugs.html\">this guide</a></b> for reporting bugs first!</p>"
0159                         "<p>To submit a bug report, click on the button below. This will open a web browser "
0160                         "window on <a href=\"https://bugs.kde.org\">https://bugs.kde.org</a> where you will find "
0161                         "a form to fill in. </p>"
0162                         "<p><b>Please paste the following information into the bug report!</b></p>"
0163                         "</qt>");
0164     QLabel *label = new QLabel(text, this);
0165     label->setOpenExternalLinks(true);
0166     label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
0167     label->setWordWrap(true);
0168     lay->addWidget(label);
0169     lay->addSpacing(10);
0170 
0171     QByteArray additionalInformation;
0172     QFile sysinfo(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita-sysinfo.log");
0173     if (sysinfo.exists()) {
0174         sysinfo.open(QFile::ReadOnly);
0175         additionalInformation += sysinfo.readAll();
0176         sysinfo.close();
0177     }
0178 
0179     additionalInformation += "\n---------------------\n";
0180 
0181     QFile log(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita.log");
0182     if (log.exists()) {
0183         log.open(QFile::ReadOnly);
0184         additionalInformation += log.readAll();
0185         log.close();
0186     }
0187 
0188     additionalInformation += "\n---------------------\n";
0189 
0190     QFile crashes(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kritacrash.log");
0191     if (crashes.exists()) {
0192         crashes.open(QFile::ReadOnly);
0193         additionalInformation += crashes.readAll();
0194         crashes.close();
0195     }
0196 
0197     QTextEdit *buginfo = new QTextEdit(this);
0198     buginfo->setText(QString::fromUtf8(additionalInformation));
0199     lay->addWidget(buginfo);
0200 
0201     QClipboard *clipboard = QGuiApplication::clipboard();
0202     clipboard->setText(QString::fromUtf8(additionalInformation));
0203 
0204     d->_k_updateUrl();
0205 
0206     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0207     okButton->setText(i18n("&Submit Bug Report"));
0208     okButton->setIcon(KisIconUtils::loadIcon(QStringLiteral("tools-report-bug")));
0209     lay->addWidget(buttonBox);
0210     setMinimumHeight(sizeHint().height() + 20);   // WORKAROUND: prevent "cropped" qcombobox
0211 }
0212 
0213 KisKBugReport::~KisKBugReport()
0214 {
0215     delete d;
0216 }
0217 
0218 void KisKBugReportPrivate::_k_updateUrl()
0219 {
0220     url = QUrl(QStringLiteral("https://bugs.kde.org/enter_bug.cgi"));
0221     QUrlQuery query;
0222     query.addQueryItem(QStringLiteral("format"), QLatin1String("guided"));    // use the guided form
0223 
0224     // the string format is product/component, where component is optional
0225     QStringList list = QStringList() << appname;
0226     query.addQueryItem(QStringLiteral("product"), list[0]);
0227     if (list.size() == 2) {
0228         query.addQueryItem(QStringLiteral("component"), list[1]);
0229     }
0230 
0231     query.addQueryItem(QStringLiteral("version"), m_strVersion);
0232 
0233     // TODO: guess and fill OS(sys_os) and Platform(rep_platform) fields
0234 #ifdef Q_OS_WIN
0235     query.addQueryItem(QStringLiteral("op_sys"), QStringLiteral("MS Windows"));
0236     query.addQueryItem(QStringLiteral("rep_platform"), QStringLiteral("MS Windows"));
0237 #endif
0238 
0239     url.setQuery(query);
0240 }
0241 
0242 void KisKBugReport::accept()
0243 {
0244     QDesktopServices::openUrl(d->url);
0245 }
0246 
0247 
0248 #include "moc_kbugreport.cpp"