Changeset View
Changeset View
Standalone View
Standalone View
src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp
Show All 13 Lines | |||||
14 | * | 14 | * | ||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | 17 | * | ||
18 | ******************************************************************/ | 18 | ******************************************************************/ | ||
19 | 19 | | |||
20 | #include "reportassistantpages_bugzilla_duplicates.h" | 20 | #include "reportassistantpages_bugzilla_duplicates.h" | ||
21 | 21 | | |||
22 | #include <QDate> | | |||
23 | #include <QTimer> | 22 | #include <QTimer> | ||
24 | #include <QTreeWidgetItem> | 23 | #include <QTreeWidgetItem> | ||
25 | #include <QHeaderView> | 24 | #include <QHeaderView> | ||
26 | 25 | | |||
27 | #include <KColorScheme> | 26 | #include <KColorScheme> | ||
28 | #include <KMessageBox> | 27 | #include <KMessageBox> | ||
29 | #include <QInputDialog> | 28 | #include <QInputDialog> | ||
30 | #include <KLocalizedString> | 29 | #include <KLocalizedString> | ||
31 | #include <KWindowConfig> | 30 | #include <KWindowConfig> | ||
32 | 31 | | |||
33 | #include "drkonqi_globals.h" | 32 | #include "drkonqi_globals.h" | ||
34 | #include "reportinterface.h" | 33 | #include "reportinterface.h" | ||
35 | #include "statuswidget.h" | 34 | #include "statuswidget.h" | ||
36 | 35 | | |||
37 | //BEGIN BugzillaDuplicatesPage | 36 | //BEGIN BugzillaDuplicatesPage | ||
38 | 37 | | |||
39 | BugzillaDuplicatesPage::BugzillaDuplicatesPage(ReportAssistantDialog * parent): | 38 | BugzillaDuplicatesPage::BugzillaDuplicatesPage(ReportAssistantDialog *parent) | ||
40 | ReportAssistantPage(parent), | 39 | : ReportAssistantPage(parent) | ||
41 | m_searching(false), | | |||
42 | m_foundDuplicate(false) | | |||
43 | { | 40 | { | ||
44 | resetDates(); | | |||
45 | | ||||
46 | connect(bugzillaManager(), &BugzillaManager::searchFinished, | 41 | connect(bugzillaManager(), &BugzillaManager::searchFinished, | ||
47 | this, &BugzillaDuplicatesPage::searchFinished); | 42 | this, &BugzillaDuplicatesPage::searchFinished); | ||
48 | connect(bugzillaManager(), SIGNAL(searchError(QString)), | 43 | connect(bugzillaManager(), &BugzillaManager::searchError, | ||
49 | this, SLOT(searchError(QString))); | 44 | this, &BugzillaDuplicatesPage::searchError); | ||
50 | 45 | | |||
51 | ui.setupUi(this); | 46 | ui.setupUi(this); | ||
52 | ui.information->hide(); | 47 | ui.information->hide(); | ||
53 | 48 | | |||
54 | connect(ui.m_bugListWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), | 49 | connect(ui.m_bugListWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), | ||
55 | this, SLOT(itemClicked(QTreeWidgetItem*,int))); | 50 | this, SLOT(itemClicked(QTreeWidgetItem*,int))); | ||
56 | connect(ui.m_bugListWidget, &QTreeWidget::itemSelectionChanged, this, &BugzillaDuplicatesPage::itemSelectionChanged); | 51 | connect(ui.m_bugListWidget, &QTreeWidget::itemSelectionChanged, | ||
52 | this, &BugzillaDuplicatesPage::itemSelectionChanged); | ||||
57 | 53 | | |||
58 | QHeaderView * header = ui.m_bugListWidget->header(); | 54 | QHeaderView * header = ui.m_bugListWidget->header(); | ||
59 | header->setSectionResizeMode(0, QHeaderView::ResizeToContents); | 55 | header->setSectionResizeMode(0, QHeaderView::ResizeToContents); | ||
60 | header->setSectionResizeMode(1, QHeaderView::Interactive); | 56 | header->setSectionResizeMode(1, QHeaderView::Interactive); | ||
61 | 57 | | |||
62 | //Create manual bug report entry (first one) | 58 | //Create manual bug report entry (first one) | ||
63 | QTreeWidgetItem * customBugItem = new QTreeWidgetItem( | 59 | QTreeWidgetItem * customBugItem = new QTreeWidgetItem( | ||
64 | QStringList() << i18nc("@item:intable custom/manaul bug report number", "Manual") | 60 | QStringList() << i18nc("@item:intable custom/manaul bug report number", "Manual") | ||
Show All 9 Lines | |||||
74 | customBugItem->setWhatsThis(0, helpMessage); | 70 | customBugItem->setWhatsThis(0, helpMessage); | ||
75 | customBugItem->setWhatsThis(1, helpMessage); | 71 | customBugItem->setWhatsThis(1, helpMessage); | ||
76 | 72 | | |||
77 | ui.m_bugListWidget->addTopLevelItem(customBugItem); | 73 | ui.m_bugListWidget->addTopLevelItem(customBugItem); | ||
78 | 74 | | |||
79 | m_searchMoreGuiItem = KGuiItem2(i18nc("@action:button", "Search for more reports"), | 75 | m_searchMoreGuiItem = KGuiItem2(i18nc("@action:button", "Search for more reports"), | ||
80 | QIcon::fromTheme(QStringLiteral("edit-find")), | 76 | QIcon::fromTheme(QStringLiteral("edit-find")), | ||
81 | i18nc("@info:tooltip", "Use this button to " | 77 | i18nc("@info:tooltip", "Use this button to " | ||
82 | "search for more similar bug reports on an " | 78 | "search for more similar bug reports")); | ||
83 | "earlier date.")); | | |||
84 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | 79 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | ||
85 | connect(ui.m_searchMoreButton, &QAbstractButton::clicked, this, &BugzillaDuplicatesPage::searchMore); | 80 | connect(ui.m_searchMoreButton, &QAbstractButton::clicked, this, &BugzillaDuplicatesPage::searchMore); | ||
86 | 81 | | |||
87 | m_retrySearchGuiItem = KGuiItem2(i18nc("@action:button", "Retry search"), | 82 | m_retrySearchGuiItem = KGuiItem2(i18nc("@action:button", "Retry search"), | ||
88 | QIcon::fromTheme(QStringLiteral("edit-find")), | 83 | QIcon::fromTheme(QStringLiteral("edit-find")), | ||
89 | i18nc("@info:tooltip", "Use this button to " | 84 | i18nc("@info:tooltip", "Use this button to " | ||
90 | "retry the search that previously " | 85 | "retry the search that previously " | ||
91 | "failed.")); | 86 | "failed.")); | ||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Line(s) | 168 | if (ui.m_bugListWidget->topLevelItemCount() != 1 && ui.m_selectedDuplicatesList->count() == 0 | |||
201 | } | 196 | } | ||
202 | } | 197 | } | ||
203 | return true; | 198 | return true; | ||
204 | } | 199 | } | ||
205 | 200 | | |||
206 | //BEGIN Search related methods | 201 | //BEGIN Search related methods | ||
207 | void BugzillaDuplicatesPage::searchMore() | 202 | void BugzillaDuplicatesPage::searchMore() | ||
208 | { | 203 | { | ||
209 | //1 year back | 204 | if (m_offset < 0) { | ||
210 | m_searchingEndDate = m_startDate; | 205 | m_offset = 0; // initialize, -1 means no search done yet | ||
211 | m_searchingStartDate = m_searchingEndDate.addYears(-1); | | |||
212 | | ||||
213 | performSearch(); | | |||
214 | } | 206 | } | ||
215 | 207 | | |||
216 | void BugzillaDuplicatesPage::performSearch() | 208 | // This is fairly inefficient, unfortunately the API's offset/limit system | ||
217 | { | 209 | // is not useful to us. The search is always sorting by lowest id, and | ||
218 | markAsSearching(true); | 210 | // negative offests are not a thing. So, offset=0&limit=1 gives the first | ||
219 | 211 | // ever reported bug in the product, while what we want is the latest. | |||
220 | QString startDateStr = m_searchingStartDate.toString(QStringLiteral("yyyy-MM-dd")); | 212 | // We also cannot query all perintent bug ids by default. While the API | ||
221 | QString endDateStr = m_searchingEndDate.toString(QStringLiteral("yyyy-MM-dd")); | 213 | // is reasonably fast, it'll still produce upwards of 2MiB just for the | ||
214 | // ids of a dolphin crash (as it includes all sorts of extra products). | ||||
215 | // So we are left with somewhat shoddy time-based queries. | ||||
222 | 216 | | |||
223 | ui.m_statusWidget->setBusy(i18nc("@info:status","Searching for duplicates (from %1 to %2)...", | 217 | markAsSearching(true); | ||
224 | startDateStr, endDateStr)); | | |||
225 | 218 | | |||
226 | //Bugzilla will not search on Today bugs if we send the date. | 219 | ui.m_statusWidget->setBusy(i18nc("@info:status", "Searching for duplicates...")); | ||
227 | //we need to send "Now" | | |||
228 | if (m_searchingEndDate == QDate::currentDate()) { | | |||
229 | endDateStr = QLatin1String("Now"); | | |||
230 | } | | |||
231 | 220 | | |||
232 | #if 1 | 221 | #warning fixme why the flip are we generateing a new report template just to get the default severity oO | ||
233 | BugReport report = reportInterface()->newBugReportTemplate(); | 222 | Bugzilla::NewBug bug = reportInterface()->newBugReportTemplate(); | ||
234 | bugzillaManager()->searchBugs(reportInterface()->relatedBugzillaProducts(), | 223 | bugzillaManager()->searchBugs(reportInterface()->relatedBugzillaProducts(), | ||
235 | report.bugSeverity(), startDateStr, endDateStr, | 224 | bug.severity, | ||
236 | reportInterface()->firstBacktraceFunctions().join(QStringLiteral(" "))); | 225 | reportInterface()->firstBacktraceFunctions().join(QStringLiteral(" ")), | ||
237 | #else //Test search | 226 | m_offset); | ||
238 | bugzillaManager()->searchBugs(QStringList() << "plasma", "crash", startDateStr, endDateStr, | | |||
239 | "QGraphicsScenePrivate::processDirtyItemsRecursive"); | | |||
240 | #endif | | |||
241 | } | 227 | } | ||
242 | 228 | | |||
243 | void BugzillaDuplicatesPage::stopCurrentSearch() | 229 | void BugzillaDuplicatesPage::stopCurrentSearch() | ||
244 | { | 230 | { | ||
245 | if (m_searching) { | 231 | if (m_searching) { | ||
246 | bugzillaManager()->stopCurrentSearch(); | 232 | bugzillaManager()->stopCurrentSearch(); | ||
247 | 233 | | |||
248 | markAsSearching(false); | 234 | markAsSearching(false); | ||
249 | 235 | | |||
250 | if (m_startDate==m_endDate) { //Never searched | 236 | if (m_offset < 0) { //Never searched | ||
251 | ui.m_statusWidget->setIdle(i18nc("@info:status","Search stopped.")); | 237 | ui.m_statusWidget->setIdle(i18nc("@info:status", "Search stopped.")); | ||
252 | } else { | 238 | } else { | ||
253 | ui.m_statusWidget->setIdle(i18nc("@info:status","Search stopped. Showing results from " | 239 | ui.m_statusWidget->setIdle(i18nc("@info:status", "Search stopped. Showing results.")); | ||
254 | "%1 to %2", m_startDate.toString(QStringLiteral("yyyy-MM-dd")), | | |||
255 | m_endDate.toString(QStringLiteral("yyyy-MM-dd")))); | | |||
256 | } | 240 | } | ||
257 | } | 241 | } | ||
258 | } | 242 | } | ||
259 | 243 | | |||
260 | void BugzillaDuplicatesPage::markAsSearching(bool searching) | 244 | void BugzillaDuplicatesPage::markAsSearching(bool searching) | ||
261 | { | 245 | { | ||
262 | m_searching = searching; | 246 | m_searching = searching; | ||
263 | emitCompleteChanged(); | 247 | emitCompleteChanged(); | ||
Show All 15 Lines | 262 | if (!searching) { | |||
279 | itemSelectionChanged(); | 263 | itemSelectionChanged(); | ||
280 | } else { | 264 | } else { | ||
281 | ui.m_openReportButton->setEnabled(false); | 265 | ui.m_openReportButton->setEnabled(false); | ||
282 | } | 266 | } | ||
283 | } | 267 | } | ||
284 | 268 | | |||
285 | bool BugzillaDuplicatesPage::canSearchMore() | 269 | bool BugzillaDuplicatesPage::canSearchMore() | ||
286 | { | 270 | { | ||
287 | return (m_startDate.year() >= 2009); | 271 | return !m_atEnd; | ||
288 | } | 272 | } | ||
289 | 273 | | |||
290 | void BugzillaDuplicatesPage::searchFinished(const BugMapList & list) | 274 | static QString statusString(const Bugzilla::Bug::Ptr &bug) | ||
275 | { | ||||
276 | #warning fixme could move the first switch to if is_open and then switch out NeedsInfo | ||||
277 | // Generate a non-geek readable status | ||||
278 | switch(bug->status()) { | ||||
279 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
280 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
281 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
282 | case Bugzilla::Bug::Status::REOPENED: | ||||
283 | return i18nc("@info bug status", "[Open]"); | ||||
284 | | ||||
285 | case Bugzilla::Bug::Status::RESOLVED: | ||||
286 | case Bugzilla::Bug::Status::VERIFIED: | ||||
287 | case Bugzilla::Bug::Status::CLOSED: | ||||
288 | switch(bug->resolution()) { | ||||
289 | case Bugzilla::Bug::Resolution::FIXED: | ||||
290 | return i18nc("@info bug resolution", "[Fixed]"); | ||||
291 | case Bugzilla::Bug::Resolution::WORKSFORME: | ||||
292 | return i18nc("@info bug resolution", "[Non-reproducible]"); | ||||
293 | case Bugzilla::Bug::Resolution::DUPLICATE: | ||||
294 | return i18nc("@info bug resolution", "[Duplicate report]"); | ||||
295 | case Bugzilla::Bug::Resolution::INVALID: | ||||
296 | return i18nc("@info bug resolution", "[Invalid]"); | ||||
297 | case Bugzilla::Bug::Resolution::UPSTREAM: | ||||
298 | case Bugzilla::Bug::Resolution::DOWNSTREAM: | ||||
299 | return i18nc("@info bug resolution", "[External problem]"); | ||||
300 | case Bugzilla::Bug::Resolution::WONTFIX: | ||||
301 | case Bugzilla::Bug::Resolution::LATER: | ||||
302 | case Bugzilla::Bug::Resolution::REMIND: | ||||
303 | case Bugzilla::Bug::Resolution::MOVED: | ||||
304 | case Bugzilla::Bug::Resolution::WAITINGFORINFO: | ||||
305 | case Bugzilla::Bug::Resolution::BACKTRACE: | ||||
306 | case Bugzilla::Bug::Resolution::UNMAINTAINED: | ||||
307 | return QString(); | ||||
308 | case Bugzilla::Bug::Resolution::Unknown: | ||||
309 | Q_UNREACHABLE(); | ||||
310 | } | ||||
311 | | ||||
312 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
313 | return i18nc("@info bug status", "[Incomplete]"); | ||||
314 | | ||||
315 | case Bugzilla::Bug::Status::Unknown: | ||||
316 | Q_UNREACHABLE(); | ||||
317 | } | ||||
318 | Q_UNREACHABLE(); | ||||
319 | QString(); | ||||
320 | } | ||||
321 | | ||||
322 | void BugzillaDuplicatesPage::searchFinished(const QList<Bugzilla::Bug::Ptr> &list) | ||||
291 | { | 323 | { | ||
292 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | 324 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | ||
293 | m_startDate = m_searchingStartDate; | | |||
294 | 325 | | |||
295 | int results = list.count(); | 326 | int results = list.count(); | ||
327 | m_offset += results; | ||||
296 | if (results > 0) { | 328 | if (results > 0) { | ||
329 | m_atEnd = false; | ||||
330 | | ||||
297 | markAsSearching(false); | 331 | markAsSearching(false); | ||
298 | 332 | | |||
299 | ui.m_statusWidget->setIdle(i18nc("@info:status","Showing results from %1 to %2", | 333 | ui.m_statusWidget->setIdle(i18nc("@info:status", "Showing results.")); | ||
300 | m_startDate.toString(QStringLiteral("yyyy-MM-dd")), | | |||
301 | m_endDate.toString(QStringLiteral("yyyy-MM-dd")))); | | |||
302 | 334 | | |||
303 | QList<int> bugIds; | | |||
304 | for (int i = 0; i < results; i++) { | 335 | for (int i = 0; i < results; i++) { | ||
305 | BugMap bug = list.at(i); | 336 | Bugzilla::Bug::Ptr bug = list.at(i); | ||
306 | | ||||
307 | bool ok; | | |||
308 | int bugId = bug.value(QStringLiteral("bug_id")).toInt(&ok); | | |||
309 | if (ok) { | | |||
310 | bugIds << bugId; | | |||
311 | } | | |||
312 | | ||||
313 | QString title; | | |||
314 | | ||||
315 | //Generate a non-geek readable status | | |||
316 | QString customStatusString; | | |||
317 | BugReport::Status status = BugReport::parseStatus(bug.value(QStringLiteral("bug_status"))); | | |||
318 | BugReport::Resolution resolution = BugReport::parseResolution(bug.value(QStringLiteral("resolution"))); | | |||
319 | if (BugReport::isOpen(status)) { | | |||
320 | customStatusString = i18nc("@info bug status", "[Open]"); | | |||
321 | } else if (BugReport::isClosed(status) && status != BugReport::NeedsInfo) { | | |||
322 | if (resolution == BugReport::Fixed) { | | |||
323 | customStatusString = i18nc("@info bug resolution", "[Fixed]"); | | |||
324 | } else if (resolution == BugReport::WorksForMe) { | | |||
325 | customStatusString = i18nc("@info bug resolution", "[Non-reproducible]"); | | |||
326 | } else if (resolution == BugReport::Duplicate) { | | |||
327 | customStatusString = i18nc("@info bug resolution", "[Duplicate report]"); | | |||
328 | } else if (resolution == BugReport::Invalid) { | | |||
329 | customStatusString = i18nc("@info bug resolution", "[Invalid]"); | | |||
330 | } else if (resolution == BugReport::Downstream | | |||
331 | || resolution == BugReport::Upstream) { | | |||
332 | customStatusString = i18nc("@info bug resolution", "[External problem]"); | | |||
333 | } | | |||
334 | } else if (status == BugReport::NeedsInfo) { | | |||
335 | customStatusString = i18nc("@info bug status", "[Incomplete]"); | | |||
336 | } | | |||
337 | 337 | | |||
338 | title = customStatusString + QLatin1Char(' ') + bug[QStringLiteral("short_desc")]; | 338 | QString title = statusString(bug) + QLatin1Char(' ') + bug->summary(); | ||
339 | 339 | | |||
340 | QStringList fields = QStringList() << bug[QStringLiteral("bug_id")] << title; | 340 | QStringList fields = QStringList() << QString::number(bug->id()) << title; | ||
341 | 341 | | |||
342 | QTreeWidgetItem * item = new QTreeWidgetItem(fields); | 342 | QTreeWidgetItem * item = new QTreeWidgetItem(fields); | ||
343 | item->setToolTip(0, bug[QStringLiteral("short_desc")]); | 343 | item->setToolTip(0, bug->summary()); | ||
344 | item->setToolTip(1, bug[QStringLiteral("short_desc")]); | 344 | item->setToolTip(1, bug->summary()); | ||
345 | 345 | | |||
346 | ui.m_bugListWidget->addTopLevelItem(item); | 346 | ui.m_bugListWidget->addTopLevelItem(item); | ||
347 | } | 347 | } | ||
348 | 348 | | |||
349 | if (!m_foundDuplicate) { | 349 | if (!m_foundDuplicate) { | ||
350 | markAsSearching(true); | 350 | markAsSearching(true); | ||
351 | DuplicateFinderJob *job = new DuplicateFinderJob(bugIds, bugzillaManager(), this); | 351 | DuplicateFinderJob *job = new DuplicateFinderJob(list, bugzillaManager(), this); | ||
352 | connect(job, SIGNAL(result(KJob*)), this, SLOT(analyzedDuplicates(KJob*))); | 352 | connect(job, &KJob::result, this, &BugzillaDuplicatesPage::analyzedDuplicates); | ||
353 | job->start(); | 353 | job->start(); | ||
354 | } | 354 | } | ||
355 | 355 | | |||
356 | ui.m_bugListWidget->sortItems(0 , Qt::DescendingOrder); | 356 | ui.m_bugListWidget->sortItems(0 , Qt::DescendingOrder); | ||
357 | ui.m_bugListWidget->resizeColumnToContents(1); | 357 | ui.m_bugListWidget->resizeColumnToContents(1); | ||
358 | 358 | | |||
359 | if (!canSearchMore()) { | 359 | if (!canSearchMore()) { | ||
360 | ui.m_searchMoreButton->setEnabled(false); | 360 | ui.m_searchMoreButton->setEnabled(false); | ||
361 | } | 361 | } | ||
362 | 362 | | |||
363 | } else { | 363 | } else { | ||
364 | m_atEnd = true; | ||||
364 | 365 | | |||
365 | if (canSearchMore()) { | 366 | if (canSearchMore()) { | ||
366 | //We don't call markAsSearching(false) to avoid flicker | 367 | //We don't call markAsSearching(false) to avoid flicker | ||
367 | //Delayed call to searchMore to avoid unexpected behaviour (signal/slot) | 368 | //Delayed call to searchMore to avoid unexpected behaviour (signal/slot) | ||
368 | //because we are in a slot, and searchMore() will be ending calling this slot again | 369 | //because we are in a slot, and searchMore() will be ending calling this slot again | ||
369 | QTimer::singleShot(0, this, &BugzillaDuplicatesPage::searchMore); | 370 | QTimer::singleShot(0, this, &BugzillaDuplicatesPage::searchMore); | ||
370 | } else { | 371 | } else { | ||
371 | markAsSearching(false); | 372 | markAsSearching(false); | ||
372 | ui.m_statusWidget->setIdle(i18nc("@info:status","Search Finished. " | 373 | ui.m_statusWidget->setIdle(i18nc("@info:status","Search Finished. " | ||
373 | "No reports found.")); | 374 | "No reports found.")); | ||
374 | ui.m_searchMoreButton->setEnabled(false); | 375 | ui.m_searchMoreButton->setEnabled(false); | ||
375 | if (ui.m_bugListWidget->topLevelItemCount() == 0) { | 376 | if (ui.m_bugListWidget->topLevelItemCount() == 0) { | ||
376 | //No reports to mark as possible duplicate | 377 | //No reports to mark as possible duplicate | ||
377 | ui.m_selectedDuplicatesList->setEnabled(false); | 378 | ui.m_selectedDuplicatesList->setEnabled(false); | ||
378 | } | 379 | } | ||
379 | } | 380 | } | ||
380 | } | 381 | } | ||
381 | } | 382 | } | ||
382 | 383 | | |||
384 | static bool isStatusOpen(Bugzilla::Bug::Status status) | ||||
385 | { | ||||
386 | switch(status) { | ||||
387 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
388 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
389 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
390 | case Bugzilla::Bug::Status::REOPENED: | ||||
391 | return true; | ||||
392 | case Bugzilla::Bug::Status::RESOLVED: | ||||
393 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
394 | case Bugzilla::Bug::Status::VERIFIED: | ||||
395 | case Bugzilla::Bug::Status::CLOSED: | ||||
396 | return false; | ||||
397 | | ||||
398 | case Bugzilla::Bug::Status::Unknown: | ||||
399 | Q_UNREACHABLE(); | ||||
400 | } | ||||
401 | Q_UNREACHABLE(); | ||||
402 | return false; | ||||
403 | } | ||||
404 | | ||||
405 | static bool isStatusClosed(Bugzilla::Bug::Status status) | ||||
406 | { | ||||
407 | return !isStatusOpen(status); | ||||
408 | } | ||||
409 | | ||||
383 | void BugzillaDuplicatesPage::analyzedDuplicates(KJob *j) | 410 | void BugzillaDuplicatesPage::analyzedDuplicates(KJob *j) | ||
384 | { | 411 | { | ||
385 | markAsSearching(false); | 412 | markAsSearching(false); | ||
386 | 413 | | |||
387 | DuplicateFinderJob *job = static_cast<DuplicateFinderJob*>(j); | 414 | DuplicateFinderJob *job = static_cast<DuplicateFinderJob*>(j); | ||
388 | m_result = job->result(); | 415 | m_result = job->result(); | ||
389 | m_foundDuplicate = m_result.parentDuplicate; | 416 | m_foundDuplicate = m_result.parentDuplicate; | ||
390 | reportInterface()->setDuplicateId(m_result.parentDuplicate); | 417 | reportInterface()->setDuplicateId(m_result.parentDuplicate); | ||
391 | ui.m_searchMoreButton->setEnabled(!m_foundDuplicate); | 418 | ui.m_searchMoreButton->setEnabled(!m_foundDuplicate); | ||
392 | ui.information->setVisible(m_foundDuplicate); | 419 | ui.information->setVisible(m_foundDuplicate); | ||
393 | BugReport::Status status = m_result.status; | 420 | auto status = m_result.status; | ||
394 | const int duplicate = m_result.duplicate; | 421 | const int duplicate = m_result.duplicate; | ||
395 | const int parentDuplicate = m_result.parentDuplicate; | 422 | const int parentDuplicate = m_result.parentDuplicate; | ||
396 | 423 | | |||
397 | if (m_foundDuplicate) { | 424 | if (m_foundDuplicate) { | ||
398 | const QList<QTreeWidgetItem*> items = ui.m_bugListWidget->findItems(QString::number(parentDuplicate), Qt::MatchExactly, 0); | 425 | const QList<QTreeWidgetItem*> items = ui.m_bugListWidget->findItems(QString::number(parentDuplicate), Qt::MatchExactly, 0); | ||
399 | const QBrush brush = KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::NeutralBackground); | 426 | const QBrush brush = KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::NeutralBackground); | ||
400 | Q_FOREACH (QTreeWidgetItem* item, items) { | 427 | Q_FOREACH (QTreeWidgetItem* item, items) { | ||
401 | for (int i = 0; i < item->columnCount(); ++i) { | 428 | for (int i = 0; i < item->columnCount(); ++i) { | ||
402 | item->setBackground(i, brush); | 429 | item->setBackground(i, brush); | ||
403 | } | 430 | } | ||
404 | } | 431 | } | ||
405 | 432 | | |||
433 | #warning fixme this feels weird. why are we not passing the bug around? | ||||
406 | QString text; | 434 | QString text; | ||
407 | if (BugReport::isOpen(status) || (BugReport::isClosed(status) && status == BugReport::NeedsInfo)) { | 435 | if (isStatusOpen(status) || status == Bugzilla::Bug::Status::NEEDSINFO) { | ||
408 | text = (parentDuplicate == duplicate ? i18nc("@label", "Your crash is a <strong>duplicate</strong> and has already been reported as <a href=\"%1\">Bug %1</a>.", QString::number(duplicate)) : | 436 | text = (parentDuplicate == duplicate ? i18nc("@label", "Your crash is a <strong>duplicate</strong> and has already been reported as <a href=\"%1\">Bug %1</a>.", QString::number(duplicate)) : | ||
409 | i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a>, which is a <strong>duplicate</strong> of <a href=\"%2\">Bug %2</a>", QString::number(duplicate), QString::number(parentDuplicate))) + | 437 | i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a>, which is a <strong>duplicate</strong> of <a href=\"%2\">Bug %2</a>", QString::number(duplicate), QString::number(parentDuplicate))) + | ||
410 | QLatin1Char('\n') + i18nc("@label", "Only <strong><a href=\"%1\">attach</a></strong> if you can add needed information to the bug report.", QStringLiteral("attach")); | 438 | QLatin1Char('\n') + i18nc("@label", "Only <strong><a href=\"%1\">attach</a></strong> if you can add needed information to the bug report.", QStringLiteral("attach")); | ||
411 | } else if (BugReport::isClosed(status)) { | 439 | } else if (isStatusClosed(status)) { | ||
412 | text = (parentDuplicate == duplicate ? i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a> which has been <strong>closed</strong>.", QString::number(duplicate)) : | 440 | text = (parentDuplicate == duplicate ? i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a> which has been <strong>closed</strong>.", QString::number(duplicate)) : | ||
413 | i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a>, which is a duplicate of the <strong>closed</strong> <a href=\"%2\">Bug %2</a>.", QString::number(duplicate), QString::number(parentDuplicate))); | 441 | i18nc("@label", "Your crash has already been reported as <a href=\"%1\">Bug %1</a>, which is a duplicate of the <strong>closed</strong> <a href=\"%2\">Bug %2</a>.", QString::number(duplicate), QString::number(parentDuplicate))); | ||
414 | } | 442 | } | ||
415 | ui.information->setText(text); | 443 | ui.information->setText(text); | ||
416 | } | 444 | } | ||
417 | } | 445 | } | ||
418 | 446 | | |||
419 | void BugzillaDuplicatesPage::informationClicked(const QString &activatedLink) | 447 | void BugzillaDuplicatesPage::informationClicked(const QString &activatedLink) | ||
Show All 15 Lines | 460 | { | |||
435 | 463 | | |||
436 | ui.m_statusWidget->setIdle(i18nc("@info:status","Error fetching the bug report list")); | 464 | ui.m_statusWidget->setIdle(i18nc("@info:status","Error fetching the bug report list")); | ||
437 | 465 | | |||
438 | KMessageBox::error(this , xi18nc("@info/rich","Error fetching the bug report list<nl/>" | 466 | KMessageBox::error(this , xi18nc("@info/rich","Error fetching the bug report list<nl/>" | ||
439 | "<message>%1.</message><nl/>" | 467 | "<message>%1.</message><nl/>" | ||
440 | "Please wait some time and try again.", err)); | 468 | "Please wait some time and try again.", err)); | ||
441 | } | 469 | } | ||
442 | 470 | | |||
443 | void BugzillaDuplicatesPage::resetDates() | | |||
444 | { | | |||
445 | m_endDate = QDate::currentDate(); | | |||
446 | m_startDate = m_endDate; | | |||
447 | } | | |||
448 | //END Search related methods | 471 | //END Search related methods | ||
449 | 472 | | |||
450 | //BEGIN Duplicates list related methods | 473 | //BEGIN Duplicates list related methods | ||
451 | void BugzillaDuplicatesPage::openSelectedReport() | 474 | void BugzillaDuplicatesPage::openSelectedReport() | ||
452 | { | 475 | { | ||
453 | QList<QTreeWidgetItem*> selected = ui.m_bugListWidget->selectedItems(); | 476 | QList<QTreeWidgetItem*> selected = ui.m_bugListWidget->selectedItems(); | ||
454 | if (selected.count() == 1) { | 477 | if (selected.count() == 1) { | ||
455 | itemClicked(selected.at(0), 0); | 478 | itemClicked(selected.at(0), 0); | ||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Line(s) | 605 | QIcon::fromTheme(QStringLiteral("list-add")), i18nc("@info:tooltip", "Use this button to suggest that " | |||
584 | "report"))); | 607 | "report"))); | ||
585 | connect(m_suggestButton, &QPushButton::clicked, this, &BugzillaReportInformationDialog::relatedReportClicked); | 608 | connect(m_suggestButton, &QPushButton::clicked, this, &BugzillaReportInformationDialog::relatedReportClicked); | ||
586 | 609 | | |||
587 | connect(ui.m_showOwnBacktraceCheckBox, &QAbstractButton::toggled, this, &BugzillaReportInformationDialog::toggleShowOwnBacktrace); | 610 | connect(ui.m_showOwnBacktraceCheckBox, &QAbstractButton::toggled, this, &BugzillaReportInformationDialog::toggleShowOwnBacktrace); | ||
588 | 611 | | |||
589 | //Connect bugzillalib signals | 612 | //Connect bugzillalib signals | ||
590 | connect(m_parent->bugzillaManager(), &BugzillaManager::bugReportFetched, | 613 | connect(m_parent->bugzillaManager(), &BugzillaManager::bugReportFetched, | ||
591 | this, &BugzillaReportInformationDialog::bugFetchFinished); | 614 | this, &BugzillaReportInformationDialog::bugFetchFinished); | ||
592 | connect(m_parent->bugzillaManager(), SIGNAL(bugReportError(QString,QObject*)), | 615 | connect(m_parent->bugzillaManager(), &BugzillaManager::bugReportError, | ||
593 | this, SLOT(bugFetchError(QString,QObject*))); | 616 | this, &BugzillaReportInformationDialog::bugFetchError); | ||
617 | connect(m_parent->bugzillaManager(), &BugzillaManager::commentsFetched, | ||||
618 | this, &BugzillaReportInformationDialog::onCommentsFetched); | ||||
619 | connect(m_parent->bugzillaManager(), &BugzillaManager::commentsError, | ||||
620 | this, &BugzillaReportInformationDialog::bugFetchError); | ||||
594 | 621 | | |||
595 | resize(QSize(800, 600)); | 622 | resize(QSize(800, 600)); | ||
596 | KConfigGroup config(KSharedConfig::openConfig(), "BugzillaReportInformationDialog"); | 623 | KConfigGroup config(KSharedConfig::openConfig(), "BugzillaReportInformationDialog"); | ||
597 | KWindowConfig::restoreWindowSize(windowHandle(), config); | 624 | KWindowConfig::restoreWindowSize(windowHandle(), config); | ||
598 | } | 625 | } | ||
599 | 626 | | |||
600 | BugzillaReportInformationDialog::~BugzillaReportInformationDialog() | 627 | BugzillaReportInformationDialog::~BugzillaReportInformationDialog() | ||
601 | { | 628 | { | ||
602 | disconnect(m_parent->bugzillaManager(), &BugzillaManager::bugReportFetched, | | |||
603 | this, &BugzillaReportInformationDialog::bugFetchFinished); | | |||
604 | disconnect(m_parent->bugzillaManager(), SIGNAL(bugReportError(QString,QObject*)), | | |||
605 | this, SLOT(bugFetchError(QString,QObject*))); | | |||
606 | | ||||
607 | KConfigGroup config(KSharedConfig::openConfig(), "BugzillaReportInformationDialog"); | 629 | KConfigGroup config(KSharedConfig::openConfig(), "BugzillaReportInformationDialog"); | ||
608 | KWindowConfig::saveWindowSize(windowHandle(), config); | 630 | KWindowConfig::saveWindowSize(windowHandle(), config); | ||
609 | } | 631 | } | ||
610 | 632 | | |||
611 | void BugzillaReportInformationDialog::reloadReport() | 633 | void BugzillaReportInformationDialog::reloadReport() | ||
612 | { | 634 | { | ||
613 | showBugReport(m_bugNumber); | 635 | showBugReport(m_bugNumber); | ||
614 | } | 636 | } | ||
Show All 30 Lines | 639 | { | |||
645 | ui.m_showOwnBacktraceCheckBox->setChecked(showOwnBacktrace); | 667 | ui.m_showOwnBacktraceCheckBox->setChecked(showOwnBacktrace); | ||
646 | if (!showOwnBacktrace) { //setChecked(false) will not emit toggled(false) | 668 | if (!showOwnBacktrace) { //setChecked(false) will not emit toggled(false) | ||
647 | toggleShowOwnBacktrace(false); | 669 | toggleShowOwnBacktrace(false); | ||
648 | } | 670 | } | ||
649 | 671 | | |||
650 | show(); | 672 | show(); | ||
651 | } | 673 | } | ||
652 | 674 | | |||
653 | void BugzillaReportInformationDialog::bugFetchFinished(BugReport report, QObject * jobOwner) | 675 | struct Status2 { | ||
676 | QString statusString; | ||||
677 | QString closedStateString; | ||||
678 | }; | ||||
679 | | ||||
680 | static Status2 statusString2(const Bugzilla::Bug::Ptr &bug) | ||||
654 | { | 681 | { | ||
655 | if (jobOwner == this && isVisible()) { | 682 | // Generate a non-geek readable status | ||
656 | if (report.isValid()) { | 683 | switch(bug->status()) { | ||
684 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
685 | return { i18nc("@info bug status", "Opened (Unconfirmed)"), QString() }; | ||||
686 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
687 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
688 | case Bugzilla::Bug::Status::REOPENED: | ||||
689 | return { i18nc("@info bug status", "Opened (Unfixed)"), QString() }; | ||||
690 | | ||||
691 | case Bugzilla::Bug::Status::RESOLVED: | ||||
692 | case Bugzilla::Bug::Status::VERIFIED: | ||||
693 | case Bugzilla::Bug::Status::CLOSED: | ||||
694 | switch(bug->resolution()) { | ||||
695 | case Bugzilla::Bug::Resolution::FIXED: { | ||||
696 | auto fixedIn = bug->customField("cf_versionfixedin").toString(); | ||||
697 | if (!fixedIn.isEmpty()) { | ||||
698 | return { i18nc("@info bug resolution, fixed in version", | ||||
699 | "Fixed in version \"%1\"", | ||||
700 | fixedIn), | ||||
701 | i18nc("@info bug resolution, fixed by kde devs in version", | ||||
702 | "the bug was fixed by KDE developers in version \"%1\"", | ||||
703 | fixedIn) | ||||
704 | }; | ||||
705 | } | ||||
706 | return { | ||||
707 | i18nc("@info bug resolution", "Fixed"), | ||||
708 | i18nc("@info bug resolution", "the bug was fixed by KDE developers") | ||||
709 | }; | ||||
710 | } | ||||
711 | | ||||
712 | case Bugzilla::Bug::Resolution::WORKSFORME: | ||||
713 | return { i18nc("@info bug resolution", "Non-reproducible"), QString() }; | ||||
714 | case Bugzilla::Bug::Resolution::DUPLICATE: | ||||
715 | return { i18nc("@info bug resolution", "Duplicate report (Already reported before)"), QString() }; | ||||
716 | case Bugzilla::Bug::Resolution::INVALID: | ||||
717 | return { i18nc("@info bug resolution", "Not a valid report/crash"), QString() }; | ||||
718 | case Bugzilla::Bug::Resolution::UPSTREAM: | ||||
719 | case Bugzilla::Bug::Resolution::DOWNSTREAM: | ||||
720 | return { i18nc("@info bug resolution", "Not caused by a problem in the KDE's Applications or libraries"), | ||||
721 | i18nc("@info bug resolution", "the bug is caused by a problem in an external application or library, or by a distribution or packaging issue") }; | ||||
722 | case Bugzilla::Bug::Resolution::WONTFIX: | ||||
723 | case Bugzilla::Bug::Resolution::LATER: | ||||
724 | case Bugzilla::Bug::Resolution::REMIND: | ||||
725 | case Bugzilla::Bug::Resolution::MOVED: | ||||
726 | case Bugzilla::Bug::Resolution::WAITINGFORINFO: | ||||
727 | case Bugzilla::Bug::Resolution::BACKTRACE: | ||||
728 | case Bugzilla::Bug::Resolution::UNMAINTAINED: | ||||
729 | return { QVariant::fromValue(bug->resolution()).toString(), QString() }; | ||||
730 | case Bugzilla::Bug::Resolution::Unknown: | ||||
731 | Q_UNREACHABLE(); | ||||
732 | } | ||||
733 | Q_UNREACHABLE(); | ||||
734 | return {}; | ||||
735 | | ||||
736 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
737 | return { i18nc("@info bug status", "Temporarily closed, because of a lack of information"), QString() }; | ||||
738 | | ||||
739 | case Bugzilla::Bug::Status::Unknown: | ||||
740 | Q_UNREACHABLE(); | ||||
741 | | ||||
742 | #warning fixme what to do with this | ||||
743 | // } else { //Fallback to other raw values | ||||
744 | // customStatusString = QStringLiteral("%1 (%2)").arg(report->status(), report->resolution()); | ||||
745 | // } | ||||
746 | } | ||||
747 | Q_UNREACHABLE(); | ||||
748 | return {}; | ||||
749 | } | ||||
750 | | ||||
751 | void BugzillaReportInformationDialog::bugFetchFinished(Bugzilla::Bug::Ptr bug, QObject *jobOwner) | ||||
752 | { | ||||
753 | if (jobOwner != this || !isVisible()) { | ||||
754 | return; | ||||
755 | } | ||||
756 | | ||||
757 | if (!bug) { | ||||
758 | bugFetchError(i18nc("@info", "Invalid report information (malformed data). This could " | ||||
759 | "mean that the bug report does not exist, or the bug tracking site " | ||||
760 | "is experiencing a problem."), this); | ||||
761 | return; | ||||
762 | } | ||||
763 | | ||||
764 | Q_ASSERT(!m_bug); // m_bug must only be set once we've selected one! | ||||
657 | 765 | | |||
658 | //Handle duplicate state | 766 | // Handle duplicate state | ||
659 | QString duplicate = report.markedAsDuplicateOf(); | 767 | if (bug->dupe_of() > 0) { | ||
660 | if (!duplicate.isEmpty()) { | | |||
661 | bool ok = false; | | |||
662 | int dupId = duplicate.toInt(&ok); | | |||
663 | if (ok && dupId > 0) { | | |||
664 | ui.m_statusWidget->setIdle(QString()); | 768 | ui.m_statusWidget->setIdle(QString()); | ||
665 | 769 | | |||
666 | KGuiItem yesItem = KStandardGuiItem::yes(); | 770 | KGuiItem yesItem = KStandardGuiItem::yes(); | ||
667 | yesItem.setText(i18nc("@action:button let the user to choose to read the " | 771 | yesItem.setText(i18nc("@action:button let the user to choose to read the " | ||
668 | "main report", "Yes, read the main report")); | 772 | "main report", "Yes, read the main report")); | ||
669 | 773 | | |||
670 | KGuiItem noItem = KStandardGuiItem::no(); | 774 | KGuiItem noItem = KStandardGuiItem::no(); | ||
671 | noItem.setText(i18nc("@action:button let the user choose to read the original " | 775 | noItem.setText(i18nc("@action:button let the user choose to read the original " | ||
672 | "report", "No, let me read the report I selected")); | 776 | "report", "No, let me read the report I selected")); | ||
673 | 777 | | |||
674 | if (KMessageBox::questionYesNo(this, | 778 | auto ret = KMessageBox::questionYesNo( | ||
779 | this, | ||||
675 | xi18nc("@info","The report you selected (bug %1) is already " | 780 | xi18nc("@info","The report you selected (bug %1) is already " | ||
676 | "marked as duplicate of bug %2. " | 781 | "marked as duplicate of bug %2. " | ||
677 | "Do you want to read that report instead? (recommended)", | 782 | "Do you want to read that report instead? (recommended)", | ||
678 | report.bugNumber(), QString::number(dupId)), | 783 | bug->id(), QString::number(bug->dupe_of())), | ||
679 | i18nc("@title:window","Nested duplicate detected"), yesItem, noItem) | 784 | i18nc("@title:window","Nested duplicate detected"), | ||
680 | == KMessageBox::Yes) { | 785 | yesItem, | ||
681 | showBugReport(dupId); | 786 | noItem); | ||
787 | if (ret == KMessageBox::Yes) { | ||||
788 | qDebug() << "REDIRECT"; | ||||
789 | showBugReport(bug->dupe_of()); | ||||
682 | return; | 790 | return; | ||
683 | } | 791 | } | ||
684 | } | 792 | } | ||
793 | | ||||
794 | // Process comments... | ||||
795 | m_bug = bug; | ||||
796 | m_parent->bugzillaManager()->fetchComments(m_bug, this); | ||||
797 | } | ||||
798 | | ||||
799 | void BugzillaReportInformationDialog::onCommentsFetched(QList<Bugzilla::Comment::Ptr> bugComments, | ||||
800 | QObject *jobOwner) | ||||
801 | { | ||||
802 | if (jobOwner != this || !isVisible()) { | ||||
803 | return; | ||||
685 | } | 804 | } | ||
686 | 805 | | |||
806 | Q_ASSERT(m_bug); | ||||
807 | | ||||
687 | //Generate html for comments (with proper numbering) | 808 | // Generate html for comments (with proper numbering) | ||
688 | QLatin1String duplicatesMark = QLatin1String("has been marked as a duplicate of this bug."); | 809 | QLatin1String duplicatesMark = QLatin1String("has been marked as a duplicate of this bug."); | ||
689 | 810 | | |||
690 | QString comments; | 811 | QString comments; | ||
691 | QStringList commentList = report.comments(); | 812 | #warning fixme comments arent very oop | ||
692 | for (int i = 0; i < commentList.count(); i++) { | 813 | QString description; // aka first comment | ||
693 | QString comment = commentList.at(i); | 814 | if (bugComments.size() > 0) { | ||
815 | description = bugComments.takeFirst()->text(); | ||||
816 | } | ||||
817 | for (auto it = bugComments.constBegin(); it != bugComments.constEnd(); ++it) { | ||||
818 | QString comment = (*it)->text(); | ||||
694 | //Don't add duplicates mark comments | 819 | //Don't add duplicates mark comments | ||
695 | if (!comment.contains(duplicatesMark)) { | 820 | if (!comment.contains(duplicatesMark)) { | ||
696 | comment.replace(QLatin1Char('\n'), QLatin1String("<br />")); | 821 | comment.replace(QLatin1Char('\n'), QLatin1String("<br />")); | ||
822 | const int i = it - bugComments.constBegin(); | ||||
697 | comments += i18nc("comment $number to use as subtitle", "<h4>Comment %1:</h4>", (i+1)) | 823 | comments += i18nc("comment $number to use as subtitle", "<h4>Comment %1:</h4>", (i+1)) | ||
698 | + QStringLiteral("<p>") + comment + QStringLiteral("</p><hr />"); | 824 | + QStringLiteral("<p>") + comment + QStringLiteral("</p><hr />"); | ||
699 | //Count the inline attached crashes (DrKonqi feature) | 825 | //Count the inline attached crashes (DrKonqi feature) | ||
700 | QLatin1String attachedCrashMark = | 826 | QLatin1String attachedCrashMark = | ||
701 | QLatin1String("New crash information added by DrKonqi"); | 827 | QLatin1String("New crash information added by DrKonqi"); | ||
702 | if (comment.contains(attachedCrashMark)) { | 828 | if (comment.contains(attachedCrashMark)) { | ||
703 | m_duplicatesCount++; | 829 | m_duplicatesCount++; | ||
704 | } | 830 | } | ||
705 | } else { | 831 | } else { | ||
706 | //Count duplicate | 832 | //Count duplicate | ||
707 | m_duplicatesCount++; | 833 | m_duplicatesCount++; | ||
708 | } | 834 | } | ||
709 | } | 835 | } | ||
710 | 836 | | |||
711 | //Generate a non-geek readable status | 837 | //Generate a non-geek readable status | ||
712 | QString customStatusString; | 838 | auto str = statusString2(m_bug); | ||
713 | BugReport::Status status = report.statusValue(); | 839 | QString customStatusString = str.statusString; | ||
714 | BugReport::Resolution resolution = report.resolutionValue(); | 840 | m_closedStateString = str.closedStateString; | ||
715 | if (status == BugReport::Unconfirmed) { | | |||
716 | customStatusString = i18nc("@info bug status", "Opened (Unconfirmed)"); | | |||
717 | } else if (report.isOpen()) { | | |||
718 | customStatusString = i18nc("@info bug status", "Opened (Unfixed)"); | | |||
719 | } else if (report.isClosed() && status != BugReport::NeedsInfo) { | | |||
720 | QString customResolutionString; | | |||
721 | if (resolution == BugReport::Fixed) { | | |||
722 | if (!report.versionFixedIn().isEmpty()) { | | |||
723 | customResolutionString = i18nc("@info bug resolution, fixed in version", | | |||
724 | "Fixed in version \"%1\"", | | |||
725 | report.versionFixedIn()); | | |||
726 | m_closedStateString = i18nc("@info bug resolution, fixed by kde devs in version", | | |||
727 | "the bug was fixed by KDE developers in version \"%1\"", | | |||
728 | report.versionFixedIn()); | | |||
729 | } else { | | |||
730 | customResolutionString = i18nc("@info bug resolution", "Fixed"); | | |||
731 | m_closedStateString = i18nc("@info bug resolution", "the bug was fixed by KDE developers"); | | |||
732 | } | | |||
733 | } else if (resolution == BugReport::WorksForMe) { | | |||
734 | customResolutionString = i18nc("@info bug resolution", "Non-reproducible"); | | |||
735 | } else if (resolution == BugReport::Duplicate) { | | |||
736 | customResolutionString = i18nc("@info bug resolution", "Duplicate report " | | |||
737 | "(Already reported before)"); | | |||
738 | } else if (resolution == BugReport::Invalid) { | | |||
739 | customResolutionString = i18nc("@info bug resolution", "Not a valid report/crash"); | | |||
740 | } else if (resolution == BugReport::Downstream || resolution == BugReport::Upstream) { | | |||
741 | customResolutionString = i18nc("@info bug resolution", "Not caused by a problem " | | |||
742 | "in the KDE's Applications or libraries"); | | |||
743 | m_closedStateString = i18nc("@info bug resolution", "the bug is caused by a " | | |||
744 | "problem in an external application or library, or " | | |||
745 | "by a distribution or packaging issue"); | | |||
746 | } else { | | |||
747 | customResolutionString = report.resolution(); | | |||
748 | } | | |||
749 | | ||||
750 | customStatusString = i18nc("@info bug status, %1 is the resolution", "Closed (%1)", | | |||
751 | customResolutionString); | | |||
752 | } else if (status == BugReport::NeedsInfo) { | | |||
753 | customStatusString = i18nc("@info bug status", "Temporarily closed, because of a lack " | | |||
754 | "of information"); | | |||
755 | } else { //Fallback to other raw values | | |||
756 | customStatusString = QStringLiteral("%1 (%2)").arg(report.bugStatus(), report.resolution()); | | |||
757 | } | | |||
758 | 841 | | |||
759 | //Generate notes | 842 | //Generate notes | ||
760 | QString notes = xi18n("<p><note>The bug report's title is often written by its reporter " | 843 | QString notes = xi18n("<p><note>The bug report's title is often written by its reporter " | ||
761 | "and may not reflect the bug's nature, root cause or other visible " | 844 | "and may not reflect the bug's nature, root cause or other visible " | ||
762 | "symptoms you could use to compare to your crash. Please read the " | 845 | "symptoms you could use to compare to your crash. Please read the " | ||
763 | "complete report and all the comments below.</note></p>"); | 846 | "complete report and all the comments below.</note></p>"); | ||
764 | 847 | | |||
765 | if (m_duplicatesCount >= 10) { //Consider a possible mass duplicate crash | 848 | if (m_duplicatesCount >= 10) { //Consider a possible mass duplicate crash | ||
766 | notes += xi18np("<p><note>This bug report has %1 duplicate report. That means this " | 849 | notes += xi18np("<p><note>This bug report has %1 duplicate report. That means this " | ||
767 | "is probably a <strong>common crash</strong>. <i>Please consider only " | 850 | "is probably a <strong>common crash</strong>. <i>Please consider only " | ||
768 | "adding a comment or a note if you can provide new valuable " | 851 | "adding a comment or a note if you can provide new valuable " | ||
769 | "information which was not already mentioned.</i></note></p>", | 852 | "information which was not already mentioned.</i></note></p>", | ||
770 | "<p><note>This bug report has %1 duplicate reports. That means this " | 853 | "<p><note>This bug report has %1 duplicate reports. That means this " | ||
771 | "is probably a <strong>common crash</strong>. <i>Please consider only " | 854 | "is probably a <strong>common crash</strong>. <i>Please consider only " | ||
772 | "adding a comment or a note if you can provide new valuable " | 855 | "adding a comment or a note if you can provide new valuable " | ||
773 | "information which was not already mentioned.</i></note></p>", | 856 | "information which was not already mentioned.</i></note></p>", | ||
774 | m_duplicatesCount); | 857 | m_duplicatesCount); | ||
775 | } | 858 | } | ||
776 | 859 | | |||
777 | //A manually entered bug ID could represent a normal bug | 860 | //A manually entered bug ID could represent a normal bug | ||
778 | if (report.bugSeverity() != QLatin1String("crash") | 861 | if (m_bug->severity() != QLatin1String("crash") | ||
779 | && report.bugSeverity() != QLatin1String("major") | 862 | && m_bug->severity() != QLatin1String("major") | ||
780 | && report.bugSeverity() != QLatin1String("grave") | 863 | && m_bug->severity() != QLatin1String("grave") | ||
781 | && report.bugSeverity() != QLatin1String("critical")) | 864 | && m_bug->severity() != QLatin1String("critical")) | ||
782 | { | 865 | { | ||
783 | notes += xi18n("<p><note>This bug report is not about a crash or about any other " | 866 | notes += xi18n("<p><note>This bug report is not about a crash or about any other " | ||
784 | "critical bug.</note></p>"); | 867 | "critical bug.</note></p>"); | ||
785 | } | 868 | } | ||
786 | 869 | | |||
787 | //Generate HTML text | 870 | //Generate HTML text | ||
788 | QString text = | 871 | QString text = | ||
789 | i18nc("@info bug report title (quoted)", | 872 | i18nc("@info bug report title (quoted)", | ||
790 | "<h3>\"%1\"</h3>", report.shortDescription()) + | 873 | "<h3>\"%1\"</h3>", m_bug->summary()) + | ||
791 | notes + | 874 | notes + | ||
792 | i18nc("@info bug report status", | 875 | i18nc("@info bug report status", | ||
793 | "<h4>Bug Report Status: %1</h4>", customStatusString) + | 876 | "<h4>Bug Report Status: %1</h4>", customStatusString) + | ||
794 | i18nc("@info bug report product and component", | 877 | i18nc("@info bug report product and component", | ||
795 | "<h4>Affected Component: %1 (%2)</h4>", | 878 | "<h4>Affected Component: %1 (%2)</h4>", | ||
796 | report.product(), report.component()) + | 879 | m_bug->product(), | ||
880 | m_bug->component()) + | ||||
797 | i18nc("@info bug report description", | 881 | i18nc("@info bug report description", | ||
798 | "<h3>Description of the bug</h3><p>%1</p>", | 882 | "<h3>Description of the bug</h3><p>%1</p>", | ||
799 | report.description().replace(QLatin1Char('\n'), QLatin1String("<br />"))); | 883 | description.replace(QLatin1Char('\n'), QLatin1String("<br />"))); | ||
800 | 884 | | |||
801 | if (!comments.isEmpty()) { | 885 | if (!comments.isEmpty()) { | ||
802 | text += i18nc("@label:textbox bug report comments (already formatted)", | 886 | text += i18nc("@label:textbox bug report comments (already formatted)", | ||
803 | "<h2>Additional Comments</h2>%1", comments); | 887 | "<h2>Additional Comments</h2>%1", comments); | ||
804 | } | 888 | } | ||
805 | 889 | | |||
806 | ui.m_infoBrowser->setText(text); | 890 | ui.m_infoBrowser->setText(text); | ||
807 | ui.m_infoBrowser->setEnabled(true); | 891 | ui.m_infoBrowser->setEnabled(true); | ||
808 | 892 | | |||
809 | m_suggestButton->setEnabled(m_relatedButtonEnabled); | 893 | m_suggestButton->setEnabled(m_relatedButtonEnabled); | ||
810 | m_suggestButton->setVisible(m_relatedButtonEnabled); | 894 | m_suggestButton->setVisible(m_relatedButtonEnabled); | ||
811 | 895 | | |||
812 | ui.m_statusWidget->setIdle(xi18nc("@info:status", "Showing bug %1", | 896 | ui.m_statusWidget->setIdle(xi18nc("@info:status", "Showing bug %1", | ||
813 | QString::number(report.bugNumberAsInt()))); | 897 | QString::number(m_bug->id()))); | ||
814 | } else { | | |||
815 | bugFetchError(i18nc("@info", "Invalid report information (malformed data). This could " | | |||
816 | "mean that the bug report does not exist, or the bug tracking site " | | |||
817 | "is experiencing a problem."), this); | | |||
818 | } | | |||
819 | } | | |||
820 | } | 898 | } | ||
821 | 899 | | |||
822 | void BugzillaReportInformationDialog::markAsDuplicate() | 900 | void BugzillaReportInformationDialog::markAsDuplicate() | ||
823 | { | 901 | { | ||
824 | emit possibleDuplicateSelected(m_bugNumber); | 902 | emit possibleDuplicateSelected(m_bugNumber); | ||
825 | hide(); | 903 | hide(); | ||
826 | } | 904 | } | ||
827 | 905 | | |||
▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines |