From f62279376c5a6e10033f7ad6ece52be351564d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 18 Dec 2025 13:59:43 +0100 Subject: [PATCH 1/6] Add index to CheckThread --- gui/checkthread.cpp | 5 +++++ gui/checkthread.h | 3 +++ gui/threadhandler.cpp | 1 + 3 files changed, 9 insertions(+) diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 8f042068ee9..2e20b831566 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -486,3 +486,8 @@ QString CheckThread::clangTidyCmd() return QString(); } + +void CheckThread::setThreadIndex(int index) +{ + mThreadIndex = index; +} diff --git a/gui/checkthread.h b/gui/checkthread.h index 4247a45094c..9c3f62b1a18 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -80,6 +80,8 @@ class CheckThread : public QThread { void stop(); + void setThreadIndex(int index); + /** * Determine command to run clang * \return Command to run clang, empty if it is not found @@ -126,6 +128,7 @@ class CheckThread : public QThread { std::atomic mState{Ready}; ThreadResult &mResult; + int mThreadIndex; Settings mSettings; std::shared_ptr mSuppressions; diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index ad4d0e2a61d..3d9885a88ad 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -147,6 +147,7 @@ void ThreadHandler::createThreads(const int count) //Create new threads for (int i = mThreads.size(); i < count; i++) { mThreads << new CheckThread(mResults); + mThreads.last()->setThreadIndex(i + 1); connect(mThreads.last(), &CheckThread::done, this, &ThreadHandler::threadDone, Qt::QueuedConnection); connect(mThreads.last(), &CheckThread::fileChecked, From acd15295f4873797658dfec4dc44cc938e66358e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 18 Dec 2025 16:55:43 +0100 Subject: [PATCH 2/6] Add startCheck, finishCheck and threadDetailsUpdated signals/slots --- gui/checkthread.cpp | 17 ++++++++++++++--- gui/checkthread.h | 13 +++++++++++-- gui/threadhandler.cpp | 42 ++++++++++++++++++++++++++++++++++++++---- gui/threadhandler.h | 28 ++++++++++++++++++++++++++++ gui/threadresult.cpp | 4 ++-- gui/threadresult.h | 8 ++++---- 6 files changed, 97 insertions(+), 15 deletions(-) diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 2e20b831566..cbaff91bc2a 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -147,9 +147,14 @@ void CheckThread::run() while (file && mState == Running) { const std::string& fname = file->spath(); qDebug() << "Checking file" << QString::fromStdString(fname); + + const Details details = { mThreadIndex, fname, QTime::currentTime(), }; + emit startCheck(details); + cppcheck.check(*file); runAddonsAndTools(mSettings, nullptr, QString::fromStdString(fname)); - emit fileChecked(QString::fromStdString(fname)); + + emit finishCheck(details); if (mState == Running) mResult.getNextFile(file); @@ -160,9 +165,15 @@ void CheckThread::run() while (fileSettings && mState == Running) { const std::string& fname = fileSettings->filename(); qDebug() << "Checking file" << QString::fromStdString(fname); - cppcheck.check(*fileSettings); + + const Details details = { mThreadIndex, fname, QTime::currentTime(), }; + emit startCheck(details); + + cppcheck.check(*file); runAddonsAndTools(mSettings, fileSettings, QString::fromStdString(fname)); - emit fileChecked(QString::fromStdString(fname)); + + emit finishCheck(details); + if (mState == Running) mResult.getNextFileSettings(fileSettings); diff --git a/gui/checkthread.h b/gui/checkthread.h index 9c3f62b1a18..8f55f8ef4e5 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -36,6 +36,7 @@ #include #include #include +#include class ThreadResult; @@ -48,6 +49,14 @@ class ThreadResult; */ class CheckThread : public QThread { Q_OBJECT + +public: + struct Details { + int index; + std::string file; + QTime startTime; + }; + public: explicit CheckThread(ThreadResult &result); @@ -104,8 +113,8 @@ class CheckThread : public QThread { */ void done(); - // NOLINTNEXTLINE(readability-inconsistent-declaration-parameter-name) - caused by generated MOC code - void fileChecked(const QString &file); + void startCheck(CheckThread::Details details); + void finishCheck(CheckThread::Details details); protected: /** diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index 3d9885a88ad..c4d694bf792 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -150,8 +150,12 @@ void ThreadHandler::createThreads(const int count) mThreads.last()->setThreadIndex(i + 1); connect(mThreads.last(), &CheckThread::done, this, &ThreadHandler::threadDone, Qt::QueuedConnection); - connect(mThreads.last(), &CheckThread::fileChecked, - &mResults, &ThreadResult::fileChecked, Qt::QueuedConnection); + connect(mThreads.last(), &CheckThread::finishCheck, + &mResults, &ThreadResult::finishCheck, Qt::QueuedConnection); + connect(mThreads.last(), &CheckThread::startCheck, + this, &ThreadHandler::startCheck, Qt::QueuedConnection); + connect(mThreads.last(), &CheckThread::finishCheck, + this, &ThreadHandler::finishCheck, Qt::QueuedConnection); } } @@ -165,8 +169,12 @@ void ThreadHandler::removeThreads() } disconnect(thread, &CheckThread::done, this, &ThreadHandler::threadDone); - disconnect(thread, &CheckThread::fileChecked, - &mResults, &ThreadResult::fileChecked); + disconnect(thread, &CheckThread::finishCheck, + &mResults, &ThreadResult::finishCheck); + disconnect(mThreads.last(), &CheckThread::startCheck, + this, &ThreadHandler::startCheck); + disconnect(mThreads.last(), &CheckThread::finishCheck, + this, &ThreadHandler::finishCheck); delete thread; } @@ -318,3 +326,29 @@ void ThreadHandler::setCheckStartTime(QDateTime checkStartTime) { mCheckStartTime = std::move(checkStartTime); } + +void ThreadHandler::startCheck(CheckThread::Details details) +{ + mThreadDetails[details.index] = details; + emit threadDetailsUpdated(buildThreadDetailsText()); +} + +void ThreadHandler::finishCheck(CheckThread::Details details) +{ + mThreadDetails.erase(details.index); + emit threadDetailsUpdated(buildThreadDetailsText()); +} + +QString ThreadHandler::buildThreadDetailsText() const +{ + QString result; + + for (const auto &details : mThreadDetails) { + result += QString("Thread %1 (%2): %3\n") + .arg(details.second.index) + .arg(details.second.startTime.toString(Qt::TextDate)) + .arg(QString::fromStdString(details.second.file)); + } + + return result; +} diff --git a/gui/threadhandler.h b/gui/threadhandler.h index cc578bd5643..2fe17168322 100644 --- a/gui/threadhandler.h +++ b/gui/threadhandler.h @@ -191,6 +191,13 @@ class ThreadHandler : public QObject { // NOLINTNEXTLINE(readability-inconsistent-declaration-parameter-name) - caused by generated MOC code void debugError(const ErrorItem &item); + /** + * @brief Emitted when thread details are updated. + * + * @param text Text for the ThreadDetails widget to display + */ + void threadDetailsUpdated(const QString &text); + public slots: /** @@ -198,6 +205,19 @@ public slots: * */ void stop(); + + /** + * @brief Slot threads use to signal this class that it started checking a file + * @param details Details about what file is being checked and by what thread + */ + void startCheck(CheckThread::Details details); + + /** + * @brief Slot threads use to signal this class that it finish checking a file + * @param details Details about what file finished being checked and by what thread + */ + void finishCheck(CheckThread::Details details); + protected slots: /** * @brief Slot that a single thread is done @@ -285,6 +305,12 @@ protected slots: Settings mCheckSettings; std::shared_ptr mCheckSuppressions; /// @} + + /** + * @bried Details about currently running threads + */ + std::map mThreadDetails; + private: /** @@ -292,6 +318,8 @@ protected slots: * included headers. Used by GetReCheckFiles() */ bool needsReCheck(const QString &filename, std::set &modified, std::set &unmodified) const; + + QString buildThreadDetailsText() const; }; /// @} #endif // THREADHANDLER_H diff --git a/gui/threadresult.cpp b/gui/threadresult.cpp index ea858c92e4a..4a98273fdec 100644 --- a/gui/threadresult.cpp +++ b/gui/threadresult.cpp @@ -34,11 +34,11 @@ void ThreadResult::reportOut(const std::string &outmsg, Color /*c*/) emit log(QString::fromStdString(outmsg)); } -void ThreadResult::fileChecked(const QString &file) +void ThreadResult::finishCheck(CheckThread::Details details) { std::lock_guard locker(mutex); - mProgress += QFile(file).size(); + mProgress += QFile(QString::fromStdString(details.file)).size(); mFilesChecked++; if (mMaxProgress > 0) { diff --git a/gui/threadresult.h b/gui/threadresult.h index dc7b5c0372a..f30d8a5dc1a 100644 --- a/gui/threadresult.h +++ b/gui/threadresult.h @@ -85,12 +85,12 @@ class ThreadResult : public QObject, public ErrorLogger { } public slots: - /** - * @brief Slot threads use to signal this class that a specific file is checked - * @param file File that is checked + * @brief Slot threads use to signal this class that it finish checking a file + * @param details Details about what file finished being checked and by what thread */ - void fileChecked(const QString &file); + void finishCheck(CheckThread::Details details); + signals: /** * @brief Progress signal From 50da21cc77019c0bda3d648b3a824500ea0d208b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Sat, 20 Dec 2025 15:40:02 +0100 Subject: [PATCH 3/6] Add ThreadDetails widget --- gui/gui.pro | 5 ++++- gui/threaddetails.cpp | 14 ++++++++++++++ gui/threaddetails.h | 22 ++++++++++++++++++++++ gui/threaddetails.ui | 31 +++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 gui/threaddetails.cpp create mode 100644 gui/threaddetails.h create mode 100644 gui/threaddetails.ui diff --git a/gui/gui.pro b/gui/gui.pro index 132f113d270..8706e86c86e 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -70,7 +70,8 @@ FORMS = about.ui \ librarydialog.ui \ libraryaddfunctiondialog.ui \ libraryeditargdialog.ui \ - newsuppressiondialog.ui + newsuppressiondialog.ui \ + threaddetails.ui TRANSLATIONS = cppcheck_de.ts \ cppcheck_es.ts \ @@ -156,6 +157,7 @@ HEADERS += aboutdialog.h \ settingsdialog.h \ showtypes.h \ statsdialog.h \ + threaddetails.h \ threadhandler.h \ threadresult.h \ translationhandler.h \ @@ -199,6 +201,7 @@ SOURCES += aboutdialog.cpp \ settingsdialog.cpp \ showtypes.cpp \ statsdialog.cpp \ + threaddetails.cpp \ threadhandler.cpp \ threadresult.cpp \ translationhandler.cpp \ diff --git a/gui/threaddetails.cpp b/gui/threaddetails.cpp new file mode 100644 index 00000000000..6b7a5fb5105 --- /dev/null +++ b/gui/threaddetails.cpp @@ -0,0 +1,14 @@ +#include "threaddetails.h" +#include "ui_threaddetails.h" + +ThreadDetails::ThreadDetails(QWidget *parent) + : QWidget(parent) + , ui(new Ui::ThreadDetails) +{ + ui->setupUi(this); +} + +ThreadDetails::~ThreadDetails() +{ + delete ui; +} diff --git a/gui/threaddetails.h b/gui/threaddetails.h new file mode 100644 index 00000000000..49ec86a634a --- /dev/null +++ b/gui/threaddetails.h @@ -0,0 +1,22 @@ +#ifndef THREADDETAILS_H +#define THREADDETAILS_H + +#include + +namespace Ui { +class ThreadDetails; +} + +class ThreadDetails : public QWidget +{ + Q_OBJECT + +public: + explicit ThreadDetails(QWidget *parent = nullptr); + ~ThreadDetails(); + +private: + Ui::ThreadDetails *ui; +}; + +#endif // THREADDETAILS_H diff --git a/gui/threaddetails.ui b/gui/threaddetails.ui new file mode 100644 index 00000000000..ab9c5ffb786 --- /dev/null +++ b/gui/threaddetails.ui @@ -0,0 +1,31 @@ + + + ThreadDetails + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + Close + + + + + + + + From 4c623c17168656acffd20e4baa9f5a07fcc1bc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Sat, 20 Dec 2025 20:40:18 +0100 Subject: [PATCH 4/6] Add threadDetailsUpdated to ThreadDetails widget --- gui/threaddetails.cpp | 6 ++++++ gui/threaddetails.h | 3 +++ gui/threadhandler.cpp | 9 +++++++-- gui/threadhandler.h | 5 +++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/gui/threaddetails.cpp b/gui/threaddetails.cpp index 6b7a5fb5105..ad52fbaa0c7 100644 --- a/gui/threaddetails.cpp +++ b/gui/threaddetails.cpp @@ -6,9 +6,15 @@ ThreadDetails::ThreadDetails(QWidget *parent) , ui(new Ui::ThreadDetails) { ui->setupUi(this); + ui->detailsBox->setReadOnly(true); } ThreadDetails::~ThreadDetails() { delete ui; } + +void ThreadDetails::threadDetailsUpdated(const QString &text) +{ + ui->detailsBox->setText(text); +} diff --git a/gui/threaddetails.h b/gui/threaddetails.h index 49ec86a634a..ac0317904a1 100644 --- a/gui/threaddetails.h +++ b/gui/threaddetails.h @@ -15,6 +15,9 @@ class ThreadDetails : public QWidget explicit ThreadDetails(QWidget *parent = nullptr); ~ThreadDetails(); +public slots: + void threadDetailsUpdated(const QString &text); + private: Ui::ThreadDetails *ui; }; diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index c4d694bf792..a59ed4c4419 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -330,13 +330,13 @@ void ThreadHandler::setCheckStartTime(QDateTime checkStartTime) void ThreadHandler::startCheck(CheckThread::Details details) { mThreadDetails[details.index] = details; - emit threadDetailsUpdated(buildThreadDetailsText()); + emitThreadDetailsUpdated(); } void ThreadHandler::finishCheck(CheckThread::Details details) { mThreadDetails.erase(details.index); - emit threadDetailsUpdated(buildThreadDetailsText()); + emitThreadDetailsUpdated(); } QString ThreadHandler::buildThreadDetailsText() const @@ -352,3 +352,8 @@ QString ThreadHandler::buildThreadDetailsText() const return result; } + +void ThreadHandler::emitThreadDetailsUpdated() +{ + emit threadDetailsUpdated(buildThreadDetailsText()); +} diff --git a/gui/threadhandler.h b/gui/threadhandler.h index 2fe17168322..007117beb4d 100644 --- a/gui/threadhandler.h +++ b/gui/threadhandler.h @@ -178,6 +178,11 @@ class ThreadHandler : public QObject { */ void setCheckStartTime(QDateTime checkStartTime); + /** + * @brief Emit the threadDetailsUpdated signal + */ + void emitThreadDetailsUpdated(); + signals: /** * @brief Signal that all threads are done From 8daf7254ba3acb51fdb9eb8081a597fe8282171c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 29 Jan 2026 12:06:15 +0100 Subject: [PATCH 5/6] Add menu entry for showing ThreadDetails widget --- gui/mainwindow.cpp | 11 +++++++++++ gui/mainwindow.h | 3 +++ gui/mainwindow.ui | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 2d71ef5e7c6..e1d8e35bc43 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -53,6 +53,7 @@ #include "threadresult.h" #include "translationhandler.h" #include "utils.h" +#include "threaddetails.h" #include "ui_mainwindow.h" @@ -183,6 +184,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : connect(mUI->mActionShowHidden, &QAction::triggered, mUI->mResults, &ResultsView::showHiddenResults); connect(mUI->mActionViewStats, &QAction::triggered, this, &MainWindow::showStatistics); connect(mUI->mActionLibraryEditor, &QAction::triggered, this, &MainWindow::showLibraryEditor); + connect(mUI->mActionShowThreadDetails, &QAction::triggered, this, &MainWindow::showThreadDetails); connect(mUI->mActionReanalyzeModified, &QAction::triggered, this, &MainWindow::reAnalyzeModified); connect(mUI->mActionReanalyzeAll, &QAction::triggered, this, &MainWindow::reAnalyzeAll); @@ -2112,6 +2114,15 @@ void MainWindow::showLibraryEditor() libraryDialog.exec(); } +void MainWindow::showThreadDetails() +{ + auto *td = new ThreadDetails; + connect(mThread, &ThreadHandler::threadDetailsUpdated, + td, &ThreadDetails::threadDetailsUpdated, Qt::QueuedConnection); + td->show(); + mThread->emitThreadDetailsUpdated(); +} + void MainWindow::filterResults() { mUI->mResults->filterResults(mLineEditFilter->text()); diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 76fda4f0de6..e29d4d48f5b 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -200,6 +200,9 @@ public slots: /** @brief Slot for showing the library editor */ void showLibraryEditor(); + /** @brief Slot for showing the thread details window */ + void showThreadDetails(); + private slots: /** @brief Slot for checkthread's done signal */ diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index a90949344e2..8483f1f9ff0 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -192,6 +192,7 @@ + @@ -1040,6 +1041,14 @@ EULA... + + + Thread details + + + Show thread details + + From 9466d2307861f12033f9564003538f86b51c55b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 29 Jan 2026 12:27:29 +0100 Subject: [PATCH 6/6] Format --- gui/threaddetails.h | 2 +- gui/threadhandler.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/threaddetails.h b/gui/threaddetails.h index ac0317904a1..14de689d44a 100644 --- a/gui/threaddetails.h +++ b/gui/threaddetails.h @@ -4,7 +4,7 @@ #include namespace Ui { -class ThreadDetails; + class ThreadDetails; } class ThreadDetails : public QWidget diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index a59ed4c4419..961794485a6 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -345,9 +345,9 @@ QString ThreadHandler::buildThreadDetailsText() const for (const auto &details : mThreadDetails) { result += QString("Thread %1 (%2): %3\n") - .arg(details.second.index) - .arg(details.second.startTime.toString(Qt::TextDate)) - .arg(QString::fromStdString(details.second.file)); + .arg(details.second.index) + .arg(details.second.startTime.toString(Qt::TextDate)) + .arg(QString::fromStdString(details.second.file)); } return result;