GUI: Refactor report saving.

Refactoring report writing to own classes and using QT's XML classes for XML output. This also fixes the ticket ##408 (GUI generates invalid xml).
https://sourceforge.net/apps/trac/cppcheck/ticket/408
This commit is contained in:
Kimmo Varis 2009-06-24 10:54:56 +03:00
parent df241441dc
commit 678714419c
10 changed files with 481 additions and 64 deletions

View File

@ -29,6 +29,9 @@ HEADERS += mainwindow.h \
common.h \
fileviewdialog.h \
projectfile.h \
report.h \
txtreport.h \
xmlreport.h \
../src/checkautovariables.h \
../src/checkdangerousfunctions.h \
../src/checkheaders.h \
@ -65,6 +68,9 @@ SOURCES += main.cpp \
aboutdialog.cpp \
fileviewdialog.cpp \
projectfile.cpp \
report.cpp \
txtreport.cpp \
xmlreport.cpp \
../src/checkautovariables.cpp \
../src/checkdangerousfunctions.cpp \
../src/checkmemoryleak.cpp \

53
gui/report.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include <QFile>
#include "report.h"
Report::Report(const QString &filename, QObject * parent) :
QObject(parent),
mFilename(filename)
{
}
Report::~Report()
{
Close();
}
bool Report::Create()
{
bool succeed = false;
if (!mFile.isOpen())
{
mFile.setFileName(mFilename);
succeed = mFile.open(QIODevice::WriteOnly | QIODevice::Text);
}
return succeed;
}
void Report::Close()
{
if (mFile.isOpen())
mFile.close();
}
QFile* Report::GetFile()
{
return &mFile;
}

84
gui/report.h Normal file
View File

@ -0,0 +1,84 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#ifndef _REPORT_H_
#define _REPORT_H_
#include <QObject>
#include <QString>
#include <QStringList>
#include <QFile>
/**
* @brief A base class for reports.
*/
class Report : public QObject
{
public:
Report(const QString &filename, QObject * parent = 0);
virtual ~Report();
/**
* @brief Create the report (file).
* @return true if succeeded, false if file could not be created.
*/
virtual bool Create();
/**
* @brief Close the report (file).
*/
virtual void Close();
/**
* @brief Write report header.
*/
virtual void WriteHeader() = 0;
/**
* @brief Write report footer.
*/
virtual void WriteFooter() = 0;
/**
* @brief Write error to report.
*/
virtual void WriteError(const QStringList &files, const QStringList &lines,
const QString &id, const QString &severity,
const QString &msg) = 0;
protected:
/**
* @brief Get the file object where the report is written to.
*/
QFile* GetFile();
private:
/**
* @brief Filename of the report.
*/
QString mFilename;
/**
* @brief Fileobject for the report file.
*/
QFile mFile;
};
#endif // _REPORT_H_

View File

