1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kbugreport.h"
9
10#include <QDesktopServices>
11#include <QDialogButtonBox>
12#include <QHBoxLayout>
13#include <QLabel>
14#include <QPushButton>
15#include <QUrl>
16#include <QUrlQuery>
17
18#include <KAboutData>
19#include <KConfig>
20#include <KLocalizedString>
21#include <KMessageBox>
22#include <KMessageDialog>
23#include <KTitleWidget>
24
25#include "config-xmlgui.h"
26#include "systeminformation_p.h"
27#include <kxmlgui_version.h>
28
29class KBugReportPrivate
30{
31public:
32 KBugReportPrivate(KBugReport *qq)
33 : q(qq)
34 {
35 }
36
37 enum BugDestination {
38 BugsKdeOrg,
39 CustomUrl,
40 };
41
42 // Update the url to match the current OS, selected app, etc
43 void updateUrl();
44
45 KBugReport *const q;
46
47 QLabel *m_version = nullptr;
48 QString m_strVersion;
49
50 QString lastError;
51 QString kde_version;
52 QString appname;
53 QString os;
54 QUrl url;
55 BugDestination bugDestination = KBugReportPrivate::CustomUrl;
56};
57
58KBugReport::KBugReport(const KAboutData &aboutData, QWidget *_parent)
59 : QDialog(_parent)
60 , d(new KBugReportPrivate(this))
61{
62 setWindowTitle(i18nc("@title:window", "Submit Bug Report"));
63
64 QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
65 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
66 connect(sender: buttonBox, signal: &QDialogButtonBox::accepted, context: this, slot: &QDialog::accept);
67 connect(sender: buttonBox, signal: &QDialogButtonBox::rejected, context: this, slot: &QDialog::reject);
68
69 const QString bugAddress = aboutData.bugAddress();
70 if (bugAddress == QLatin1String("submit@bugs.kde.org")) {
71 // This is a core KDE application -> redirect to the web form
72 d->bugDestination = KBugReportPrivate::BugsKdeOrg;
73 } else if (!QUrl(bugAddress).scheme().isEmpty()) {
74 // The bug reporting address is a URL -> redirect to that
75 d->bugDestination = KBugReportPrivate::CustomUrl;
76 }
77
78 KGuiItem::assign(button: buttonBox->button(which: QDialogButtonBox::Cancel), item: KStandardGuiItem::close());
79
80 QLabel *tmpLabel;
81 QVBoxLayout *lay = new QVBoxLayout(this);
82
83 KTitleWidget *title = new KTitleWidget(this);
84 title->setText(i18n("Submit Bug Report"));
85 title->setIconSize(QSize(32, 32));
86 title->setIcon(icon: QIcon::fromTheme(QStringLiteral("tools-report-bug")));
87 lay->addWidget(title);
88
89 QGridLayout *glay = new QGridLayout();
90 lay->addLayout(layout: glay);
91
92 int row = 0;
93
94 // Program name
95 QString qwtstr =
96 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");
97 tmpLabel = new QLabel(i18n("Application: "), this);
98 glay->addWidget(tmpLabel, row, column: 0);
99 tmpLabel->setWhatsThis(qwtstr);
100 QLabel *appLabel = new QLabel(this);
101 d->appname = aboutData.productName();
102 appLabel->setText(d->appname);
103 glay->addWidget(appLabel, row, column: 1);
104 tmpLabel->setWhatsThis(qwtstr);
105
106 // Version
107 qwtstr = i18n("The version of this application - please make sure that no newer version is available before sending a bug report");
108 tmpLabel = new QLabel(i18n("Version:"), this);
109 glay->addWidget(tmpLabel, row: ++row, column: 0);
110 tmpLabel->setWhatsThis(qwtstr);
111 d->m_strVersion = aboutData.version();
112 if (d->m_strVersion.isEmpty()) {
113 d->m_strVersion = i18n("no version set (programmer error)");
114 }
115 d->kde_version = QStringLiteral(KXMLGUI_VERSION_STRING);
116 if (d->bugDestination != KBugReportPrivate::BugsKdeOrg) {
117 d->m_strVersion += QLatin1Char(' ') + d->kde_version;
118 }
119 d->m_version = new QLabel(d->m_strVersion, this);
120 d->m_version->setTextInteractionFlags(Qt::TextBrowserInteraction);
121 // glay->addWidget( d->m_version, row, 1 );
122 glay->addWidget(d->m_version, row, column: 1, rowSpan: 1, columnSpan: 2);
123 d->m_version->setWhatsThis(qwtstr);
124
125 tmpLabel = new QLabel(i18n("OS:"), this);
126 glay->addWidget(tmpLabel, row: ++row, column: 0);
127
128#ifdef Q_OS_WINDOWS
129 d->os = i18nc("%1 is the operating system name, e.g. 'Windows 10', %2 is the CPU architecture, e.g. 'x86_64'",
130 "%1 (%2)",
131 QSysInfo::prettyProductName(),
132 QSysInfo::currentCpuArchitecture());
133#else
134 if (QSysInfo::productVersion() != QLatin1String("unknown")) {
135 d->os = i18nc(
136 "%1 is the operating system name, e.g. 'Fedora Linux', %2 is the operating system version, e.g. '35', %3 is the CPU architecture, e.g. 'x86_64'",
137 "%1 %2 (%3)",
138 QSysInfo::prettyProductName(),
139 QSysInfo::productVersion(),
140 QSysInfo::currentCpuArchitecture());
141 } else {
142 d->os = i18nc("%1 is the operating system name, e.g. 'Fedora Linux', %2 is the CPU architecture, e.g. 'x86_64'",
143 "%1 (%2)",
144 QSysInfo::prettyProductName(),
145 QSysInfo::currentCpuArchitecture());
146 }
147#endif
148
149 tmpLabel = new QLabel(d->os, this);
150 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
151 glay->addWidget(tmpLabel, row, column: 1, rowSpan: 1, columnSpan: 2);
152 // Point to the web form
153
154 QString text;
155 if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) {
156 text = i18n(
157 "<qt>To submit a bug report, click on the button below. This will open a web browser "
158 "window on <a href=\"https://bugs.kde.org\">https://bugs.kde.org</a> where you will find "
159 "a form to fill in. The information displayed above will be transferred to that server.</qt>");
160 d->updateUrl();
161 } else {
162 text = i18n(
163 "<qt>To submit a bug report, click on the button below. This will open a web browser "
164 "window on <a href=\"%1\">%2</a>.</qt>",
165 bugAddress,
166 bugAddress);
167 d->url = QUrl(bugAddress);
168 }
169
170 lay->addSpacing(size: 10);
171 QLabel *label = new QLabel(text, this);
172 label->setOpenExternalLinks(true);
173 label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
174 label->setWordWrap(true);
175 lay->addWidget(label);
176 lay->addSpacing(size: 10);
177
178 QPushButton *okButton = buttonBox->button(which: QDialogButtonBox::Ok);
179 if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) {
180 okButton->setText(i18nc("@action:button", "&Launch Bug Report Wizard"));
181 } else {
182 okButton->setText(i18nc("@action:button", "&Submit Bug Report"));
183 }
184 okButton->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug")));
185
186 lay->addWidget(buttonBox);
187 setMinimumHeight(sizeHint().height() + 20); // WORKAROUND: prevent "cropped" qcombobox
188}
189
190KBugReport::~KBugReport() = default;
191
192void KBugReportPrivate::updateUrl()
193{
194 url = QUrl(QStringLiteral("https://bugs.kde.org/enter_bug.cgi"));
195 QUrlQuery query;
196 query.addQueryItem(QStringLiteral("format"), QStringLiteral("guided")); // use the guided form
197
198 // the string format is product/component, where component is optional
199 QStringList list = appname.split(sep: QLatin1Char('/'));
200 query.addQueryItem(QStringLiteral("product"), value: list[0]);
201 if (list.size() == 2) {
202 query.addQueryItem(QStringLiteral("component"), value: list[1]);
203 }
204
205 query.addQueryItem(QStringLiteral("version"), value: m_strVersion);
206 url.setQuery(query);
207
208 // TODO: guess and fill OS(sys_os) and Platform(rep_platform) fields
209}
210
211void KBugReport::accept()
212{
213 QDesktopServices::openUrl(url: d->url);
214 QDialog::accept();
215}
216
217#include "moc_kbugreport.cpp"
218

source code of kxmlgui/src/kbugreport.cpp