Cppcheck
mainwindow.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "mainwindow.h"
20 
21 #include "addoninfo.h"
22 #include "applicationlist.h"
23 #include "aboutdialog.h"
24 #include "analyzerinfo.h"
25 #include "checkthread.h"
26 #include "common.h"
27 #include "cppcheck.h"
28 #include "errortypes.h"
29 #include "filelist.h"
30 #include "filesettings.h"
31 #include "compliancereportdialog.h"
32 #include "fileviewdialog.h"
33 #include "helpdialog.h"
34 #include "importproject.h"
35 #include "librarydialog.h"
36 #include "platform.h"
37 #include "projectfile.h"
38 #include "projectfiledialog.h"
39 #include "report.h"
40 #include "resultsview.h"
41 #include "scratchpad.h"
42 #include "settings.h"
43 #include "showtypes.h"
44 #include "statsdialog.h"
45 #include "settingsdialog.h"
46 #include "standards.h"
47 #include "suppressions.h"
48 #include "threadhandler.h"
49 #include "threadresult.h"
50 #include "translationhandler.h"
51 
52 #include "ui_mainwindow.h"
53 
54 #include <algorithm>
55 #include <iterator>
56 #include <list>
57 #include <set>
58 #include <string>
59 #include <unordered_set>
60 #include <utility>
61 #include <vector>
62 
63 #include <QApplication>
64 #include <QAction>
65 #include <QActionGroup>
66 #include <QByteArray>
67 #include <QChar>
68 #include <QCloseEvent>
69 #include <QCoreApplication>
70 #include <QDateTime>
71 #include <QDebug>
72 #include <QDialog>
73 #include <QDir>
74 #include <QFile>
75 #include <QFileInfo>
76 #include <QHBoxLayout>
77 #include <QInputDialog>
78 #include <QKeySequence>
79 #include <QLabel>
80 #include <QLineEdit>
81 #include <QList>
82 #include <QMap>
83 #include <QMenu>
84 #include <QMessageBox>
85 #include <QtNetwork/QNetworkAccessManager>
86 #include <QtNetwork/QNetworkReply>
87 #include <QtNetwork/QNetworkRequest>
88 #include <QPushButton>
89 #include <QRegularExpression>
90 #include <QSettings>
91 #include <QSize>
92 #include <QTimer>
93 #include <QTemporaryFile>
94 #include <QToolBar>
95 #include <QUrl>
96 #include <QVariant>
97 #include <Qt>
98 
99 #include "json.h"
100 
101 static const QString compile_commands_json("compile_commands.json");
102 
103 static QString fromNativePath(const QString& p) {
104 #ifdef Q_OS_WIN
105  QString ret(p);
106  ret.replace('\\', '/');
107  return ret;
108 #else
109  return p;
110 #endif
111 }
112 
113 MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
114  mSettings(settings),
115  mApplications(new ApplicationList(this)),
116  mTranslation(th),
117  mUI(new Ui::MainWindow),
118  mPlatformActions(new QActionGroup(this)),
119  mCStandardActions(new QActionGroup(this)),
120  mCppStandardActions(new QActionGroup(this)),
121  mSelectLanguageActions(new QActionGroup(this))
122 {
123  {
124  Settings tempSettings;
125  tempSettings.exename = QCoreApplication::applicationFilePath().toStdString();
126  Settings::loadCppcheckCfg(tempSettings, tempSettings.supprs); // TODO: how to handle error?
127  mCppcheckCfgProductName = QString::fromStdString(tempSettings.cppcheckCfgProductName);
128  mCppcheckCfgAbout = QString::fromStdString(tempSettings.cppcheckCfgAbout);
129  }
130 
131  mUI->setupUi(this);
132  mThread = new ThreadHandler(this);
133  mUI->mResults->initialize(mSettings, mApplications, mThread);
134 
135  // Filter timer to delay filtering results slightly while typing
136  mFilterTimer = new QTimer(this);
137  mFilterTimer->setInterval(500);
138  mFilterTimer->setSingleShot(true);
139  connect(mFilterTimer, &QTimer::timeout, this, &MainWindow::filterResults);
140 
141  // "Filter" toolbar
142  mLineEditFilter = new QLineEdit(mUI->mToolBarFilter);
143  mLineEditFilter->setPlaceholderText(tr("Quick Filter:"));
144  mLineEditFilter->setClearButtonEnabled(true);
145  mUI->mToolBarFilter->addWidget(mLineEditFilter);
146  connect(mLineEditFilter, SIGNAL(textChanged(QString)), mFilterTimer, SLOT(start()));
147  connect(mLineEditFilter, &QLineEdit::returnPressed, this, &MainWindow::filterResults);
148 
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);
152  connect(mUI->mActionAnalyzeFiles, &QAction::triggered, this, &MainWindow::analyzeFiles);
153  connect(mUI->mActionAnalyzeDirectory, &QAction::triggered, this, &MainWindow::analyzeDirectory);
154  connect(mUI->mActionSettings, &QAction::triggered, this, &MainWindow::programSettings);
155  connect(mUI->mActionClearResults, &QAction::triggered, this, &MainWindow::clearResults);
156  connect(mUI->mActionOpenXML, &QAction::triggered, this, &MainWindow::openResults);
157 
158  connect(mUI->mActionShowStyle, &QAction::toggled, this, &MainWindow::showStyle);
159  connect(mUI->mActionShowErrors, &QAction::toggled, this, &MainWindow::showErrors);
160  connect(mUI->mActionShowWarnings, &QAction::toggled, this, &MainWindow::showWarnings);
161  connect(mUI->mActionShowPortability, &QAction::toggled, this, &MainWindow::showPortability);
162  connect(mUI->mActionShowPerformance, &QAction::toggled, this, &MainWindow::showPerformance);
163  connect(mUI->mActionShowInformation, &QAction::toggled, this, &MainWindow::showInformation);
164  connect(mUI->mActionShowCppcheck, &QAction::toggled, mUI->mResults, &ResultsView::showCppcheckResults);
165  connect(mUI->mActionShowClang, &QAction::toggled, mUI->mResults, &ResultsView::showClangResults);
166  connect(mUI->mActionCheckAll, &QAction::triggered, this, &MainWindow::checkAll);
167  connect(mUI->mActionUncheckAll, &QAction::triggered, this, &MainWindow::uncheckAll);
168  connect(mUI->mActionCollapseAll, &QAction::triggered, mUI->mResults, &ResultsView::collapseAllResults);
169  connect(mUI->mActionExpandAll, &QAction::triggered, mUI->mResults, &ResultsView::expandAllResults);
170  connect(mUI->mActionShowHidden, &QAction::triggered, mUI->mResults, &ResultsView::showHiddenResults);
171  connect(mUI->mActionViewStats, &QAction::triggered, this, &MainWindow::showStatistics);
172  connect(mUI->mActionLibraryEditor, &QAction::triggered, this, &MainWindow::showLibraryEditor);
173 
174  connect(mUI->mActionReanalyzeModified, &QAction::triggered, this, &MainWindow::reAnalyzeModified);
175  connect(mUI->mActionReanalyzeAll, &QAction::triggered, this, &MainWindow::reAnalyzeAll);
176  connect(mUI->mActionCheckLibrary, &QAction::triggered, this, &MainWindow::checkLibrary);
177  connect(mUI->mActionCheckConfiguration, &QAction::triggered, this, &MainWindow::checkConfiguration);
178 
179  connect(mUI->mActionStop, &QAction::triggered, this, &MainWindow::stopAnalysis);
180  connect(mUI->mActionSave, &QAction::triggered, this, &MainWindow::save);
181  connect(mUI->mActionComplianceReport, &QAction::triggered, this, &MainWindow::complianceReport);
182 
183  // About menu
184  connect(mUI->mActionAbout, &QAction::triggered, this, &MainWindow::about);
185  connect(mUI->mActionLicense, &QAction::triggered, this, &MainWindow::showLicense);
186 
187  // View > Toolbar menu
188  connect(mUI->mActionToolBarMain, SIGNAL(toggled(bool)), this, SLOT(toggleMainToolBar()));
189  connect(mUI->mActionToolBarView, SIGNAL(toggled(bool)), this, SLOT(toggleViewToolBar()));
190  connect(mUI->mActionToolBarFilter, SIGNAL(toggled(bool)), this, SLOT(toggleFilterToolBar()));
191 
192  connect(mUI->mActionAuthors, &QAction::triggered, this, &MainWindow::showAuthors);
194  connect(mThread, &ThreadHandler::log, mUI->mResults, &ResultsView::log);
196  connect(mUI->mResults, &ResultsView::gotResults, this, &MainWindow::resultsAdded);
197  connect(mUI->mResults, &ResultsView::resultsHidden, mUI->mActionShowHidden, &QAction::setEnabled);
199  connect(mUI->mResults, &ResultsView::suppressIds, this, &MainWindow::suppressIds);
200  connect(mUI->mMenuView, &QMenu::aboutToShow, this, &MainWindow::aboutToShowViewMenu);
201 
202  // File menu
203  connect(mUI->mActionNewProjectFile, &QAction::triggered, this, &MainWindow::newProjectFile);
204  connect(mUI->mActionOpenProjectFile, &QAction::triggered, this, &MainWindow::openProjectFile);
205  connect(mUI->mActionShowScratchpad, &QAction::triggered, this, &MainWindow::showScratchpad);
206  connect(mUI->mActionCloseProjectFile, &QAction::triggered, this, &MainWindow::closeProjectFile);
207  connect(mUI->mActionEditProjectFile, &QAction::triggered, this, &MainWindow::editProjectFile);
208 
209  connect(mUI->mActionHelpContents, &QAction::triggered, this, &MainWindow::openHelpContents);
210 
211  loadSettings();
212 
213  mThread->initialize(mUI->mResults);
214  if (mProjectFile)
215  formatAndSetTitle(tr("Project:") + ' ' + mProjectFile->getFilename());
216  else
218 
219  mUI->mActionComplianceReport->setVisible(isCppcheckPremium());
220 
221  enableCheckButtons(true);
222 
223  mUI->mActionPrint->setShortcut(QKeySequence::Print);
226  enableProjectActions(false);
227 
228  // Must setup MRU menu before CLI param handling as it can load a
229  // project file and update MRU menu.
230  for (int i = 0; i < MaxRecentProjects; ++i) {
231  mRecentProjectActs[i] = new QAction(this);
232  mRecentProjectActs[i]->setVisible(false);
233  connect(mRecentProjectActs[i], SIGNAL(triggered()),
234  this, SLOT(openRecentProject()));
235  }
236  mRecentProjectActs[MaxRecentProjects] = nullptr; // The separator
237  mUI->mActionProjectMRU->setVisible(false);
239 
240  QStringList args = QCoreApplication::arguments();
241  //Remove the application itself
242  args.removeFirst();
243  if (!args.isEmpty()) {
244  handleCLIParams(args);
245  }
246 
247  mUI->mActionCloseProjectFile->setEnabled(mProjectFile != nullptr);
248  mUI->mActionEditProjectFile->setEnabled(mProjectFile != nullptr);
249 
250  for (int i = 0; i < mPlatforms.getCount(); i++) {
251  PlatformData platform = mPlatforms.mPlatforms[i];
252  auto *action = new QAction(this);
253  platform.mActMainWindow = action;
254  mPlatforms.mPlatforms[i] = platform;
255  action->setText(platform.mTitle);
256  action->setData(platform.mType);
257  action->setCheckable(true);
258  action->setActionGroup(mPlatformActions);
259  mUI->mMenuAnalyze->insertAction(mUI->mActionPlatforms, action);
260  connect(action, SIGNAL(triggered()), this, SLOT(selectPlatform()));
261  }
262 
263  mUI->mActionC89->setActionGroup(mCStandardActions);
264  mUI->mActionC99->setActionGroup(mCStandardActions);
265  mUI->mActionC11->setActionGroup(mCStandardActions);
266 
267  mUI->mActionCpp03->setActionGroup(mCppStandardActions);
268  mUI->mActionCpp11->setActionGroup(mCppStandardActions);
269  mUI->mActionCpp14->setActionGroup(mCppStandardActions);
270  mUI->mActionCpp17->setActionGroup(mCppStandardActions);
271  mUI->mActionCpp20->setActionGroup(mCppStandardActions);
272  //mUI->mActionCpp23->setActionGroup(mCppStandardActions);
273 
274  mUI->mActionEnforceC->setActionGroup(mSelectLanguageActions);
275  mUI->mActionEnforceCpp->setActionGroup(mSelectLanguageActions);
276  mUI->mActionAutoDetectLanguage->setActionGroup(mSelectLanguageActions);
277 
278  // TODO: we no longer default to a Windows platform in CLI - so we should probably also get rid of this in the GUI
279  // For Windows platforms default to Win32 checked platform.
280  // For other platforms default to unspecified/default which means the
281  // platform Cppcheck GUI was compiled on.
282 #if defined(_WIN32)
283  constexpr Platform::Type defaultPlatform = Platform::Type::Win32W;
284 #else
285  constexpr Platform::Type defaultPlatform = Platform::Type::Unspecified;
286 #endif
287  PlatformData &platform = mPlatforms.get((Platform::Type)mSettings->value(SETTINGS_CHECKED_PLATFORM, defaultPlatform).toInt());
288  platform.mActMainWindow->setChecked(true);
289 
290  mNetworkAccessManager = new QNetworkAccessManager(this);
291  connect(mNetworkAccessManager, &QNetworkAccessManager::finished,
293 
294  mUI->mLabelInformation->setVisible(false);
295  mUI->mButtonHideInformation->setVisible(false);
296  connect(mUI->mButtonHideInformation, &QPushButton::clicked,
298 
299  if (mSettings->value(SETTINGS_CHECK_FOR_UPDATES, false).toBool()) {
300  // Is there a new version?
301  if (isCppcheckPremium()) {
302  const QUrl url("https://files.cppchecksolutions.com/version.txt");
303  mNetworkAccessManager->get(QNetworkRequest(url));
304  } else {
305  const QUrl url("https://cppcheck.sourceforge.io/version.txt");
306  mNetworkAccessManager->get(QNetworkRequest(url));
307  }
308  } else {
309  delete mUI->mLayoutInformation;
310  }
311 }
312 
314 {
315  delete mProjectFile;
316  delete mScratchPad;
317  delete mUI;
318 }
319 
320 void MainWindow::handleCLIParams(const QStringList &params)
321 {
322  int index;
323  if (params.contains("-p")) {
324  index = params.indexOf("-p");
325  if ((index + 1) < params.length())
326  loadProjectFile(params[index + 1]);
327  } else if (params.contains("-l")) {
328  QString logFile;
329  index = params.indexOf("-l");
330  if ((index + 1) < params.length())
331  logFile = params[index + 1];
332 
333  if (params.contains("-d")) {
334  QString checkedDir;
335  index = params.indexOf("-d");
336  if ((index + 1) < params.length())
337  checkedDir = params[index + 1];
338 
339  loadResults(logFile, checkedDir);
340  } else {
341  loadResults(logFile);
342  }
343  } else if ((index = params.indexOf(QRegularExpression(".*\\.cppcheck$", QRegularExpression::CaseInsensitiveOption))) >= 0 && index < params.length() && QFile(params[index]).exists()) {
344  loadProjectFile(params[index]);
345  } else if ((index = params.indexOf(QRegularExpression(".*\\.xml$", QRegularExpression::CaseInsensitiveOption))) >= 0 && index < params.length() && QFile(params[index]).exists()) {
346  loadResults(params[index],QDir::currentPath());
347  } else
348  doAnalyzeFiles(params);
349 }
350 
352 {
353  // Window/dialog sizes
354  if (mSettings->value(SETTINGS_WINDOW_MAXIMIZED, false).toBool()) {
355  showMaximized();
356  } else {
357  resize(mSettings->value(SETTINGS_WINDOW_WIDTH, 800).toInt(),
358  mSettings->value(SETTINGS_WINDOW_HEIGHT, 600).toInt());
359  }
360 
361  const ShowTypes &types = mUI->mResults->getShowTypes();
362  mUI->mActionShowStyle->setChecked(types.isShown(ShowTypes::ShowStyle));
363  mUI->mActionShowErrors->setChecked(types.isShown(ShowTypes::ShowErrors));
364  mUI->mActionShowWarnings->setChecked(types.isShown(ShowTypes::ShowWarnings));
365  mUI->mActionShowPortability->setChecked(types.isShown(ShowTypes::ShowPortability));
366  mUI->mActionShowPerformance->setChecked(types.isShown(ShowTypes::ShowPerformance));
367  mUI->mActionShowInformation->setChecked(types.isShown(ShowTypes::ShowInformation));
368  mUI->mActionShowCppcheck->setChecked(true);
369  mUI->mActionShowClang->setChecked(true);
370 
371  Standards standards;
372  standards.setC(mSettings->value(SETTINGS_STD_C, QString()).toString().toStdString());
373  mUI->mActionC89->setChecked(standards.c == Standards::C89);
374  mUI->mActionC99->setChecked(standards.c == Standards::C99);
375  mUI->mActionC11->setChecked(standards.c == Standards::C11);
376  standards.setCPP(mSettings->value(SETTINGS_STD_CPP, QString()).toString().toStdString());
377  mUI->mActionCpp03->setChecked(standards.cpp == Standards::CPP03);
378  mUI->mActionCpp11->setChecked(standards.cpp == Standards::CPP11);
379  mUI->mActionCpp14->setChecked(standards.cpp == Standards::CPP14);
380  mUI->mActionCpp17->setChecked(standards.cpp == Standards::CPP17);
381  mUI->mActionCpp20->setChecked(standards.cpp == Standards::CPP20);
382  //mUI->mActionCpp23->setChecked(standards.cpp == Standards::CPP23);
383 
384  // Main window settings
385  const bool showMainToolbar = mSettings->value(SETTINGS_TOOLBARS_MAIN_SHOW, true).toBool();
386  mUI->mActionToolBarMain->setChecked(showMainToolbar);
387  mUI->mToolBarMain->setVisible(showMainToolbar);
388 
389  const bool showViewToolbar = mSettings->value(SETTINGS_TOOLBARS_VIEW_SHOW, true).toBool();
390  mUI->mActionToolBarView->setChecked(showViewToolbar);
391  mUI->mToolBarView->setVisible(showViewToolbar);
392 
393  const bool showFilterToolbar = mSettings->value(SETTINGS_TOOLBARS_FILTER_SHOW, true).toBool();
394  mUI->mActionToolBarFilter->setChecked(showFilterToolbar);
395  mUI->mToolBarFilter->setVisible(showFilterToolbar);
396 
397  const Standards::Language enforcedLanguage = (Standards::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
398  if (enforcedLanguage == Standards::Language::CPP)
399  mUI->mActionEnforceCpp->setChecked(true);
400  else if (enforcedLanguage == Standards::Language::C)
401  mUI->mActionEnforceC->setChecked(true);
402  else
403  mUI->mActionAutoDetectLanguage->setChecked(true);
404 
405  const bool succeeded = mApplications->loadSettings();
406  if (!succeeded) {
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,
412  tr("Cppcheck"),
413  msg,
414  QMessageBox::Ok,
415  this);
416  msgBox.exec();
417  }
418 
419  const QString projectFile = mSettings->value(SETTINGS_OPEN_PROJECT, QString()).toString();
420  if (!projectFile.isEmpty() && QCoreApplication::arguments().size()==1) {
421  QFileInfo inf(projectFile);
422  if (inf.exists() && inf.isReadable()) {
423  setPath(SETTINGS_LAST_PROJECT_PATH, projectFile);
424  mProjectFile = new ProjectFile(this);
426  mProjectFile->read(projectFile);
427  loadLastResults();
428  QDir::setCurrent(inf.absolutePath());
429  }
430  }
431 }
432 
434 {
435  // Window/dialog sizes
436  mSettings->setValue(SETTINGS_WINDOW_WIDTH, size().width());
437  mSettings->setValue(SETTINGS_WINDOW_HEIGHT, size().height());
438  mSettings->setValue(SETTINGS_WINDOW_MAXIMIZED, isMaximized());
439 
440  // Show * states
441  mSettings->setValue(SETTINGS_SHOW_STYLE, mUI->mActionShowStyle->isChecked());
442  mSettings->setValue(SETTINGS_SHOW_ERRORS, mUI->mActionShowErrors->isChecked());
443  mSettings->setValue(SETTINGS_SHOW_WARNINGS, mUI->mActionShowWarnings->isChecked());
444  mSettings->setValue(SETTINGS_SHOW_PORTABILITY, mUI->mActionShowPortability->isChecked());
445  mSettings->setValue(SETTINGS_SHOW_PERFORMANCE, mUI->mActionShowPerformance->isChecked());
446  mSettings->setValue(SETTINGS_SHOW_INFORMATION, mUI->mActionShowInformation->isChecked());
447 
448  if (mUI->mActionC89->isChecked())
449  mSettings->setValue(SETTINGS_STD_C, "C89");
450  if (mUI->mActionC99->isChecked())
451  mSettings->setValue(SETTINGS_STD_C, "C99");
452  if (mUI->mActionC11->isChecked())
453  mSettings->setValue(SETTINGS_STD_C, "C11");
454 
455  if (mUI->mActionCpp03->isChecked())
456  mSettings->setValue(SETTINGS_STD_CPP, "C++03");
457  if (mUI->mActionCpp11->isChecked())
458  mSettings->setValue(SETTINGS_STD_CPP, "C++11");
459  if (mUI->mActionCpp14->isChecked())
460  mSettings->setValue(SETTINGS_STD_CPP, "C++14");
461  if (mUI->mActionCpp17->isChecked())
462  mSettings->setValue(SETTINGS_STD_CPP, "C++17");
463  if (mUI->mActionCpp20->isChecked())
464  mSettings->setValue(SETTINGS_STD_CPP, "C++20");
465  //if (mUI.mActionCpp23->isChecked())
466  // mSettings->setValue(SETTINGS_STD_CPP, "C++23");
467 
468  // Main window settings
469  mSettings->setValue(SETTINGS_TOOLBARS_MAIN_SHOW, mUI->mToolBarMain->isVisible());
470  mSettings->setValue(SETTINGS_TOOLBARS_VIEW_SHOW, mUI->mToolBarView->isVisible());
471  mSettings->setValue(SETTINGS_TOOLBARS_FILTER_SHOW, mUI->mToolBarFilter->isVisible());
472 
473  if (mUI->mActionEnforceCpp->isChecked())
474  mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::CPP);
475  else if (mUI->mActionEnforceC->isChecked())
476  mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::C);
477  else
478  mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::None);
479 
481 
483 
485 
486  mUI->mResults->saveSettings(mSettings);
487 }
488 
489 void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, const bool checkConfiguration)
490 {
491  QPair<bool,Settings> checkSettingsPair = getCppcheckSettings();
492  if (!checkSettingsPair.first)
493  return;
494  Settings& checkSettings = checkSettingsPair.second;
495 
496  clearResults();
497 
498  mIsLogfileLoaded = false;
499  if (mProjectFile) {
500  std::vector<std::string> v;
501  const QStringList excluded = mProjectFile->getExcludedPaths();
502  std::transform(excluded.cbegin(), excluded.cend(), std::back_inserter(v), [](const QString& e) {
503  return e.toStdString();
504  });
505  p.ignorePaths(v);
506 
508  const Platform::Type platform = (Platform::Type) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt();
509  std::vector<std::string> configurations;
510  const QStringList configs = mProjectFile->getVsConfigurations();
511  std::transform(configs.cbegin(), configs.cend(), std::back_inserter(configurations), [](const QString& e) {
512  return e.toStdString();
513  });
514  p.selectVsConfigurations(platform, configurations);
515  }
516  } else {
517  enableProjectActions(false);
518  }
519 
520  mUI->mResults->clear(true);
521  mThread->clearFiles();
522 
523  mUI->mResults->checkingStarted(p.fileSettings.size());
524 
525  QDir inf(mCurrentDirectory);
526  const QString checkPath = inf.canonicalPath();
527  setPath(SETTINGS_LAST_CHECK_PATH, checkPath);
528 
529  checkLockDownUI(); // lock UI while checking
530 
531  mUI->mResults->setCheckDirectory(checkPath);
532  checkSettings.force = false;
533  checkSettings.checkLibrary = checkLibrary;
534  checkSettings.checkConfiguration = checkConfiguration;
535 
536  if (mProjectFile)
537  qDebug() << "Checking project file" << mProjectFile->getFilename();
538 
539  if (!checkSettings.buildDir.empty()) {
540  checkSettings.loadSummaries();
541  std::list<std::string> sourcefiles;
542  AnalyzerInformation::writeFilesTxt(checkSettings.buildDir, sourcefiles, checkSettings.userDefines, p.fileSettings);
543  }
544 
545  //mThread->SetanalyzeProject(true);
546  if (mProjectFile) {
548  QString clangHeaders = mSettings->value(SETTINGS_VS_INCLUDE_PATHS).toString();
549  mThread->setClangIncludePaths(clangHeaders.split(";"));
551  }
552  mThread->setProject(p);
553  mThread->check(checkSettings);
554  mUI->mResults->setCheckSettings(checkSettings);
555 }
556 
557 void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration)
558 {
559  if (files.isEmpty())
560  return;
561 
562  QPair<bool, Settings> checkSettingsPair = getCppcheckSettings();
563  if (!checkSettingsPair.first)
564  return;
565  Settings& checkSettings = checkSettingsPair.second;
566 
567  clearResults();
568 
569  mIsLogfileLoaded = false;
570  FileList pathList;
571  pathList.addPathList(files);
572  if (mProjectFile) {
574  } else {
575  enableProjectActions(false);
576  }
577  QStringList fileNames = pathList.getFileList();
578 
579  mUI->mResults->clear(true);
580  mThread->clearFiles();
581 
582  if (fileNames.isEmpty()) {
583  QMessageBox msg(QMessageBox::Warning,
584  tr("Cppcheck"),
585  tr("No suitable files found to analyze!"),
586  QMessageBox::Ok,
587  this);
588  msg.exec();
589  return;
590  }
591 
592  mUI->mResults->checkingStarted(fileNames.count());
593 
594  mThread->setFiles(fileNames);
597  mThread->setSuppressions(mProjectFile ? mProjectFile->getCheckingSuppressions() : QList<SuppressionList::Suppression>());
598  QDir inf(mCurrentDirectory);
599  const QString checkPath = inf.canonicalPath();
600  setPath(SETTINGS_LAST_CHECK_PATH, checkPath);
601 
602  checkLockDownUI(); // lock UI while checking
603 
604  mUI->mResults->setCheckDirectory(checkPath);
605  checkSettings.checkLibrary = checkLibrary;
606  checkSettings.checkConfiguration = checkConfiguration;
607 
608  if (mProjectFile)
609  qDebug() << "Checking project file" << mProjectFile->getFilename();
610 
611  if (!checkSettings.buildDir.empty()) {
612  checkSettings.loadSummaries();
613  std::list<std::string> sourcefiles;
614  std::transform(fileNames.cbegin(), fileNames.cend(), std::back_inserter(sourcefiles), [](const QString& s) {
615  return s.toStdString();
616  });
617  AnalyzerInformation::writeFilesTxt(checkSettings.buildDir, sourcefiles, checkSettings.userDefines, {});
618  }
619 
620  mThread->setCheckFiles(true);
621  mThread->check(checkSettings);
622  mUI->mResults->setCheckSettings(checkSettings);
623 }
624 
625 void MainWindow::analyzeCode(const QString& code, const QString& filename)
626 {
627  const QPair<bool, Settings>& checkSettingsPair = getCppcheckSettings();
628  if (!checkSettingsPair.first)
629  return;
630  const Settings& checkSettings = checkSettingsPair.second;
631 
632  // Initialize dummy ThreadResult as ErrorLogger
633  ThreadResult result;
634  result.setFiles(QStringList(filename));
635  connect(&result, SIGNAL(progress(int,QString)),
636  mUI->mResults, SLOT(progress(int,QString)));
637  connect(&result, SIGNAL(error(ErrorItem)),
638  mUI->mResults, SLOT(error(ErrorItem)));
639  connect(&result, SIGNAL(log(QString)),
640  mUI->mResults, SLOT(log(QString)));
641  connect(&result, SIGNAL(debugError(ErrorItem)),
642  mUI->mResults, SLOT(debugError(ErrorItem)));
643 
644  // Create CppCheck instance
645  CppCheck cppcheck(result, true, nullptr);
646  cppcheck.settings() = checkSettings;
647 
648  // Check
649  checkLockDownUI();
650  clearResults();
651  mUI->mResults->checkingStarted(1);
652  cppcheck.check(filename.toStdString(), code.toStdString());
653  analysisDone();
654 
655  // Expand results
656  if (mUI->mResults->hasVisibleResults())
657  mUI->mResults->expandAllResults();
658 }
659 
660 QStringList MainWindow::selectFilesToAnalyze(QFileDialog::FileMode mode)
661 {
662  if (mProjectFile) {
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!"));
666  msgBox.setText(msg);
667  msgBox.setIcon(QMessageBox::Critical);
668  msgBox.exec();
669  return QStringList();
670  }
671 
672  QStringList selected;
673 
674  // NOTE: we use QFileDialog::getOpenFileNames() and
675  // QFileDialog::getExistingDirectory() because they show native Windows
676  // selection dialog which is a lot more usable than Qt:s own dialog.
677  if (mode == QFileDialog::ExistingFiles) {
678  QMap<QString,QString> filters;
679  filters[tr("C/C++ Source")] = FileList::getDefaultFilters().join(" ");
680  filters[tr("Compile database")] = compile_commands_json;
681  filters[tr("Visual Studio")] = "*.sln *.vcxproj";
682  filters[tr("Borland C++ Builder 6")] = "*.bpr";
683  QString lastFilter = mSettings->value(SETTINGS_LAST_ANALYZE_FILES_FILTER).toString();
684  selected = QFileDialog::getOpenFileNames(this,
685  tr("Select files to analyze"),
687  toFilterString(filters),
688  &lastFilter);
689  mSettings->setValue(SETTINGS_LAST_ANALYZE_FILES_FILTER, lastFilter);
690 
691  if (selected.isEmpty())
692  mCurrentDirectory.clear();
693  else {
694  QFileInfo inf(selected[0]);
695  mCurrentDirectory = inf.absolutePath();
696  }
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;
704  mCurrentDirectory = dir;
705  selected.append(dir);
706  dir = QDir::toNativeSeparators(dir);
707  formatAndSetTitle(dir);
708  }
709  }
710  if (!mCurrentDirectory.isEmpty())
712 
713  return selected;
714 }
715 
717 {
718  Settings::terminate(false);
719 
720  QStringList selected = selectFilesToAnalyze(QFileDialog::ExistingFiles);
721 
722  const QString file0 = (!selected.empty() ? selected[0].toLower() : QString());
723  if (file0.endsWith(".sln")
724  || file0.endsWith(".vcxproj")
725  || file0.endsWith(compile_commands_json)
726  || file0.endsWith(".bpr")) {
727  ImportProject p;
728  p.import(selected[0].toStdString());
729 
730  if (file0.endsWith(".sln")) {
731  QStringList configs;
732  for (std::list<FileSettings>::const_iterator it = p.fileSettings.cbegin(); it != p.fileSettings.cend(); ++it) {
733  const QString cfg(QString::fromStdString(it->cfg));
734  if (!configs.contains(cfg))
735  configs.push_back(cfg);
736  }
737  configs.sort();
738 
739  bool ok = false;
740  const QString cfg = QInputDialog::getItem(this, tr("Select configuration"), tr("Select the configuration that will be analyzed"), configs, 0, false, &ok);
741  if (!ok)
742  return;
743  p.ignoreOtherConfigs(cfg.toStdString());
744  }
745 
746  doAnalyzeProject(p);
747  return;
748  }
749 
750  doAnalyzeFiles(selected);
751 }
752 
754 {
755  QStringList dir = selectFilesToAnalyze(QFileDialog::Directory);
756  if (dir.isEmpty())
757  return;
758 
759  QDir checkDir(dir[0]);
760  QStringList filters;
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) {
767  // If one project file found, suggest loading it
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]));
772  msgBox.setText(msg);
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("/"))
781  path += "/";
782  path += projFiles[0];
783  loadProjectFile(path);
784  } else {
785  doAnalyzeFiles(dir);
786  }
787  } else {
788  // If multiple project files found inform that there are project
789  // files also available.
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?"));
795  msgBox.setText(msg);
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) {
802  doAnalyzeFiles(dir);
803  }
804  }
805  } else {
806  doAnalyzeFiles(dir);
807  }
808 }
809 
810 void MainWindow::addIncludeDirs(const QStringList &includeDirs, Settings &result)
811 {
812  for (const QString& dir : includeDirs) {
813  QString incdir;
814  if (!QDir::isAbsolutePath(dir))
815  incdir = mCurrentDirectory + "/";
816  incdir += dir;
817  incdir = QDir::cleanPath(incdir);
818 
819  // include paths must end with '/'
820  if (!incdir.endsWith("/"))
821  incdir += "/";
822  result.includePaths.push_back(incdir.toStdString());
823  }
824 }
825 
826 Library::Error MainWindow::loadLibrary(Library &library, const QString &filename)
827 {
828  Library::Error ret;
829 
830  // Try to load the library from the project folder..
831  if (mProjectFile) {
832  QString path = QFileInfo(mProjectFile->getFilename()).canonicalPath();
833  ret = library.load(nullptr, (path+"/"+filename).toLatin1());
835  return ret;
836  }
837 
838  // Try to load the library from the application folder..
839  const QString appPath = QFileInfo(QCoreApplication::applicationFilePath()).canonicalPath();
840  ret = library.load(nullptr, (appPath+"/"+filename).toLatin1());
842  return ret;
843  ret = library.load(nullptr, (appPath+"/cfg/"+filename).toLatin1());
845  return ret;
846 
847 #ifdef FILESDIR
848  // Try to load the library from FILESDIR/cfg..
849  const QString filesdir = FILESDIR;
850  if (!filesdir.isEmpty()) {
851  ret = library.load(nullptr, (filesdir+"/cfg/"+filename).toLatin1());
853  return ret;
854  ret = library.load(nullptr, (filesdir+filename).toLatin1());
856  return ret;
857  }
858 #endif
859 
860  // Try to load the library from the cfg subfolder..
861  const QString datadir = getDataDir();
862  if (!datadir.isEmpty()) {
863  ret = library.load(nullptr, (datadir+"/"+filename).toLatin1());
865  return ret;
866  ret = library.load(nullptr, (datadir+"/cfg/"+filename).toLatin1());
868  return ret;
869  }
870 
871  return ret;
872 }
873 
874 bool MainWindow::tryLoadLibrary(Library &library, const QString& filename)
875 {
876  const Library::Error error = loadLibrary(library, filename);
877  if (error.errorcode != Library::ErrorCode::OK) {
878  if (error.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) {
879  QMessageBox::information(this, tr("Information"), tr("The library '%1' contains unknown elements:\n%2").arg(filename).arg(error.reason.c_str()));
880  return true;
881  }
882 
883  QString errmsg;
884  switch (error.errorcode) {
886  break;
888  errmsg = tr("File not found");
889  break;
891  errmsg = tr("Bad XML");
892  break;
894  errmsg = tr("Missing attribute");
895  break;
897  errmsg = tr("Bad attribute value");
898  break;
900  errmsg = tr("Unsupported format");
901  break;
903  errmsg = tr("Duplicate platform type");
904  break;
906  errmsg = tr("Platform type redefined");
907  break;
909  errmsg = tr("Duplicate define");
910  break;
912  errmsg = tr("Unknown element");
913  break;
914  default:
915  errmsg = tr("Unknown issue");
916  break;
917  }
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));
921  return false;
922  }
923  return true;
924 }
925 
926 QString MainWindow::loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString& addon)
927 {
928  const QString addonFilePath = fromNativePath(ProjectFile::getAddonFilePath(filesDir, addon));
929 
930  if (addonFilePath.isEmpty())
931  return tr("File not found: '%1'").arg(addon);
932 
933  picojson::object obj;
934  obj["script"] = picojson::value(addonFilePath.toStdString());
935  if (!pythonCmd.isEmpty())
936  obj["python"] = picojson::value(pythonCmd.toStdString());
937 
938  if (!isCppcheckPremium() && addon == "misra") {
939  const QString misraFile = fromNativePath(mSettings->value(SETTINGS_MISRA_FILE).toString());
940  if (!misraFile.isEmpty()) {
941  QString arg;
942  if (misraFile.endsWith(".pdf", Qt::CaseInsensitive))
943  arg = "--misra-pdf=" + misraFile;
944  else
945  arg = "--rule-texts=" + misraFile;
946  obj["args"] = picojson::value(arg.toStdString());
947  }
948  }
949 
950  const std::string& json_str = picojson::value(obj).serialize();
951 
952  AddonInfo addonInfo;
953  const std::string errmsg = addonInfo.getAddonInfo(json_str, settings.exename);
954  if (!errmsg.empty())
955  return tr("Failed to load/setup addon %1: %2").arg(addon, QString::fromStdString(errmsg));
956  settings.addonInfos.emplace_back(std::move(addonInfo));
957 
958  settings.addons.emplace(json_str);
959 
960  return "";
961 }
962 
963 QPair<bool,Settings> MainWindow::getCppcheckSettings()
964 {
965  saveSettings(); // Save settings
966 
967  Settings::terminate(true);
968  Settings result;
969 
970  result.exename = QCoreApplication::applicationFilePath().toStdString();
971 
972  // default to --check-level=normal for GUI for now
974 
975  const bool std = tryLoadLibrary(result.library, "std.cfg");
976  if (!std) {
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"));
978  return {false, {}};
979  }
980 
981  const QString filesDir(getDataDir());
982  const QString pythonCmd = fromNativePath(mSettings->value(SETTINGS_PYTHON_PATH).toString());
983 
984  {
985  const QString cfgErr = QString::fromStdString(Settings::loadCppcheckCfg(result, result.supprs));
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));
988  return {false, {}};
989  }
990 
991  const auto cfgAddons = result.addons;
992  result.addons.clear();
993  for (const std::string& addon : cfgAddons) {
994  // TODO: support addons which are a script and not a file
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));
998  return {false, {}};
999  }
1000  }
1001  }
1002 
1003  // If project file loaded, read settings from it
1004  if (mProjectFile) {
1005  QStringList dirs = mProjectFile->getIncludeDirs();
1006  addIncludeDirs(dirs, result);
1007 
1008  const QStringList defines = mProjectFile->getDefines();
1009  for (const QString& define : defines) {
1010  if (!result.userDefines.empty())
1011  result.userDefines += ";";
1012  result.userDefines += define.toStdString();
1013  }
1014 
1015  result.clang = mProjectFile->clangParser;
1016 
1017  const QStringList undefines = mProjectFile->getUndefines();
1018  for (const QString& undefine : undefines)
1019  result.userUndefs.insert(undefine.toStdString());
1020 
1021  const QStringList libraries = mProjectFile->getLibraries();
1022  for (const QString& library : libraries) {
1023  result.libraries.emplace_back(library.toStdString());
1024  const QString filename = library + ".cfg";
1025  tryLoadLibrary(result.library, filename);
1026  }
1027 
1028  for (const SuppressionList::Suppression &suppression : mProjectFile->getCheckingSuppressions()) {
1029  result.supprs.nomsg.addSuppression(suppression);
1030  }
1031 
1032  // Only check the given -D configuration
1033  if (!defines.isEmpty())
1034  result.maxConfigs = 1;
1035 
1036  // If importing a project, only check the given configuration
1037  if (!mProjectFile->getImportProject().isEmpty())
1038  result.checkAllConfigurations = false;
1039 
1040  const QString &buildDir = fromNativePath(mProjectFile->getBuildDir());
1041  if (!buildDir.isEmpty()) {
1042  if (QDir(buildDir).isAbsolute()) {
1043  result.buildDir = buildDir.toStdString();
1044  } else {
1045  QString prjpath = QFileInfo(mProjectFile->getFilename()).absolutePath();
1046  result.buildDir = (prjpath + '/' + buildDir).toStdString();
1047  }
1048  }
1049 
1050  const QString platform = mProjectFile->getPlatform();
1051  if (platform.endsWith(".xml")) {
1052  const QString applicationFilePath = QCoreApplication::applicationFilePath();
1053  result.platform.loadFromFile(applicationFilePath.toStdString().c_str(), platform.toStdString());
1054  } else {
1055  for (int i = Platform::Type::Native; i <= Platform::Type::Unix64; i++) {
1056  const auto p = (Platform::Type)i;
1057  if (platform == Platform::toString(p)) {
1058  result.platform.set(p);
1059  break;
1060  }
1061  }
1062  }
1063 
1068  else
1076  for (const QString& s : mProjectFile->getCheckUnknownFunctionReturn())
1077  result.checkUnknownFunctionReturn.insert(s.toStdString());
1078 
1079  for (const QString& addon : mProjectFile->getAddons()) {
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));
1083  return {false, {}};
1084  }
1085  }
1086 
1087  if (isCppcheckPremium()) {
1088  QString premiumArgs;
1089  if (mProjectFile->getBughunting())
1090  premiumArgs += " --bughunting";
1091  if (mProjectFile->getCertIntPrecision() > 0)
1092  premiumArgs += " --cert-c-int-precision=" + QString::number(mProjectFile->getCertIntPrecision());
1093  for (const QString& c: mProjectFile->getCodingStandards())
1094  premiumArgs += " --" + c;
1095  if (!premiumArgs.contains("misra") && mProjectFile->getAddons().contains("misra"))
1096  premiumArgs += " --misra-c-2012";
1097  result.premiumArgs = premiumArgs.mid(1).toStdString();
1099  }
1100  }
1101 
1102  // Include directories (and files) are searched in listed order.
1103  // Global include directories must be added AFTER the per project include
1104  // directories so per project include directories can override global ones.
1105  const QString globalIncludes = mSettings->value(SETTINGS_GLOBAL_INCLUDE_PATHS).toString();
1106  if (!globalIncludes.isEmpty()) {
1107  QStringList includes = globalIncludes.split(";");
1108  addIncludeDirs(includes, result);
1109  }
1110 
1117  if (!result.buildDir.empty())
1119  result.debugwarnings = mSettings->value(SETTINGS_SHOW_DEBUG_WARNINGS, false).toBool();
1120  result.quiet = false;
1121  result.verbose = true;
1122  result.force = mSettings->value(SETTINGS_CHECK_FORCE, 1).toBool();
1123  result.xml = false;
1124  result.jobs = mSettings->value(SETTINGS_CHECK_THREADS, 1).toInt();
1125  result.inlineSuppressions = mSettings->value(SETTINGS_INLINE_SUPPRESSIONS, false).toBool();
1127  if (!mProjectFile || result.platform.type == Platform::Type::Unspecified)
1128  result.platform.set((Platform::Type) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt());
1129  result.standards.setCPP(mSettings->value(SETTINGS_STD_CPP, QString()).toString().toStdString());
1130  result.standards.setC(mSettings->value(SETTINGS_STD_C, QString()).toString().toStdString());
1132 
1133  if (result.jobs <= 1) {
1134  result.jobs = 1;
1135  }
1136 
1137  Settings::terminate(false);
1138 
1139  return {true, std::move(result)};
1140 }
1141 
1143 {
1144  if (mExiting) {
1145  close();
1146  return;
1147  }
1148 
1149  mUI->mResults->checkingFinished();
1150  enableCheckButtons(true);
1151  mUI->mActionSettings->setEnabled(true);
1152  mUI->mActionOpenXML->setEnabled(true);
1153  if (mProjectFile) {
1154  enableProjectActions(true);
1155  } else if (mIsLogfileLoaded) {
1156  mUI->mActionReanalyzeModified->setEnabled(false);
1157  mUI->mActionReanalyzeAll->setEnabled(false);
1158  }
1160  mPlatformActions->setEnabled(true);
1161  mCStandardActions->setEnabled(true);
1162  mCppStandardActions->setEnabled(true);
1163  mSelectLanguageActions->setEnabled(true);
1164  mUI->mActionPosix->setEnabled(true);
1165  if (mScratchPad)
1166  mScratchPad->setEnabled(true);
1167  mUI->mActionViewStats->setEnabled(true);
1168 
1169  if (mProjectFile && !mProjectFile->getBuildDir().isEmpty()) {
1170  const QString prjpath = QFileInfo(mProjectFile->getFilename()).absolutePath();
1171  const QString buildDir = prjpath + '/' + mProjectFile->getBuildDir();
1172  if (QDir(buildDir).exists()) {
1173  mUI->mResults->saveStatistics(buildDir + "/statistics.txt");
1174  mUI->mResults->updateFromOldReport(buildDir + "/lastResults.xml");
1175  mUI->mResults->save(buildDir + "/lastResults.xml", Report::XMLV2, mCppcheckCfgProductName);
1176  }
1177  }
1178 
1180 
1181  for (QAction* recentProjectAct : mRecentProjectActs) {
1182  if (recentProjectAct != nullptr)
1183  recentProjectAct->setEnabled(true);
1184  }
1185 
1186  // Notify user - if the window is not active - that check is ready
1187  QApplication::alert(this, 3000);
1188  if (mSettings->value(SETTINGS_SHOW_STATISTICS, false).toBool())
1189  showStatistics();
1190 }
1191 
1193 {
1194  enableCheckButtons(false);
1195  mUI->mActionSettings->setEnabled(false);
1196  mUI->mActionOpenXML->setEnabled(false);
1197  enableProjectActions(false);
1198  enableProjectOpenActions(false);
1199  mPlatformActions->setEnabled(false);
1200  mCStandardActions->setEnabled(false);
1201  mCppStandardActions->setEnabled(false);
1202  mSelectLanguageActions->setEnabled(false);
1203  mUI->mActionPosix->setEnabled(false);
1204  if (mScratchPad)
1205  mScratchPad->setEnabled(false);
1206 
1207  for (QAction* recentProjectAct : mRecentProjectActs) {
1208  if (recentProjectAct != nullptr)
1209  recentProjectAct->setEnabled(false);
1210  }
1211 }
1212 
1214 {
1216  if (dialog.exec() == QDialog::Accepted) {
1217  dialog.saveSettingValues();
1218  mSettings->sync();
1219  mUI->mResults->updateSettings(dialog.showFullPath(),
1220  dialog.saveFullPath(),
1221  dialog.saveAllErrors(),
1222  dialog.showNoErrorsMessage(),
1223  dialog.showErrorId(),
1224  dialog.showInconclusive());
1225  mUI->mResults->updateStyleSetting(mSettings);
1226  const QString newLang = mSettings->value(SETTINGS_LANGUAGE, "en").toString();
1227  setLanguage(newLang);
1228  }
1229 }
1230 
1232 {
1233  reAnalyze(false);
1234 }
1235 
1237 {
1238  if (mProjectFile)
1240  else
1241  reAnalyze(true);
1242 }
1243 
1245 {
1246  if (mProjectFile)
1248 }
1249 
1251 {
1252  if (mProjectFile)
1253  analyzeProject(mProjectFile, false, true);
1254 }
1255 
1256 void MainWindow::reAnalyzeSelected(const QStringList& files)
1257 {
1258  if (files.empty())
1259  return;
1260  if (mThread->isChecking())
1261  return;
1262 
1263  const QPair<bool, Settings> checkSettingsPair = getCppcheckSettings();
1264  if (!checkSettingsPair.first)
1265  return;
1266  const Settings& checkSettings = checkSettingsPair.second;
1267 
1268  // Clear details, statistics and progress
1269  mUI->mResults->clear(false);
1270  for (int i = 0; i < files.size(); ++i)
1271  mUI->mResults->clearRecheckFile(files[i]);
1272 
1273  mCurrentDirectory = mUI->mResults->getCheckDirectory();
1274  FileList pathList;
1275  pathList.addPathList(files);
1276  if (mProjectFile)
1278  QStringList fileNames = pathList.getFileList();
1279  checkLockDownUI(); // lock UI while checking
1280  mUI->mResults->checkingStarted(fileNames.size());
1281  mThread->setCheckFiles(fileNames);
1282 
1283  // Saving last check start time, otherwise unchecked modified files will not be
1284  // considered in "Modified Files Check" performed after "Selected Files Check"
1285  // TODO: Should we store per file CheckStartTime?
1286  QDateTime saveCheckStartTime = mThread->getCheckStartTime();
1287  mThread->check(checkSettings);
1288  mUI->mResults->setCheckSettings(checkSettings);
1289  mThread->setCheckStartTime(std::move(saveCheckStartTime));
1290 }
1291 
1293 {
1294  const QStringList files = mThread->getReCheckFiles(all);
1295  if (files.empty())
1296  return;
1297 
1298  const QPair<bool, Settings>& checkSettingsPair = getCppcheckSettings();
1299  if (!checkSettingsPair.first)
1300  return;
1301  const Settings& checkSettings = checkSettingsPair.second;
1302 
1303  // Clear details, statistics and progress
1304  mUI->mResults->clear(all);
1305 
1306  // Clear results for changed files
1307  for (int i = 0; i < files.size(); ++i)
1308  mUI->mResults->clear(files[i]);
1309 
1310  checkLockDownUI(); // lock UI while checking
1311  mUI->mResults->checkingStarted(files.size());
1312 
1313  if (mProjectFile)
1314  qDebug() << "Rechecking project file" << mProjectFile->getFilename();
1315 
1316  mThread->setCheckFiles(all);
1317  mThread->check(checkSettings);
1318  mUI->mResults->setCheckSettings(checkSettings);
1319 }
1320 
1322 {
1323  if (mProjectFile && !mProjectFile->getBuildDir().isEmpty()) {
1324  QDir dir(QFileInfo(mProjectFile->getFilename()).absolutePath() + '/' + mProjectFile->getBuildDir());
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())
1329  dir.remove(f);
1330  }
1331  }
1332  }
1333  mUI->mResults->clear(true);
1334  Q_ASSERT(false == mUI->mResults->hasResults());
1336 }
1337 
1339 {
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) {
1353  return;
1354  }
1355  }
1356 
1357  QString selectedFilter;
1358  const QString filter(tr("XML files (*.xml)"));
1359  QString selectedFile = QFileDialog::getOpenFileName(this,
1360  tr("Open the report file"),
1362  filter,
1363  &selectedFilter);
1364 
1365  if (!selectedFile.isEmpty()) {
1366  loadResults(selectedFile);
1367  }
1368 }
1369 
1370 void MainWindow::loadResults(const QString &selectedFile)
1371 {
1372  if (selectedFile.isEmpty())
1373  return;
1374  if (mProjectFile)
1375  closeProjectFile();
1376  mIsLogfileLoaded = true;
1377  mUI->mResults->clear(true);
1378  mUI->mActionReanalyzeModified->setEnabled(false);
1379  mUI->mActionReanalyzeAll->setEnabled(false);
1380  mUI->mResults->readErrorsXml(selectedFile);
1381  setPath(SETTINGS_LAST_RESULT_PATH, selectedFile);
1382  formatAndSetTitle(selectedFile);
1383 }
1384 
1385 void MainWindow::loadResults(const QString &selectedFile, const QString &sourceDirectory)
1386 {
1387  loadResults(selectedFile);
1388  mUI->mResults->setCheckDirectory(sourceDirectory);
1389 }
1390 
1392 {
1393  mUI->mActionStop->setEnabled(!enable);
1394  mUI->mActionAnalyzeFiles->setEnabled(enable);
1395 
1396  if (mProjectFile) {
1397  mUI->mActionReanalyzeModified->setEnabled(false);
1398  mUI->mActionReanalyzeAll->setEnabled(enable);
1399  } else if (!enable || mThread->hasPreviousFiles()) {
1400  mUI->mActionReanalyzeModified->setEnabled(enable);
1401  mUI->mActionReanalyzeAll->setEnabled(enable);
1402  }
1403 
1404  mUI->mActionAnalyzeDirectory->setEnabled(enable);
1405 
1406  if (isCppcheckPremium()) {
1407  mUI->mActionComplianceReport->setEnabled(enable && mProjectFile && (mProjectFile->getAddons().contains("misra") || !mProjectFile->getCodingStandards().empty()));
1408  }
1409 }
1410 
1412 {
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);
1418 }
1419 
1420 void MainWindow::showStyle(bool checked)
1421 {
1422  mUI->mResults->showResults(ShowTypes::ShowStyle, checked);
1423 }
1424 
1425 void MainWindow::showErrors(bool checked)
1426 {
1427  mUI->mResults->showResults(ShowTypes::ShowErrors, checked);
1428 }
1429 
1430 void MainWindow::showWarnings(bool checked)
1431 {
1432  mUI->mResults->showResults(ShowTypes::ShowWarnings, checked);
1433 }
1434 
1436 {
1437  mUI->mResults->showResults(ShowTypes::ShowPortability, checked);
1438 }
1439 
1441 {
1442  mUI->mResults->showResults(ShowTypes::ShowPerformance, checked);
1443 }
1444 
1446 {
1447  mUI->mResults->showResults(ShowTypes::ShowInformation, checked);
1448 }
1449 
1451 {
1452  toggleAllChecked(true);
1453 }
1454 
1456 {
1457  toggleAllChecked(false);
1458 }
1459 
1460 void MainWindow::closeEvent(QCloseEvent *event)
1461 {
1462  // Check that we aren't checking files
1463  if (!mThread->isChecking()) {
1464  saveSettings();
1465  event->accept();
1466  } else {
1467  const QString text(tr("Analyzer is running.\n\n" \
1468  "Do you want to stop the analysis and exit Cppcheck?"));
1469 
1470  QMessageBox msg(QMessageBox::Warning,
1471  tr("Cppcheck"),
1472  text,
1473  QMessageBox::Yes | QMessageBox::No,
1474  this);
1475 
1476  msg.setDefaultButton(QMessageBox::No);
1477  const int rv = msg.exec();
1478  if (rv == QMessageBox::Yes) {
1479  // This isn't really very clean way to close threads but since the app is
1480  // exiting it doesn't matter.
1481  mThread->stop();
1482  saveSettings();
1483  mExiting = true;
1484  }
1485  event->ignore();
1486  }
1487 }
1488 
1490 {
1491  mUI->mActionShowStyle->setChecked(checked);
1492  showStyle(checked);
1493  mUI->mActionShowErrors->setChecked(checked);
1494  showErrors(checked);
1495  mUI->mActionShowWarnings->setChecked(checked);
1496  showWarnings(checked);
1497  mUI->mActionShowPortability->setChecked(checked);
1498  showPortability(checked);
1499  mUI->mActionShowPerformance->setChecked(checked);
1500  showPerformance(checked);
1501  mUI->mActionShowInformation->setChecked(checked);
1502  showInformation(checked);
1503 }
1504 
1506 {
1507  if (!mCppcheckCfgAbout.isEmpty()) {
1508  QMessageBox msg(QMessageBox::Information,
1509  tr("About"),
1511  QMessageBox::Ok,
1512  this);
1513  msg.exec();
1514  }
1515  else {
1516  auto *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
1517  dlg->exec();
1518  }
1519 }
1520 
1522 {
1523  auto *dlg = new FileViewDialog(":COPYING", tr("License"), this);
1524  dlg->resize(570, 400);
1525  dlg->exec();
1526 }
1527 
1529 {
1530  auto *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this);
1531  dlg->resize(350, 400);
1532  dlg->exec();
1533 }
1534 
1535 void MainWindow::performSelectedFilesCheck(const QStringList &selectedFilesList)
1536 {
1537  reAnalyzeSelected(selectedFilesList);
1538 }
1539 
1541 {
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"),
1547  filter,
1548  &selectedFilter);
1549 
1550  if (!selectedFile.isEmpty()) {
1551  Report::Type type = Report::TXT;
1552  if (selectedFilter == tr("XML files (*.xml)")) {
1553  type = Report::XMLV2;
1554  if (!selectedFile.endsWith(".xml", Qt::CaseInsensitive))
1555  selectedFile += ".xml";
1556  } else if (selectedFilter == tr("Text files (*.txt)")) {
1557  type = Report::TXT;
1558  if (!selectedFile.endsWith(".txt", Qt::CaseInsensitive))
1559  selectedFile += ".txt";
1560  } else if (selectedFilter == tr("CSV files (*.csv)")) {
1561  type = Report::CSV;
1562  if (!selectedFile.endsWith(".csv", Qt::CaseInsensitive))
1563  selectedFile += ".csv";
1564  } else {
1565  if (selectedFile.endsWith(".xml", Qt::CaseInsensitive))
1566  type = Report::XMLV2;
1567  else if (selectedFile.endsWith(".txt", Qt::CaseInsensitive))
1568  type = Report::TXT;
1569  else if (selectedFile.endsWith(".csv", Qt::CaseInsensitive))
1570  type = Report::CSV;
1571  }
1572 
1573  mUI->mResults->save(selectedFile, type, mCppcheckCfgProductName);
1574  setPath(SETTINGS_LAST_RESULT_PATH, selectedFile);
1575  }
1576 }
1577 
1579 {
1580  if (!mUI->mResults->isSuccess()) {
1581  QMessageBox m(QMessageBox::Critical,
1582  "Cppcheck",
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."),
1584  QMessageBox::Ok,
1585  this);
1586  m.exec();
1587  return;
1588  }
1589 
1590  QTemporaryFile tempResults;
1591  tempResults.open();
1592  tempResults.close();
1593 
1594  mUI->mResults->save(tempResults.fileName(), Report::XMLV2, mCppcheckCfgProductName);
1595 
1596  ComplianceReportDialog dlg(mProjectFile, tempResults.fileName());
1597  dlg.exec();
1598 }
1599 
1601 {}
1602 
1604 {
1605  mUI->mToolBarMain->setVisible(mUI->mActionToolBarMain->isChecked());
1606 }
1607 
1609 {
1610  mUI->mToolBarView->setVisible(mUI->mActionToolBarView->isChecked());
1611 }
1612 
1614 {
1615  mUI->mToolBarFilter->setVisible(mUI->mActionToolBarFilter->isChecked());
1616  mLineEditFilter->clear(); // Clearing the filter also disables filtering
1617 }
1618 
1619 void MainWindow::formatAndSetTitle(const QString &text)
1620 {
1621  QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version());
1622 
1623  QString extraVersion = CppCheck::extraVersion();
1624  if (!extraVersion.isEmpty()) {
1625  nameWithVersion += " (" + extraVersion + ")";
1626  }
1627 
1628  if (!mCppcheckCfgProductName.isEmpty())
1629  nameWithVersion = mCppcheckCfgProductName;
1630 
1631  QString title;
1632  if (text.isEmpty())
1633  title = nameWithVersion;
1634  else
1635  title = QString("%1 - %2").arg(nameWithVersion, text);
1636  setWindowTitle(title);
1637 }
1638 
1639 void MainWindow::setLanguage(const QString &code)
1640 {
1641  const QString currentLang = mTranslation->getCurrentLanguage();
1642  if (currentLang == code)
1643  return;
1644 
1645  if (mTranslation->setLanguage(code)) {
1646  //Translate everything that is visible here
1647  mUI->retranslateUi(this);
1648  mUI->mResults->translate();
1649  mLineEditFilter->setPlaceholderText(QCoreApplication::translate("MainWindow", "Quick Filter:"));
1650  if (mProjectFile)
1651  formatAndSetTitle(tr("Project:") + ' ' + mProjectFile->getFilename());
1652  if (mScratchPad)
1654  }
1655 }
1656 
1658 {
1659  mUI->mActionToolBarMain->setChecked(mUI->mToolBarMain->isVisible());
1660  mUI->mActionToolBarView->setChecked(mUI->mToolBarView->isVisible());
1661  mUI->mActionToolBarFilter->setChecked(mUI->mToolBarFilter->isVisible());
1662 }
1663 
1665 {
1666  mThread->stop();
1667  mUI->mResults->stopAnalysis();
1668  mUI->mResults->disableProgressbar();
1669  const QString &lastResults = getLastResults();
1670  if (!lastResults.isEmpty()) {
1671  mUI->mResults->updateFromOldReport(lastResults);
1672  }
1673 }
1674 
1676 {
1677  openOnlineHelp();
1678 }
1679 
1681 {
1682  auto *helpDialog = new HelpDialog;
1683  helpDialog->showMaximized();
1684 }
1685 
1687 {
1688  const QString filter = tr("Project files (*.cppcheck);;All files(*.*)");
1689  const QString filepath = QFileDialog::getOpenFileName(this,
1690  tr("Select Project File"),
1692  filter);
1693 
1694  if (!filepath.isEmpty()) {
1695  const QFileInfo fi(filepath);
1696  if (fi.exists() && fi.isFile() && fi.isReadable()) {
1698  loadProjectFile(filepath);
1699  }
1700  }
1701 }
1702 
1704 {
1705  if (!mScratchPad)
1706  mScratchPad = new ScratchPad(*this);
1707 
1708  mScratchPad->show();
1709 
1710  if (!mScratchPad->isActiveWindow())
1711  mScratchPad->activateWindow();
1712 }
1713 
1714 void MainWindow::loadProjectFile(const QString &filePath)
1715 {
1716  QFileInfo inf(filePath);
1717  const QString filename = inf.fileName();
1718  formatAndSetTitle(tr("Project:") + ' ' + filename);
1719  addProjectMRU(filePath);
1720 
1721  mIsLogfileLoaded = false;
1722  mUI->mActionCloseProjectFile->setEnabled(true);
1723  mUI->mActionEditProjectFile->setEnabled(true);
1724  delete mProjectFile;
1725  mProjectFile = new ProjectFile(filePath, this);
1727  if (!loadLastResults())
1729 }
1730 
1732 {
1733  if (!mProjectFile || mProjectFile->getBuildDir().isEmpty())
1734  return QString();
1735  return QFileInfo(mProjectFile->getFilename()).absolutePath() + '/' + mProjectFile->getBuildDir() + "/lastResults.xml";
1736 }
1737 
1739 {
1740  const QString &lastResults = getLastResults();
1741  if (lastResults.isEmpty())
1742  return false;
1743  if (!QFileInfo::exists(lastResults))
1744  return false;
1745  mUI->mResults->readErrorsXml(lastResults);
1746  mUI->mResults->setCheckDirectory(mSettings->value(SETTINGS_LAST_CHECK_PATH,QString()).toString());
1747  mUI->mActionViewStats->setEnabled(true);
1749  return true;
1750 }
1751 
1752 void MainWindow::analyzeProject(const ProjectFile *projectFile, const bool checkLibrary, const bool checkConfiguration)
1753 {
1754  Settings::terminate(false);
1755 
1756  QFileInfo inf(projectFile->getFilename());
1757  const QString& rootpath = projectFile->getRootPath();
1758 
1759  QDir::setCurrent(inf.absolutePath());
1760 
1761  mThread->setAddonsAndTools(projectFile->getAddonsAndTools());
1762 
1763  // If the root path is not given or is not "current dir", use project
1764  // file's location directory as root path
1765  if (rootpath.isEmpty() || rootpath == ".")
1766  mCurrentDirectory = inf.canonicalPath();
1767  else if (rootpath.startsWith("./"))
1768  mCurrentDirectory = inf.canonicalPath() + rootpath.mid(1);
1769  else
1770  mCurrentDirectory = rootpath;
1771 
1772  if (!projectFile->getBuildDir().isEmpty()) {
1773  QString buildDir = projectFile->getBuildDir();
1774  if (!QDir::isAbsolutePath(buildDir))
1775  buildDir = inf.canonicalPath() + '/' + buildDir;
1776  if (!QDir(buildDir).exists()) {
1777  QMessageBox msg(QMessageBox::Question,
1778  tr("Cppcheck"),
1779  tr("Build dir '%1' does not exist, create it?").arg(buildDir),
1780  QMessageBox::Yes | QMessageBox::No,
1781  this);
1782  if (msg.exec() == QMessageBox::Yes) {
1783  QDir().mkpath(buildDir);
1784  } else if (!projectFile->getAddons().isEmpty()) {
1785  QMessageBox m(QMessageBox::Critical,
1786  tr("Cppcheck"),
1787  tr("To check the project using addons, you need a build directory."),
1788  QMessageBox::Ok,
1789  this);
1790  m.exec();
1791  return;
1792  }
1793  }
1794  }
1795 
1796  if (!projectFile->getImportProject().isEmpty()) {
1797  ImportProject p;
1798  QString prjfile;
1799 
1800  if (QFileInfo(projectFile->getImportProject()).isAbsolute()) {
1801  prjfile = projectFile->getImportProject();
1802  } else {
1803  prjfile = inf.canonicalPath() + '/' + projectFile->getImportProject();
1804  }
1805  try {
1806 
1807  const ImportProject::Type result = p.import(prjfile.toStdString());
1808 
1809  QString errorMessage;
1810  switch (result) {
1816  // Loading was successful
1817  break;
1819  errorMessage = tr("Failed to open file");
1820  break;
1822  errorMessage = tr("Unknown project file format");
1823  break;
1825  errorMessage = tr("Failed to import project file");
1826  break;
1828  // can never happen
1829  break;
1830  }
1831 
1832  if (!errorMessage.isEmpty()) {
1833  QMessageBox msg(QMessageBox::Critical,
1834  tr("Cppcheck"),
1835  tr("Failed to import '%1': %2\n\nAnalysis is stopped.").arg(prjfile).arg(errorMessage),
1836  QMessageBox::Ok,
1837  this);
1838  msg.exec();
1839  return;
1840  }
1841  } catch (InternalError &e) {
1842  QMessageBox msg(QMessageBox::Critical,
1843  tr("Cppcheck"),
1844  tr("Failed to import '%1' (%2), analysis is stopped").arg(prjfile).arg(QString::fromStdString(e.errorMessage)),
1845  QMessageBox::Ok,
1846  this);
1847  msg.exec();
1848  return;
1849  }
1851  return;
1852  }
1853 
1854  QStringList paths = projectFile->getCheckPaths();
1855 
1856  // If paths not given then check the root path (which may be the project
1857  // file's location, see above). This is to keep the compatibility with
1858  // old "silent" project file loading when we checked the director where the
1859  // project file was located.
1860  if (paths.isEmpty()) {
1861  paths << mCurrentDirectory;
1862  }
1864 }
1865 
1867 {
1868  const QString filter = tr("Project files (*.cppcheck)");
1869  QString filepath = QFileDialog::getSaveFileName(this,
1870  tr("Select Project Filename"),
1872  filter);
1873 
1874  if (filepath.isEmpty())
1875  return;
1876  if (!filepath.endsWith(".cppcheck", Qt::CaseInsensitive))
1877  filepath += ".cppcheck";
1878 
1880 
1881  QFileInfo inf(filepath);
1882  const QString filename = inf.fileName();
1883  formatAndSetTitle(tr("Project:") + QString(" ") + filename);
1884 
1885  delete mProjectFile;
1886  mProjectFile = new ProjectFile(this);
1888  mProjectFile->setFilename(filepath);
1889  mProjectFile->setProjectName(filename.left(filename.indexOf(".")));
1890  mProjectFile->setBuildDir(filename.left(filename.indexOf(".")) + "-cppcheck-build-dir");
1891 
1893  if (dlg.exec() == QDialog::Accepted) {
1894  addProjectMRU(filepath);
1896  } else {
1897  closeProjectFile();
1898  }
1899 }
1900 
1902 {
1903  delete mProjectFile;
1904  mProjectFile = nullptr;
1905  mUI->mResults->clear(true);
1906  enableProjectActions(false);
1909 }
1910 
1912 {
1913  if (!mProjectFile) {
1914  QMessageBox msg(QMessageBox::Critical,
1915  tr("Cppcheck"),
1916  QString(tr("No project file loaded")),
1917  QMessageBox::Ok,
1918  this);
1919  msg.exec();
1920  return;
1921  }
1922 
1924  if (dlg.exec() == QDialog::Accepted) {
1925  mProjectFile->write();
1927  }
1928 }
1929 
1931 {
1932  StatsDialog statsDialog(this);
1933 
1934  // Show a dialog with the previous scan statistics and project information
1935  statsDialog.setProject(mProjectFile);
1936  statsDialog.setPathSelected(mCurrentDirectory);
1938  statsDialog.setScanDuration(mThread->getPreviousScanDuration() / 1000.0);
1939  statsDialog.setStatistics(mUI->mResults->getStatistics());
1940 
1941  statsDialog.exec();
1942 }
1943 
1945 {
1946  LibraryDialog libraryDialog(this);
1947  libraryDialog.exec();
1948 }
1949 
1951 {
1952  mUI->mResults->filterResults(mLineEditFilter->text());
1953 }
1954 
1956 {
1957  mUI->mActionCloseProjectFile->setEnabled(enable);
1958  mUI->mActionEditProjectFile->setEnabled(enable);
1959  mUI->mActionCheckLibrary->setEnabled(enable);
1960  mUI->mActionCheckConfiguration->setEnabled(enable);
1961 }
1962 
1964 {
1965  mUI->mActionNewProjectFile->setEnabled(enable);
1966  mUI->mActionOpenProjectFile->setEnabled(enable);
1967 }
1968 
1970 {
1971  auto *action = qobject_cast<QAction *>(sender());
1972  if (!action)
1973  return;
1974  const QString project = action->data().toString();
1975  QFileInfo inf(project);
1976  if (inf.exists()) {
1977  if (inf.suffix() == "xml")
1978  loadResults(project);
1979  else {
1980  loadProjectFile(project);
1981  loadLastResults();
1982  }
1983  } else {
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));
1987 
1988  QMessageBox msg(QMessageBox::Warning,
1989  tr("Cppcheck"),
1990  text,
1991  QMessageBox::Yes | QMessageBox::No,
1992  this);
1993 
1994  msg.setDefaultButton(QMessageBox::No);
1995  const int rv = msg.exec();
1996  if (rv == QMessageBox::Yes) {
1997  removeProjectMRU(project);
1998  }
1999  }
2000 }
2001 
2003 {
2004  for (QAction* recentProjectAct : mRecentProjectActs) {
2005  if (recentProjectAct != nullptr)
2006  mUI->mMenuFile->removeAction(recentProjectAct);
2007  }
2008 
2009  QStringList projects = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList();
2010 
2011  // Do a sanity check - remove duplicates and non-existing projects
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);
2016  removed++;
2017  }
2018  }
2019 
2020  if (removed)
2021  mSettings->setValue(SETTINGS_MRU_PROJECTS, projects);
2022 
2023  const int numRecentProjects = qMin(projects.size(), (int)MaxRecentProjects);
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);
2027  mRecentProjectActs[i]->setText(text);
2028  mRecentProjectActs[i]->setData(projects[i]);
2029  mRecentProjectActs[i]->setVisible(true);
2030  mUI->mMenuFile->insertAction(mUI->mActionProjectMRU, mRecentProjectActs[i]);
2031  }
2032 
2033  if (numRecentProjects > 1)
2034  mRecentProjectActs[numRecentProjects] = mUI->mMenuFile->insertSeparator(mUI->mActionProjectMRU);
2035 }
2036 
2037 void MainWindow::addProjectMRU(const QString &project)
2038 {
2039  QStringList files = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList();
2040  files.removeAll(project);
2041  files.prepend(project);
2042  while (files.size() > MaxRecentProjects)
2043  files.removeLast();
2044 
2045  mSettings->setValue(SETTINGS_MRU_PROJECTS, files);
2047 }
2048 
2049 void MainWindow::removeProjectMRU(const QString &project)
2050 {
2051  QStringList files = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList();
2052  files.removeAll(project);
2053 
2054  mSettings->setValue(SETTINGS_MRU_PROJECTS, files);
2056 }
2057 
2059 {
2060  auto *action = qobject_cast<QAction *>(sender());
2061  if (action) {
2062  const Platform::Type platform = (Platform::Type) action->data().toInt();
2063  mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform);
2064  }
2065 }
2066 
2067 void MainWindow::suppressIds(QStringList ids)
2068 {
2069  if (!mProjectFile)
2070  return;
2071  ids.removeDuplicates();
2072 
2073  QList<SuppressionList::Suppression> suppressions = mProjectFile->getSuppressions();
2074  for (const QString& id : ids) {
2075  // Remove all matching suppressions
2076  std::string id2 = id.toStdString();
2077  for (int i = 0; i < suppressions.size();) {
2078  if (suppressions[i].errorId == id2)
2079  suppressions.removeAt(i);
2080  else
2081  ++i;
2082  }
2083 
2084  SuppressionList::Suppression newSuppression;
2085  newSuppression.errorId = id2;
2086  suppressions << newSuppression;
2087  }
2088 
2089  mProjectFile->setSuppressions(suppressions);
2090  mProjectFile->write();
2091 }
2092 
2093 static int getVersion(const QString& nameWithVersion) {
2094  int ret = 0;
2095  int v = 0;
2096  int dot = 0;
2097  for (const auto c: nameWithVersion) {
2098  if (c == '\n' || c == '\r')
2099  break;
2100  if (c == ' ') {
2101  if (ret > 0 && dot == 1 && nameWithVersion.endsWith(" dev"))
2102  return ret * 1000000 + v * 1000 + 500;
2103  dot = ret = v = 0;
2104  }
2105  else if (c == '.') {
2106  ++dot;
2107  ret = ret * 1000 + v;
2108  v = 0;
2109  } else if (c >= '0' && c <= '9')
2110  v = v * 10 + (c.toLatin1() - '0');
2111  }
2112  ret = ret * 1000 + v;
2113  while (dot < 2) {
2114  ++dot;
2115  ret *= 1000;
2116  }
2117  return ret;
2118 }
2119 
2120 void MainWindow::replyFinished(QNetworkReply *reply) {
2121  reply->deleteLater();
2122  if (reply->error()) {
2123  mUI->mLayoutInformation->deleteLater();
2124  qDebug() << "Response: ERROR";
2125  return;
2126  }
2127  const QString str = reply->readAll();
2128  qDebug() << "Response: " << str;
2129  if (reply->url().fileName() == "version.txt") {
2130  QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version());
2131  if (!mCppcheckCfgProductName.isEmpty())
2132  nameWithVersion = mCppcheckCfgProductName;
2133  const int appVersion = getVersion(nameWithVersion);
2134  const int latestVersion = getVersion(str.trimmed());
2135  if (appVersion < latestVersion) {
2136  if (mSettings->value(SETTINGS_CHECK_VERSION, 0).toInt() != latestVersion) {
2137  QString install;
2138  if (isCppcheckPremium()) {
2139 #ifdef Q_OS_WIN
2140  const QString url("https://cppchecksolutions.com/cppcheck-premium-installation");
2141 #else
2142  const QString url("https://cppchecksolutions.com/cppcheck-premium-linux-installation");
2143 #endif
2144  install = "<a href=\"" + url + "\">" + tr("Install") + "</a>";
2145  }
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));
2149  }
2150  }
2151  }
2152  if (!mUI->mLabelInformation->isVisible()) {
2153  mUI->mLayoutInformation->deleteLater();
2154  }
2155 }
2156 
2158  int version = getVersion(mUI->mLabelInformation->text());
2159  mSettings->setValue(SETTINGS_CHECK_VERSION, version);
2160  mUI->mLabelInformation->setVisible(false);
2161  mUI->mButtonHideInformation->setVisible(false);
2162  mUI->mLayoutInformation->deleteLater();
2163 }
2164 
2166  return mCppcheckCfgProductName.startsWith("Cppcheck Premium ");
2167 }
2168 
About dialog.
Definition: aboutdialog.h:38
static void writeFilesTxt(const std::string &buildDir, const std::list< std::string > &sourcefiles, const std::string &userDefines, const std::list< FileSettings > &fileSettings)
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)
Definition: checkthread.cpp:60
This is the base class which will use other classes to do static code analysis for C and C++ code to ...
Definition: cppcheck.h:60
static const char * version()
Returns current version number as a string.
Definition: cppcheck.cpp:354
static const char * extraVersion()
Returns extra version info as a string.
Definition: cppcheck.cpp:359
A class containing error data for one error.
Definition: erroritem.h:72
A class for listing files and directories to check.
Definition: filelist.h:39
static QStringList getDefaultFilters()
Return list of default filename extensions included.
Definition: filelist.cpp:31
QStringList getFileList() const
Return list of filenames (to check).
Definition: filelist.cpp:93
void addPathList(const QStringList &paths)
Add list of filenames and directories to the list.
Definition: filelist.cpp:82
void addExcludeList(const QStringList &paths)
Add list of paths to exclusion list.
Definition: filelist.cpp:106
File view -dialog.
Importing project settings.
Definition: importproject.h:52
std::list< FileSettings > fileSettings
Definition: importproject.h:70
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)
ErrorCode errorcode
Definition: library.h:74
Library definitions handling.
Definition: library.h:52
Error load(const char exename[], const char path[])
Definition: library.cpp:68
Main window for cppcheck-gui.
Definition: mainwindow.h:58
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
Definition: mainwindow.h:482
ThreadHandler * mThread
Thread to analyze files.
Definition: mainwindow.h:428
void loadResults(const QString &selectedFile)
Load XML file to the GUI.
QStringList selectFilesToAnalyze(QFileDialog::FileMode mode)
Select files/or directory to analyze.
Definition: mainwindow.cpp:660
void showStatistics()
Slot for showing the scan and project statistics.
void showErrors(bool checked)
Show errors with type "error".
~MainWindow() override
Definition: mainwindow.cpp:313
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...
Definition: mainwindow.h:468
void uncheckAll()
Slot to uncheck all "Show errors" menu items.
void handleCLIParams(const QStringList &params)
Handle command line parameters given to GUI.
Definition: mainwindow.cpp:320
void showScratchpad()
Slot to show scratchpad.
void hideInformation()
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.
Definition: mainwindow.cpp:625
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.
Definition: mainwindow.cpp:557
void enableCheckButtons(bool enable)
Helper function to enable/disable all check,recheck buttons.
QAction * mRecentProjectActs[MaxRecentProjects+1]
Project MRU menu actions.
Definition: mainwindow.h:477
void replyFinished(QNetworkReply *reply)
void openHelpContents()
Open help file contents.
QString mCppcheckCfgProductName
Definition: mainwindow.h:480
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.
Definition: mainwindow.cpp:874
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.
Definition: mainwindow.h:471
void reAnalyzeSelected(const QStringList &files)
Reanalyze selected files.
void analysisDone()
Slot for checkthread's done signal.
void analyzeDirectory()
Slot for analyze directory menu item.
Definition: mainwindow.cpp:753
Library::Error loadLibrary(Library &library, const QString &filename)
Load library file.
Definition: mainwindow.cpp:826
void updateMRUMenuItems()
Update project MRU items in File-menu.
ScratchPad * mScratchPad
Scratchpad.
Definition: mainwindow.h:443
void showInformation(bool checked)
Show errors with type "information".
QActionGroup * mCppStandardActions
Definition: mainwindow.h:458
QTimer * mFilterTimer
Timer to delay filtering while typing.
Definition: mainwindow.h:452
void removeProjectMRU(const QString &project)
Remove project file (path) from the MRU list.
QActionGroup * mCStandardActions
GUI actions for selecting the coding standard.
Definition: mainwindow.h:458
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.
Definition: mainwindow.cpp:716
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.
Definition: mainwindow.cpp:810
QLineEdit * mLineEditFilter
Filter field in the Filter toolbar.
Definition: mainwindow.h:449
Platforms mPlatforms
List of checked platforms.
Definition: mainwindow.h:75
QString loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString &addon)
Definition: mainwindow.cpp:926
ApplicationList * mApplications
List of user defined applications to open errors with.
Definition: mainwindow.h:431
void saveSettings() const
Save program settings.
Definition: mainwindow.cpp:433
@ MaxRecentProjects
Definition: mainwindow.h:65
void openResults()
Slot to open XML report file.
void loadSettings()
Load program settings.
Definition: mainwindow.cpp:351
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.
Definition: mainwindow.h:461
static void openOnlineHelp()
Show help contents.
Ui::MainWindow * mUI
Class holding all UI components.
Definition: mainwindow.h:437
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).
Definition: mainwindow.h:446
void showPerformance(bool checked)
Show errors with type "performance".
TranslationHandler * mTranslation
Class to handle translation changes.
Definition: mainwindow.h:434
void resultsAdded()
Slot for enabling save and clear button.
QString mCurrentDirectory
Current analyzed directory.
Definition: mainwindow.h:440
QActionGroup * mPlatformActions
GUI actions for selecting the analyzed platform.
Definition: mainwindow.h:455
QSettings * mSettings
Program settings.
Definition: mainwindow.h:425
QPair< bool, Settings > getCppcheckSettings()
Get our default cppcheck settings and read project file.
Definition: mainwindow.cpp:963
void doAnalyzeProject(ImportProject p, const bool checkLibrary=false, const bool checkConfiguration=false)
Analyze project.
Definition: mainwindow.cpp:489
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)
Definition: mainwindow.cpp:113
void showPortability(bool checked)
Show errors with type "portability".
QString mCppcheckCfgAbout
Definition: mainwindow.h:479
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.
bool loadFromFile(const char exename[], const std::string &filename, bool verbose=false)
load platform file
Definition: platform.cpp:192
const char * toString() const
Definition: platform.h:148
Type type
platform type
Definition: platform.h:118
bool set(Type t)
set the platform type for predefined platforms - deprecated use set(const std::string&,...
Definition: platform.cpp:36
int getCount() const
Definition: platforms.cpp:46
QList< PlatformData > mPlatforms
Definition: platforms.h:55
PlatformData & get(Platform::Type platform)
Definition: platforms.cpp:51
A dialog for editing project file data.
A class that reads and writes project files.
Definition: projectfile.h:46
SafeChecks safeChecks
Definition: projectfile.h:414
const QStringList & getCodingStandards() const
Get list of coding standards (checked by Cppcheck Premium).
Definition: projectfile.h:370
QStringList getAddonsAndTools() const
Get list of addons and tools.
bool clangParser
Use Clang parser.
Definition: projectfile.h:427
int getMaxCtuDepth() const
Definition: projectfile.h:237
QList< SuppressionList::Suppression > getCheckingSuppressions() const
Get "checking" suppressions.
void setActiveProject()
Definition: projectfile.h:64
const QStringList & getAddons() const
Get list addons.
Definition: projectfile.h:200
const QString & getPlatform() const
Get platform.
Definition: projectfile.h:170
bool isCheckLevelExhaustive() const
const QString & getFilename() const
Get filename for the project file.
Definition: projectfile.h:257
const QString & getRootPath() const
Get project root path.
Definition: projectfile.h:78
bool getBughunting() const
Definition: projectfile.h:365
void setBuildDir(const QString &buildDir)
Definition: projectfile.h:269
const QList< SuppressionList::Suppression > & getSuppressions() const
Get "raw" suppressions.
Definition: projectfile.h:186
const QStringList & getCheckUnknownFunctionReturn() const
Check unknown function return values.
Definition: projectfile.h:417
const QStringList & getDefines() const
Get list of defines.
Definition: projectfile.h:122
QStringList getCheckPaths() const
Get list of paths to check.
Definition: projectfile.h:138
bool getAnalyzeAllVsConfigs() const
Definition: projectfile.h:90
int getCertIntPrecision() const
Definition: projectfile.h:386
int getMaxTemplateRecursion() const
Definition: projectfile.h:245
const QStringList & getUndefines() const
Get list of undefines.
Definition: projectfile.h:130
const QStringList & getVsConfigurations() const
Get list of paths to exclude from the check.
Definition: projectfile.h:154
static QString getAddonFilePath(QString filesDir, const QString &addon)
Get path to addon python script.
bool read(const QString &filename=QString())
Read the project file.
Definition: projectfile.cpp:94
void setProjectName(QString projectName)
Definition: projectfile.h:178
void setFilename(const QString &filename)
Set filename for the project file.
Definition: projectfile.h:401
bool getCheckUnusedTemplates() const
Definition: projectfile.h:102
QStringList getExcludedPaths() const
Get list of paths to exclude from the check.
Definition: projectfile.h:146
QStringList getIncludeDirs() const
Get list of include directories.
Definition: projectfile.h:114
bool getCheckHeaders() const
Definition: projectfile.h:94
const QStringList & getLibraries() const
Get list libraries.
Definition: projectfile.h:162
const QString & getBuildDir() const
Definition: projectfile.h:82
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
Definition: projectfile.h:86
Type
Definition: report.h:36
@ CSV
Definition: report.h:39
@ XMLV2
Definition: report.h:38
@ TXT
Definition: report.h:37
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 .
Definition: scratchpad.h:37
void translate()
Translate dialog.
Definition: scratchpad.cpp:44
Settings 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...
Definition: settings.h:95
std::set< std::string > userUndefs
undefines given by the user
Definition: settings.h:389
static void terminate(bool t=true)
Request termination of checking.
Definition: settings.h:444
void loadSummaries()
Definition: settings.cpp:283
static std::string loadCppcheckCfg(Settings &settings, Suppressions &suppressions)
Definition: settings.cpp:65
bool quiet
Is –quiet given?
Definition: settings.h:282
bool checkLibrary
Check for incomplete info in library files?
Definition: settings.h:135
bool checkHeaders
Check code in the headers, this is on by default but can be turned off to save CPU.
Definition: settings.h:132
bool checkAllConfigurations
check all configurations (false if -D or –max-configs is used
Definition: settings.h:124
int maxCtuDepth
–max-ctu-depth
Definition: settings.h:247
Suppressions supprs
suppressions
Definition: settings.h:369
Standards::Language enforcedLang
Name of the language that is enforced.
Definition: settings.h:190
std::string exename
Definition: settings.h:210
SimpleEnableGroup< Checks > checks
Definition: settings.h:360
bool xml
write XML results (–xml)
Definition: settings.h:401
bool checkConfiguration
Is the 'configuration checking' wanted?
Definition: settings.h:127
std::unordered_set< std::string > addons
addons, either filename of python/json file or json data
Definition: settings.h:109
Library library
Library.
Definition: settings.h:237
void setMisraRuleTexts(const ExecuteCmdFn &executeCommand)
Definition: settings.cpp:572
SafeChecks safeChecks
Definition: settings.h:356
bool clang
Use Clang.
Definition: settings.h:150
std::string buildDir
–cppcheck-build-dir.
Definition: settings.h:121
std::string cppcheckCfgProductName
cppcheck.cfg: Custom product name
Definition: settings.h:165
std::string userDefines
defines given by the user
Definition: settings.h:386
std::vector< AddonInfo > addonInfos
the loaded addons infos
Definition: settings.h:112
std::string premiumArgs
Extra arguments for Cppcheck Premium addon.
Definition: settings.h:273
bool inlineSuppressions
Is –inline-suppr given?
Definition: settings.h:227
Platform platform
Definition: settings.h:255
void setCheckLevel(CheckLevel level)
Definition: settings.cpp:288
std::string cppcheckCfgAbout
cppcheck.cfg: About text
Definition: settings.h:168
unsigned int jobs
How many processes/threads should do checking at the same time.
Definition: settings.h:231
bool force
Force checking the files with "too many" configurations (–force).
Definition: settings.h:220
bool verbose
Is –verbose given?
Definition: settings.h:398
std::set< std::string > checkUnknownFunctionReturn
check unknown function return values
Definition: settings.h:144
std::list< std::string > libraries
–library=
Definition: settings.h:234
std::list< std::string > includePaths
List of include paths, e.g.
Definition: settings.h:224
int maxTemplateRecursion
max template recursion
Definition: settings.h:250
SimpleEnableGroup< Certainty > certainty
Definition: settings.h:359
int maxConfigs
Maximum number of configurations to check before bailing.
Definition: settings.h:244
SimpleEnableGroup< Severity > severity
Definition: settings.h:358
bool checkUnusedTemplates
Check unused/uninstantiated templates.
Definition: settings.h:147
bool debugwarnings
Is –debug-warnings given?
Definition: settings.h:183
Standards standards
Struct contains standards settings.
Definition: settings.h:366
A class for different show types we have.
Definition: showtypes.h:38
@ ShowPerformance
Definition: showtypes.h:47
@ ShowInformation
Definition: showtypes.h:49
@ ShowPortability
Definition: showtypes.h:48
@ ShowErrors
Definition: showtypes.h:50
@ ShowWarnings
Definition: showtypes.h:46
@ ShowStyle
Definition: showtypes.h:45
bool isShown(ShowTypes::ShowType category) const
Is the showtype visible in the GUI?
Definition: showtypes.cpp:117
void setEnabled(T flag, bool enabled)
Definition: settings.h:81
void enable(T flag)
Definition: settings.h:69
A dialog that shows project and scan statistics.
Definition: statsdialog.h:40
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.
Definition: statsdialog.cpp:95
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.
Definition: threadhandler.h:50
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)
Definition: threadhandler.h:81
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)
Definition: threadhandler.h:89
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)
Definition: threadhandler.h:85
Threads use this class to obtain new files to process and to publish results.
Definition: threadresult.h:46
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)
Definition: color.cpp:54
@ warning
Warning.
@ portability
Portability warning.
@ style
Style warning.
@ information
Checking information.
@ performance
Performance warning.
@ error
Programming error.
@ missingInclude
@ unusedFunction
#define SETTINGS_LAST_ANALYZE_FILES_FILTER
Definition: common.h:104
#define SETTINGS_SHOW_INFORMATION
Definition: common.h:56
#define SETTINGS_WINDOW_HEIGHT
Definition: common.h:38
#define SETTINGS_PYTHON_PATH
Definition: common.h:80
#define SETTINGS_ENFORCED_LANGUAGE
Definition: common.h:64
#define SETTINGS_TOOLBARS_FILTER_SHOW
Definition: common.h:49
#define SETTINGS_LAST_RESULT_PATH
Definition: common.h:100
#define SETTINGS_INLINE_SUPPRESSIONS
Definition: common.h:84
#define SETTINGS_LAST_CHECK_PATH
Definition: common.h:98
QString getPath(const QString &type)
Obtains the path of specified type Returns the path of specified type if not empty.
Definition: common.cpp:32
QString getDataDir()
Get configured data dir.
Definition: common.cpp:75
#define SETTINGS_CHECKED_PLATFORM
Definition: common.h:96
#define SETTINGS_TOOLBARS_VIEW_SHOW
Definition: common.h:48
#define SETTINGS_SHOW_ERRORS
Definition: common.h:53
#define SETTINGS_TOOLBARS_MAIN_SHOW
Definition: common.h:47
#define SETTINGS_CHECK_FOR_UPDATES
Definition: common.h:91
#define SETTINGS_CHECK_FORCE
Definition: common.h:67
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...
Definition: common.cpp:52
#define SETTINGS_SHOW_PERFORMANCE
Definition: common.h:55
#define SETTINGS_STD_CPP
Definition: common.h:60
#define SETTINGS_VS_INCLUDE_PATHS
Definition: common.h:83
#define SETTINGS_LANGUAGE
Definition: common.h:78
#define SETTINGS_STD_C
Definition: common.h:61
#define SETTINGS_MRU_PROJECTS
Definition: common.h:86
#define SETTINGS_CHECK_VERSION
Definition: common.h:90
#define SETTINGS_SHOW_DEBUG_WARNINGS
Definition: common.h:71
#define SETTINGS_WINDOW_MAXIMIZED
QSetting value names.
Definition: common.h:36
#define SETTINGS_SHOW_STYLE
Definition: common.h:52
#define SETTINGS_INCONCLUSIVE_ERRORS
Definition: common.h:85
#define SETTINGS_WINDOW_WIDTH
Definition: common.h:37
#define SETTINGS_LAST_PROJECT_PATH
Definition: common.h:99
#define SETTINGS_MISRA_FILE
Definition: common.h:81
#define SETTINGS_SHOW_WARNINGS
Definition: common.h:54
#define SETTINGS_GLOBAL_INCLUDE_PATHS
Definition: common.h:79
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.
Definition: common.cpp:46
#define SETTINGS_SHOW_STATISTICS
Definition: common.h:88
#define SETTINGS_OPEN_PROJECT
Definition: common.h:89
#define SETTINGS_SHOW_PORTABILITY
Definition: common.h:57
#define SETTINGS_CHECK_THREADS
Definition: common.h:68
static int getVersion(const QString &nameWithVersion)
static const QString compile_commands_json("compile_commands.json")
static QString fromNativePath(const QString &p)
Definition: mainwindow.cpp:103
Definition: aboutdialog.h:27
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)
Definition: addoninfo.cpp:127
Simple container to be thrown when internal error is detected.
Definition: errortypes.h:36
std::string errorMessage
Definition: errortypes.h:43
Checked platform GUI-data.
Definition: platforms.h:36
Platform::Type mType
Type in the core.
Definition: platforms.h:38
QString mTitle
Text visible in the GUI.
Definition: platforms.h:37
QAction * mActMainWindow
Pointer to main window action item.
Definition: platforms.h:39
bool classes
Public interface of classes.
Definition: settings.h:334
bool externalVariables
Global variables that can be modified outside the TU.
Definition: settings.h:353
bool externalFunctions
External functions.
Definition: settings.h:341
bool internalFunctions
Experimental: assume that internal functions can be used in any way This is only available in the GUI...
Definition: settings.h:347
This is just a container for standards settings.
Definition: standards.h:36
bool setC(const std::string &str)
Definition: standards.h:48
enum Standards::cstd_t c
bool setCPP(std::string str)
Definition: standards.h:97
enum Standards::cppstd_t cpp
SuppressionList nomsg
suppress message (–suppressions)
Definition: suppressions.h:264