GUI: Recheck changed files. Ticket: #816
This commit is contained in:
parent
2e13a51d08
commit
87a118cd16
|
@ -27,6 +27,7 @@ ErrorItem::ErrorItem()
|
||||||
ErrorItem::ErrorItem(const ErrorItem &item)
|
ErrorItem::ErrorItem(const ErrorItem &item)
|
||||||
{
|
{
|
||||||
file = item.file;
|
file = item.file;
|
||||||
|
file0 = item.file0;
|
||||||
files = item.files;
|
files = item.files;
|
||||||
lines = item.lines;
|
lines = item.lines;
|
||||||
errorId = item.errorId;
|
errorId = item.errorId;
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
|
|
||||||
QString file;
|
QString file;
|
||||||
QStringList files;
|
QStringList files;
|
||||||
|
QString file0;
|
||||||
QList<unsigned int> lines;
|
QList<unsigned int> lines;
|
||||||
QString errorId;
|
QString errorId;
|
||||||
Severity::SeverityType severity;
|
Severity::SeverityType severity;
|
||||||
|
|
|
@ -582,12 +582,16 @@ void MainWindow::ProgramSettings()
|
||||||
|
|
||||||
void MainWindow::ReCheck()
|
void MainWindow::ReCheck()
|
||||||
{
|
{
|
||||||
ClearResults();
|
const QStringList files = mThread->GetReCheckFiles();
|
||||||
CheckLockDownUI(); // lock UI while checking
|
if (files.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
const int filesCount = mThread->GetPreviousFilesCount();
|
// Clear results for changed files
|
||||||
Q_ASSERT(filesCount > 0); // If no files should not be able to recheck
|
for (int i = 0; i < files.size(); ++i)
|
||||||
mUI.mResults->CheckingStarted(filesCount);
|
mUI.mResults->Clear(files[i]);
|
||||||
|
|
||||||
|
CheckLockDownUI(); // lock UI while checking
|
||||||
|
mUI.mResults->CheckingStarted(files.size());
|
||||||
|
|
||||||
if (mProject)
|
if (mProject)
|
||||||
qDebug() << "Rechecking project file" << mProject->GetProjectFile()->GetFilename();
|
qDebug() << "Rechecking project file" << mProject->GetProjectFile()->GetFilename();
|
||||||
|
|
|
@ -134,7 +134,7 @@ void ResultsTree::AddErrorItem(const ErrorItem &item)
|
||||||
line.severity = item.severity;
|
line.severity = item.severity;
|
||||||
//Create the base item for the error and ensure it has a proper
|
//Create the base item for the error and ensure it has a proper
|
||||||
//file item as a parent
|
//file item as a parent
|
||||||
QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, hide),
|
QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, item.file0, hide),
|
||||||
line,
|
line,
|
||||||
hide,
|
hide,
|
||||||
SeverityToIcon(line.severity));
|
SeverityToIcon(line.severity));
|
||||||
|
@ -152,6 +152,7 @@ void ResultsTree::AddErrorItem(const ErrorItem &item)
|
||||||
data["line"] = item.lines[0];
|
data["line"] = item.lines[0];
|
||||||
data["id"] = item.errorId;
|
data["id"] = item.errorId;
|
||||||
data["inconclusive"] = item.inconclusive;
|
data["inconclusive"] = item.inconclusive;
|
||||||
|
data["file0"] = item.file0;
|
||||||
stditem->setData(QVariant(data));
|
stditem->setData(QVariant(data));
|
||||||
|
|
||||||
//Add backtrace files as children
|
//Add backtrace files as children
|
||||||
|
@ -303,6 +304,25 @@ void ResultsTree::Clear()
|
||||||
mModel.removeRows(0, mModel.rowCount());
|
mModel.removeRows(0, mModel.rowCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResultsTree::Clear(const QString &filename)
|
||||||
|
{
|
||||||
|
const QString stripped = StripPath(filename, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < mModel.rowCount(); ++i) {
|
||||||
|
const QStandardItem *item = mModel.item(i, 0);
|
||||||
|
if (!item)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QVariantMap data = item->data().toMap();
|
||||||
|
if (stripped == data["file"].toString() ||
|
||||||
|
filename == data["file0"].toString()) {
|
||||||
|
mModel.removeRow(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ResultsTree::LoadSettings()
|
void ResultsTree::LoadSettings()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mModel.columnCount(); i++) {
|
for (int i = 0; i < mModel.columnCount(); i++) {
|
||||||
|
@ -433,7 +453,7 @@ void ResultsTree::RefreshTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStandardItem *ResultsTree::EnsureFileItem(const QString &fullpath, bool hide)
|
QStandardItem *ResultsTree::EnsureFileItem(const QString &fullpath, const QString &file0, bool hide)
|
||||||
{
|
{
|
||||||
QString name = StripPath(fullpath, false);
|
QString name = StripPath(fullpath, false);
|
||||||
// Since item has path with native separators we must use path with
|
// Since item has path with native separators we must use path with
|
||||||
|
@ -452,6 +472,7 @@ QStandardItem *ResultsTree::EnsureFileItem(const QString &fullpath, bool hide)
|
||||||
//Add user data to that item
|
//Add user data to that item
|
||||||
QMap<QString, QVariant> data;
|
QMap<QString, QVariant> data;
|
||||||
data["file"] = fullpath;
|
data["file"] = fullpath;
|
||||||
|
data["file0"] = file0;
|
||||||
item->setData(QVariant(data));
|
item->setData(QVariant(data));
|
||||||
mModel.appendRow(item);
|
mModel.appendRow(item);
|
||||||
|
|
||||||
|
@ -828,6 +849,7 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
|
||||||
item.message = data["message"].toString();
|
item.message = data["message"].toString();
|
||||||
item.errorId = data["id"].toString();
|
item.errorId = data["id"].toString();
|
||||||
item.inconclusive = data["inconclusive"].toBool();
|
item.inconclusive = data["inconclusive"].toBool();
|
||||||
|
item.file0 = data["file0"].toString();
|
||||||
QString file = StripPath(data["file"].toString(), true);
|
QString file = StripPath(data["file"].toString(), true);
|
||||||
unsigned int line = data["line"].toUInt();
|
unsigned int line = data["line"].toUInt();
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear errors for a specific file from the tree
|
||||||
|
*/
|
||||||
|
void Clear(const QString &filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function to show/hide certain type of errors
|
* @brief Function to show/hide certain type of errors
|
||||||
* Refreshes the tree.
|
* Refreshes the tree.
|
||||||
|
@ -339,10 +344,11 @@ protected:
|
||||||
* @brief Ensures there's a item in the model for the specified file
|
* @brief Ensures there's a item in the model for the specified file
|
||||||
*
|
*
|
||||||
* @param fullpath Full path to the file item.
|
* @param fullpath Full path to the file item.
|
||||||
|
* @param file0 Source file
|
||||||
* @param hide is the error (we want this file item for) hidden?
|
* @param hide is the error (we want this file item for) hidden?
|
||||||
* @return QStandardItem to be used as a parent for all errors for specified file
|
* @return QStandardItem to be used as a parent for all errors for specified file
|
||||||
*/
|
*/
|
||||||
QStandardItem *EnsureFileItem(const QString &fullpath, bool hide);
|
QStandardItem *EnsureFileItem(const QString &fullpath, const QString &file0, bool hide);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Show a file item
|
* @brief Show a file item
|
||||||
|
|
|
@ -80,6 +80,19 @@ void ResultsView::Clear()
|
||||||
mUI.mProgress->setFormat("%p%");
|
mUI.mProgress->setFormat("%p%");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResultsView::Clear(const QString &filename)
|
||||||
|
{
|
||||||
|
mUI.mTree->Clear(filename);
|
||||||
|
mUI.mDetails->setText("");
|
||||||
|
mErrorsFound = false;
|
||||||
|
mStatistics->Clear();
|
||||||
|
|
||||||
|
// Clear the progressbar
|
||||||
|
mUI.mProgress->setMaximum(PROGRESS_MAX);
|
||||||
|
mUI.mProgress->setValue(0);
|
||||||
|
mUI.mProgress->setFormat("%p%");
|
||||||
|
}
|
||||||
|
|
||||||
void ResultsView::Progress(int value, const QString& description)
|
void ResultsView::Progress(int value, const QString& description)
|
||||||
{
|
{
|
||||||
mUI.mProgress->setValue(value);
|
mUI.mProgress->setValue(value);
|
||||||
|
|
|
@ -64,6 +64,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear results for a specific file
|
||||||
|
*/
|
||||||
|
void Clear(const QString &filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Save results to a file
|
* @brief Save results to a file
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -51,7 +52,8 @@ void ThreadHandler::SetFiles(const QStringList &files)
|
||||||
void ThreadHandler::Check(const Settings &settings, bool recheck)
|
void ThreadHandler::Check(const Settings &settings, bool recheck)
|
||||||
{
|
{
|
||||||
if (recheck && mRunningThreadCount == 0) {
|
if (recheck && mRunningThreadCount == 0) {
|
||||||
mResults.SetFiles(mLastFiles);
|
// only recheck changed files
|
||||||
|
mResults.SetFiles(GetReCheckFiles());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mResults.GetFileCount() == 0 || mRunningThreadCount > 0 || settings._jobs <= 0) {
|
if (mResults.GetFileCount() == 0 || mRunningThreadCount > 0 || settings._jobs <= 0) {
|
||||||
|
@ -72,6 +74,9 @@ void ThreadHandler::Check(const Settings &settings, bool recheck)
|
||||||
mThreads[i]->Check(settings);
|
mThreads[i]->Check(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Date and time when checking starts..
|
||||||
|
mCheckStartTime = QDateTime::currentDateTime();
|
||||||
|
|
||||||
mTime.start();
|
mTime.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,11 +129,18 @@ void ThreadHandler::ThreadDone()
|
||||||
emit Done();
|
emit Done();
|
||||||
|
|
||||||
mScanDuration = mTime.elapsed();
|
mScanDuration = mTime.elapsed();
|
||||||
|
|
||||||
|
// Set date/time used by the recheck
|
||||||
|
if (!mCheckStartTime.isNull()) {
|
||||||
|
mLastCheckTime = mCheckStartTime;
|
||||||
|
mCheckStartTime = QDateTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadHandler::Stop()
|
void ThreadHandler::Stop()
|
||||||
{
|
{
|
||||||
|
mCheckStartTime = QDateTime();
|
||||||
for (int i = 0; i < mThreads.size(); i++) {
|
for (int i = 0; i < mThreads.size(); i++) {
|
||||||
mThreads[i]->stop();
|
mThreads[i]->stop();
|
||||||
}
|
}
|
||||||
|
@ -177,3 +189,59 @@ int ThreadHandler::GetPreviousScanDuration() const
|
||||||
{
|
{
|
||||||
return mScanDuration;
|
return mScanDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList ThreadHandler::GetReCheckFiles() const
|
||||||
|
{
|
||||||
|
if (mLastCheckTime.isNull())
|
||||||
|
return mLastFiles;
|
||||||
|
|
||||||
|
std::set<QString> modified;
|
||||||
|
std::set<QString> unmodified;
|
||||||
|
|
||||||
|
QStringList files;
|
||||||
|
for (int i = 0; i < mLastFiles.size(); ++i) {
|
||||||
|
if (NeedsReCheck(mLastFiles[i], modified, unmodified))
|
||||||
|
files.push_back(mLastFiles[i]);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadHandler::NeedsReCheck(const QString &filename, std::set<QString> &modified, std::set<QString> &unmodified) const
|
||||||
|
{
|
||||||
|
if (modified.find(filename) != modified.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (unmodified.find(filename) != unmodified.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (QFileInfo(filename).lastModified() > mLastCheckTime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse included files recursively
|
||||||
|
QFile f(filename);
|
||||||
|
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// prevent recursion..
|
||||||
|
unmodified.insert(filename);
|
||||||
|
|
||||||
|
QTextStream in(&f);
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
QString line = in.readLine();
|
||||||
|
if (line.startsWith("#include \"")) {
|
||||||
|
line.remove(0,10);
|
||||||
|
int i = line.indexOf("\"");
|
||||||
|
if (i > 0) {
|
||||||
|
line.remove(i,line.length());
|
||||||
|
line = QFileInfo(filename).absolutePath() + "/" + line;
|
||||||
|
if (NeedsReCheck(line, modified, unmodified)) {
|
||||||
|
modified.insert(line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTime>
|
#include <QDateTime>
|
||||||
|
#include <set>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
#include "threadresult.h"
|
#include "threadresult.h"
|
||||||
|
@ -117,6 +118,12 @@ public:
|
||||||
*/
|
*/
|
||||||
int GetPreviousScanDuration() const;
|
int GetPreviousScanDuration() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get files that should be rechecked because they have been
|
||||||
|
* changed.
|
||||||
|
*/
|
||||||
|
QStringList GetReCheckFiles() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* @brief Signal that all threads are done
|
* @brief Signal that all threads are done
|
||||||
|
@ -147,6 +154,14 @@ protected:
|
||||||
*/
|
*/
|
||||||
QStringList mLastFiles;
|
QStringList mLastFiles;
|
||||||
|
|
||||||
|
/** @brief date and time when current checking started */
|
||||||
|
QDateTime mCheckStartTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief when was the files checked the last time (used when rechecking)
|
||||||
|
*/
|
||||||
|
QDateTime mLastCheckTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Timer used for measuring scan duration
|
* @brief Timer used for measuring scan duration
|
||||||
*
|
*
|
||||||
|
@ -183,6 +198,12 @@ protected:
|
||||||
*/
|
*/
|
||||||
int mRunningThreadCount;
|
int mRunningThreadCount;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a file needs to be rechecked. Recursively checks
|
||||||
|
* included headers. Used by GetReCheckFiles()
|
||||||
|
*/
|
||||||
|
bool NeedsReCheck(const QString &filename, std::set<QString> &modified, std::set<QString> &unmodified) const;
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
#endif // THREADHANDLER_H
|
#endif // THREADHANDLER_H
|
||||||
|
|
|
@ -72,14 +72,15 @@ void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorItem item;
|
ErrorItem item;
|
||||||
item.file = QString(callStackToString(msg._callStack).c_str());
|
item.file = QString::fromStdString(callStackToString(msg._callStack));
|
||||||
item.files = files;
|
item.files = files;
|
||||||
item.errorId = QString(msg._id.c_str());
|
item.errorId = QString::fromStdString(msg._id);
|
||||||
item.lines = lines;
|
item.lines = lines;
|
||||||
item.summary = QString::fromStdString(msg.shortMessage());
|
item.summary = QString::fromStdString(msg.shortMessage());
|
||||||
item.message = QString::fromStdString(msg.verboseMessage());
|
item.message = QString::fromStdString(msg.verboseMessage());
|
||||||
item.severity = msg._severity;
|
item.severity = msg._severity;
|
||||||
item.inconclusive = msg._inconclusive;
|
item.inconclusive = msg._inconclusive;
|
||||||
|
item.file0 = QString::fromStdString(msg.file0);
|
||||||
|
|
||||||
if (msg._severity != Severity::debug)
|
if (msg._severity != Severity::debug)
|
||||||
emit Error(item);
|
emit Error(item);
|
||||||
|
|
Loading…
Reference in New Issue