Fixed #1862 (GUI: Allow user to tag errors)

This commit is contained in:
Daniel Marjamäki 2017-08-02 22:28:45 +02:00
parent 39955973e9
commit 952c31638c
6 changed files with 96 additions and 21 deletions

View File

@ -125,6 +125,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
connect(mUI.mResults, &ResultsView::gotResults, this, &MainWindow::resultsAdded); connect(mUI.mResults, &ResultsView::gotResults, this, &MainWindow::resultsAdded);
connect(mUI.mResults, &ResultsView::resultsHidden, mUI.mActionShowHidden, &QAction::setEnabled); connect(mUI.mResults, &ResultsView::resultsHidden, mUI.mActionShowHidden, &QAction::setEnabled);
connect(mUI.mResults, &ResultsView::checkSelected, this, &MainWindow::performSelectedFilesCheck); connect(mUI.mResults, &ResultsView::checkSelected, this, &MainWindow::performSelectedFilesCheck);
connect(mUI.mResults, &ResultsView::tagged, this, &MainWindow::tagged);
connect(mUI.mMenuView, &QMenu::aboutToShow, this, &MainWindow::aboutToShowViewMenu); connect(mUI.mMenuView, &QMenu::aboutToShow, this, &MainWindow::aboutToShowViewMenu);
// File menu // File menu
@ -1279,12 +1280,9 @@ void MainWindow::stopAnalysis()
{ {
mThread->stop(); mThread->stop();
mUI.mResults->disableProgressbar(); mUI.mResults->disableProgressbar();
if (mProjectFile && !mProjectFile->getBuildDir().isEmpty()) { const QString &lastResults = getLastResults();
const QString prjpath = QFileInfo(mProjectFile->getFilename()).absolutePath(); if (!lastResults.isEmpty()) {
const QString buildDir = prjpath + '/' + mProjectFile->getBuildDir(); mUI.mResults->updateFromOldReport(lastResults);
if (QDir(buildDir).exists()) {
mUI.mResults->updateFromOldReport(buildDir + "/lastResults.xml");
}
} }
} }
@ -1343,14 +1341,18 @@ void MainWindow::loadProjectFile(const QString &filePath)
analyzeProject(mProjectFile); analyzeProject(mProjectFile);
} }
QString MainWindow::getLastResults() const
{
if (!mProjectFile || mProjectFile->getBuildDir().isEmpty())
return QString();
return QFileInfo(mProjectFile->getFilename()).absolutePath() + '/' + mProjectFile->getBuildDir() + "/lastResults.xml";
}
bool MainWindow::loadLastResults() bool MainWindow::loadLastResults()
{ {
if (!mProjectFile) const QString &lastResults = getLastResults();
if (lastResults.isEmpty())
return false; return false;
if (mProjectFile->getBuildDir().isEmpty())
return false;
const QString buildDir = QFileInfo(mProjectFile->getFilename()).absolutePath() + '/' + mProjectFile->getBuildDir();
const QString lastResults = buildDir + "/lastResults.xml";
if (!QFileInfo(lastResults).exists()) if (!QFileInfo(lastResults).exists())
return false; return false;
mUI.mResults->readErrorsXml(lastResults); mUI.mResults->readErrorsXml(lastResults);
@ -1631,3 +1633,10 @@ void MainWindow::selectPlatform()
mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform); mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform);
} }
} }
void MainWindow::tagged()
{
const QString &lastResults = getLastResults();
if (!lastResults.isEmpty())
mUI.mResults->save(lastResults, Report::XMLV2);
}

View File

@ -221,8 +221,14 @@ protected slots:
/** @brief Selects the platform as analyzed platform. */ /** @brief Selects the platform as analyzed platform. */
void selectPlatform(); void selectPlatform();
/** Some results were tagged */
void tagged();
private: private:
/** Get filename for last results */
QString getLastResults() const;
/** @brief Reanalyzes files */ /** @brief Reanalyzes files */
void reAnalyze(bool all); void reAnalyze(bool all);

View File