@ -16,8 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include "resultstree.h"
#include <QApplication>
#include <QDebug>
#include <QMenu>
@ -27,6 +25,8 @@
#include <QMessageBox>
#include <QFileInfo>
#include <QClipboard>
#include "resultstree.h"
#include "xmlreport.h"
ResultsTree::ResultsTree(QSettings &settings, ApplicationList &list) :
mSettings(settings),
@ -533,26 +533,20 @@ QString ResultsTree::SeverityToIcon(const QString &severity)
return "";
}
void ResultsTree::SaveResults(QTextStream &out, bool xml)
void ResultsTree::SaveResults(Report *report)
{
if (xml)
{
out << "<?xml version=\"1.0\"?>" << endl << "<results>" << endl;
}
report->WriteHeader();
for (int i = 0;i < mModel.rowCount();i++)
{
QStandardItem *item = mModel.item(i, 0);
SaveErrors(out, item, xml);
SaveErrors(report, item);
}
if (xml)
{
out << "</results>" << endl;
}
report->WriteFooter();
}
void ResultsTree::SaveErrors(QTextStream &out, QStandardItem *item, bool xml)
void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
{
if (!item)
{
@ -592,47 +586,14 @@ void ResultsTree::SaveErrors(QTextStream &out, QStandardItem *item, bool xml)
continue;
}
for (int i = 0; i < files.count(); i++)
files[i] = StripPath(files[i], true);
QStringList linesStr;
for (int i = 0; i < lines.count(); i++)
linesStr << lines[i].toString();
if (xml)
{
/*
Error example from the core program in xml
<error file="gui/test.cpp" line="14" id="mismatchAllocDealloc" severity="error" msg="Mismatching allocation and deallocation: k"/>
The callstack seems to be ignored here aswell, instead last item of the stack is used
*/
line = QString("<error file=\"%1\" line=\"%2\" id=\"%3\" severity=\"%4\" msg=\"%5\"/>").
arg(StripPath(files[files.size()-1], true)). //filename
arg(lines[lines.size()-1].toInt()). //line
arg(id). //ID
arg(severity). //severity
arg(message); //Message
}
else
{
/*
Error example from the core program in text
[gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k
*/
for (int i = 0;i < lines.size();i++)
{
line += QString("[%1:%2]").arg(StripPath(files[i], true)).arg(lines[i].toInt());
if (i < lines.size() - 1 && lines.size() > 0)
{
line += " -> ";
}
if (i == lines.size() - 1)
{
line += ": ";
}
}
line += QString("(%1) %2").arg(severity).arg(message);
}
out << line << endl;
report->WriteError(files, linesStr, id, severity, message);
}
}

View File

@ -29,6 +29,8 @@
#include "applicationlist.h"
#include <QTextStream>
class Report;
/**
* @brief Cppcheck's results are shown in this tree
*
@ -75,7 +77,7 @@ public:
* @brief Save results to a text stream
*
*/
void SaveResults(QTextStream &out, bool xml);
void SaveResults(Report *report);
/**
* @brief Update tree settings
@ -162,9 +164,8 @@ protected:
* @brief Save all errors under spesified item
*
* @param item Item whose errors to save
* @param xml Should errors be saved as xml (true) or as text (false)
*/
void SaveErrors(QTextStream &out, QStandardItem *item, bool xml);
void SaveErrors(Report *report, QStandardItem *item);
/**
* @brief Convert a severity string to a icon filename

View File

@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include "resultsview.h"
#include <QDebug>
#include <QVBoxLayout>
#include <QFile>
#include <QMessageBox>
#include "resultsview.h"
#include "txtreport.h"
#include "xmlreport.h"
ResultsView::ResultsView(QSettings &settings, ApplicationList &list) :
mErrorsFound(false),
@ -136,17 +137,32 @@ void ResultsView::Save(const QString &filename, bool xml)
msgBox.exec();
}
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
if (xml)
{
return;
XmlReport report(filename);
if (report.Create())
mTree->SaveResults(&report);
else
{
QMessageBox msgBox;
msgBox.setText("Failed to save the report.");
msgBox.exec();
}
}
else
{
TxtReport report(filename);
if (report.Create())
mTree->SaveResults(&report);
else
{
QMessageBox msgBox;
msgBox.setText("Failed to save the report.");
msgBox.exec();
}
}
QTextStream out(&file);
mTree->SaveResults(out, xml);
}
void ResultsView::UpdateSettings(bool showFullPath,
bool saveFullPath,
bool saveAllErrors,

83
gui/txtreport.cpp Normal file
View File

@ -0,0 +1,83 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include <QFile>
#include <QTextStream>
#include "txtreport.h"
TxtReport::TxtReport(const QString &filename, QObject * parent) :
Report(filename, parent)
{
}
TxtReport::~TxtReport()
{
Close();
}
bool TxtReport::Create()
{
bool success = false;
if (Report::Create())
{
mTxtWriter.setDevice(Report::GetFile());
success = true;
}
return success;
}
void TxtReport::WriteHeader()
{
// No header for txt report
}
void TxtReport::WriteFooter()
{
// No footer for txt report
}
void TxtReport::WriteError(const QStringList &files, const QStringList &lines,
const QString &id, const QString &severity, const QString &msg)
{
Q_UNUSED(id);
/*
Error example from the core program in text
[gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k
*/
QString line;
for (int i = 0; i < lines.size(); i++)
{
line += QString("[%1:%2]").arg(files[i]).arg(lines[i]);
if (i < lines.size() - 1 && lines.size() > 0)
{
line += " -> ";
}
if (i == lines.size() - 1)
{
line += ": ";
}
}
line += QString("(%1) %2").arg(severity).arg(msg);
mTxtWriter << line << endl;
}

