diff --git a/gui/erroritem.cpp b/gui/erroritem.cpp
index 2d7aa1c0bbe..ca9e8475b97 100644
--- a/gui/erroritem.cpp
+++ b/gui/erroritem.cpp
@@ -70,21 +70,22 @@ QString ErrorItem::tool() const
QString ErrorItem::toString() const
{
- QString str = errorPath.back().file + " - " + errorId + " - ";
+ const int i = getMainLocIndex();
+ QString ret = errorPath[i].file + ":" + QString::number(errorPath[i].line) + ":" + QString::number(errorPath[i].column) + ":";
+ ret += GuiSeverity::toString(severity);
if (inconclusive)
- str += "inconclusive ";
- str += GuiSeverity::toString(severity) +"\n";
- str += summary + "\n";
- str += message + "\n";
- for (const QErrorPathItem& i : errorPath) {
- str += " " + i.file + ": " + QString::number(i.line) + "\n";
+ ret += ",inconclusive";
+ ret += ": " + summary + " [" + errorId + "]";
+ if (errorPath.size() >= 2) {
+ for (const auto& e: errorPath)
+ ret += "\n" + e.file + ":" + QString::number(e.line) + ":" + QString::number(e.column) + ":note: " + e.info;
}
- return str;
+ return ret;
}
-bool ErrorItem::sameCID(const ErrorItem &errorItem1, const ErrorItem &errorItem2)
+bool ErrorItem::same(const ErrorItem &errorItem1, const ErrorItem &errorItem2)
{
- if (errorItem1.hash || errorItem2.hash)
+ if (errorItem1.hash && errorItem2.hash)
return errorItem1.hash == errorItem2.hash;
// fallback
@@ -95,3 +96,19 @@ bool ErrorItem::sameCID(const ErrorItem &errorItem1, const ErrorItem &errorItem2
errorItem1.inconclusive == errorItem2.inconclusive &&
errorItem1.severity == errorItem2.severity;
}
+
+bool ErrorItem::filterMatch(const QString& filter) const
+{
+ if (filter.isEmpty())
+ return true;
+ if (summary.contains(filter, Qt::CaseInsensitive) ||
+ message.contains(filter, Qt::CaseInsensitive) ||
+ errorId.contains(filter, Qt::CaseInsensitive) ||
+ classification.contains(filter, Qt::CaseInsensitive))
+ return true;
+ return std::any_of(errorPath.cbegin(), errorPath.cend(),
+ [filter](const auto& e) {
+ return e.file.contains(filter, Qt::CaseInsensitive) ||
+ e.info.contains(filter, Qt::CaseInsensitive);
+ });
+}
diff --git a/gui/erroritem.h b/gui/erroritem.h
index dfd48fbadfd..a95d9eb2204 100644
--- a/gui/erroritem.h
+++ b/gui/erroritem.h
@@ -81,6 +81,20 @@ class ErrorItem {
QString toString() const;
QString tool() const;
+ int getMainLocIndex() const {
+ return isClangResult() ? 0 : errorPath.size() - 1;
+ }
+
+ QString getFile() const {
+ return errorPath.isEmpty() ? QString() : errorPath[getMainLocIndex()].file;
+ }
+
+ bool isClangResult() const {
+ return errorId.startsWith("clang");
+ }
+
+ bool filterMatch(const QString& filter) const;
+
QString file0;
QString errorId;
Severity severity;
@@ -100,33 +114,9 @@ class ErrorItem {
QString tags;
/**
- * Compare "CID"
+ * Compare Hash and fields
*/
- static bool sameCID(const ErrorItem &errorItem1, const ErrorItem &errorItem2);
+ static bool same(const ErrorItem &errorItem1, const ErrorItem &errorItem2);
};
-
-// NOLINTNEXTLINE(performance-no-int-to-ptr)
-Q_DECLARE_METATYPE(ErrorItem)
-
-/**
- * @brief A class containing error data for one shown error line.
- */
-class ErrorLine {
-public:
- QString file;
- int line;
- QString file0;
- QString errorId;
- int cwe;
- unsigned long long hash;
- bool inconclusive;
- Severity severity;
- QString summary;
- QString message;
- QString sinceDate;
- QString tags;
- QString remark;
-};
-
/// @}
#endif // ERRORITEM_H
diff --git a/gui/resultitem.cpp b/gui/resultitem.cpp
new file mode 100644
index 00000000000..b68830b90ba
--- /dev/null
+++ b/gui/resultitem.cpp
@@ -0,0 +1,23 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2025 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "resultitem.h"
+
+ResultItem::ResultItem(QSharedPointer errorItem, Type type, int errorPathIndex)
+ : errorItem(std::move(errorItem)), mType(type), mErrorPathIndex(errorPathIndex)
+{}
diff --git a/gui/resultitem.h b/gui/resultitem.h
new file mode 100644
index 00000000000..a7669d2a3b4
--- /dev/null
+++ b/gui/resultitem.h
@@ -0,0 +1,49 @@
+/* -*- C++ -*-
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2025 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef RESULTITEM_H
+#define RESULTITEM_H
+
+#include "erroritem.h"
+#include
+#include
+
+class ResultItem : public QStandardItem
+{
+public:
+ enum class Type: std::uint8_t {file, message, note};
+
+ ResultItem(QSharedPointer errorItem, Type type, int errorPathIndex);
+ QSharedPointer errorItem;
+ bool hidden{};
+
+ QErrorPathItem getErrorPathItem() const {
+ if (!errorItem || mErrorPathIndex < 0 || mErrorPathIndex >= errorItem->errorPath.size())
+ return {};
+ return errorItem->errorPath[mErrorPathIndex];
+ }
+
+ Type getType() const {
+ return mType;
+ }
+private:
+ const Type mType;
+ const int mErrorPathIndex;
+};
+
+#endif // RESULTITEM_H
diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp
index e5e2ff9ead2..12191b05cbd 100644
--- a/gui/resultstree.cpp
+++ b/gui/resultstree.cpp
@@ -28,6 +28,7 @@
#include "path.h"
#include "projectfile.h"
#include "report.h"
+#include "resultitem.h"
#include "showtypes.h"
#include "suppressions.h"
#include "threadhandler.h"
@@ -59,31 +60,11 @@
#include
#include
#include
-#include
#include
#include
-#include
-#include
#include
#include
-static constexpr char COLUMN[] = "column";
-static constexpr char CWE[] = "cwe";
-static constexpr char ERRORID[] = "id";
-static constexpr char FILENAME[] = "file";
-static constexpr char FILE0[] = "file0";
-static constexpr char HASH[] = "hash";
-static constexpr char HIDE[] = "hide";
-static constexpr char INCONCLUSIVE[] = "inconclusive";
-static constexpr char LINE[] = "line";
-static constexpr char MESSAGE[] = "message";
-static constexpr char REMARK[] = "remark";
-static constexpr char SEVERITY[] = "severity";
-static constexpr char SINCEDATE[] = "sinceDate";
-static constexpr char SYMBOLNAMES[] = "symbolNames";
-static constexpr char SUMMARY[] = "summary";
-static constexpr char TAGS[] = "tags";
-
// These must match column headers given in ResultsTree::translate()
static constexpr int COLUMN_FILE = 0;
static constexpr int COLUMN_LINE = 1;
@@ -172,19 +153,17 @@ void ResultsTree::setReportType(ReportType reportType) {
mGuideline = createGuidelineMapping(reportType);
for (int i = 0; i < mModel->rowCount(); ++i) {
- const QStandardItem *fileItem = mModel->item(i, COLUMN_FILE);
+ auto *fileItem = dynamic_cast(mModel->item(i, COLUMN_FILE));
if (!fileItem)
continue;
for (int j = 0; j < fileItem->rowCount(); ++j) {
- const auto& childdata = fileItem->child(j,0)->data().toMap();
- const QString& errorId = childdata[ERRORID].toString();
- Severity severity = ShowTypes::ShowTypeToSeverity(ShowTypes::VariantToShowType(childdata[SEVERITY]));
- const QString& guideline = getGuideline(mReportType, mGuideline, errorId, severity);
- const QString& classification = getClassification(mReportType, guideline);
- fileItem->child(j, COLUMN_CERT_LEVEL)->setText(classification);
- fileItem->child(j, COLUMN_CERT_RULE)->setText(guideline);
- fileItem->child(j, COLUMN_MISRA_CLASSIFICATION)->setText(classification);
- fileItem->child(j, COLUMN_MISRA_GUIDELINE)->setText(guideline);
+ QSharedPointer& errorItem = dynamic_cast(fileItem->child(j,0))->errorItem;
+ errorItem->guideline = getGuideline(mReportType, mGuideline, errorItem->errorId, errorItem->severity);
+ errorItem->classification = getClassification(mReportType, errorItem->guideline);
+ fileItem->child(j, COLUMN_CERT_LEVEL)->setText(errorItem->classification);
+ fileItem->child(j, COLUMN_CERT_RULE)->setText(errorItem->guideline);
+ fileItem->child(j, COLUMN_MISRA_CLASSIFICATION)->setText(errorItem->classification);
+ fileItem->child(j, COLUMN_MISRA_GUIDELINE)->setText(errorItem->guideline);
}
}
@@ -221,163 +200,93 @@ void ResultsTree::initialize(QSettings *settings, ApplicationList *list, ThreadH
loadSettings();
}
+ResultItem *ResultsTree::createNormalItem(const QString &text, QSharedPointer errorItem, ResultItem::Type type, int errorPathIndex)
+{
+ auto *item = new ResultItem(std::move(errorItem), type, errorPathIndex);
+ item->setText(text);
+ item->setEditable(false);
+ return item;
+}
-QStandardItem *ResultsTree::createNormalItem(const QString &name)
+ResultItem *ResultsTree::createFilenameItem(const QSharedPointer& errorItem, ResultItem::Type type, int errorPathIndex)
{
- auto *item = new QStandardItem(name);
- item->setData(name, Qt::ToolTipRole);
+ auto *item = new ResultItem(errorItem, type, errorPathIndex);
+ item->setText(QDir::toNativeSeparators(stripPath(errorItem->errorPath[errorPathIndex].file, false)));
item->setEditable(false);
return item;
}
-QStandardItem *ResultsTree::createCheckboxItem(bool checked)
+ResultItem *ResultsTree::createCheckboxItem(bool checked, QSharedPointer errorItem, ResultItem::Type type, int errorPathIndex)
{
- auto *item = new QStandardItem;
+ auto *item = new ResultItem(std::move(errorItem), type, errorPathIndex);
item->setCheckable(true);
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
item->setEnabled(false);
return item;
}
-QStandardItem *ResultsTree::createLineNumberItem(const QString &linenumber)
+ResultItem *ResultsTree::createLineNumberItem(int linenumber, QSharedPointer errorItem, ResultItem::Type type, int errorPathIndex)
{
- auto *item = new QStandardItem();
- item->setData(QVariant(linenumber.toInt()), Qt::DisplayRole);
- item->setToolTip(linenumber);
+ auto *item = new ResultItem(std::move(errorItem), type, errorPathIndex);
+ item->setText(QString::number(linenumber));
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
item->setEditable(false);
return item;
}
-bool ResultsTree::addErrorItem(const ErrorItem &item)
+bool ResultsTree::addErrorItem(const ErrorItem& errorItem)
{
- if (item.errorPath.isEmpty()) {
+ if (errorItem.errorPath.isEmpty())
return false;
- }
-
- const QErrorPathItem &loc = item.errorId.startsWith("clang") ? item.errorPath.front() : item.errorPath.back();
- QString realfile = stripPath(loc.file, false);
- if (realfile.isEmpty()) {
- realfile = tr("Undefined file");
- }
-
- bool showItem = true;
+ QSharedPointer errorItemPtr{new ErrorItem(errorItem)};
- // Ids that are temporarily hidden..
- if (mHiddenMessageId.contains(item.errorId))
- showItem = false;
-
- //If specified, filter on summary, message, filename, and id
- if (showItem && !mFilter.isEmpty()) {
- if (!item.summary.contains(mFilter, Qt::CaseInsensitive) &&
- !item.message.contains(mFilter, Qt::CaseInsensitive) &&
- !item.errorPath.back().file.contains(mFilter, Qt::CaseInsensitive) &&
- !item.errorId.contains(mFilter, Qt::CaseInsensitive)) {
- showItem = false;
- }
+ if (mReportType != ReportType::normal) {
+ errorItemPtr->guideline = getGuideline(mReportType, mGuideline, errorItemPtr->errorId, errorItemPtr->severity);
+ errorItemPtr->classification = getClassification(mReportType, errorItemPtr->guideline);
}
- if (showItem) {
- if (mReportType == ReportType::normal)
- showItem = mShowSeverities.isShown(item.severity);
- else {
- const QString& guideline = getGuideline(mReportType, mGuideline, item.errorId, item.severity);
- const QString& classification = getClassification(mReportType, guideline);
- showItem = !classification.isEmpty() && mShowSeverities.isShown(getSeverityFromClassification(classification));
- }
- }
+ const bool showItem = !isErrorItemHidden(errorItemPtr);
// if there is at least one error that is not hidden, we have a visible error
mVisibleErrors |= showItem;
- ErrorLine line;
- line.file = realfile;
- line.line = loc.line;
- line.errorId = item.errorId;
- line.cwe = item.cwe;
- line.hash = item.hash;
- line.inconclusive = item.inconclusive;
- line.summary = item.summary;
- line.message = item.message;
- line.severity = item.severity;
- line.sinceDate = item.sinceDate;
- if (const ProjectFile *activeProject = ProjectFile::getActiveProject()) {
- line.tags = activeProject->getWarningTags(item.hash);
- }
- line.remark = item.remark;
+ if (const ProjectFile *activeProject = ProjectFile::getActiveProject())
+ errorItemPtr->tags = activeProject->getWarningTags(errorItemPtr->hash);
//Create the base item for the error and ensure it has a proper
//file item as a parent
- QStandardItem* fileItem = ensureFileItem(loc.file, item.file0, !showItem);
- QStandardItem* stditem = addBacktraceFiles(fileItem,
- line,
- !showItem,
- severityToIcon(line.severity),
- false);
+ ResultItem* fileItem = ensureFileItem(errorItemPtr, !showItem);
+ ResultItem* stditem = addBacktraceFiles(fileItem,
+ errorItemPtr,
+ !showItem,
+ severityToIcon(errorItemPtr->severity),
+ ResultItem::Type::message,
+ errorItemPtr->getMainLocIndex());
if (!stditem)
return false;
- //Add user data to that item
- QMap itemdata;
- itemdata[SEVERITY] = ShowTypes::SeverityToShowType(item.severity);
- itemdata[SUMMARY] = item.summary;
- itemdata[MESSAGE] = item.message;
- itemdata[FILENAME] = loc.file;
- itemdata[LINE] = loc.line;
- itemdata[COLUMN] = loc.column;
- itemdata[ERRORID] = item.errorId;
- itemdata[CWE] = item.cwe;
- itemdata[HASH] = item.hash;
- itemdata[INCONCLUSIVE] = item.inconclusive;
- itemdata[FILE0] = stripPath(item.file0, true);
- itemdata[SINCEDATE] = item.sinceDate;
- itemdata[SYMBOLNAMES] = item.symbolNames;
- itemdata[TAGS] = line.tags;
- itemdata[REMARK] = line.remark;
- itemdata[HIDE] = false;
- stditem->setData(QVariant(itemdata));
-
//Add backtrace files as children
- if (item.errorPath.size() > 1) {
- for (int i = 0; i < item.errorPath.size(); i++) {
- const QErrorPathItem &e = item.errorPath[i];
- line.file = e.file;
- line.line = e.line;
- line.message = line.summary = e.info;
- QStandardItem *child_item = addBacktraceFiles(stditem,
- line,
- false,
- ":images/go-down.png",
- true);
- if (!child_item)
- continue;
-
- // Add user data to that item
- QMap child_data;
- child_data[SEVERITY] = ShowTypes::SeverityToShowType(line.severity);
- child_data[SUMMARY] = line.summary;
- child_data[MESSAGE] = line.message;
- child_data[FILENAME] = e.file;
- child_data[LINE] = e.line;
- child_data[COLUMN] = e.column;
- child_data[ERRORID] = line.errorId;
- child_data[CWE] = line.cwe;
- child_data[HASH] = line.hash;
- child_data[INCONCLUSIVE] = line.inconclusive;
- child_data[SYMBOLNAMES] = item.symbolNames;
- child_item->setData(QVariant(child_data));
+ if (errorItemPtr->errorPath.size() > 1) {
+ for (int i = 0; i < errorItemPtr->errorPath.size(); i++) {
+ addBacktraceFiles(stditem,
+ errorItemPtr,
+ false,
+ ":images/go-down.png",
+ ResultItem::Type::note,
+ i);
}
}
return true;
}
-QStandardItem *ResultsTree::addBacktraceFiles(QStandardItem *parent,
- const ErrorLine &item,
- const bool hide,
- const QString &icon,
- bool childOfMessage)
+ResultItem *ResultsTree::addBacktraceFiles(ResultItem *parent,
+ const QSharedPointer& errorItem,
+ const bool hide,
+ const QString &icon,
+ ResultItem::Type type,
+ int errorPathIndex)
{
if (!parent)
return nullptr;
@@ -385,56 +294,52 @@ QStandardItem *ResultsTree::addBacktraceFiles(QStandardItem *parent,
//TODO message has parameter names so we'll need changes to the core
//cppcheck so we can get proper translations
- const QString itemSeverity = childOfMessage ? tr("note") : severityToTranslatedString(item.severity);
+ const bool childOfMessage = (type == ResultItem::Type::note);
+ const QString itemSeverity = childOfMessage ? tr("note") : severityToTranslatedString(errorItem->severity);
+
+ const auto& loc = errorItem->errorPath[errorPathIndex];
// Check for duplicate rows and don't add them if found
- for (int i = 0; i < parent->rowCount(); i++) {
+ for (int i = 0; i < errorPathIndex; i++) {
// The first column is the file name and is always the same
-
- // the third column is the line number so check it first
- if (parent->child(i, COLUMN_LINE)->text() == QString::number(item.line)) {
- // the second column is the severity so check it next
- if (parent->child(i, COLUMN_SEVERITY)->text() == itemSeverity) {
- // the sixth column is the summary so check it last
- if (parent->child(i, COLUMN_SUMMARY)->text() == item.summary) {
- // this row matches so don't add it
- return nullptr;
- }
- }
- }
+ const auto& e = errorItem->errorPath[i];
+ if (loc.line == e.line && loc.info == e.info)
+ return nullptr;
}
- QMap columns;
- const QString guideline = getGuideline(mReportType, mGuideline, item.errorId, item.severity);
- const QString classification = getClassification(mReportType, guideline);
- columns[COLUMN_CERT_LEVEL] = createNormalItem(classification);
- columns[COLUMN_CERT_RULE] = createNormalItem(guideline);
- columns[COLUMN_CWE] = createNormalItem(item.cwe > 0 ? QString::number(item.cwe) : QString());
- columns[COLUMN_FILE] = createNormalItem(QDir::toNativeSeparators(item.file));
- columns[COLUMN_ID] = createNormalItem(childOfMessage ? QString() : item.errorId);
- columns[COLUMN_INCONCLUSIVE] = childOfMessage ? createNormalItem(QString()) : createCheckboxItem(item.inconclusive);
- columns[COLUMN_LINE] = createLineNumberItem(QString::number(item.line));
- columns[COLUMN_MISRA_CLASSIFICATION] = createNormalItem(classification);
- columns[COLUMN_MISRA_GUIDELINE] = createNormalItem(guideline);
- columns[COLUMN_SEVERITY] = createNormalItem(itemSeverity);
- columns[COLUMN_SINCE_DATE] = createNormalItem(item.sinceDate);
- columns[COLUMN_SUMMARY] = createNormalItem(item.summary);
- columns[COLUMN_TAGS] = createNormalItem(item.tags);
+ const QString text = childOfMessage ? loc.info : errorItem->summary;
const int numberOfColumns = getLabels().size();
+ QList columns(numberOfColumns);
+ columns[COLUMN_FILE] = createFilenameItem(errorItem, type, errorPathIndex);
+ columns[COLUMN_LINE] = createLineNumberItem(loc.line, errorItem, type, errorPathIndex);
+ columns[COLUMN_SEVERITY] = createNormalItem(itemSeverity, errorItem, type, errorPathIndex);
+ columns[COLUMN_SUMMARY] = createNormalItem(text, errorItem, type, errorPathIndex);
+ if (type == ResultItem::Type::message) {
+ columns[COLUMN_CERT_LEVEL] = createNormalItem(errorItem->classification, errorItem, type, errorPathIndex);
+ columns[COLUMN_CERT_RULE] = createNormalItem(errorItem->guideline, errorItem, type, errorPathIndex);
+ columns[COLUMN_CWE] = createNormalItem(errorItem->cwe > 0 ? QString::number(errorItem->cwe) : QString(), errorItem, type, errorPathIndex);
+ columns[COLUMN_ID] = createNormalItem(errorItem->errorId, errorItem, type, errorPathIndex);
+ columns[COLUMN_INCONCLUSIVE] = createCheckboxItem(errorItem->inconclusive, errorItem, type, errorPathIndex);
+ columns[COLUMN_MISRA_CLASSIFICATION] = createNormalItem(errorItem->classification, errorItem, type, errorPathIndex);
+ columns[COLUMN_MISRA_GUIDELINE] = createNormalItem(errorItem->guideline, errorItem, type, errorPathIndex);
+ columns[COLUMN_SINCE_DATE] = createNormalItem(errorItem->sinceDate, errorItem, type, errorPathIndex);
+ columns[COLUMN_TAGS] = createNormalItem(errorItem->tags, errorItem, type, errorPathIndex);
+ }
+
QList list;
for (int i = 0; i < numberOfColumns; ++i)
- list << columns[i];
+ list << (columns[i] ? columns[i] : createNormalItem(QString(), errorItem, type, errorPathIndex));
parent->appendRow(list);
setRowHidden(parent->rowCount() - 1, parent->index(), hide);
if (!icon.isEmpty()) {
- list[0]->setIcon(QIcon(icon));
+ list[COLUMN_FILE]->setIcon(QIcon(icon));
}
- return list[0];
+ return columns[COLUMN_FILE];
}
QString ResultsTree::severityToTranslatedString(Severity severity)
@@ -470,7 +375,7 @@ QString ResultsTree::severityToTranslatedString(Severity severity)
}
}
-QStandardItem *ResultsTree::findFileItem(const QString &name) const
+ResultItem *ResultsTree::findFileItem(const QString &name) const
{
// The first column contains the file name. In Windows we can get filenames
// "header.h" and "Header.h" and must compare them as identical.
@@ -481,7 +386,7 @@ QStandardItem *ResultsTree::findFileItem(const QString &name) const
#else
if (mModel->item(i, COLUMN_FILE)->text() == name)
#endif
- return mModel->item(i, COLUMN_FILE);
+ return dynamic_cast(mModel->item(i, COLUMN_FILE));
}
return nullptr;
}
@@ -504,16 +409,15 @@ void ResultsTree::clear()
void ResultsTree::clear(const QString &filename)
{
- const QString stripped = stripPath(filename, false);
+ const QString stripped = QDir::toNativeSeparators(stripPath(filename, false));
for (int i = 0; i < mModel->rowCount(); ++i) {
- const QStandardItem *fileItem = mModel->item(i, COLUMN_FILE);
+ const auto *fileItem = dynamic_cast(mModel->item(i, COLUMN_FILE));
if (!fileItem)
continue;
- QVariantMap fitemdata = fileItem->data().toMap();
- if (stripped == fitemdata[FILENAME].toString() ||
- filename == fitemdata[FILE0].toString()) {
+ if (stripped == fileItem->text() ||
+ filename == fileItem->errorItem->file0) {
mModel->removeRow(i);
break;
}
@@ -523,13 +427,12 @@ void ResultsTree::clear(const QString &filename)
void ResultsTree::clearRecheckFile(const QString &filename)
{
for (int i = 0; i < mModel->rowCount(); ++i) {
- const QStandardItem *fileItem = mModel->item(i, COLUMN_FILE);
+ const auto *fileItem = dynamic_cast(mModel->item(i, COLUMN_FILE));
if (!fileItem)
continue;
QString actualfile((!mCheckPath.isEmpty() && filename.startsWith(mCheckPath)) ? filename.mid(mCheckPath.length() + 1) : filename);
- QVariantMap fitemdata = fileItem->data().toMap();
- QString storedfile = fitemdata[FILENAME].toString();
+ QString storedfile = fileItem->getErrorPathItem().file;
storedfile = ((!mCheckPath.isEmpty() && storedfile.startsWith(mCheckPath)) ? storedfile.mid(mCheckPath.length() + 1) : storedfile);
if (actualfile == storedfile) {
mModel->removeRow(i);
@@ -605,7 +508,7 @@ void ResultsTree::refreshTree()
for (int i = 0; i < filecount; i++) {
//Get file i
- QStandardItem *fileItem = mModel->item(i, 0);
+ auto *fileItem = dynamic_cast(mModel->item(i, 0));
if (!fileItem) {
continue;
}
@@ -618,44 +521,13 @@ void ResultsTree::refreshTree()
for (int j = 0; j < errorcount; j++) {
//Get the error itself
- QStandardItem *child = fileItem->child(j, 0);
+ const auto *child = dynamic_cast(fileItem->child(j, 0));
if (!child) {
continue;
}
- //Get error's user data and convert it to QVariantMap
- QVariantMap userdata = child->data().toMap();
-
//Check if this error should be hidden
- bool hide = userdata[HIDE].toBool() || mHiddenMessageId.contains(userdata[ERRORID].toString());
-
- if (!hide) {
- if (mReportType == ReportType::normal)
- hide = !mShowSeverities.isShown(ShowTypes::VariantToShowType(userdata[SEVERITY]));
- else {
- const QString& classification = fileItem->child(j, COLUMN_MISRA_CLASSIFICATION)->text();
- hide = classification.isEmpty() || !mShowSeverities.isShown(getSeverityFromClassification(classification));
- }
- }
-
- // If specified, filter on summary, message, filename, and id
- if (!hide && !mFilter.isEmpty()) {
- if (!userdata[SUMMARY].toString().contains(mFilter, Qt::CaseInsensitive) &&
- !userdata[MESSAGE].toString().contains(mFilter, Qt::CaseInsensitive) &&
- !userdata[FILENAME].toString().contains(mFilter, Qt::CaseInsensitive) &&
- !userdata[ERRORID].toString().contains(mFilter, Qt::CaseInsensitive) &&
- !fileItem->child(j, COLUMN_MISRA_CLASSIFICATION)->text().contains(mFilter, Qt::CaseInsensitive)) {
- hide = true;
- }
- }
-
- // Tool filter
- if (!hide) {
- if (userdata[ERRORID].toString().startsWith("clang"))
- hide = !mShowClang;
- else
- hide = !mShowCppcheck;
- }
+ const bool hide = child->hidden || isErrorItemHidden(child->errorItem);
if (!hide) {
showFile = true;
@@ -672,34 +544,54 @@ void ResultsTree::refreshTree()
sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
}
-QStandardItem *ResultsTree::ensureFileItem(const QString &fullpath, const QString &file0, bool hide)
+bool ResultsTree::isErrorItemHidden(const QSharedPointer& errorItem) const {
+ //Check if this error should be hidden
+ if (mHiddenMessageId.contains(errorItem->errorId))
+ return true;
+
+ bool hide;
+ if (mReportType == ReportType::normal)
+ hide = !mShowSeverities.isShown(errorItem->severity);
+ else
+ hide = errorItem->classification.isEmpty() || !mShowSeverities.isShown(getSeverityFromClassification(errorItem->classification));
+
+ // If specified, filter on summary, message, filename, and id
+ if (!hide && !mFilter.isEmpty())
+ hide = !errorItem->filterMatch(mFilter);
+
+ // Tool filter
+ if (!hide) {
+ if (errorItem->isClangResult())
+ hide = !mShowClang;
+ else
+ hide = !mShowCppcheck;
+ }
+
+ return hide;
+}
+
+ResultItem *ResultsTree::ensureFileItem(const QSharedPointer& errorItem, bool hide)
{
- QString name = stripPath(fullpath, false);
+ QString name = QDir::toNativeSeparators(stripPath(errorItem->getFile(), false));
// Since item has path with native separators we must use path with
// native separators to find it.
- QStandardItem *item = findFileItem(QDir::toNativeSeparators(name));
+ ResultItem *fileItem = findFileItem(name);
- if (item) {
+ if (fileItem) {
if (!hide)
- setRowHidden(item->row(), QModelIndex(), hide);
- return item;
+ setRowHidden(fileItem->row(), QModelIndex(), hide);
+ return fileItem;
}
// Ensure shown path is with native separators
- name = QDir::toNativeSeparators(name);
- item = createNormalItem(name);
- item->setIcon(QIcon(":images/text-x-generic.png"));
+ fileItem = createFilenameItem(errorItem, ResultItem::Type::file, errorItem->getMainLocIndex());
+ fileItem->setIcon(QIcon(":images/text-x-generic.png"));
- //Add user data to that item
- QMap itemdata;
- itemdata[FILENAME] = fullpath;
- itemdata[FILE0] = file0;
- item->setData(QVariant(itemdata));
- mModel->appendRow(item);
+ mModel->appendRow(fileItem);
- setRowHidden(item->row(), QModelIndex(), hide);
+ setRowHidden(fileItem->row(), QModelIndex(), hide);
- return item;
+ return fileItem;
}
void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
@@ -712,7 +604,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
if (mSelectionModel->selectedRows().count() > 1)
multipleSelection = true;
- mContextItem = mModel->itemFromIndex(index);
+ mContextItem = dynamic_cast(mModel->itemFromIndex(index));
//Create a new context menu
QMenu menu(this);
@@ -788,10 +680,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
auto *suppress = new QAction(tr("Suppress selected id(s)"), &menu);
{
- QVariantMap itemdata = mContextItem->data().toMap();
- const QString messageId = itemdata[ERRORID].toString();
-
- if (selectedResults == 0 || ErrorLogger::isCriticalErrorId(messageId.toStdString()))
+ if (selectedResults == 0 || ErrorLogger::isCriticalErrorId(mContextItem->errorItem->errorId.toStdString()))
suppress->setDisabled(true);
}
menu.addAction(suppress);
@@ -831,13 +720,12 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
//Start the menu
menu.exec(e->globalPos());
index = indexAt(e->pos());
- if (index.isValid()) {
- mContextItem = mModel->itemFromIndex(index);
- }
+ if (index.isValid())
+ mContextItem = dynamic_cast(mModel->itemFromIndex(index));
}
}
-void ResultsTree::startApplication(const QStandardItem *target, int application)
+void ResultsTree::startApplication(const ResultItem *target, int application)
{
//If there are no applications specified, tell the user about it
if (mApplications->getApplicationCount() == 0) {
@@ -863,22 +751,16 @@ void ResultsTree::startApplication(const QStandardItem *target, int application)
this);
msg.exec();
return;
-
}
if (target && application >= 0 && application < mApplications->getApplicationCount() && target->parent()) {
- // Make sure we are working with the first column
- if (target->column() != 0)
- target = target->parent()->child(target->row(), 0);
-
- QVariantMap targetdata = target->data().toMap();
+ const auto& errorPathItem = target->getErrorPathItem();
//Replace (file) with filename
- QString file = targetdata[FILENAME].toString();
- file = QDir::toNativeSeparators(file);
+ QString file = QDir::toNativeSeparators(errorPathItem.file);
qDebug() << "Opening file: " << file;
- QFileInfo info(file);
+ const QFileInfo info(file);
if (!info.exists()) {
if (info.isAbsolute()) {
QMessageBox msgbox(this);
@@ -907,11 +789,10 @@ void ResultsTree::startApplication(const QStandardItem *target, int application)
QString params = app.getParameters();
params.replace("(file)", file, Qt::CaseInsensitive);
- QVariant line = targetdata[LINE];
- params.replace("(line)", QString("%1").arg(line.toInt()), Qt::CaseInsensitive);
+ params.replace("(line)", QString::number(errorPathItem.line), Qt::CaseInsensitive);
- params.replace("(message)", targetdata[MESSAGE].toString(), Qt::CaseInsensitive);
- params.replace("(severity)", targetdata[SEVERITY].toString(), Qt::CaseInsensitive);
+ params.replace("(message)", target->errorItem->message, Qt::CaseInsensitive);
+ params.replace("(severity)", severityToTranslatedString(target->errorItem->severity), Qt::CaseInsensitive);
QString program = app.getPath();
@@ -998,25 +879,17 @@ void ResultsTree::copy()
QString text;
for (const QModelIndex& index : mSelectionModel->selectedRows()) {
- const QStandardItem *item = mModel->itemFromIndex(index);
- if (!item->parent()) {
- text += item->text() + '\n';
+ const auto *item = dynamic_cast(mModel->itemFromIndex(index));
+ if (!item)
continue;
+ if (item->getType() == ResultItem::Type::file)
+ text += item->text() + '\n';
+ else if (item->getType() == ResultItem::Type::message)
+ text += item->errorItem->toString() + '\n';
+ else if (item->getType() == ResultItem::Type::note) {
+ const auto e = item->getErrorPathItem();
+ text += e.file + ":" + QString::number(e.line) + ":" + QString::number(e.column) + ":note: " + e.info + '\n';
}
- if (item->parent()->parent())
- item = item->parent();
- QVariantMap itemdata = item->data().toMap();
- if (!itemdata.contains("id"))
- continue;
- QString inconclusive = itemdata[INCONCLUSIVE].toBool() ? ",inconclusive" : "";
- text += itemdata[FILENAME].toString() + ':' + QString::number(itemdata[LINE].toInt()) + ':' + QString::number(itemdata[COLUMN].toInt())
- + ": "
- + QString::fromStdString(severityToString(ShowTypes::ShowTypeToSeverity(static_cast(itemdata[SEVERITY].toInt())))) + inconclusive
- + ": "
- + itemdata[MESSAGE].toString()
- + " ["
- + itemdata[ERRORID].toString()
- + "]\n";
}
QClipboard *clipboard = QApplication::clipboard();
@@ -1027,14 +900,13 @@ void ResultsTree::hideResult()
{
if (!mSelectionModel)
return;
-
- for (QModelIndex index : mSelectionModel->selectedRows()) {
- QStandardItem *item = mModel->itemFromIndex(index);
- //Set the "hide" flag for this item
- QVariantMap itemdata = item->data().toMap();
- itemdata[HIDE] = true;
- item->setData(QVariant(itemdata));
-
+ bool hide = false;
+ for (const QModelIndex& index : mSelectionModel->selectedRows()) {
+ auto *item = dynamic_cast(mModel->itemFromIndex(index));
+ if (item && item->getType() == ResultItem::Type::message)
+ hide = item->hidden = true;
+ }
+ if (hide) {
refreshTree();
emit resultsHidden(true);
}
@@ -1046,15 +918,15 @@ void ResultsTree::recheckSelectedFiles()
return;
QStringList selectedItems;
- for (QModelIndex index : mSelectionModel->selectedRows()) {
- QStandardItem *item = mModel->itemFromIndex(index);
+ for (const QModelIndex& index : mSelectionModel->selectedRows()) {
+ const auto *item = dynamic_cast(mModel->itemFromIndex(index));
while (item->parent())
- item = item->parent();
- QVariantMap itemdata = item->data().toMap();
- QString currentFile = itemdata[FILENAME].toString();
+ item = dynamic_cast(item->parent());
+ const auto e = item->getErrorPathItem();
+ const QString currentFile = e.file;
if (!currentFile.isEmpty()) {
QString fileNameWithCheckPath;
- QFileInfo curfileInfo(currentFile);
+ const QFileInfo curfileInfo(currentFile);
if (!curfileInfo.exists() && !mCheckPath.isEmpty() && currentFile.indexOf(mCheckPath) != 0)
fileNameWithCheckPath = mCheckPath + "/" + currentFile;
else
@@ -1065,13 +937,13 @@ void ResultsTree::recheckSelectedFiles()
return;
}
if (Path::isHeader(currentFile.toStdString())) {
- if (!itemdata[FILE0].toString().isEmpty() && !selectedItems.contains(itemdata[FILE0].toString())) {
- selectedItems<<((!mCheckPath.isEmpty() && (itemdata[FILE0].toString().indexOf(mCheckPath) != 0)) ? (mCheckPath + "/" + itemdata[FILE0].toString()) : itemdata[FILE0].toString());
+ if (!item->errorItem->file0.isEmpty() && !selectedItems.contains(item->errorItem->file0)) {
+ selectedItems << ((!mCheckPath.isEmpty() && (item->errorItem->file0.indexOf(mCheckPath) != 0)) ? (mCheckPath + "/" + item->errorItem->file0) : item->errorItem->file0);
if (!selectedItems.contains(fileNameWithCheckPath))
- selectedItems<parent())
+ if (!mContextItem || mContextItem->getType() == ResultItem::Type::file)
return;
- // Make sure we are working with the first column
- if (mContextItem->column() != 0)
- mContextItem = mContextItem->parent()->child(mContextItem->row(), 0);
- QVariantMap itemdata = mContextItem->data().toMap();
-
- QString messageId = itemdata[ERRORID].toString();
-
- mHiddenMessageId.append(messageId);
+ mHiddenMessageId.append(mContextItem->errorItem->errorId);
refreshTree();
emit resultsHidden(true);
@@ -1101,25 +966,19 @@ void ResultsTree::suppressSelectedIds()
return;
QSet selectedIds;
- for (QModelIndex index : mSelectionModel->selectedRows()) {
- QStandardItem *item = mModel->itemFromIndex(index);
- if (!item->parent())
- continue;
- if (item->parent()->parent())
- item = item->parent();
- QVariantMap itemdata = item->data().toMap();
- if (!itemdata.contains("id"))
+ for (const QModelIndex& index : mSelectionModel->selectedRows()) {
+ const auto *item = dynamic_cast(mModel->itemFromIndex(index));
+ if (!item || item->getType() == ResultItem::Type::file || !item->errorItem)
continue;
- selectedIds << itemdata[ERRORID].toString();
+ selectedIds << item->errorItem->errorId;
}
// delete all errors with selected message Ids
for (int i = 0; i < mModel->rowCount(); i++) {
QStandardItem * const file = mModel->item(i, 0);
for (int j = 0; j < file->rowCount();) {
- QStandardItem *errorItem = file->child(j, 0);
- QVariantMap userdata = errorItem->data().toMap();
- if (selectedIds.contains(userdata[ERRORID].toString())) {
+ const auto *errorItem = dynamic_cast(file->child(j, 0));
+ if (errorItem && errorItem->errorItem && selectedIds.contains(errorItem->errorItem->errorId)) {
file->removeRow(j);
} else {
j++;
@@ -1129,8 +988,10 @@ void ResultsTree::suppressSelectedIds()
mModel->removeRow(file->row());
}
-
- emit suppressIds(selectedIds.values());
+ if (!selectedIds.isEmpty()) {
+ refreshTree(); // If all visible warnings was suppressed then the file item should be hidden
+ emit suppressIds(selectedIds.values());
+ }
}
void ResultsTree::suppressHash()
@@ -1138,31 +999,26 @@ void ResultsTree::suppressHash()
if (!mSelectionModel)
return;
- // Extract selected warnings
- QSet selectedWarnings;
+ bool changed = false;
+ ProjectFile *projectFile = ProjectFile::getActiveProject();
+
for (QModelIndex index : mSelectionModel->selectedRows()) {
- QStandardItem *item = mModel->itemFromIndex(index);
- if (!item->parent())
+ auto *item = dynamic_cast(mModel->itemFromIndex(index));
+ if (!item || item->getType() == ResultItem::Type::file)
continue;
- while (item->parent()->parent())
- item = item->parent();
- selectedWarnings.insert(item);
- }
+ if (item->getType() == ResultItem::Type::note)
+ item = dynamic_cast(item->parent());
- bool changed = false;
- ProjectFile *projectFile = ProjectFile::getActiveProject();
- for (QStandardItem *item: selectedWarnings) {
- QStandardItem *fileItem = item->parent();
- const QVariantMap itemdata = item->data().toMap();
- if (projectFile && itemdata.contains(HASH)) {
+ // Suppress
+ if (projectFile && item->errorItem->hash > 0) {
SuppressionList::Suppression suppression;
- suppression.hash = itemdata[HASH].toULongLong();
- suppression.errorId = itemdata[ERRORID].toString().toStdString();
- suppression.fileName = itemdata[FILENAME].toString().toStdString();
- suppression.lineNumber = itemdata[LINE].toInt();
+ suppression.hash = item->errorItem->hash;
projectFile->addSuppression(suppression);
changed = true;
}
+
+ // Remove item
+ QStandardItem *fileItem = item->parent();
fileItem->removeRow(item->row());
if (fileItem->rowCount() == 0)
mModel->removeRow(fileItem->row());
@@ -1174,7 +1030,9 @@ void ResultsTree::suppressHash()
void ResultsTree::openContainingFolder()
{
- QString filePath = getFilePath(mContextItem, true);
+ if (!mContextItem)
+ return;
+ QString filePath = mContextItem->getErrorPathItem().file;
if (!filePath.isEmpty()) {
filePath = QFileInfo(filePath).absolutePath();
QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
@@ -1188,15 +1046,15 @@ void ResultsTree::tagSelectedItems(const QString &tag)
bool isTagged = false;
ProjectFile *currentProject = ProjectFile::getActiveProject();
for (QModelIndex index : mSelectionModel->selectedRows()) {
- QStandardItem *item = mModel->itemFromIndex(index);
- QVariantMap itemdata = item->data().toMap();
- if (itemdata.contains("tags")) {
- itemdata[TAGS] = tag;
- item->setData(QVariant(itemdata));
+ auto *item = dynamic_cast(mModel->itemFromIndex(index));
+ if (item && item->getType() != ResultItem::Type::file) {
+ if (item->getType() == ResultItem::Type::note)
+ item = dynamic_cast(item->parent());
+ item->errorItem->tags = tag;
item->parent()->child(index.row(), COLUMN_TAGS)->setText(tag);
- if (currentProject && itemdata.contains(HASH)) {
+ if (currentProject && item->errorItem->hash > 0) {
isTagged = true;
- currentProject->setWarningTags(itemdata[HASH].toULongLong(), tag);
+ currentProject->setWarningTags(item->errorItem->hash, tag);
}
}
}
@@ -1211,30 +1069,7 @@ void ResultsTree::context(int application)
void ResultsTree::quickStartApplication(const QModelIndex &index)
{
- startApplication(mModel->itemFromIndex(index));
-}
-
-QString ResultsTree::getFilePath(const QStandardItem *target, bool fullPath)
-{
- if (target) {
- // Make sure we are working with the first column
- if (target->column() != 0)
- target = target->parent()->child(target->row(), 0);
-
- QVariantMap targetdata = target->data().toMap();
-
- //Replace (file) with filename
- QString file = targetdata[FILENAME].toString();
- QString pathStr = QDir::toNativeSeparators(file);
- if (!fullPath) {
- QFileInfo fi(pathStr);
- pathStr = fi.fileName();
- }
-
- return pathStr;
- }
-
- return QString();
+ startApplication(dynamic_cast(mModel->itemFromIndex(index)));
}
QString ResultsTree::severityToIcon(Severity severity)
@@ -1263,20 +1098,20 @@ void ResultsTree::saveResults(Report *report) const
for (int i = 0; i < mModel->rowCount(); i++) {
if (mSaveAllErrors || !isRowHidden(i, QModelIndex()))
- saveErrors(report, mModel->item(i, 0));
+ saveErrors(report, dynamic_cast(mModel->item(i, 0)));
}
report->writeFooter();
}
-void ResultsTree::saveErrors(Report *report, const QStandardItem *fileItem) const
+void ResultsTree::saveErrors(Report *report, const ResultItem *fileItem) const
{
if (!fileItem) {
return;
}
for (int i = 0; i < fileItem->rowCount(); i++) {
- const QStandardItem *error = fileItem->child(i, 0);
+ const auto *error = dynamic_cast(fileItem->child(i, 0));
if (!error) {
continue;
@@ -1286,21 +1121,10 @@ void ResultsTree::saveErrors(Report *report, const QStandardItem *fileItem) cons
continue;
}
- ErrorItem item;
- readErrorItem(error, &item);
-
- report->writeError(item);
+ report->writeError(*error->errorItem);
}
}
-static int indexOf(const QList &list, const ErrorItem &item)
-{
- auto it = std::find_if(list.cbegin(), list.cend(), [&](const ErrorItem& e) {
- return ErrorItem::sameCID(item, e);
- });
- return it == list.cend() ? -1 : static_cast(std::distance(list.cbegin(), it));
-}
-
void ResultsTree::updateFromOldReport(const QString &filename)
{
showColumn(COLUMN_SINCE_DATE);
@@ -1314,80 +1138,35 @@ void ResultsTree::updateFromOldReport(const QString &filename)
// Read current results..
for (int i = 0; i < mModel->rowCount(); i++) {
- QStandardItem *fileItem = mModel->item(i,0);
+ auto *fileItem = dynamic_cast(mModel->item(i,COLUMN_FILE));
for (int j = 0; j < fileItem->rowCount(); j++) {
- QStandardItem *error = fileItem->child(j,0);
- ErrorItem errorItem;
- readErrorItem(error, &errorItem);
- const int oldErrorIndex = indexOf(oldErrors, errorItem);
- QVariantMap errordata = error->data().toMap();
+ auto *error = dynamic_cast(fileItem->child(j,COLUMN_FILE));
+ if (!error)
+ // FIXME..
+ continue;
+ const auto it = std::find_if(oldErrors.cbegin(),
+ oldErrors.cend(),
+ [error](const ErrorItem& err) {
+ return ErrorItem::same(err, *error->errorItem);
+ });
+ const ErrorItem* oldError = (it == oldErrors.cend()) ? nullptr : &*it;
// New error .. set the "sinceDate" property
- if (oldErrorIndex >= 0 && !oldErrors[oldErrorIndex].sinceDate.isEmpty()) {
- errordata[SINCEDATE] = oldErrors[oldErrorIndex].sinceDate;
- error->setData(errordata);
- fileItem->child(j, COLUMN_SINCE_DATE)->setText(oldErrors[oldErrorIndex].sinceDate);
- } else if (oldErrorIndex < 0 || errordata[SINCEDATE].toString().isEmpty()) {
+ if (oldError && !oldError->sinceDate.isEmpty()) {
+ error->errorItem->sinceDate = oldError->sinceDate;
+ fileItem->child(j, COLUMN_SINCE_DATE)->setText(error->errorItem->sinceDate);
+ } else if (oldError == nullptr || error->errorItem->sinceDate.isEmpty()) {
const QString sinceDate = QLocale::system().toString(QDate::currentDate(), QLocale::ShortFormat);
- errordata[SINCEDATE] = sinceDate;
- error->setData(errordata);
+ error->errorItem->sinceDate = sinceDate;
fileItem->child(j, COLUMN_SINCE_DATE)->setText(sinceDate);
- if (oldErrorIndex < 0)
- continue;
}
- if (!errorItem.tags.isEmpty())
- continue;
-
- const ErrorItem &oldErrorItem = oldErrors[oldErrorIndex];
- errordata[TAGS] = oldErrorItem.tags;
- error->setData(errordata);
+ if (oldError && error->errorItem->tags.isEmpty())
+ error->errorItem->tags = oldError->tags;
}
}
}
-void ResultsTree::readErrorItem(const QStandardItem *error, ErrorItem *item) const
-{
- // Get error's user data
- QVariantMap errordata = error->data().toMap();
-
- item->severity = ShowTypes::ShowTypeToSeverity(ShowTypes::VariantToShowType(errordata[SEVERITY]));
- item->summary = errordata[SUMMARY].toString();
- item->message = errordata[MESSAGE].toString();
- item->errorId = errordata[ERRORID].toString();
- item->cwe = errordata[CWE].toInt();
- item->hash = errordata[HASH].toULongLong();
- item->inconclusive = errordata[INCONCLUSIVE].toBool();
- item->file0 = errordata[FILE0].toString();
- item->sinceDate = errordata[SINCEDATE].toString();
- item->tags = errordata[TAGS].toString();
- item->remark = errordata[REMARK].toString();
- item->classification = error->parent()->child(error->row(), COLUMN_MISRA_CLASSIFICATION)->text();
- item->guideline = error->parent()->child(error->row(), COLUMN_MISRA_GUIDELINE)->text();
-
- if (error->rowCount() == 0) {
- QErrorPathItem e;
- e.file = stripPath(errordata[FILENAME].toString(), true);
- e.line = errordata[LINE].toInt();
- e.info = errordata[MESSAGE].toString();
- item->errorPath << e;
- }
-
- for (int j = 0; j < error->rowCount(); j++) {
- const QStandardItem *child_error = error->child(j, 0);
- //Get error's user data
- QVariant child_userdata = child_error->data();
- //Convert it to QVariantMap
- QVariantMap child_data = child_userdata.toMap();
-
- QErrorPathItem e;
- e.file = stripPath(child_data[FILENAME].toString(), true);
- e.line = child_data[LINE].toInt();
- e.info = child_data[MESSAGE].toString();
- item->errorPath << e;
- }
-}
-
void ResultsTree::updateSettings(bool showFullPath,
bool saveFullPath,
bool saveAllErrors,
@@ -1431,60 +1210,38 @@ QString ResultsTree::stripPath(const QString &path, bool saving) const
return dir.relativeFilePath(path);
}
-void ResultsTree::refreshFilePaths(QStandardItem *item)
+void ResultsTree::refreshFilePaths(ResultItem *fileItem)
{
- if (!item) {
+ if (!fileItem)
return;
- }
- //Mark that this file's path hasn't been updated yet
- bool updated = false;
+ auto refreshItem = [this](ResultItem* item) {
+ item->setText(QDir::toNativeSeparators(stripPath(item->getErrorPathItem().file, false)));
+ };
+
+ refreshItem(fileItem);
//Loop through all errors within this file
- for (int i = 0; i < item->rowCount(); i++) {
+ for (int i = 0; i < fileItem->rowCount(); i++) {
//Get error i
- QStandardItem *error = item->child(i, 0);
+ auto *error = dynamic_cast(fileItem->child(i, COLUMN_FILE));
if (!error) {
continue;
}
- //Get error's user data and convert it to QVariantMap
- QVariantMap userdata = error->data().toMap();
-
- //Get list of files
- QString file = userdata[FILENAME].toString();
-
//Update this error's text
- error->setText(stripPath(file, false));
-
- //If this error has backtraces make sure the files list has enough filenames
- if (error->hasChildren()) {
- //Loop through all files within the error
- for (int j = 0; j < error->rowCount(); j++) {
- //Get file
- QStandardItem *child = error->child(j, 0);
- if (!child) {
- continue;
- }
- //Get child's user data
- QVariant child_userdata = child->data();
- //Convert it to QVariantMap
- QVariantMap child_data = child_userdata.toMap();
+ refreshItem(error);
- //Get list of files
- QString child_files = child_data[FILENAME].toString();
+ //Loop through all files within the error
+ for (int j = 0; j < error->rowCount(); j++) {
+ //Get file
+ auto *child = dynamic_cast(error->child(j, COLUMN_FILE));
+ if (child) {
//Update file's path
- child->setText(stripPath(child_files, false));
+ refreshItem(child);
}
}
-
- //if the main file hasn't been updated yet, update it now
- if (!updated) {
- updated = true;
- item->setText(error->text());
- }
-
}
}
@@ -1493,8 +1250,8 @@ void ResultsTree::refreshFilePaths()
qDebug("Refreshing file paths");
//Go through all file items (these are parent items that contain the errors)
- for (int i = 0; i < mModel->rowCount(); i++) {
- refreshFilePaths(mModel->item(i, 0));
+ for (int row = 0; row < mModel->rowCount(); row++) {
+ refreshFilePaths(dynamic_cast(mModel->item(row, COLUMN_FILE)));
}
}
@@ -1534,7 +1291,8 @@ void ResultsTree::showInconclusiveColumn(bool show)
void ResultsTree::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
QTreeView::currentChanged(current, previous);
- emit treeSelectionChanged(current);
+ const auto *item = dynamic_cast(mModel->itemFromIndex(current));
+ emit treeSelectionChanged(item);
}
bool ResultsTree::isCertReport() const {
diff --git a/gui/resultstree.h b/gui/resultstree.h
index e73014fe12e..9537d6d929a 100644
--- a/gui/resultstree.h
+++ b/gui/resultstree.h
@@ -22,6 +22,7 @@
#include "showtypes.h"
#include "checkers.h"
+#include "resultitem.h"
#include
#include