25 #include "ui_statsdialog.h" 
   27 #include <QApplication> 
   30 #include <QFileDialog> 
   37 #include <QPlainTextEdit> 
   39 #include <QPushButton> 
   40 #include <QStringList> 
   41 #include <QTextDocument> 
   48 #include <QAbstractSeries> 
   51 #include <QDateTimeAxis> 
   56 #include <QLineSeries> 
   60 #include <QRegularExpression> 
   61 #include <QTextStream> 
   64 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) 
   65 QT_CHARTS_USE_NAMESPACE
 
   68 static QLineSeries *numberOfReports(
const QString &fileName, 
const QString &severity);
 
   69 static QChartView *createChart(
const QString &statsFile, 
const QString &tool);
 
   80     QFont font(
"courier");
 
   81     font.setStyleHint(QFont::Monospace);
 
   82     mUI->mCheckersReport->setFont(font);
 
   84     setWindowFlags(Qt::Window);
 
  103 #ifndef QT_CHARTS_LIB 
  104         mUI->mTabHistory->setVisible(
false);
 
  108             const QString prjpath = QFileInfo(projectFile->
getFilename()).absolutePath();
 
  109             const QString buildDir = prjpath + 
'/' + projectFile->
getBuildDir();
 
  110             if (QDir(buildDir).exists()) {
 
  111                 statsFile = buildDir + 
"/statistics.txt";
 
  114         mUI->mLblHistoryFile->setText(tr(
"File: ") + (statsFile.isEmpty() ? tr(
"No cppcheck build dir") : statsFile));
 
  115         if (!statsFile.isEmpty()) {
 
  116             QChartView *chartView = createChart(statsFile, 
"cppcheck");
 
  117             mUI->mTabHistory->layout()->addWidget(chartView);
 
  120                 mUI->mTabHistory->layout()->addWidget(chartView);
 
  123                 chartView = createChart(statsFile, 
CLANG_TIDY);
 
  124                 mUI->mTabHistory->layout()->addWidget(chartView);
 
  129         mUI->mProject->setText(QString());
 
  130         mUI->mPaths->setText(QString());
 
  131         mUI->mIncludePaths->setText(QString());
 
  132         mUI->mDefines->setText(QString());
 
  133         mUI->mUndefines->setText(QString());
 
  139     mUI->mPath->setText(path);
 
  144     mUI->mNumberOfFilesScanned->setText(QString::number(num));
 
  151     const int days = secs / (24 * 60 * 60);
 
  152     secs -= days * (24 * 60 * 60);
 
  153     const int hours = secs / (60 * 60);
 
  154     secs -= hours * (60 * 60);
 
  155     const int mins = secs / 60;
 
  161         parts << ((days == 1) ? tr(
"1 day") : tr(
"%1 days").arg(days));
 
  163         parts << ((hours == 1) ? tr(
"1 hour") : tr(
"%1 hours").arg(hours));
 
  164     if (mins && parts.size() < 2)
 
  165         parts << ((mins == 1) ? tr(
"1 minute") : tr(
"%1 minutes").arg(mins));
 
  166     if (secs && parts.size() < 2)
 
  167         parts << ((secs == 1) ? tr(
"1 second") : tr(
"%1 seconds").arg(secs));
 
  171         parts << tr(
"0.%1 seconds").arg(
int(10.0 *(seconds - secs)));
 
  173     mUI->mScanDuration->setText(parts.join(tr(
" and ")));
 
  177     const QString Stat = QString(
 
  178         "<center><h1>%1   %2</h1></center>\n" 
  179         "<font color=\"red\"><h3>%3   :   %4</h3></font>\n" 
  180         "<font color=\"green\"><h3>%5   :   %6</h3></font>\n" 
  181         "<font color=\"orange\"><h3>%7   :   %8</h3></font>\n" 
  182         "<font color=\"blue\"><h3>%9   :   %10</h3></font>\n" 
  183         "<font color=\"blue\"><h3>%11  :   %12</h3></font>\n" 
  184         "<font color=\"purple\"><h3>%13  :   %14</h3></font>\n")
 
  185                          .arg(tr(
"Statistics"))
 
  186                          .arg(QDate::currentDate().
toString(
"dd.MM.yyyy"))
 
  191                          .arg(tr(
"Style warnings"))
 
  193                          .arg(tr(
"Portability warnings"))
 
  195                          .arg(tr(
"Performance warnings"))
 
  197                          .arg(tr(
"Information messages"))
 
  200     QString fileName = QFileDialog::getSaveFileName((QWidget*)
nullptr, tr(
"Export PDF"), QString(), 
"*.pdf");
 
  201     if (QFileInfo(fileName).suffix().isEmpty()) {
 
  202         fileName.append(
".pdf");
 
  204     QPrinter printer(QPrinter::PrinterResolution);
 
  205     printer.setOutputFormat(QPrinter::PdfFormat);
 
  206     printer.setPageSize(QPageSize(QPageSize::A4));
 
  207     printer.setOutputFileName(fileName);
 
  218     QClipboard *clipboard = QApplication::clipboard();
 
  222     const QString projSettings(tr(
"Project Settings"));
 
  223     const QString project(tr(
"Project"));
 
  224     const QString paths(tr(
"Paths"));
 
  225     const QString incPaths(tr(
"Include paths"));
 
  226     const QString defines(tr(
"Defines"));
 
  227     const QString undefines(tr(
"Undefines"));
 
  228     const QString prevScan(tr(
"Previous Scan"));
 
  229     const QString selPath(tr(
"Path selected"));
 
  230     const QString numFiles(tr(
"Number of files scanned"));
 
  231     const QString duration(tr(
"Scan duration"));
 
  232     const QString stats(tr(
"Statistics"));
 
  233     const QString errors(tr(
"Errors"));
 
  234     const QString warnings(tr(
"Warnings"));
 
  235     const QString 
style(tr(
"Style warnings"));
 
  236     const QString 
portability(tr(
"Portability warnings"));
 
  237     const QString 
performance(tr(
"Performance warnings"));
 
  238     const QString 
information(tr(
"Information messages"));
 
  241     const QString settings = QString(
 
  251                              .arg(
mUI->mProject->text())
 
  253                              .arg(
mUI->mPaths->text())
 
  255                              .arg(
mUI->mIncludePaths->text())
 
  257                              .arg(
mUI->mDefines->text())
 
  259                              .arg(
mUI->mUndefines->text());
 
  261     const QString previous = QString(
 
  269                              .arg(
mUI->mPath->text())
 
  271                              .arg(
mUI->mNumberOfFilesScanned->text())
 
  273                              .arg(
mUI->mScanDuration->text());
 
  275     const QString statistics = QString(
 
  298     const QString textSummary = settings + previous + statistics;
 
  301     const QString htmlSettings = QString(
 
  304         " <tr><th>%2:</th><td>%3</td></tr>\n" 
  305         " <tr><th>%4:</th><td>%5</td></tr>\n" 
  306         " <tr><th>%6:</th><td>%7</td></tr>\n" 
  307         " <tr><th>%8:</th><td>%9</td></tr>\n" 
  308         " <tr><th>%10:</th><td>%11</td></tr>\n" 
  313                                  .arg(
mUI->mProject->text())
 
  315                                  .arg(
mUI->mPaths->text())
 
  317                                  .arg(
mUI->mIncludePaths->text())
 
  319                                  .arg(
mUI->mDefines->text())
 
  321                                  .arg(
mUI->mUndefines->text());
 
  323     const QString htmlPrevious = QString(
 
  326         " <tr><th>%2:</th><td>%3</td></tr>\n" 
  327         " <tr><th>%4:</th><td>%5</td></tr>\n" 
  328         " <tr><th>%6:</th><td>%7</td></tr>\n" 
  333                                  .arg(
mUI->mPath->text())
 
  335                                  .arg(
mUI->mNumberOfFilesScanned->text())
 
  337                                  .arg(
mUI->mScanDuration->text());
 
  339     const QString htmlStatistics = QString(
 
  341         " <tr><th>%2:</th><td>%3</td></tr>\n" 
  342         " <tr><th>%4:</th><td>%5</td></tr>\n" 
  343         " <tr><th>%6:</th><td>%7</td></tr>\n" 
  344         " <tr><th>%8:</th><td>%9</td></tr>\n" 
  345         " <tr><th>%10:</th><td>%11</td></tr>\n" 
  346         " <tr><th>%12:</th><td>%13</td></tr>\n" 
  363     const QString htmlSummary = htmlSettings + htmlPrevious + htmlStatistics;
 
  365     auto *mimeData = 
new QMimeData();
 
  366     mimeData->setText(textSummary);
 
  367     mimeData->setHtml(htmlSummary);
 
  368     clipboard->setMimeData(mimeData);
 
  385 QChartView *createChart(
const QString &statsFile, 
const QString &tool)
 
  387     auto *chart = 
new QChart;
 
  388     chart->addSeries(numberOfReports(statsFile, tool + 
"-error"));
 
  389     chart->addSeries(numberOfReports(statsFile, tool + 
"-warning"));
 
  390     chart->addSeries(numberOfReports(statsFile, tool + 
"-style"));
 
  391     chart->addSeries(numberOfReports(statsFile, tool + 
"-performance"));
 
  392     chart->addSeries(numberOfReports(statsFile, tool + 
"-portability"));
 
  394     auto *axisX = 
new QDateTimeAxis;
 
  395     axisX->setTitleText(
"Date");
 
  396     chart->addAxis(axisX, Qt::AlignBottom);
 
  398     for (QAbstractSeries *s : chart->series()) {
 
  399         s->attachAxis(axisX);
 
  402     auto *axisY = 
new QValueAxis;
 
  403     axisY->setLabelFormat(
"%i");
 
  404     axisY->setTitleText(
"Count");
 
  405     chart->addAxis(axisY, Qt::AlignLeft);
 
  408     for (QAbstractSeries *s : chart->series()) {
 
  409         s->attachAxis(axisY);
 
  410         if (
const auto *ls = 
dynamic_cast<const QLineSeries*
>(s)) {
 
  411             for (QPointF p : ls->points()) {
 
  420     chart->setTitle(tool);
 
  422     auto *chartView = 
new QChartView(chart);
 
  423     chartView->setRenderHint(QPainter::Antialiasing);
 
  427 QLineSeries *numberOfReports(
const QString &fileName, 
const QString &severity)
 
  429     auto *series = 
new QLineSeries();
 
  430     series->setName(severity);
 
  432     if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 
  435         while (!in.atEnd()) {
 
  436             QString line = in.readLine();
 
  437             static const QRegularExpression rxdate(
"^\\[(\\d\\d)\\.(\\d\\d)\\.(\\d\\d\\d\\d)\\]$");
 
  438             const QRegularExpressionMatch matchRes = rxdate.match(line);
 
  439             if (matchRes.hasMatch()) {
 
  440                 const int y = matchRes.captured(3).toInt();
 
  441                 const int m = matchRes.captured(2).toInt();
 
  442                 const int d = matchRes.captured(1).toInt();
 
  444                 dt.setDate(QDate(y,m,d));
 
  445                 if (t == dt.toMSecsSinceEpoch())
 
  448                     t = dt.toMSecsSinceEpoch();
 
  450             if (line.startsWith(severity + 
':')) {
 
  451                 const int y = line.mid(1+severity.length()).toInt();
 
  452                 series->append(t, y);
 
A class for check statistics.
 
const QString & getCheckersReport() const
 
unsigned getCount(const QString &tool, ShowTypes::ShowType type) const
Return statistics for given type.
 
int getNumberOfActiveCheckers() const
 
A class that reads and writes project files.
 
const QString & getFilename() const
Get filename for the project file.
 
const QString & getRootPath() const
Get project root path.
 
bool getClangAnalyzer() const
 
const QStringList & getDefines() const
Get list of defines.
 
QStringList getCheckPaths() const
Get list of paths to check.
 
bool getClangTidy() const
 
const QStringList & getUndefines() const
Get list of undefines.
 
QStringList getIncludeDirs() const
Get list of include directories.
 
const QString & getBuildDir() const
 
A dialog that shows project and scan statistics.
 
void setScanDuration(double seconds)
Sets the number of seconds to display beside "Scan Duration:".
 
void setNumberOfFilesScanned(int num)
Sets the number to display beside "Number of Files Scanned:".
 
void setProject(const ProjectFile *projectFile)
Sets the project to extract statistics from.
 
void setStatistics(const CheckStatistics *stats)
Sets the numbers of different error/warnings found.
 
void setPathSelected(const QString &path)
Sets the string to display beside "Path Selected:".
 
const CheckStatistics * mStatistics
 
StatsDialog(QWidget *parent=nullptr)
 
std::string toString(Color c)
 
@ portability
Portability warning.
 
@ information
Checking information.
 
@ performance
Performance warning.
 
static const QString CPPCHECK("cppcheck")