52 #include "ui_mainwindow.h"
59 #include <unordered_set>
63 #include <QApplication>
65 #include <QActionGroup>
68 #include <QCloseEvent>
69 #include <QCoreApplication>
76 #include <QHBoxLayout>
77 #include <QInputDialog>
78 #include <QKeySequence>
84 #include <QMessageBox>
85 #include <QtNetwork/QNetworkAccessManager>
86 #include <QtNetwork/QNetworkReply>
87 #include <QtNetwork/QNetworkRequest>
88 #include <QPushButton>
89 #include <QRegularExpression>
93 #include <QTemporaryFile>
106 ret.replace(
'\\',
'/');
118 mPlatformActions(new QActionGroup(this)),
119 mCStandardActions(new QActionGroup(this)),
120 mCppStandardActions(new QActionGroup(this)),
121 mSelectLanguageActions(new QActionGroup(this))
125 tempSettings.
exename = QCoreApplication::applicationFilePath().toStdString();
149 connect(
mUI->mActionPrint, SIGNAL(triggered()),
mUI->mResults, SLOT(print()));
150 connect(
mUI->mActionPrintPreview, SIGNAL(triggered()),
mUI->mResults, SLOT(printPreview()));
151 connect(
mUI->mActionQuit, &QAction::triggered,
this, &MainWindow::close);
223 mUI->mActionPrint->setShortcut(QKeySequence::Print);
237 mUI->mActionProjectMRU->setVisible(
false);
240 QStringList args = QCoreApplication::arguments();
243 if (!args.isEmpty()) {
252 auto *action =
new QAction(
this);
255 action->setText(platform.
mTitle);
256 action->setData(platform.
mType);
257 action->setCheckable(
true);
259 mUI->mMenuAnalyze->insertAction(
mUI->mActionPlatforms, action);
260 connect(action, SIGNAL(triggered()),
this, SLOT(
selectPlatform()));
283 constexpr
Platform::Type defaultPlatform = Platform::Type::Win32W;
285 constexpr
Platform::Type defaultPlatform = Platform::Type::Unspecified;
294 mUI->mLabelInformation->setVisible(
false);
295 mUI->mButtonHideInformation->setVisible(
false);
296 connect(
mUI->mButtonHideInformation, &QPushButton::clicked,
302 const QUrl url(
"https://files.cppchecksolutions.com/version.txt");
305 const QUrl url(
"https://cppcheck.sourceforge.io/version.txt");
309 delete mUI->mLayoutInformation;
323 if (params.contains(
"-p")) {
324 index = params.indexOf(
"-p");
325 if ((index + 1) < params.length())
327 }
else if (params.contains(
"-l")) {
329 index = params.indexOf(
"-l");
330 if ((index + 1) < params.length())
331 logFile = params[index + 1];
333 if (params.contains(
"-d")) {
335 index = params.indexOf(
"-d");
336 if ((index + 1) < params.length())
337 checkedDir = params[index + 1];
343 }
else if ((index = params.indexOf(QRegularExpression(
".*\\.cppcheck$", QRegularExpression::CaseInsensitiveOption))) >= 0 && index < params.length() && QFile(params[index]).exists()) {
345 }
else if ((index = params.indexOf(QRegularExpression(
".*\\.xml$", QRegularExpression::CaseInsensitiveOption))) >= 0 && index < params.length() && QFile(params[index]).exists()) {
368 mUI->mActionShowCppcheck->setChecked(
true);
369 mUI->mActionShowClang->setChecked(
true);
386 mUI->mActionToolBarMain->setChecked(showMainToolbar);
387 mUI->mToolBarMain->setVisible(showMainToolbar);
390 mUI->mActionToolBarView->setChecked(showViewToolbar);
391 mUI->mToolBarView->setVisible(showViewToolbar);
394 mUI->mActionToolBarFilter->setChecked(showFilterToolbar);
395 mUI->mToolBarFilter->setVisible(showFilterToolbar);
398 if (enforcedLanguage == Standards::Language::CPP)
399 mUI->mActionEnforceCpp->setChecked(
true);
400 else if (enforcedLanguage == Standards::Language::C)
401 mUI->mActionEnforceC->setChecked(
true);
403 mUI->mActionAutoDetectLanguage->setChecked(
true);
407 const QString msg = tr(
"There was a problem with loading the editor application settings.\n\n"
408 "This is probably because the settings were changed between the Cppcheck versions. "
409 "Please check (and fix) the editor application settings, otherwise the editor "
410 "program might not start correctly.");
411 QMessageBox msgBox(QMessageBox::Warning,
420 if (!projectFile.isEmpty() && QCoreApplication::arguments().size()==1) {
421 QFileInfo inf(projectFile);
422 if (inf.exists() && inf.isReadable()) {
428 QDir::setCurrent(inf.absolutePath());
448 if (
mUI->mActionC89->isChecked())
450 if (
mUI->mActionC99->isChecked())
452 if (
mUI->mActionC11->isChecked())
455 if (
mUI->mActionCpp03->isChecked())
457 if (
mUI->mActionCpp11->isChecked())
459 if (
mUI->mActionCpp14->isChecked())
461 if (
mUI->mActionCpp17->isChecked())
463 if (
mUI->mActionCpp20->isChecked())
473 if (
mUI->mActionEnforceCpp->isChecked())
475 else if (
mUI->mActionEnforceC->isChecked())
492 if (!checkSettingsPair.first)
494 Settings& checkSettings = checkSettingsPair.second;
500 std::vector<std::string> v;
502 std::transform(excluded.cbegin(), excluded.cend(), std::back_inserter(v), [](
const QString& e) {
503 return e.toStdString();
509 std::vector<std::string> configurations;
511 std::transform(configs.cbegin(), configs.cend(), std::back_inserter(configurations), [](
const QString& e) {
512 return e.toStdString();
520 mUI->mResults->clear(
true);
526 const QString checkPath = inf.canonicalPath();
531 mUI->mResults->setCheckDirectory(checkPath);
532 checkSettings.
force =
false;
539 if (!checkSettings.
buildDir.empty()) {
541 std::list<std::string> sourcefiles;
554 mUI->mResults->setCheckSettings(checkSettings);
563 if (!checkSettingsPair.first)
565 Settings& checkSettings = checkSettingsPair.second;
579 mUI->mResults->clear(
true);
582 if (fileNames.isEmpty()) {
583 QMessageBox msg(QMessageBox::Warning,
585 tr(
"No suitable files found to analyze!"),
592 mUI->mResults->checkingStarted(fileNames.count());
599 const QString checkPath = inf.canonicalPath();
604 mUI->mResults->setCheckDirectory(checkPath);
611 if (!checkSettings.
buildDir.empty()) {
613 std::list<std::string> sourcefiles;
614 std::transform(fileNames.cbegin(), fileNames.cend(), std::back_inserter(sourcefiles), [](
const QString& s) {
615 return s.toStdString();
622 mUI->mResults->setCheckSettings(checkSettings);
628 if (!checkSettingsPair.first)
630 const Settings& checkSettings = checkSettingsPair.second;
634 result.
setFiles(QStringList(filename));
635 connect(&result, SIGNAL(progress(
int,QString)),
636 mUI->mResults, SLOT(progress(
int,QString)));
639 connect(&result, SIGNAL(log(QString)),
640 mUI->mResults, SLOT(log(QString)));
641 connect(&result, SIGNAL(debugError(
ErrorItem)),
646 cppcheck.settings() = checkSettings;
651 mUI->mResults->checkingStarted(1);
652 cppcheck.check(filename.toStdString(), code.toStdString());
656 if (
mUI->mResults->hasVisibleResults())
657 mUI->mResults->expandAllResults();
663 QMessageBox msgBox(
this);
664 msgBox.setWindowTitle(tr(
"Cppcheck"));
665 const QString msg(tr(
"You must close the project file before selecting new files or directories!"));
667 msgBox.setIcon(QMessageBox::Critical);
669 return QStringList();
672 QStringList selected;
677 if (mode == QFileDialog::ExistingFiles) {
678 QMap<QString,QString> filters;
681 filters[tr(
"Visual Studio")] =
"*.sln *.vcxproj";
682 filters[tr(
"Borland C++ Builder 6")] =
"*.bpr";
684 selected = QFileDialog::getOpenFileNames(
this,
685 tr(
"Select files to analyze"),
691 if (selected.isEmpty())
694 QFileInfo inf(selected[0]);
698 }
else if (mode == QFileDialog::Directory) {
699 QString dir = QFileDialog::getExistingDirectory(
this,
700 tr(
"Select directory to analyze"),
702 if (!dir.isEmpty()) {
703 qDebug() <<
"Setting current directory to: " << dir;
705 selected.append(dir);
706 dir = QDir::toNativeSeparators(dir);
722 const QString file0 = (!selected.empty() ? selected[0].toLower() : QString());
723 if (file0.endsWith(
".sln")
724 || file0.endsWith(
".vcxproj")
726 || file0.endsWith(
".bpr")) {
728 p.
import(selected[0].toStdString());
730 if (file0.endsWith(
".sln")) {
733 const QString
cfg(QString::fromStdString(it->cfg));
734 if (!configs.contains(
cfg))
735 configs.push_back(
cfg);
740 const QString
cfg = QInputDialog::getItem(
this, tr(
"Select configuration"), tr(
"Select the configuration that will be analyzed"), configs, 0,
false, &ok);
759 QDir checkDir(dir[0]);
761 filters <<
"*.cppcheck";
762 checkDir.setFilter(QDir::Files | QDir::Readable);
763 checkDir.setNameFilters(filters);
764 QStringList projFiles = checkDir.entryList();
765 if (!projFiles.empty()) {
766 if (projFiles.size() == 1) {
768 QMessageBox msgBox(
this);
769 msgBox.setWindowTitle(tr(
"Cppcheck"));
770 const QString msg(tr(
"Found project file: %1\n\nDo you want to "
771 "load this project file instead?").arg(projFiles[0]));
773 msgBox.setIcon(QMessageBox::Warning);
774 msgBox.addButton(QMessageBox::Yes);
775 msgBox.addButton(QMessageBox::No);
776 msgBox.setDefaultButton(QMessageBox::Yes);
777 const int dlgResult = msgBox.exec();
778 if (dlgResult == QMessageBox::Yes) {
779 QString path = checkDir.canonicalPath();
780 if (!path.endsWith(
"/"))
782 path += projFiles[0];
790 QMessageBox msgBox(
this);
791 msgBox.setWindowTitle(tr(
"Cppcheck"));
792 const QString msg(tr(
"Found project files from the directory.\n\n"
793 "Do you want to proceed analysis without "
794 "using any of these project files?"));
796 msgBox.setIcon(QMessageBox::Warning);
797 msgBox.addButton(QMessageBox::Yes);
798 msgBox.addButton(QMessageBox::No);
799 msgBox.setDefaultButton(QMessageBox::Yes);
800 const int dlgResult = msgBox.exec();
801 if (dlgResult == QMessageBox::Yes) {
812 for (
const QString& dir : includeDirs) {
814 if (!QDir::isAbsolutePath(dir))
817 incdir = QDir::cleanPath(incdir);
820 if (!incdir.endsWith(
"/"))
833 ret = library.
load(
nullptr, (path+
"/"+filename).toLatin1());
839 const QString appPath = QFileInfo(QCoreApplication::applicationFilePath()).canonicalPath();
840 ret = library.
load(
nullptr, (appPath+
"/"+filename).toLatin1());
843 ret = library.
load(
nullptr, (appPath+
"/cfg/"+filename).toLatin1());
849 const QString filesdir = FILESDIR;
850 if (!filesdir.isEmpty()) {
851 ret = library.
load(
nullptr, (filesdir+
"/cfg/"+filename).toLatin1());
854 ret = library.
load(
nullptr, (filesdir+filename).toLatin1());
862 if (!datadir.isEmpty()) {
863 ret = library.
load(
nullptr, (datadir+
"/"+filename).toLatin1());
866 ret = library.
load(
nullptr, (datadir+
"/cfg/"+filename).toLatin1());
879 QMessageBox::information(
this, tr(
"Information"), tr(
"The library '%1' contains unknown elements:\n%2").arg(filename).arg(
error.reason.c_str()));
884 switch (
error.errorcode) {
888 errmsg = tr(
"File not found");
891 errmsg = tr(
"Bad XML");
894 errmsg = tr(
"Missing attribute");
897 errmsg = tr(
"Bad attribute value");
900 errmsg = tr(
"Unsupported format");
903 errmsg = tr(
"Duplicate platform type");
906 errmsg = tr(
"Platform type redefined");
909 errmsg = tr(
"Duplicate define");
912 errmsg = tr(
"Unknown element");
915 errmsg = tr(
"Unknown issue");
918 if (!
error.reason.empty())
919 errmsg +=
" '" + QString::fromStdString(
error.reason) +
"'";
920 QMessageBox::information(
this, tr(
"Information"), tr(
"Failed to load the selected library '%1'.\n%2").arg(filename).arg(errmsg));
930 if (addonFilePath.isEmpty())
931 return tr(
"File not found: '%1'").arg(addon);
933 picojson::object obj;
934 obj[
"script"] = picojson::value(addonFilePath.toStdString());
935 if (!pythonCmd.isEmpty())
936 obj[
"python"] = picojson::value(pythonCmd.toStdString());
940 if (!misraFile.isEmpty()) {
942 if (misraFile.endsWith(
".pdf", Qt::CaseInsensitive))
943 arg =
"--misra-pdf=" + misraFile;
945 arg =
"--rule-texts=" + misraFile;
946 obj[
"args"] = picojson::value(arg.toStdString());
950 const std::string& json_str = picojson::value(obj).serialize();
955 return tr(
"Failed to load/setup addon %1: %2").arg(addon, QString::fromStdString(errmsg));
956 settings.
addonInfos.emplace_back(std::move(addonInfo));
958 settings.
addons.emplace(json_str);
970 result.
exename = QCoreApplication::applicationFilePath().toStdString();
977 QMessageBox::critical(
this, tr(
"Error"), tr(
"Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.\n\nAnalysis is aborted.").arg(
"std.cfg"));
986 if (!cfgErr.isEmpty()) {
987 QMessageBox::critical(
this, tr(
"Error"), tr(
"Failed to load %1 - %2\n\nAnalysis is aborted.").arg(
"cppcheck.cfg").arg(cfgErr));
991 const auto cfgAddons = result.
addons;
993 for (
const std::string& addon : cfgAddons) {
995 const QString addonError =
loadAddon(result, filesDir, pythonCmd, QString::fromStdString(addon));
996 if (!addonError.isEmpty()) {
997 QMessageBox::critical(
this, tr(
"Error"), tr(
"%1\n\nAnalysis is aborted.").arg(addonError));
1009 for (
const QString& define : defines) {
1018 for (
const QString& undefine : undefines)
1019 result.
userUndefs.insert(undefine.toStdString());
1022 for (
const QString& library : libraries) {
1023 result.
libraries.emplace_back(library.toStdString());
1024 const QString filename = library +
".cfg";
1033 if (!defines.isEmpty())
1041 if (!buildDir.isEmpty()) {
1042 if (QDir(buildDir).isAbsolute()) {
1043 result.
buildDir = buildDir.toStdString();
1046 result.
buildDir = (prjpath +
'/' + buildDir).toStdString();
1051 if (platform.endsWith(
".xml")) {
1052 const QString applicationFilePath = QCoreApplication::applicationFilePath();
1053 result.
platform.
loadFromFile(applicationFilePath.toStdString().c_str(), platform.toStdString());
1055 for (
int i = Platform::Type::Native; i <= Platform::Type::Unix64; i++) {
1080 const QString addonError =
loadAddon(result, filesDir, pythonCmd, addon);
1081 if (!addonError.isEmpty()) {
1082 QMessageBox::critical(
this, tr(
"Error"), tr(
"%1\n\nAnalysis is aborted.").arg(addonError));
1088 QString premiumArgs;
1090 premiumArgs +=
" --bughunting";
1094 premiumArgs +=
" --" + c;
1096 premiumArgs +=
" --misra-c-2012";
1097 result.
premiumArgs = premiumArgs.mid(1).toStdString();
1106 if (!globalIncludes.isEmpty()) {
1107 QStringList includes = globalIncludes.split(
";");
1120 result.
quiet =
false;
1133 if (result.
jobs <= 1) {
1139 return {
true, std::move(result)};
1149 mUI->mResults->checkingFinished();
1151 mUI->mActionSettings->setEnabled(
true);
1152 mUI->mActionOpenXML->setEnabled(
true);
1156 mUI->mActionReanalyzeModified->setEnabled(
false);
1157 mUI->mActionReanalyzeAll->setEnabled(
false);
1164 mUI->mActionPosix->setEnabled(
true);
1167 mUI->mActionViewStats->setEnabled(
true);
1172 if (QDir(buildDir).exists()) {
1173 mUI->mResults->saveStatistics(buildDir +
"/statistics.txt");
1174 mUI->mResults->updateFromOldReport(buildDir +
"/lastResults.xml");
1182 if (recentProjectAct !=
nullptr)
1183 recentProjectAct->setEnabled(
true);
1187 QApplication::alert(
this, 3000);
1195 mUI->mActionSettings->setEnabled(
false);
1196 mUI->mActionOpenXML->setEnabled(
false);
1203 mUI->mActionPosix->setEnabled(
false);
1208 if (recentProjectAct !=
nullptr)
1209 recentProjectAct->setEnabled(
false);
1216 if (dialog.exec() == QDialog::Accepted) {
1264 if (!checkSettingsPair.first)
1266 const Settings& checkSettings = checkSettingsPair.second;
1269 mUI->mResults->clear(
false);
1270 for (
int i = 0; i < files.size(); ++i)
1271 mUI->mResults->clearRecheckFile(files[i]);
1280 mUI->mResults->checkingStarted(fileNames.size());
1288 mUI->mResults->setCheckSettings(checkSettings);
1299 if (!checkSettingsPair.first)
1301 const Settings& checkSettings = checkSettingsPair.second;
1304 mUI->mResults->clear(all);
1307 for (
int i = 0; i < files.size(); ++i)
1308 mUI->mResults->clear(files[i]);
1311 mUI->mResults->checkingStarted(files.size());
1318 mUI->mResults->setCheckSettings(checkSettings);
1325 for (
const QString& f: dir.entryList(QDir::Files)) {
1326 if (!f.endsWith(
"files.txt")) {
1327 static const QRegularExpression rx(
"^.*.s[0-9]+$");
1328 if (!rx.match(f).hasMatch())
1333 mUI->mResults->clear(
true);
1334 Q_ASSERT(
false ==
mUI->mResults->hasResults());
1340 if (
mUI->mResults->hasResults()) {
1341 QMessageBox msgBox(
this);
1342 msgBox.setWindowTitle(tr(
"Cppcheck"));
1343 const QString msg(tr(
"Current results will be cleared.\n\n"
1344 "Opening a new XML file will clear current results.\n"
1345 "Do you want to proceed?"));
1346 msgBox.setText(msg);
1347 msgBox.setIcon(QMessageBox::Warning);
1348 msgBox.addButton(QMessageBox::Yes);
1349 msgBox.addButton(QMessageBox::No);
1350 msgBox.setDefaultButton(QMessageBox::Yes);
1351 const int dlgResult = msgBox.exec();
1352 if (dlgResult == QMessageBox::No) {
1357 QString selectedFilter;
1358 const QString filter(tr(
"XML files (*.xml)"));
1359 QString selectedFile = QFileDialog::getOpenFileName(
this,
1360 tr(
"Open the report file"),
1365 if (!selectedFile.isEmpty()) {
1372 if (selectedFile.isEmpty())
1377 mUI->mResults->clear(
true);
1378 mUI->mActionReanalyzeModified->setEnabled(
false);
1379 mUI->mActionReanalyzeAll->setEnabled(
false);
1380 mUI->mResults->readErrorsXml(selectedFile);
1388 mUI->mResults->setCheckDirectory(sourceDirectory);
1393 mUI->mActionStop->setEnabled(!enable);
1394 mUI->mActionAnalyzeFiles->setEnabled(enable);
1397 mUI->mActionReanalyzeModified->setEnabled(
false);
1398 mUI->mActionReanalyzeAll->setEnabled(enable);
1400 mUI->mActionReanalyzeModified->setEnabled(enable);
1401 mUI->mActionReanalyzeAll->setEnabled(enable);
1404 mUI->mActionAnalyzeDirectory->setEnabled(enable);
1413 const bool enabled =
mUI->mResults->hasResults();
1414 mUI->mActionClearResults->setEnabled(enabled);
1415 mUI->mActionSave->setEnabled(enabled);
1416 mUI->mActionPrint->setEnabled(enabled);
1417 mUI->mActionPrintPreview->setEnabled(enabled);
1467 const QString text(tr(
"Analyzer is running.\n\n" \
1468 "Do you want to stop the analysis and exit Cppcheck?"));
1470 QMessageBox msg(QMessageBox::Warning,
1473 QMessageBox::Yes | QMessageBox::No,
1476 msg.setDefaultButton(QMessageBox::No);
1477 const int rv = msg.exec();
1478 if (rv == QMessageBox::Yes) {
1491 mUI->mActionShowStyle->setChecked(checked);
1493 mUI->mActionShowErrors->setChecked(checked);
1495 mUI->mActionShowWarnings->setChecked(checked);
1497 mUI->mActionShowPortability->setChecked(checked);
1499 mUI->mActionShowPerformance->setChecked(checked);
1501 mUI->mActionShowInformation->setChecked(checked);
1508 QMessageBox msg(QMessageBox::Information,
1524 dlg->resize(570, 400);
1531 dlg->resize(350, 400);
1542 QString selectedFilter;
1543 const QString filter(tr(
"XML files (*.xml);;Text files (*.txt);;CSV files (*.csv)"));
1544 QString selectedFile = QFileDialog::getSaveFileName(
this,
1545 tr(
"Save the report file"),
1550 if (!selectedFile.isEmpty()) {
1552 if (selectedFilter == tr(
"XML files (*.xml)")) {
1554 if (!selectedFile.endsWith(
".xml", Qt::CaseInsensitive))
1555 selectedFile +=
".xml";
1556 }
else if (selectedFilter == tr(
"Text files (*.txt)")) {
1558 if (!selectedFile.endsWith(
".txt", Qt::CaseInsensitive))
1559 selectedFile +=
".txt";
1560 }
else if (selectedFilter == tr(
"CSV files (*.csv)")) {
1562 if (!selectedFile.endsWith(
".csv", Qt::CaseInsensitive))
1563 selectedFile +=
".csv";
1565 if (selectedFile.endsWith(
".xml", Qt::CaseInsensitive))
1567 else if (selectedFile.endsWith(
".txt", Qt::CaseInsensitive))
1569 else if (selectedFile.endsWith(
".csv", Qt::CaseInsensitive))
1580 if (!
mUI->mResults->isSuccess()) {
1581 QMessageBox m(QMessageBox::Critical,
1583 tr(
"Cannot generate a compliance report right now, an analysis must finish successfully. Try to reanalyze the code and ensure there are no critical errors."),
1590 QTemporaryFile tempResults;
1592 tempResults.close();
1605 mUI->mToolBarMain->setVisible(
mUI->mActionToolBarMain->isChecked());
1610 mUI->mToolBarView->setVisible(
mUI->mActionToolBarView->isChecked());
1615 mUI->mToolBarFilter->setVisible(
mUI->mActionToolBarFilter->isChecked());
1624 if (!extraVersion.isEmpty()) {
1625 nameWithVersion +=
" (" + extraVersion +
")";
1633 title = nameWithVersion;
1635 title = QString(
"%1 - %2").arg(nameWithVersion, text);
1636 setWindowTitle(title);
1642 if (currentLang == code)
1647 mUI->retranslateUi(
this);
1648 mUI->mResults->translate();
1649 mLineEditFilter->setPlaceholderText(QCoreApplication::translate(
"MainWindow",
"Quick Filter:"));
1659 mUI->mActionToolBarMain->setChecked(
mUI->mToolBarMain->isVisible());
1660 mUI->mActionToolBarView->setChecked(
mUI->mToolBarView->isVisible());
1661 mUI->mActionToolBarFilter->setChecked(
mUI->mToolBarFilter->isVisible());
1667 mUI->mResults->stopAnalysis();
1668 mUI->mResults->disableProgressbar();
1670 if (!lastResults.isEmpty()) {
1671 mUI->mResults->updateFromOldReport(lastResults);
1683 helpDialog->showMaximized();
1688 const QString filter = tr(
"Project files (*.cppcheck);;All files(*.*)");
1689 const QString filepath = QFileDialog::getOpenFileName(
this,
1690 tr(
"Select Project File"),
1694 if (!filepath.isEmpty()) {
1695 const QFileInfo fi(filepath);
1696 if (fi.exists() && fi.isFile() && fi.isReadable()) {
1716 QFileInfo inf(filePath);
1717 const QString filename = inf.fileName();
1722 mUI->mActionCloseProjectFile->setEnabled(
true);
1723 mUI->mActionEditProjectFile->setEnabled(
true);
1741 if (lastResults.isEmpty())
1743 if (!QFileInfo::exists(lastResults))
1745 mUI->mResults->readErrorsXml(lastResults);
1747 mUI->mActionViewStats->setEnabled(
true);
1757 const QString& rootpath = projectFile->
getRootPath();
1759 QDir::setCurrent(inf.absolutePath());
1765 if (rootpath.isEmpty() || rootpath ==
".")
1767 else if (rootpath.startsWith(
"./"))
1774 if (!QDir::isAbsolutePath(buildDir))
1775 buildDir = inf.canonicalPath() +
'/' + buildDir;
1776 if (!QDir(buildDir).exists()) {
1777 QMessageBox msg(QMessageBox::Question,
1779 tr(
"Build dir '%1' does not exist, create it?").arg(buildDir),
1780 QMessageBox::Yes | QMessageBox::No,
1782 if (msg.exec() == QMessageBox::Yes) {
1783 QDir().mkpath(buildDir);
1784 }
else if (!projectFile->
getAddons().isEmpty()) {
1785 QMessageBox m(QMessageBox::Critical,
1787 tr(
"To check the project using addons, you need a build directory."),
1809 QString errorMessage;
1819 errorMessage = tr(
"Failed to open file");
1822 errorMessage = tr(
"Unknown project file format");
1825 errorMessage = tr(
"Failed to import project file");
1832 if (!errorMessage.isEmpty()) {
1833 QMessageBox msg(QMessageBox::Critical,
1835 tr(
"Failed to import '%1': %2\n\nAnalysis is stopped.").arg(prjfile).arg(errorMessage),
1842 QMessageBox msg(QMessageBox::Critical,
1844 tr(
"Failed to import '%1' (%2), analysis is stopped").arg(prjfile).arg(QString::fromStdString(e.
errorMessage)),
1860 if (paths.isEmpty()) {
1868 const QString filter = tr(
"Project files (*.cppcheck)");
1869 QString filepath = QFileDialog::getSaveFileName(
this,
1870 tr(
"Select Project Filename"),
1874 if (filepath.isEmpty())
1876 if (!filepath.endsWith(
".cppcheck", Qt::CaseInsensitive))
1877 filepath +=
".cppcheck";
1881 QFileInfo inf(filepath);
1882 const QString filename = inf.fileName();
1893 if (dlg.exec() == QDialog::Accepted) {
1905 mUI->mResults->clear(
true);
1914 QMessageBox msg(QMessageBox::Critical,
1916 QString(tr(
"No project file loaded")),
1924 if (dlg.exec() == QDialog::Accepted) {
1947 libraryDialog.exec();
1957 mUI->mActionCloseProjectFile->setEnabled(enable);
1958 mUI->mActionEditProjectFile->setEnabled(enable);
1959 mUI->mActionCheckLibrary->setEnabled(enable);
1960 mUI->mActionCheckConfiguration->setEnabled(enable);
1965 mUI->mActionNewProjectFile->setEnabled(enable);
1966 mUI->mActionOpenProjectFile->setEnabled(enable);
1971 auto *action = qobject_cast<QAction *>(sender());
1974 const QString project = action->data().toString();
1975 QFileInfo inf(project);
1977 if (inf.suffix() ==
"xml")
1984 const QString text(tr(
"The project file\n\n%1\n\n could not be found!\n\n"
1985 "Do you want to remove the file from the recently "
1986 "used projects -list?").arg(project));
1988 QMessageBox msg(QMessageBox::Warning,
1991 QMessageBox::Yes | QMessageBox::No,
1994 msg.setDefaultButton(QMessageBox::No);
1995 const int rv = msg.exec();
1996 if (rv == QMessageBox::Yes) {
2005 if (recentProjectAct !=
nullptr)
2006 mUI->mMenuFile->removeAction(recentProjectAct);
2012 int removed = projects.removeDuplicates();
2013 for (
int i = projects.size() - 1; i >= 0; i--) {
2014 if (!QFileInfo::exists(projects[i])) {
2015 projects.removeAt(i);
2024 for (
int i = 0; i < numRecentProjects; i++) {
2025 const QString filename = QFileInfo(projects[i]).fileName();
2026 const QString text = QString(
"&%1 %2").arg(i + 1).arg(filename);
2033 if (numRecentProjects > 1)
2040 files.removeAll(project);
2041 files.prepend(project);
2052 files.removeAll(project);
2060 auto *action = qobject_cast<QAction *>(sender());
2071 ids.removeDuplicates();
2074 for (
const QString&
id : ids) {
2076 std::string id2 =
id.toStdString();
2077 for (
int i = 0; i < suppressions.size();) {
2078 if (suppressions[i].errorId == id2)
2079 suppressions.removeAt(i);
2086 suppressions << newSuppression;
2097 for (
const auto c: nameWithVersion) {
2098 if (c ==
'\n' || c ==
'\r')
2101 if (ret > 0 && dot == 1 && nameWithVersion.endsWith(
" dev"))
2102 return ret * 1000000 + v * 1000 + 500;
2105 else if (c ==
'.') {
2107 ret = ret * 1000 + v;
2109 }
else if (c >=
'0' && c <=
'9')
2110 v = v * 10 + (c.toLatin1() -
'0');
2112 ret = ret * 1000 + v;
2121 reply->deleteLater();
2122 if (reply->error()) {
2123 mUI->mLayoutInformation->deleteLater();
2124 qDebug() <<
"Response: ERROR";
2127 const QString str = reply->readAll();
2128 qDebug() <<
"Response: " << str;
2129 if (reply->url().fileName() ==
"version.txt") {
2133 const int appVersion =
getVersion(nameWithVersion);
2134 const int latestVersion =
getVersion(str.trimmed());
2135 if (appVersion < latestVersion) {
2140 const QString url(
"https://cppchecksolutions.com/cppcheck-premium-installation");
2142 const QString url(
"https://cppchecksolutions.com/cppcheck-premium-linux-installation");
2144 install =
"<a href=\"" + url +
"\">" + tr(
"Install") +
"</a>";
2146 mUI->mButtonHideInformation->setVisible(
true);
2147 mUI->mLabelInformation->setVisible(
true);
2148 mUI->mLabelInformation->setText(tr(
"New version available: %1. %2").arg(str.trimmed()).arg(install));
2152 if (!
mUI->mLabelInformation->isVisible()) {
2153 mUI->mLayoutInformation->deleteLater();
2160 mUI->mLabelInformation->setVisible(
false);
2161 mUI->mButtonHideInformation->setVisible(
false);
2162 mUI->mLayoutInformation->deleteLater();
List of applications user has specified to open errors with.
bool loadSettings()
Load all applications.
void saveSettings() const
Save all applications.
static int executeCommand(std::string exe, std::vector< std::string > args, std::string redirect, std::string &output)
This is the base class which will use other classes to do static code analysis for C and C++ code to ...
static const char * version()
Returns current version number as a string.
static const char * extraVersion()
Returns extra version info as a string.
A class containing error data for one error.
A class for listing files and directories to check.
static QStringList getDefaultFilters()
Return list of default filename extensions included.
QStringList getFileList() const
Return list of filenames (to check).
void addPathList(const QStringList &paths)
Add list of filenames and directories to the list.
void addExcludeList(const QStringList &paths)
Add list of paths to exclusion list.
Importing project settings.
std::list< FileSettings > fileSettings
void selectVsConfigurations(Platform::Type platform, const std::vector< std::string > &configurations)
void ignorePaths(const std::vector< std::string > &ipaths)
void ignoreOtherConfigs(const std::string &cfg)
Type import(const std::string &filename, Settings *settings=nullptr)
Library definitions handling.
@ DUPLICATE_PLATFORM_TYPE
@ PLATFORM_TYPE_REDEFINED
Error load(const char exename[], const char path[])
Main window for cppcheck-gui.
void filterResults()
Filters the results in the result list.
void newProjectFile()
Slot to create new project file.
void enableProjectActions(bool enable)
Enable or disable project file actions.
void reAnalyzeAll()
Slot to reanalyze all files.
void closeEvent(QCloseEvent *event) override
Event coming when application is about to close.
bool loadLastResults()
Load last project results to the GUI.
QNetworkAccessManager * mNetworkAccessManager
ThreadHandler * mThread
Thread to analyze files.
void loadResults(const QString &selectedFile)
Load XML file to the GUI.
QStringList selectFilesToAnalyze(QFileDialog::FileMode mode)
Select files/or directory to analyze.
void showStatistics()
Slot for showing the scan and project statistics.
void showErrors(bool checked)
Show errors with type "error".
void setLanguage(const QString &code)
Set current language.
bool mExiting
Are we exiting the cppcheck? If this is true then the cppcheck is waiting for check threads to exit s...
void uncheckAll()
Slot to uncheck all "Show errors" menu items.
void handleCLIParams(const QStringList ¶ms)
Handle command line parameters given to GUI.
void showScratchpad()
Slot to show scratchpad.
void toggleMainToolBar()
Slot for showing/hiding standard toolbar.
void closeProjectFile()
Slot to close open project file.
void loadProjectFile(const QString &filePath)
Load project file to the GUI.
void enableProjectOpenActions(bool enable)
Enable or disable project file actions.
void analyzeCode(const QString &code, const QString &filename)
Analyze given code.
void save()
Slot to save results.
void checkAll()
Slot to check all "Show errors" menu items.
void clearResults()
Slot to clear all search results.
void doAnalyzeFiles(const QStringList &files, const bool checkLibrary=false, const bool checkConfiguration=false)
Analyze all files specified in parameter files.
void enableCheckButtons(bool enable)
Helper function to enable/disable all check,recheck buttons.
QAction * mRecentProjectActs[MaxRecentProjects+1]
Project MRU menu actions.
void replyFinished(QNetworkReply *reply)
void openHelpContents()
Open help file contents.
QString mCppcheckCfgProductName
void addProjectMRU(const QString &project)
Add project file (path) to the MRU list.
bool tryLoadLibrary(Library &library, const QString &filename)
Tries to load library file, prints message on error.
void checkLibrary()
Slot to reanalyze with checking library configuration.
void showLicense()
Slot to to show license text.
void toggleViewToolBar()
Slot for showing/hiding Categories toolbar.
bool mIsLogfileLoaded
Set to true in case of loading log file.
void reAnalyzeSelected(const QStringList &files)
Reanalyze selected files.
void analysisDone()
Slot for checkthread's done signal.
void analyzeDirectory()
Slot for analyze directory menu item.
Library::Error loadLibrary(Library &library, const QString &filename)
Load library file.
void updateMRUMenuItems()
Update project MRU items in File-menu.
ScratchPad * mScratchPad
Scratchpad.
void showInformation(bool checked)
Show errors with type "information".
QActionGroup * mCppStandardActions
QTimer * mFilterTimer
Timer to delay filtering while typing.
void removeProjectMRU(const QString &project)
Remove project file (path) from the MRU list.
QActionGroup * mCStandardActions
GUI actions for selecting the coding standard.
void programSettings()
Slot to open program's settings dialog.
void about()
Slot to open program's about dialog.
void showStyle(bool checked)
Show errors with type "style".
void analyzeFiles()
Slot for analyze files menu item.
void openRecentProject()
Opens recently opened project file.
void showLibraryEditor()
Slot for showing the library editor.
void addIncludeDirs(const QStringList &includeDirs, Settings &result)
Add include directories.
QLineEdit * mLineEditFilter
Filter field in the Filter toolbar.
Platforms mPlatforms
List of checked platforms.
QString loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString &addon)
ApplicationList * mApplications
List of user defined applications to open errors with.
void saveSettings() const
Save program settings.
void openResults()
Slot to open XML report file.
void loadSettings()
Load program settings.
void openProjectFile()
Slot to open project file and start analyzing contained paths.
void enableResultsButtons()
Helper function to enable/disable results buttons (clear,save,print)
QActionGroup * mSelectLanguageActions
GUI actions for selecting language.
static void openOnlineHelp()
Show help contents.
Ui::MainWindow * mUI
Class holding all UI components.
void aboutToShowViewMenu()
Slot for updating View-menu before it is shown.
void analyzeProject(const ProjectFile *projectFile, const bool checkLibrary=false, const bool checkConfiguration=false)
Analyze the project.
bool isCppcheckPremium() const
ProjectFile * mProjectFile
Project (file).
void showPerformance(bool checked)
Show errors with type "performance".
TranslationHandler * mTranslation
Class to handle translation changes.
void resultsAdded()
Slot for enabling save and clear button.
QString mCurrentDirectory
Current analyzed directory.
QActionGroup * mPlatformActions
GUI actions for selecting the analyzed platform.
QSettings * mSettings
Program settings.
QPair< bool, Settings > getCppcheckSettings()
Get our default cppcheck settings and read project file.
void doAnalyzeProject(ImportProject p, const bool checkLibrary=false, const bool checkConfiguration=false)
Analyze project.
void toggleFilterToolBar()
Slot for showing/hiding Filter toolbar.
void toggleAllChecked(bool checked)
Helper function to toggle all show error menu items.
void stopAnalysis()
Slot when stop analysis button is pressed.
MainWindow(TranslationHandler *th, QSettings *settings)
void showPortability(bool checked)
Show errors with type "portability".
QString mCppcheckCfgAbout
QString getLastResults() const
Get filename for last results.
void complianceReport()
Slot to generate compliance report.
void showWarnings(bool checked)
Show errors with type "warning".
void reAnalyzeModified()
Slot to reanalyze modified files.
void checkConfiguration()
Slot to check configuration.
void formatAndSetTitle(const QString &text=QString())
Format main window title.
void suppressIds(QStringList ids)
Suppress error ids.
void showAuthors()
Slot to to show authors list.
void editProjectFile()
Slot to edit project file.
void selectPlatform()
Selects the platform as analyzed platform.
void reAnalyze(bool all)
Reanalyzes files.
void checkLockDownUI()
Lock down UI while analyzing.
void performSelectedFilesCheck(const QStringList &selectedFilesList)
Slot to reanalyze selected files.
A dialog for editing project file data.
A class that reads and writes project files.
const QStringList & getCodingStandards() const
Get list of coding standards (checked by Cppcheck Premium).
QStringList getAddonsAndTools() const
Get list of addons and tools.
bool clangParser
Use Clang parser.
int getMaxCtuDepth() const
QList< SuppressionList::Suppression > getCheckingSuppressions() const
Get "checking" suppressions.
const QStringList & getAddons() const
Get list addons.
const QString & getPlatform() const
Get platform.
bool isCheckLevelExhaustive() const
const QString & getFilename() const
Get filename for the project file.
const QString & getRootPath() const
Get project root path.
bool getBughunting() const
void setBuildDir(const QString &buildDir)
const QList< SuppressionList::Suppression > & getSuppressions() const
Get "raw" suppressions.
const QStringList & getCheckUnknownFunctionReturn() const
Check unknown function return values.
const QStringList & getDefines() const
Get list of defines.
QStringList getCheckPaths() const
Get list of paths to check.
bool getAnalyzeAllVsConfigs() const
int getCertIntPrecision() const
int getMaxTemplateRecursion() const
const QStringList & getUndefines() const
Get list of undefines.
const QStringList & getVsConfigurations() const
Get list of paths to exclude from the check.
static QString getAddonFilePath(QString filesDir, const QString &addon)
Get path to addon python script.
bool read(const QString &filename=QString())
Read the project file.
void setProjectName(QString projectName)
void setFilename(const QString &filename)
Set filename for the project file.
bool getCheckUnusedTemplates() const
QStringList getExcludedPaths() const
Get list of paths to exclude from the check.
QStringList getIncludeDirs() const
Get list of include directories.
bool getCheckHeaders() const
const QStringList & getLibraries() const
Get list libraries.
const QString & getBuildDir() const
bool write(const QString &filename=QString())
Write project file (to disk).
void setSuppressions(const QList< SuppressionList::Suppression > &suppressions)
Set list of suppressions.
const QString & getImportProject() const
void checkSelected(QStringList selectedFilesList)
Signal to perform recheck of selected files.
void suppressIds(QStringList ids)
Suppress Ids.
void showCppcheckResults(bool show)
Show/hide cppcheck errors.
void collapseAllResults()
Collapse all results in the result list.
void showHiddenResults()
Show hidden results in the result list.
void showClangResults(bool show)
Show/hide clang-tidy/clang-analyzer errors.
void resultsHidden(bool hidden)
Signal that results have been hidden or shown.
void gotResults()
Signal to be emitted when we have results.
void expandAllResults()
Expand all results in the result list.
void log(const QString &str)
Log message.
void debugError(const ErrorItem &item)
debug message
A window with a text field that .
void translate()
Translate dialog.
bool showNoErrorsMessage() const
Get checkbox value for mNoErrorsMessage.
bool saveAllErrors() const
Get checkbox value for mSaveAllErrors.
void saveSettingValues() const
Save all values to QSettings.
bool saveFullPath() const
Get checkbox value for mSaveFullPath.
bool showInconclusive() const
Get checkbox value for mEnableInconclusive.
bool showFullPath() const
Get checkbox value for mShowFullPath.
bool showErrorId() const
Get checkbox value for mShowIdColumn.
This is just a container for general settings so that we don't need to pass individual values to func...
std::set< std::string > userUndefs
undefines given by the user
static void terminate(bool t=true)
Request termination of checking.
static std::string loadCppcheckCfg(Settings &settings, Suppressions &suppressions)
bool quiet
Is –quiet given?
bool checkLibrary
Check for incomplete info in library files?
bool checkHeaders
Check code in the headers, this is on by default but can be turned off to save CPU.
bool checkAllConfigurations
check all configurations (false if -D or –max-configs is used
int maxCtuDepth
–max-ctu-depth
Suppressions supprs
suppressions
Standards::Language enforcedLang
Name of the language that is enforced.
SimpleEnableGroup< Checks > checks
bool xml
write XML results (–xml)
bool checkConfiguration
Is the 'configuration checking' wanted?
std::unordered_set< std::string > addons
addons, either filename of python/json file or json data
void setMisraRuleTexts(const ExecuteCmdFn &executeCommand)
std::string buildDir
–cppcheck-build-dir.
std::string cppcheckCfgProductName
cppcheck.cfg: Custom product name
std::string userDefines
defines given by the user
std::vector< AddonInfo > addonInfos
the loaded addons infos
std::string premiumArgs
Extra arguments for Cppcheck Premium addon.
bool inlineSuppressions
Is –inline-suppr given?
void setCheckLevel(CheckLevel level)
std::string cppcheckCfgAbout
cppcheck.cfg: About text
unsigned int jobs
How many processes/threads should do checking at the same time.
bool force
Force checking the files with "too many" configurations (–force).
bool verbose
Is –verbose given?
std::set< std::string > checkUnknownFunctionReturn
check unknown function return values
std::list< std::string > libraries
–library=
std::list< std::string > includePaths
List of include paths, e.g.
int maxTemplateRecursion
max template recursion
SimpleEnableGroup< Certainty > certainty
int maxConfigs
Maximum number of configurations to check before bailing.
SimpleEnableGroup< Severity > severity
bool checkUnusedTemplates
Check unused/uninstantiated templates.
bool debugwarnings
Is –debug-warnings given?
Standards standards
Struct contains standards settings.
A class for different show types we have.
bool isShown(ShowTypes::ShowType category) const
Is the showtype visible in the GUI?
void setEnabled(T flag, bool enabled)
A dialog that shows project and scan statistics.
void setScanDuration(double seconds)
Sets the number of seconds to display beside "Scan Duration:".
void setNumberOfFilesScanned(int num)
Sets the number to display beside "Number of Files Scanned:".
void setProject(const ProjectFile *projectFile)
Sets the project to extract statistics from.
void setStatistics(const CheckStatistics *stats)
Sets the numbers of different error/warnings found.
void setPathSelected(const QString &path)
Sets the string to display beside "Path Selected:".
std::string addSuppression(Suppression suppression)
Don't show this error.
This class handles creating threadresult and starting threads.
bool hasPreviousFiles() const
Have we checked files already?
void done()
Signal that all threads are done.
void check(const Settings &settings)
Start the threads to check the files.
QDateTime getCheckStartTime() const
Get start time of last check.
void setAddonsAndTools(const QStringList &addonsAndTools)
QStringList getReCheckFiles(bool all) const
Get files that should be rechecked because they have been changed.
void stop()
Slot to stop all threads.
void setClangIncludePaths(const QStringList &s)
void debugError(const ErrorItem &item)
bool isChecking() const
Is checking running?
void log(const QString &msg)
void setProject(const ImportProject &prj)
Set project to check.
int getPreviousFilesCount() const
Return count of files we checked last time.
void setCheckStartTime(QDateTime checkStartTime)
Set start time of check.
void clearFiles()
Clear all files from cppcheck.
int getPreviousScanDuration() const
Return the time elapsed while scanning the previous time.
void setCheckFiles(bool all)
Set files to check.
void initialize(const ResultsView *view)
Initialize the threads (connect all signals to resultsview's slots)
void setFiles(const QStringList &files)
Set files to check.
void setSuppressions(const QList< SuppressionList::Suppression > &s)
Threads use this class to obtain new files to process and to publish results.
void setFiles(const QStringList &files)
Set list of files to check.
A class handling the available translations.
const QString & getCurrentLanguage() const
Get currently selected translation.
bool setLanguage(const QString &code)
Set active translation.
std::string toString(Color c)
@ portability
Portability warning.
@ information
Checking information.
@ performance
Performance warning.
@ error
Programming error.
#define SETTINGS_LAST_ANALYZE_FILES_FILTER
#define SETTINGS_SHOW_INFORMATION
#define SETTINGS_WINDOW_HEIGHT
#define SETTINGS_PYTHON_PATH
#define SETTINGS_ENFORCED_LANGUAGE
#define SETTINGS_TOOLBARS_FILTER_SHOW
#define SETTINGS_LAST_RESULT_PATH
#define SETTINGS_INLINE_SUPPRESSIONS
#define SETTINGS_LAST_CHECK_PATH
QString getPath(const QString &type)
Obtains the path of specified type Returns the path of specified type if not empty.
QString getDataDir()
Get configured data dir.
#define SETTINGS_CHECKED_PLATFORM
#define SETTINGS_TOOLBARS_VIEW_SHOW
#define SETTINGS_SHOW_ERRORS
#define SETTINGS_TOOLBARS_MAIN_SHOW
#define SETTINGS_CHECK_FOR_UPDATES
#define SETTINGS_CHECK_FORCE
QString toFilterString(const QMap< QString, QString > &filters, bool addAllSupported, bool addAll)
Creates a string suitable for passing as the filter argument to methods like QFileDialog::getOpenFile...
#define SETTINGS_SHOW_PERFORMANCE
#define SETTINGS_VS_INCLUDE_PATHS
#define SETTINGS_LANGUAGE
#define SETTINGS_MRU_PROJECTS
#define SETTINGS_CHECK_VERSION
#define SETTINGS_SHOW_DEBUG_WARNINGS
#define SETTINGS_WINDOW_MAXIMIZED
QSetting value names.
#define SETTINGS_SHOW_STYLE
#define SETTINGS_INCONCLUSIVE_ERRORS
#define SETTINGS_WINDOW_WIDTH
#define SETTINGS_LAST_PROJECT_PATH
#define SETTINGS_MISRA_FILE
#define SETTINGS_SHOW_WARNINGS
#define SETTINGS_GLOBAL_INCLUDE_PATHS
void setPath(const QString &type, const QString &value)
Stores last used path of specified type Stores provided path as last used path for specified type.
#define SETTINGS_SHOW_STATISTICS
#define SETTINGS_OPEN_PROJECT
#define SETTINGS_SHOW_PORTABILITY
#define SETTINGS_CHECK_THREADS
static int getVersion(const QString &nameWithVersion)
static const QString compile_commands_json("compile_commands.json")
static QString fromNativePath(const QString &p)
static std::string cfg(const std::vector< std::string > &configs, const std::string &userDefines)
std::string getAddonInfo(const std::string &fileName, const std::string &exename)
Simple container to be thrown when internal error is detected.
bool classes
Public interface of classes.
bool externalVariables
Global variables that can be modified outside the TU.
bool externalFunctions
External functions.
bool internalFunctions
Experimental: assume that internal functions can be used in any way This is only available in the GUI...
This is just a container for standards settings.
bool setC(const std::string &str)
bool setCPP(std::string str)
enum Standards::cppstd_t cpp
SuppressionList nomsg
suppress message (–suppressions)