@ -184,6 +184,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
data["id"] = item.errorId; data["id"] = item.errorId;
data["inconclusive"] = item.inconclusive; data["inconclusive"] = item.inconclusive;
data["file0"] = stripPath(item.file0, true); data["file0"] = stripPath(item.file0, true);
data["sinceDate"] = item.sinceDate;
data["tag"] = item.tag;
stditem->setData(QVariant(data)); stditem->setData(QVariant(data));
//Add backtrace files as children //Add backtrace files as children
@ -246,13 +248,13 @@ QStandardItem *ResultsTree::addBacktraceFiles(QStandardItem *parent,
list << createNormalItem(""); list << createNormalItem("");
break; break;
case ErrorItem::FP: case ErrorItem::FP:
list << createNormalItem("fp"); list << createNormalItem(tr("False positive"));
break; break;
case ErrorItem::IGNORE: case ErrorItem::IGNORE:
list << createNormalItem("ignore"); list << createNormalItem(tr("Ignore"));
break; break;
case ErrorItem::BUG: case ErrorItem::BUG:
list << createNormalItem("bug"); list << createNormalItem(tr("bug"));
break; break;
}; };
//TODO message has parameter names so we'll need changes to the core //TODO message has parameter names so we'll need changes to the core
@ -629,6 +631,17 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
connect(hide, SIGNAL(triggered()), this, SLOT(hideResult())); connect(hide, SIGNAL(triggered()), this, SLOT(hideResult()));
connect(hideallid, SIGNAL(triggered()), this, SLOT(hideAllIdResult())); connect(hideallid, SIGNAL(triggered()), this, SLOT(hideAllIdResult()));
connect(opencontainingfolder, SIGNAL(triggered()), this, SLOT(openContainingFolder())); connect(opencontainingfolder, SIGNAL(triggered()), this, SLOT(openContainingFolder()));
menu.addSeparator();
QAction *fp = new QAction(tr("False positive"), &menu);
QAction *ignore = new QAction(tr("Ignore"), &menu);
QAction *bug = new QAction(tr("Bug"), &menu);
menu.addAction(fp);
menu.addAction(ignore);
menu.addAction(bug);
connect(fp, &QAction::triggered, this, &ResultsTree::tagFP);
connect(ignore, &QAction::triggered, this, &ResultsTree::tagIgnore);
connect(bug, &QAction::triggered, this, &ResultsTree::tagBug);
} }
//Start the menu //Start the menu
@ -929,6 +942,41 @@ void ResultsTree::openContainingFolder()
} }
} }
void ResultsTree::tagSelectedItems(int tagNumber, const QString &tag)
{
if (!mSelectionModel)
return;
bool isTagged = false;
foreach (QModelIndex index, mSelectionModel->selectedRows()) {
QStandardItem *item = mModel.itemFromIndex(index);
QVariantMap data = item->data().toMap();
if (data.contains("tag")) {
data["tag"] = tagNumber;
item->setData(QVariant(data));
item->parent()->child(index.row(), COLUMN_TAG)->setText(tag);
isTagged = true;
}
}
if (isTagged)
emit tagged();
}
void ResultsTree::tagFP(bool)
{
tagSelectedItems(ErrorItem::FP, tr("False positive"));
}
void ResultsTree::tagIgnore(bool)
{
tagSelectedItems(ErrorItem::IGNORE, tr("Ignore"));
}
void ResultsTree::tagBug(bool)
{
tagSelectedItems(ErrorItem::BUG, tr("Bug"));
}
void ResultsTree::context(int application) void ResultsTree::context(int application)
{ {
startApplication(mContextItem, application); startApplication(mContextItem, application);
@ -1097,13 +1145,7 @@ void ResultsTree::readErrorItem(const QStandardItem *error, ErrorItem *item) con
item->inconclusive = data["inconclusive"].toBool(); item->inconclusive = data["inconclusive"].toBool();
item->file0 = data["file0"].toString(); item->file0 = data["file0"].toString();
item->sinceDate = data["sinceDate"].toString(); item->sinceDate = data["sinceDate"].toString();
QString tag = data["tag"].toString(); item->tag = (ErrorItem::Tag)data["tag"].toInt();
if (tag == "fp")
item->tag = ErrorItem::FP;
else if (tag == "ignore")
item->tag = ErrorItem::IGNORE;
else if (tag == "bug")
item->tag = ErrorItem::BUG;
if (error->rowCount() == 0) { if (error->rowCount() == 0) {
QErrorPathItem e; QErrorPathItem e;

View File

@ -205,6 +205,11 @@ signals:
*/ */
void selectionChanged(const QModelIndex &current); void selectionChanged(const QModelIndex &current);
/**
* Selected item(s) has been tagged
*/
void tagged();
protected slots: protected slots:
/** /**
* @brief Slot to quickstart an error with default application * @brief Slot to quickstart an error with default application
@ -275,6 +280,10 @@ protected slots:
*/ */
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous); virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous);
void tagFP(bool);
void tagIgnore(bool);
void tagBug(bool);
protected: protected:
/** /**
@ -503,6 +512,9 @@ protected:
bool mVisibleErrors; bool mVisibleErrors;
private: private:
/** tag selected items */
void tagSelectedItems(int tagNumber, const QString &tag);
/** @brief Convert GUI error item into data error item */ /** @brief Convert GUI error item into data error item */
void readErrorItem(const QStandardItem *error, ErrorItem *item) const; void readErrorItem(const QStandardItem *error, ErrorItem *item) const;

View File

@ -51,6 +51,7 @@ ResultsView::ResultsView(QWidget * parent) :
connect(mUI.mTree, &ResultsTree::resultsHidden, this, &ResultsView::resultsHidden); connect(mUI.mTree, &ResultsTree::resultsHidden, this, &ResultsView::resultsHidden);
connect(mUI.mTree, &ResultsTree::checkSelected, this, &ResultsView::checkSelected); connect(mUI.mTree, &ResultsTree::checkSelected, this, &ResultsView::checkSelected);
connect(mUI.mTree, &ResultsTree::selectionChanged, this, &ResultsView::updateDetails); connect(mUI.mTree, &ResultsTree::selectionChanged, this, &ResultsView::updateDetails);
connect(mUI.mTree, &ResultsTree::tagged, this, &ResultsView::tagged);
} }
void ResultsView::initialize(QSettings *settings, ApplicationList *list, ThreadHandler *checkThreadHandler) void ResultsView::initialize(QSettings *settings, ApplicationList *list, ThreadHandler *checkThreadHandler)

View File

@ -213,6 +213,11 @@ signals:
*/ */
void checkSelected(QStringList selectedFilesList); void checkSelected(QStringList selectedFilesList);
/**
* Some results have been tagged
*/
void tagged();
public slots: public slots:
/** /**