70
gui/txtreport.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#ifndef _TXT_REPORT_H_
#define _TXT_REPORT_H_
#include <QObject>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include "Report.h"
/**
* @brief Text file report.
* This report mimics the output of the command line cppcheck.
*/
class TxtReport : public Report
{
public:
TxtReport(const QString &filename, QObject * parent = 0);
~TxtReport();
/**
* @brief Create the report (file).
* @return true if succeeded, false if file could not be created.
*/
virtual bool Create();
/**
* @brief Write report header.
*/
virtual void WriteHeader();
/**
* @brief Write report footer.
*/
virtual void WriteFooter();
/**
* @brief Write error to report.
*/
virtual void WriteError(const QStringList &files, const QStringList &lines,
const QString &id, const QString &severity,
const QString &msg);
private:
/**
* @brief Text stream writer for writing the report in text format.
*/
QTextStream mTxtWriter;
};
#endif // _TXT_REPORT_H_

73
gui/xmlreport.cpp Normal file
View File

@ -0,0 +1,73 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include <QFile>
#include <QXmlStreamWriter>
#include "xmlreport.h"
XmlReport::XmlReport(const QString &filename, QObject * parent) :
Report(filename, parent)
{
}
XmlReport::~XmlReport()
{
Close();
}
bool XmlReport::Create()
{
bool success = false;
if (Report::Create())
{
mXmlWriter.setDevice(Report::GetFile());
success = true;
}
return success;
}
void XmlReport::WriteHeader()
{
mXmlWriter.setAutoFormatting(true);
mXmlWriter.writeStartDocument();
mXmlWriter.writeStartElement("results");
}
void XmlReport::WriteFooter()
{
mXmlWriter.writeEndElement();
mXmlWriter.writeEndDocument();
}
void XmlReport::WriteError(const QStringList &files, const QStringList &lines,
const QString &id, const QString &severity, const QString &msg)
{
/*
Error example from the core program in xml
<error file="gui/test.cpp" line="14" id="mismatchAllocDealloc" severity="error" msg="Mismatching allocation and deallocation: k"/>
The callstack seems to be ignored here aswell, instead last item of the stack is used
*/
mXmlWriter.writeStartElement("error");
mXmlWriter.writeAttribute("file", files[files.size() - 1]);
mXmlWriter.writeAttribute("line", lines[lines.size() - 1]);
mXmlWriter.writeAttribute("id", id);
mXmlWriter.writeAttribute("severity", severity);
mXmlWriter.writeAttribute("msg", msg);
mXmlWriter.writeEndElement();
}

70
gui/xmlreport.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#ifndef _XML_REPORT_H_
#define _XML_REPORT_H_
#include <QObject>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QXmlStreamWriter>
#include "Report.h"
/**
* @brief XML file report.
* This report outputs XML-formatted report. The XML format must match command
* line version's XML output.
*/
class XmlReport : public Report
{
public:
XmlReport(const QString &filename, QObject * parent = 0);
~XmlReport();
/**
* @brief Create the report (file).
* @return true if succeeded, false if file could not be created.
*/
virtual bool Create();
/**
* @brief Write report header.
*/
virtual void WriteHeader();
/**
* @brief Write report footer.
*/
virtual void WriteFooter();
/**
* @brief Write error to report.
*/
virtual void WriteError(const QStringList &files, const QStringList &lines,
const QString &id, const QString &severity, const QString &msg);
private:
/**
* @brief XML stream writer for writing the report in XML format.
*/
QXmlStreamWriter mXmlWriter;
};
#endif // _XML_REPORT_H_