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)
|
||||
{
|
||||
file = item.file;
|
||||
file0 = item.file0;
|
||||
files = item.files;
|
||||
lines = item.lines;
|
||||
errorId = item.errorId;
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
|
||||
QString file;
|
||||
QStringList files;
|
||||
QString file0;
|
||||
QList<unsigned int> lines;
|
||||
QString errorId;
|
||||
Severity::SeverityType severity;
|
||||
|
|
|
@ -582,12 +582,16 @@ void MainWindow::ProgramSettings()
|
|||
|
||||
void MainWindow::ReCheck()
|
||||
{
|
||||
ClearResults();
|
||||
CheckLockDownUI(); // lock UI while checking
|
||||
const QStringList files = mThread->GetReCheckFiles();
|
||||
if (files.empty())
|
||||
return;
|
||||
|
||||
const int filesCount = mThread->GetPreviousFilesCount();
|
||||
Q_ASSERT(filesCount > 0); // If no files should not be able to recheck
|
||||
mUI.mResults->CheckingStarted(filesCount);
|
||||
// Clear results for changed files
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
mUI.mResults->Clear(files[i]);
|
||||
|
||||
CheckLockDownUI(); // lock UI while checking
|
||||
mUI.mResults->CheckingStarted(files.size());
|
||||
|
||||
if (mProject)
|
||||
qDebug() << "Rechecking project file" << mProject->GetProjectFile()->GetFilename();
|
||||
|
|
|
@ -134,7 +134,7 @@ void ResultsTree::AddErrorItem(const ErrorItem &item)
|
|||
line.severity = item.severity;
|
||||
//Create the base item for the error and ensure it has a proper
|
||||
//file item as a parent
|
||||
QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, hide),
|
||||
QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, item.file0, hide),
|
||||
line,
|
||||
hide,
|
||||
SeverityToIcon(line.severity));
|
||||
|
@ -152,6 +152,7 @@ void ResultsTree::AddErrorItem(const ErrorItem &item)
|
|||
data["line"] = item.lines[0];
|
||||
data["id"] = item.errorId;
|
||||
data["inconclusive"] = item.inconclusive;
|
||||
data["file0"] = item.file0;
|
||||
stditem->setData(QVariant(data));
|
||||
|
||||
//Add backtrace files as children
|
||||
|
@ -303,6 +304,25 @@ void ResultsTree::Clear()
|
|||
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()
|
||||
{
|
||||
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);
|
||||
// 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
|
||||
QMap<QString, QVariant> data;
|
||||
data["file"] = fullpath;
|
||||
data["file0"] = file0;
|
||||
item->setData(QVariant(data));
|
||||
mModel.appendRow(item);
|
||||
|
||||
|
@ -828,6 +849,7 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
|
|||
item.message = data["message"].toString();
|
||||
item.errorId = data["id"].toString();
|
||||
item.inconclusive = data["inconclusive"].toBool();
|
||||
item.file0 = data["file0"].toString();
|
||||
QString file = StripPath(data["file"].toString(), true);
|
||||
unsigned int line = data["line"].toUInt();
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
*/
|
||||
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
|
||||
* Refreshes the tree.
|
||||
|
@ -339,10 +344,11 @@ protected:
|
|||
* @brief Ensures there's a item in the model for the specified file
|
||||
*
|
||||
* @param fullpath Full path to the file item.
|
||||
* @param file0 Source file
|
||||
* @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
|
||||
*/
|
||||
QStandardItem *EnsureFileItem(const QString &fullpath, bool hide);
|
||||
QStandardItem *EnsureFileItem(const QString &fullpath, const QString &file0, bool hide);
|
||||
|
||||
/**
|
||||
* @brief Show a file item
|
||||
|
|
|
@ -80,6 +80,19 @@ void ResultsView::Clear()
|
|||
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)
|
||||
{
|
||||
mUI.mProgress->setValue(value);
|
||||
|
|
|
@ -64,6 +64,11 @@ public:
|
|||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* @brief Clear results for a specific file
|
||||
*/
|
||||
void Clear(const QString &filename);
|
||||
|
||||
/**
|
||||
* @brief Save results to a file
|
||||
*
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <QObject>
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include "settings.h"
|
||||
|
@ -51,7 +52,8 @@ void ThreadHandler::SetFiles(const QStringList &files)
|
|||
void ThreadHandler::Check(const Settings &settings, bool recheck)
|
||||
{
|
||||
if (recheck && mRunningThreadCount == 0) {
|
||||
mResults.SetFiles(mLastFiles);
|
||||
// only recheck changed files
|
||||
mResults.SetFiles(GetReCheckFiles());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Date and time when checking starts..
|
||||
mCheckStartTime = QDateTime::currentDateTime();
|
||||
|
||||
mTime.start();
|
||||
}
|
||||
|
||||
|
@ -124,11 +129,18 @@ void ThreadHandler::ThreadDone()
|
|||
emit Done();
|
||||
|
||||
mScanDuration = mTime.elapsed();
|
||||
|
||||
// Set date/time used by the recheck
|
||||
if (!mCheckStartTime.isNull()) {
|
||||
mLastCheckTime = mCheckStartTime;
|
||||
mCheckStartTime = QDateTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadHandler::Stop()
|
||||
{
|
||||
mCheckStartTime = QDateTime();
|
||||
for (int i = 0; i < mThreads.size(); i++) {
|
||||
mThreads[i]->stop();
|
||||
}
|
||||
|
@ -177,3 +189,59 @@ int ThreadHandler::GetPreviousScanDuration() const
|
|||
{
|
||||
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 <QStringList>
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
#include <set>
|
||||
#include "settings.h"
|
||||
#include "cppcheck.h"
|
||||
#include "threadresult.h"
|
||||
|
@ -117,6 +118,12 @@ public:
|
|||
*/
|
||||
int GetPreviousScanDuration() const;
|
||||
|
||||
/**
|
||||
* @brief Get files that should be rechecked because they have been
|
||||
* changed.
|
||||
*/
|
||||
QStringList GetReCheckFiles() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal that all threads are done
|
||||
|
@ -147,6 +154,14 @@ protected:
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
@ -183,6 +198,12 @@ protected:
|
|||
*/
|
||||
int mRunningThreadCount;
|
||||
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
|
||||
|
|
|
@ -72,14 +72,15 @@ void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg)
|
|||
}
|
||||
|
||||
ErrorItem item;
|
||||
item.file = QString(callStackToString(msg._callStack).c_str());
|
||||
item.file = QString::fromStdString(callStackToString(msg._callStack));
|
||||
item.files = files;
|
||||
item.errorId = QString(msg._id.c_str());
|
||||
item.errorId = QString::fromStdString(msg._id);
|
||||
item.lines = lines;
|
||||
item.summary = QString::fromStdString(msg.shortMessage());
|
||||
item.message = QString::fromStdString(msg.verboseMessage());
|
||||
item.severity = msg._severity;
|
||||
item.inconclusive = msg._inconclusive;
|
||||
item.file0 = QString::fromStdString(msg.file0);
|
||||
|
||||
if (msg._severity != Severity::debug)
|
||||
emit Error(item);
|
||||
|
|
Loading…
Reference in New Issue