Changeset View
Changeset View
Standalone View
Standalone View
src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp
Show All 39 Lines | 39 | BugzillaDuplicatesPage::BugzillaDuplicatesPage(ReportAssistantDialog * parent): | |||
---|---|---|---|---|---|
40 | ReportAssistantPage(parent), | 40 | ReportAssistantPage(parent), | ||
41 | m_searching(false), | 41 | m_searching(false), | ||
42 | m_foundDuplicate(false) | 42 | m_foundDuplicate(false) | ||
43 | { | 43 | { | ||
44 | resetDates(); | 44 | resetDates(); | ||
45 | 45 | | |||
46 | connect(bugzillaManager(), &BugzillaManager::searchFinished, | 46 | connect(bugzillaManager(), &BugzillaManager::searchFinished, | ||
47 | this, &BugzillaDuplicatesPage::searchFinished); | 47 | this, &BugzillaDuplicatesPage::searchFinished); | ||
48 | connect(bugzillaManager(), SIGNAL(searchError(QString)), | 48 | connect(bugzillaManager(), &BugzillaManager::searchError, | ||
49 | this, SLOT(searchError(QString))); | 49 | this, &BugzillaDuplicatesPage::searchError); | ||
50 | 50 | | |||
51 | ui.setupUi(this); | 51 | ui.setupUi(this); | ||
52 | ui.information->hide(); | 52 | ui.information->hide(); | ||
53 | 53 | | |||
54 | connect(ui.m_bugListWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), | 54 | connect(ui.m_bugListWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), | ||
55 | this, SLOT(itemClicked(QTreeWidgetItem*,int))); | 55 | this, SLOT(itemClicked(QTreeWidgetItem*,int))); | ||
56 | connect(ui.m_bugListWidget, &QTreeWidget::itemSelectionChanged, this, &BugzillaDuplicatesPage::itemSelectionChanged); | 56 | connect(ui.m_bugListWidget, &QTreeWidget::itemSelectionChanged, this, &BugzillaDuplicatesPage::itemSelectionChanged); | ||
57 | 57 | | |||
▲ Show 20 Lines • Show All 143 Lines • ▼ Show 20 Line(s) | 173 | if (ui.m_bugListWidget->topLevelItemCount() != 1 && ui.m_selectedDuplicatesList->count() == 0 | |||
201 | } | 201 | } | ||
202 | } | 202 | } | ||
203 | return true; | 203 | return true; | ||
204 | } | 204 | } | ||
205 | 205 | | |||
206 | //BEGIN Search related methods | 206 | //BEGIN Search related methods | ||
207 | void BugzillaDuplicatesPage::searchMore() | 207 | void BugzillaDuplicatesPage::searchMore() | ||
208 | { | 208 | { | ||
209 | //1 year back | 209 | // Start search 6 months before our previous search (or 6 months before now) | ||
210 | m_searchingEndDate = m_startDate; | 210 | m_searchingStartDate = m_startDate.addMonths(-6); | ||
211 | m_searchingStartDate = m_searchingEndDate.addYears(-1); | | |||
212 | 211 | | |||
213 | performSearch(); | 212 | performSearch(); | ||
214 | } | 213 | } | ||
215 | 214 | | |||
216 | void BugzillaDuplicatesPage::performSearch() | 215 | void BugzillaDuplicatesPage::performSearch() | ||
217 | { | 216 | { | ||
217 | #warning search needs porting to limit + offset (i.e. pagination) as by-date offsetting is not supported by the service api | ||||
218 | markAsSearching(true); | 218 | markAsSearching(true); | ||
219 | 219 | | |||
220 | QString startDateStr = m_searchingStartDate.toString(QStringLiteral("yyyy-MM-dd")); | 220 | QString creationDateStr = m_searchingStartDate.toString(QStringLiteral("yyyy-MM-dd")); | ||
221 | QString endDateStr = m_searchingEndDate.toString(QStringLiteral("yyyy-MM-dd")); | | |||
222 | 221 | | |||
223 | ui.m_statusWidget->setBusy(i18nc("@info:status","Searching for duplicates (from %1 to %2)...", | 222 | ui.m_statusWidget->setBusy(i18nc("@info:status","Searching for duplicates (crated since %1)...", creationDateStr)); | ||
224 | startDateStr, endDateStr)); | | |||
225 | 223 | | |||
226 | //Bugzilla will not search on Today bugs if we send the date. | 224 | #warning fixme why the flip are we generateing a new report template just to get the default severity oO | ||
227 | //we need to send "Now" | 225 | Bugzilla::NewBug bug = reportInterface()->newBugReportTemplate(); | ||
228 | if (m_searchingEndDate == QDate::currentDate()) { | | |||
229 | endDateStr = QLatin1String("Now"); | | |||
230 | } | | |||
231 | | ||||
232 | #if 1 | | |||
233 | BugReport report = reportInterface()->newBugReportTemplate(); | | |||
234 | bugzillaManager()->searchBugs(reportInterface()->relatedBugzillaProducts(), | 226 | bugzillaManager()->searchBugs(reportInterface()->relatedBugzillaProducts(), | ||
235 | report.bugSeverity(), startDateStr, endDateStr, | 227 | bug.severity, creationDateStr, | ||
236 | reportInterface()->firstBacktraceFunctions().join(QStringLiteral(" "))); | 228 | reportInterface()->firstBacktraceFunctions().join(QStringLiteral(" "))); | ||
237 | #else //Test search | | |||
238 | bugzillaManager()->searchBugs(QStringList() << "plasma", "crash", startDateStr, endDateStr, | | |||
239 | "QGraphicsScenePrivate::processDirtyItemsRecursive"); | | |||
240 | #endif | | |||
241 | } | 229 | } | ||
242 | 230 | | |||
243 | void BugzillaDuplicatesPage::stopCurrentSearch() | 231 | void BugzillaDuplicatesPage::stopCurrentSearch() | ||
244 | { | 232 | { | ||
245 | if (m_searching) { | 233 | if (m_searching) { | ||
246 | bugzillaManager()->stopCurrentSearch(); | 234 | bugzillaManager()->stopCurrentSearch(); | ||
247 | 235 | | |||
248 | markAsSearching(false); | 236 | markAsSearching(false); | ||
Show All 33 Lines | 249 | { | |||
282 | } | 270 | } | ||
283 | } | 271 | } | ||
284 | 272 | | |||
285 | bool BugzillaDuplicatesPage::canSearchMore() | 273 | bool BugzillaDuplicatesPage::canSearchMore() | ||
286 | { | 274 | { | ||
287 | return (m_startDate.year() >= 2009); | 275 | return (m_startDate.year() >= 2009); | ||
288 | } | 276 | } | ||
289 | 277 | | |||
290 | void BugzillaDuplicatesPage::searchFinished(const BugMapList & list) | 278 | static QString statusString(const Bugzilla::Bug::Ptr &bug) | ||
279 | { | ||||
280 | #warning fixme could move the first switch to if is_open and then switch out NeedsInfo | ||||
281 | // Generate a non-geek readable status | ||||
282 | switch(bug->status()) { | ||||
283 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
284 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
285 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
286 | case Bugzilla::Bug::Status::REOPENED: | ||||
287 | return i18nc("@info bug status", "[Open]"); | ||||
288 | | ||||
289 | case Bugzilla::Bug::Status::RESOLVED: | ||||
290 | case Bugzilla::Bug::Status::VERIFIED: | ||||
291 | case Bugzilla::Bug::Status::CLOSED: | ||||
292 | switch(bug->resolution()) { | ||||
293 | case Bugzilla::Bug::Resolution::FIXED: | ||||
294 | return i18nc("@info bug resolution", "[Fixed]"); | ||||
295 | case Bugzilla::Bug::Resolution::WORKSFORME: | ||||
296 | return i18nc("@info bug resolution", "[Non-reproducible]"); | ||||
297 | case Bugzilla::Bug::Resolution::DUPLICATE: | ||||
298 | return i18nc("@info bug resolution", "[Duplicate report]"); | ||||
299 | case Bugzilla::Bug::Resolution::INVALID: | ||||
300 | return i18nc("@info bug resolution", "[Invalid]"); | ||||
301 | case Bugzilla::Bug::Resolution::UPSTREAM: | ||||
302 | case Bugzilla::Bug::Resolution::DOWNSTREAM: | ||||
303 | return i18nc("@info bug resolution", "[External problem]"); | ||||
304 | case Bugzilla::Bug::Resolution::WONTFIX: | ||||
305 | case Bugzilla::Bug::Resolution::LATER: | ||||
306 | case Bugzilla::Bug::Resolution::REMIND: | ||||
307 | case Bugzilla::Bug::Resolution::MOVED: | ||||
308 | case Bugzilla::Bug::Resolution::WAITINGFORINFO: | ||||
309 | case Bugzilla::Bug::Resolution::BACKTRACE: | ||||
310 | case Bugzilla::Bug::Resolution::UNMAINTAINED: | ||||
311 | return QString(); | ||||
312 | case Bugzilla::Bug::Resolution::Unknown: | ||||
313 | Q_UNREACHABLE(); | ||||
314 | } | ||||
315 | | ||||
316 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
317 | return i18nc("@info bug status", "[Incomplete]"); | ||||
318 | | ||||
319 | case Bugzilla::Bug::Status::Unknown: | ||||
320 | Q_UNREACHABLE(); | ||||
321 | } | ||||
322 | Q_UNREACHABLE(); | ||||
323 | QString(); | ||||
324 | } | ||||
325 | | ||||
326 | void BugzillaDuplicatesPage::searchFinished(const QList<Bugzilla::Bug::Ptr> & list) | ||||
291 | { | 327 | { | ||
292 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | 328 | KGuiItem::assign(ui.m_searchMoreButton, m_searchMoreGuiItem); | ||
293 | m_startDate = m_searchingStartDate; | 329 | m_startDate = m_searchingStartDate; | ||
294 | 330 | | |||
295 | int results = list.count(); | 331 | int results = list.count(); | ||
296 | if (results > 0) { | 332 | if (results > 0) { | ||
297 | markAsSearching(false); | 333 | markAsSearching(false); | ||
298 | 334 | | |||
299 | ui.m_statusWidget->setIdle(i18nc("@info:status","Showing results from %1 to %2", | 335 | ui.m_statusWidget->setIdle(i18nc("@info:status","Showing results from %1 to %2", | ||
300 | m_startDate.toString(QStringLiteral("yyyy-MM-dd")), | 336 | m_startDate.toString(QStringLiteral("yyyy-MM-dd")), | ||
301 | m_endDate.toString(QStringLiteral("yyyy-MM-dd")))); | 337 | m_endDate.toString(QStringLiteral("yyyy-MM-dd")))); | ||
302 | 338 | | |||
303 | QList<int> bugIds; | 339 | QList<int> bugIds; | ||
304 | for (int i = 0; i < results; i++) { | 340 | for (int i = 0; i < results; i++) { | ||
305 | BugMap bug = list.at(i); | 341 | Bugzilla::Bug::Ptr bug = list.at(i); | ||
306 | 342 | | |||
307 | bool ok; | 343 | QString title = statusString(bug) + QLatin1Char(' ') + bug->summary(); | ||
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 | 344 | | |||
338 | title = customStatusString + QLatin1Char(' ') + bug[QStringLiteral("short_desc")]; | 345 | QStringList fields = QStringList() << QString::number(bug->id()) << title; | ||
339 | | ||||
340 | QStringList fields = QStringList() << bug[QStringLiteral("bug_id")] << title; | | |||
341 | 346 | | |||
342 | QTreeWidgetItem * item = new QTreeWidgetItem(fields); | 347 | QTreeWidgetItem * item = new QTreeWidgetItem(fields); | ||
343 | item->setToolTip(0, bug[QStringLiteral("short_desc")]); | 348 | item->setToolTip(0, bug->summary()); | ||
344 | item->setToolTip(1, bug[QStringLiteral("short_desc")]); | 349 | item->setToolTip(1, bug->summary()); | ||
345 | 350 | | |||
346 | ui.m_bugListWidget->addTopLevelItem(item); | 351 | ui.m_bugListWidget->addTopLevelItem(item); | ||
347 | } | 352 | } | ||
348 | 353 | | |||
349 | if (!m_foundDuplicate) { | 354 | if (!m_foundDuplicate) { | ||
350 | markAsSearching(true); | 355 | markAsSearching(true); | ||
351 | DuplicateFinderJob *job = new DuplicateFinderJob(bugIds, bugzillaManager(), this); | 356 | DuplicateFinderJob *job = new DuplicateFinderJob(bugIds, bugzillaManager(), this); | ||
352 | connect(job, SIGNAL(result(KJob*)), this, SLOT(analyzedDuplicates(KJob*))); | 357 | connect(job, &KJob::result, this, &BugzillaDuplicatesPage::analyzedDuplicates); | ||
353 | job->start(); | 358 | job->start(); | ||
354 | } | 359 | } | ||
355 | 360 | | |||
356 | ui.m_bugListWidget->sortItems(0 , Qt::DescendingOrder); | 361 | ui.m_bugListWidget->sortItems(0 , Qt::DescendingOrder); | ||
357 | ui.m_bugListWidget->resizeColumnToContents(1); | 362 | ui.m_bugListWidget->resizeColumnToContents(1); | ||
358 | 363 | | |||
359 | if (!canSearchMore()) { | 364 | if (!canSearchMore()) { | ||
360 | ui.m_searchMoreButton->setEnabled(false); | 365 | ui.m_searchMoreButton->setEnabled(false); | ||
Show All 14 Lines | 375 | } else { | |||
375 | if (ui.m_bugListWidget->topLevelItemCount() == 0) { | 380 | if (ui.m_bugListWidget->topLevelItemCount() == 0) { | ||
376 | //No reports to mark as possible duplicate | 381 | //No reports to mark as possible duplicate | ||
377 | ui.m_selectedDuplicatesList->setEnabled(false); | 382 | ui.m_selectedDuplicatesList->setEnabled(false); | ||
378 | } | 383 | } | ||
379 | } | 384 | } | ||
380 | } | 385 | } | ||
381 | } | 386 | } | ||
382 | 387 | | |||
388 | static bool isStatusOpen(Bugzilla::Bug::Status status) | ||||
389 | { | ||||
390 | switch(status) { | ||||
391 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
392 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
393 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
394 | case Bugzilla::Bug::Status::REOPENED: | ||||
395 | return true; | ||||
396 | case Bugzilla::Bug::Status::RESOLVED: | ||||
397 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
398 | case Bugzilla::Bug::Status::VERIFIED: | ||||
399 | case Bugzilla::Bug::Status::CLOSED: | ||||
400 | return false; | ||||
401 | | ||||
402 | case Bugzilla::Bug::Status::Unknown: | ||||
403 | Q_UNREACHABLE(); | ||||
404 | } | ||||
405 | Q_UNREACHABLE(); | ||||
406 | return false; | ||||
407 | } | ||||
408 | | ||||
409 | static bool isStatusClosed(Bugzilla::Bug::Status status) | ||||
410 | { | ||||
411 | return !isStatusOpen(status); | ||||
412 | } | ||||
413 | | ||||
383 | void BugzillaDuplicatesPage::analyzedDuplicates(KJob *j) | 414 | void BugzillaDuplicatesPage::analyzedDuplicates(KJob *j) | ||
384 | { | 415 | { | ||
385 | markAsSearching(false); | 416 | markAsSearching(false); | ||
386 | 417 | | |||
387 | DuplicateFinderJob *job = static_cast<DuplicateFinderJob*>(j); | 418 | DuplicateFinderJob *job = static_cast<DuplicateFinderJob*>(j); | ||
388 | m_result = job->result(); | 419 | m_result = job->result(); | ||
389 | m_foundDuplicate = m_result.parentDuplicate; | 420 | m_foundDuplicate = m_result.parentDuplicate; | ||
390 | reportInterface()->setDuplicateId(m_result.parentDuplicate); | 421 | reportInterface()->setDuplicateId(m_result.parentDuplicate); | ||
391 | ui.m_searchMoreButton->setEnabled(!m_foundDuplicate); | 422 | ui.m_searchMoreButton->setEnabled(!m_foundDuplicate); | ||
392 | ui.information->setVisible(m_foundDuplicate); | 423 | ui.information->setVisible(m_foundDuplicate); | ||
393 | BugReport::Status status = m_result.status; | 424 | auto status = m_result.status; | ||
394 | const int duplicate = m_result.duplicate; | 425 | const int duplicate = m_result.duplicate; | ||
395 | const int parentDuplicate = m_result.parentDuplicate; | 426 | const int parentDuplicate = m_result.parentDuplicate; | ||
396 | 427 | | |||
397 | if (m_foundDuplicate) { | 428 | if (m_foundDuplicate) { | ||
398 | const QList<QTreeWidgetItem*> items = ui.m_bugListWidget->findItems(QString::number(parentDuplicate), Qt::MatchExactly, 0); | 429 | 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); | 430 | const QBrush brush = KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::NeutralBackground); | ||
400 | Q_FOREACH (QTreeWidgetItem* item, items) { | 431 | Q_FOREACH (QTreeWidgetItem* item, items) { | ||
401 | for (int i = 0; i < item->columnCount(); ++i) { | 432 | for (int i = 0; i < item->columnCount(); ++i) { | ||
402 | item->setBackground(i, brush); | 433 | item->setBackground(i, brush); | ||
403 | } | 434 | } | ||
404 | } | 435 | } | ||
405 | 436 | | |||
437 | #warning fixme this feels weird. why are we not passing the bug around? | ||||
406 | QString text; | 438 | QString text; | ||
407 | if (BugReport::isOpen(status) || (BugReport::isClosed(status) && status == BugReport::NeedsInfo)) { | 439 | 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)) : | 440 | 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))) + | 441 | 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")); | 442 | 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)) { | 443 | } 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)) : | 444 | 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))); | 445 | 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 | } | 446 | } | ||
415 | ui.information->setText(text); | 447 | ui.information->setText(text); | ||
416 | } | 448 | } | ||
417 | } | 449 | } | ||
418 | 450 | | |||
419 | void BugzillaDuplicatesPage::informationClicked(const QString &activatedLink) | 451 | void BugzillaDuplicatesPage::informationClicked(const QString &activatedLink) | ||
▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Line(s) | 649 | { | |||
645 | ui.m_showOwnBacktraceCheckBox->setChecked(showOwnBacktrace); | 677 | ui.m_showOwnBacktraceCheckBox->setChecked(showOwnBacktrace); | ||
646 | if (!showOwnBacktrace) { //setChecked(false) will not emit toggled(false) | 678 | if (!showOwnBacktrace) { //setChecked(false) will not emit toggled(false) | ||
647 | toggleShowOwnBacktrace(false); | 679 | toggleShowOwnBacktrace(false); | ||
648 | } | 680 | } | ||
649 | 681 | | |||
650 | show(); | 682 | show(); | ||
651 | } | 683 | } | ||
652 | 684 | | |||
653 | void BugzillaReportInformationDialog::bugFetchFinished(BugReport report, QObject * jobOwner) | 685 | struct Status2 { | ||
686 | QString statusString; | ||||
687 | QString closedStateString; | ||||
688 | }; | ||||
689 | | ||||
690 | static Status2 statusString2(const Bugzilla::Bug::Ptr &bug) | ||||
654 | { | 691 | { | ||
655 | if (jobOwner == this && isVisible()) { | 692 | // Generate a non-geek readable status | ||
656 | if (report.isValid()) { | 693 | switch(bug->status()) { | ||
694 | case Bugzilla::Bug::Status::UNCONFIRMED: | ||||
695 | return { i18nc("@info bug status", "Opened (Unconfirmed)"), QString() }; | ||||
696 | case Bugzilla::Bug::Status::CONFIRMED: | ||||
697 | case Bugzilla::Bug::Status::ASSIGNED: | ||||
698 | case Bugzilla::Bug::Status::REOPENED: | ||||
699 | return { i18nc("@info bug status", "Opened (Unfixed)"), QString() }; | ||||
700 | | ||||
701 | case Bugzilla::Bug::Status::RESOLVED: | ||||
702 | case Bugzilla::Bug::Status::VERIFIED: | ||||
703 | case Bugzilla::Bug::Status::CLOSED: | ||||
704 | switch(bug->resolution()) { | ||||
705 | case Bugzilla::Bug::Resolution::FIXED: { | ||||
706 | auto fixedIn = bug->customField("cf_versionfixedin").toString(); | ||||
707 | if (!fixedIn.isEmpty()) { | ||||
708 | return { i18nc("@info bug resolution, fixed in version", | ||||
709 | "Fixed in version \"%1\"", | ||||
710 | fixedIn), | ||||
711 | i18nc("@info bug resolution, fixed by kde devs in version", | ||||
712 | "the bug was fixed by KDE developers in version \"%1\"", | ||||
713 | fixedIn) | ||||
714 | }; | ||||
715 | } | ||||
716 | return { | ||||
717 | i18nc("@info bug resolution", "Fixed"), | ||||
718 | i18nc("@info bug resolution", "the bug was fixed by KDE developers") | ||||
719 | }; | ||||
720 | } | ||||
721 | | ||||
722 | case Bugzilla::Bug::Resolution::WORKSFORME: | ||||
723 | return { i18nc("@info bug resolution", "Non-reproducible"), QString() }; | ||||
724 | case Bugzilla::Bug::Resolution::DUPLICATE: | ||||
725 | return { i18nc("@info bug resolution", "Duplicate report (Already reported before)"), QString() }; | ||||
726 | case Bugzilla::Bug::Resolution::INVALID: | ||||
727 | return { i18nc("@info bug resolution", "Not a valid report/crash"), QString() }; | ||||
728 | case Bugzilla::Bug::Resolution::UPSTREAM: | ||||
729 | case Bugzilla::Bug::Resolution::DOWNSTREAM: | ||||
730 | return { i18nc("@info bug resolution", "Not caused by a problem in the KDE's Applications or libraries"), | ||||
731 | i18nc("@info bug resolution", "the bug is caused by a problem in an external application or library, or by a distribution or packaging issue") }; | ||||
732 | case Bugzilla::Bug::Resolution::WONTFIX: | ||||
733 | case Bugzilla::Bug::Resolution::LATER: | ||||
734 | case Bugzilla::Bug::Resolution::REMIND: | ||||
735 | case Bugzilla::Bug::Resolution::MOVED: | ||||
736 | case Bugzilla::Bug::Resolution::WAITINGFORINFO: | ||||
737 | case Bugzilla::Bug::Resolution::BACKTRACE: | ||||
738 | case Bugzilla::Bug::Resolution::UNMAINTAINED: | ||||
739 | return { QVariant::fromValue(bug->resolution()).toString(), QString() }; | ||||
740 | case Bugzilla::Bug::Resolution::Unknown: | ||||
741 | Q_UNREACHABLE(); | ||||
742 | } | ||||
743 | Q_UNREACHABLE(); | ||||
744 | return {}; | ||||
745 | | ||||
746 | case Bugzilla::Bug::Status::NEEDSINFO: | ||||
747 | return { i18nc("@info bug status", "Temporarily closed, because of a lack of information"), QString() }; | ||||
748 | | ||||
749 | case Bugzilla::Bug::Status::Unknown: | ||||
750 | Q_UNREACHABLE(); | ||||
751 | | ||||
752 | #warning fixme what to do with this | ||||
753 | // } else { //Fallback to other raw values | ||||
754 | // customStatusString = QStringLiteral("%1 (%2)").arg(report->status(), report->resolution()); | ||||
755 | // } | ||||
756 | } | ||||
757 | Q_UNREACHABLE(); | ||||
758 | return {}; | ||||
759 | } | ||||
760 | | ||||
761 | void BugzillaReportInformationDialog::bugFetchFinished(Bugzilla::Bug::Ptr report, QObject * jobOwner) | ||||
762 | { | ||||
763 | #warning off what the fuck eh jobowner what how why huh? this is killing me | ||||
764 | if (jobOwner != this || !isVisible()) { | ||||
765 | return; | ||||
766 | } | ||||
767 | | ||||
768 | if (!report) { | ||||
769 | bugFetchError(i18nc("@info", "Invalid report information (malformed data). This could " | ||||
770 | "mean that the bug report does not exist, or the bug tracking site " | ||||
771 | "is experiencing a problem."), this); | ||||
772 | return; | ||||
773 | } | ||||
774 | | ||||
657 | 775 | | |||
658 | //Handle duplicate state | 776 | // Handle duplicate state | ||
659 | QString duplicate = report.markedAsDuplicateOf(); | 777 | if (report->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()); | 778 | ui.m_statusWidget->setIdle(QString()); | ||
665 | 779 | | |||
666 | KGuiItem yesItem = KStandardGuiItem::yes(); | 780 | KGuiItem yesItem = KStandardGuiItem::yes(); | ||
667 | yesItem.setText(i18nc("@action:button let the user to choose to read the " | 781 | yesItem.setText(i18nc("@action:button let the user to choose to read the " | ||
668 | "main report", "Yes, read the main report")); | 782 | "main report", "Yes, read the main report")); | ||
669 | 783 | | |||
670 | KGuiItem noItem = KStandardGuiItem::no(); | 784 | KGuiItem noItem = KStandardGuiItem::no(); | ||
671 | noItem.setText(i18nc("@action:button let the user choose to read the original " | 785 | noItem.setText(i18nc("@action:button let the user choose to read the original " | ||
672 | "report", "No, let me read the report I selected")); | 786 | "report", "No, let me read the report I selected")); | ||
673 | 787 | | |||
674 | if (KMessageBox::questionYesNo(this, | 788 | auto ret = KMessageBox::questionYesNo( | ||
789 | this, | ||||
675 | xi18nc("@info","The report you selected (bug %1) is already " | 790 | xi18nc("@info","The report you selected (bug %1) is already " | ||
676 | "marked as duplicate of bug %2. " | 791 | "marked as duplicate of bug %2. " | ||
677 | "Do you want to read that report instead? (recommended)", | 792 | "Do you want to read that report instead? (recommended)", | ||
678 | report.bugNumber(), QString::number(dupId)), | 793 | report->id(), QString::number(report->dupe_of())), | ||
679 | i18nc("@title:window","Nested duplicate detected"), yesItem, noItem) | 794 | i18nc("@title:window","Nested duplicate detected"), | ||
680 | == KMessageBox::Yes) { | 795 | yesItem, | ||
681 | showBugReport(dupId); | 796 | noItem); | ||
797 | if (ret == KMessageBox::Yes) { | ||||
798 | qDebug() << "REDIRECT"; | ||||
799 | showBugReport(report->dupe_of()); | ||||
682 | return; | 800 | return; | ||
683 | } | 801 | } | ||
684 | } | 802 | } | ||
685 | } | | |||
686 | 803 | | |||
687 | //Generate html for comments (with proper numbering) | 804 | // Generate html for comments (with proper numbering) | ||
688 | QLatin1String duplicatesMark = QLatin1String("has been marked as a duplicate of this bug."); | 805 | QLatin1String duplicatesMark = QLatin1String("has been marked as a duplicate of this bug."); | ||
689 | 806 | | |||
690 | QString comments; | 807 | QString comments; | ||
691 | QStringList commentList = report.comments(); | 808 | #warning fixme comments arent very oop | ||
692 | for (int i = 0; i < commentList.count(); i++) { | 809 | QString description; // aka first comment | ||
693 | QString comment = commentList.at(i); | 810 | auto commentsList = report->comments(); | ||
811 | if (commentsList.size() > 0) { | ||||
812 | description = commentsList.takeFirst()->text(); | ||||
813 | } | ||||
814 | for (auto it = commentsList.constBegin(); it != commentsList.constEnd(); ++it) { | ||||
815 | QString comment = (*it)->text(); | ||||
694 | //Don't add duplicates mark comments | 816 | //Don't add duplicates mark comments | ||
695 | if (!comment.contains(duplicatesMark)) { | 817 | if (!comment.contains(duplicatesMark)) { | ||
696 | comment.replace(QLatin1Char('\n'), QLatin1String("<br />")); | 818 | comment.replace(QLatin1Char('\n'), QLatin1String("<br />")); | ||
819 | const int i = it - commentsList.constBegin(); | ||||
697 | comments += i18nc("comment $number to use as subtitle", "<h4>Comment %1:</h4>", (i+1)) | 820 | comments += i18nc("comment $number to use as subtitle", "<h4>Comment %1:</h4>", (i+1)) | ||
698 | + QStringLiteral("<p>") + comment + QStringLiteral("</p><hr />"); | 821 | + QStringLiteral("<p>") + comment + QStringLiteral("</p><hr />"); | ||
699 | //Count the inline attached crashes (DrKonqi feature) | 822 | //Count the inline attached crashes (DrKonqi feature) | ||
700 | QLatin1String attachedCrashMark = | 823 | QLatin1String attachedCrashMark = | ||
701 | QLatin1String("New crash information added by DrKonqi"); | 824 | QLatin1String("New crash information added by DrKonqi"); | ||
702 | if (comment.contains(attachedCrashMark)) { | 825 | if (comment.contains(attachedCrashMark)) { | ||
703 | m_duplicatesCount++; | 826 | m_duplicatesCount++; | ||
704 | } | 827 | } | ||
705 | } else { | 828 | } else { | ||
706 | //Count duplicate | 829 | //Count duplicate | ||
707 | m_duplicatesCount++; | 830 | m_duplicatesCount++; | ||
708 | } | 831 | } | ||
709 | } | 832 | } | ||
710 | 833 | | |||
711 | //Generate a non-geek readable status | 834 | //Generate a non-geek readable status | ||
712 | QString customStatusString; | 835 | auto str = statusString2(report); | ||
713 | BugReport::Status status = report.statusValue(); | 836 | QString customStatusString = str.statusString; | ||
714 | BugReport::Resolution resolution = report.resolutionValue(); | 837 | 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 | 838 | | |||
759 | //Generate notes | 839 | //Generate notes | ||
760 | QString notes = xi18n("<p><note>The bug report's title is often written by its reporter " | 840 | 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 " | 841 | "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 " | 842 | "symptoms you could use to compare to your crash. Please read the " | ||
763 | "complete report and all the comments below.</note></p>"); | 843 | "complete report and all the comments below.</note></p>"); | ||
764 | 844 | | |||
765 | if (m_duplicatesCount >= 10) { //Consider a possible mass duplicate crash | 845 | 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 " | 846 | 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 " | 847 | "is probably a <strong>common crash</strong>. <i>Please consider only " | ||
768 | "adding a comment or a note if you can provide new valuable " | 848 | "adding a comment or a note if you can provide new valuable " | ||
769 | "information which was not already mentioned.</i></note></p>", | 849 | "information which was not already mentioned.</i></note></p>", | ||
770 | "<p><note>This bug report has %1 duplicate reports. That means this " | 850 | "<p><note>This bug report has %1 duplicate reports. That means this " | ||
771 | "is probably a <strong>common crash</strong>. <i>Please consider only " | 851 | "is probably a <strong>common crash</strong>. <i>Please consider only " | ||
772 | "adding a comment or a note if you can provide new valuable " | 852 | "adding a comment or a note if you can provide new valuable " | ||
773 | "information which was not already mentioned.</i></note></p>", | 853 | "information which was not already mentioned.</i></note></p>", | ||
774 | m_duplicatesCount); | 854 | m_duplicatesCount); | ||
775 | } | 855 | } | ||
776 | 856 | | |||
777 | //A manually entered bug ID could represent a normal bug | 857 | //A manually entered bug ID could represent a normal bug | ||
778 | if (report.bugSeverity() != QLatin1String("crash") | 858 | if (report->severity() != QLatin1String("crash") | ||
779 | && report.bugSeverity() != QLatin1String("major") | 859 | && report->severity() != QLatin1String("major") | ||
780 | && report.bugSeverity() != QLatin1String("grave") | 860 | && report->severity() != QLatin1String("grave") | ||
781 | && report.bugSeverity() != QLatin1String("critical")) | 861 | && report->severity() != QLatin1String("critical")) | ||
782 | { | 862 | { | ||
783 | notes += xi18n("<p><note>This bug report is not about a crash or about any other " | 863 | notes += xi18n("<p><note>This bug report is not about a crash or about any other " | ||
784 | "critical bug.</note></p>"); | 864 | "critical bug.</note></p>"); | ||
785 | } | 865 | } | ||
786 | 866 | | |||
787 | //Generate HTML text | 867 | //Generate HTML text | ||
788 | QString text = | 868 | QString text = | ||
789 | i18nc("@info bug report title (quoted)", | 869 | i18nc("@info bug report title (quoted)", | ||
790 | "<h3>\"%1\"</h3>", report.shortDescription()) + | 870 | "<h3>\"%1\"</h3>", report->summary()) + | ||
791 | notes + | 871 | notes + | ||
792 | i18nc("@info bug report status", | 872 | i18nc("@info bug report status", | ||
793 | "<h4>Bug Report Status: %1</h4>", customStatusString) + | 873 | "<h4>Bug Report Status: %1</h4>", customStatusString) + | ||
794 | i18nc("@info bug report product and component", | 874 | i18nc("@info bug report product and component", | ||
795 | "<h4>Affected Component: %1 (%2)</h4>", | 875 | "<h4>Affected Component: %1 (%2)</h4>", | ||
796 | report.product(), report.component()) + | 876 | report->product(), | ||
877 | report->component()) + | ||||
797 | i18nc("@info bug report description", | 878 | i18nc("@info bug report description", | ||
798 | "<h3>Description of the bug</h3><p>%1</p>", | 879 | "<h3>Description of the bug</h3><p>%1</p>", | ||
799 | report.description().replace(QLatin1Char('\n'), QLatin1String("<br />"))); | 880 | description.replace(QLatin1Char('\n'), QLatin1String("<br />"))); | ||
800 | 881 | | |||
801 | if (!comments.isEmpty()) { | 882 | if (!comments.isEmpty()) { | ||
802 | text += i18nc("@label:textbox bug report comments (already formatted)", | 883 | text += i18nc("@label:textbox bug report comments (already formatted)", | ||
803 | "<h2>Additional Comments</h2>%1", comments); | 884 | "<h2>Additional Comments</h2>%1", comments); | ||
804 | } | 885 | } | ||
805 | 886 | | |||
806 | ui.m_infoBrowser->setText(text); | 887 | ui.m_infoBrowser->setText(text); | ||
807 | ui.m_infoBrowser->setEnabled(true); | 888 | ui.m_infoBrowser->setEnabled(true); | ||
808 | 889 | | |||
809 | m_suggestButton->setEnabled(m_relatedButtonEnabled); | 890 | m_suggestButton->setEnabled(m_relatedButtonEnabled); | ||
810 | m_suggestButton->setVisible(m_relatedButtonEnabled); | 891 | m_suggestButton->setVisible(m_relatedButtonEnabled); | ||
811 | 892 | | |||
812 | ui.m_statusWidget->setIdle(xi18nc("@info:status", "Showing bug %1", | 893 | ui.m_statusWidget->setIdle(xi18nc("@info:status", "Showing bug %1", | ||
813 | QString::number(report.bugNumberAsInt()))); | 894 | QString::number(report->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 | } | 895 | } | ||
821 | 896 | | |||
822 | void BugzillaReportInformationDialog::markAsDuplicate() | 897 | void BugzillaReportInformationDialog::markAsDuplicate() | ||
823 | { | 898 | { | ||
824 | emit possibleDuplicateSelected(m_bugNumber); | 899 | emit possibleDuplicateSelected(m_bugNumber); | ||
825 | hide(); | 900 | hide(); | ||
826 | } | 901 | } | ||
827 | 902 | | |||
▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines |