Merge branch 'gui-load-xml'

This commit is contained in:
Kimmo Varis 2010-07-11 16:30:22 +03:00
commit d5946a8359
22 changed files with 462 additions and 133 deletions

View File

@ -51,19 +51,16 @@ void CsvReport::WriteFooter()
// No footer for CSV report // No footer for CSV report
} }
void CsvReport::WriteError(const QStringList &files, const QStringList &lines, void CsvReport::WriteError(const ErrorItem &error)
const QString &id, const QString &severity, const QString &msg)
{ {
Q_UNUSED(id);
/* /*
Error as CSV line Error as CSV line
gui/test.cpp,23,error,Mismatching allocation and deallocation: k gui/test.cpp,23,error,Mismatching allocation and deallocation: k
*/ */
QString line; QString line;
line += QString("%1,%2,").arg(files[files.size() - 1]).arg(lines[lines.size() - 1]); line += QString("%1,%2,").arg(error.files[error.files.size() - 1]).arg(error.lines[error.lines.size() - 1]);
line += QString("%1,%2").arg(severity).arg(msg); line += QString("%1,%2").arg(error.severity).arg(error.msg);
mTxtWriter << line << endl; mTxtWriter << line << endl;
} }

View File

@ -60,10 +60,9 @@ public:
/** /**
* @brief Write error to report. * @brief Write error to report.
* @param error Error data.
*/ */
virtual void WriteError(const QStringList &files, const QStringList &lines, virtual void WriteError(const ErrorItem &error);
const QString &id, const QString &severity,
const QString &msg);
private: private:

39
gui/erroritem.cpp Normal file
View File

@ -0,0 +1,39 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2010 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 "erroritem.h"
ErrorItem::ErrorItem(const ErrorItem &item)
{
file = item.file;
files = item.files;
lines = item.lines;
id = item.id;
severity = item.severity;
msg = item.msg;
}
ErrorItem::ErrorItem(const ErrorLine &line)
{
file = line.file;
files.append(line.file);
lines.append(line.line.toUInt());
id = line.id;
severity = line.severity;
msg = line.msg;
}

62
gui/erroritem.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2010 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 ERRORITEM_H
#define ERRORITEM_H
#include <QString>
#include <QStringList>
class ErrorLine;
/// @addtogroup GUI
/// @{
/**
* @brief A class containing error data for one error.
*/
class ErrorItem
{
public:
ErrorItem() { }
ErrorItem(const ErrorItem &item);
ErrorItem(const ErrorLine &line);
QString file;
QStringList files;
QList<unsigned int> lines;
QString id;
QString severity;
QString msg;
};
/**
* @brief A class containing error data for one shown error line.
*/
class ErrorLine
{
public:
QString file;
QString line;
QString id;
QString severity;
QString msg;
};
/// @}
#endif // ERRORITEM_H

View File

@ -50,6 +50,7 @@ HEADERS += mainwindow.h \
applicationdialog.h \ applicationdialog.h \
aboutdialog.h \ aboutdialog.h \
common.h \ common.h \
erroritem.h \
fileviewdialog.h \ fileviewdialog.h \
projectfile.h \ projectfile.h \
report.h \ report.h \
@ -70,6 +71,7 @@ SOURCES += main.cpp \
aboutdialog.cpp \ aboutdialog.cpp \
fileviewdialog.cpp \ fileviewdialog.cpp \
projectfile.cpp \ projectfile.cpp \
erroritem.cpp \
report.cpp \ report.cpp \
txtreport.cpp \ txtreport.cpp \
xmlreport.cpp \ xmlreport.cpp \

View File

@ -20,6 +20,7 @@
#include <QApplication> #include <QApplication>
#include <QTextCodec> #include <QTextCodec>
#include <QTranslator> #include <QTranslator>
#include <QMetaType>
#include "mainwindow.h" #include "mainwindow.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -27,6 +28,9 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
app.setWindowIcon(QIcon(":icon.png")); app.setWindowIcon(QIcon(":icon.png"));
// Register this metatype that is used to transfer error info
qRegisterMetaType<QList<unsigned int>>("QList<unsigned int>");
// Set codecs so that UTF-8 strings in sources are handled correctly. // Set codecs so that UTF-8 strings in sources are handled correctly.
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

View File

@ -73,6 +73,7 @@
<property name="title"> <property name="title">
<string>&amp;File</string> <string>&amp;File</string>
</property> </property>
<addaction name="mActionOpenXML"/>
<addaction name="mActionSave"/> <addaction name="mActionSave"/>
<addaction name="mActionQuit"/> <addaction name="mActionQuit"/>
</widget> </widget>
@ -347,6 +348,11 @@
<string>Error categories</string> <string>Error categories</string>
</property> </property>
</action> </action>
<action name="mActionOpenXML">
<property name="text">
<string>&amp;Open XML...</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -56,6 +56,7 @@ MainWindow::MainWindow() :
connect(mUI.mActionCheckDirectory, SIGNAL(triggered()), this, SLOT(CheckDirectory())); connect(mUI.mActionCheckDirectory, SIGNAL(triggered()), this, SLOT(CheckDirectory()));
connect(mUI.mActionSettings, SIGNAL(triggered()), this, SLOT(ProgramSettings())); connect(mUI.mActionSettings, SIGNAL(triggered()), this, SLOT(ProgramSettings()));
connect(mUI.mActionClearResults, SIGNAL(triggered()), this, SLOT(ClearResults())); connect(mUI.mActionClearResults, SIGNAL(triggered()), this, SLOT(ClearResults()));
connect(mUI.mActionOpenXML, SIGNAL(triggered()), this, SLOT(OpenXML()));
connect(mUI.mActionShowStyle, SIGNAL(toggled(bool)), this, SLOT(ShowStyle(bool))); connect(mUI.mActionShowStyle, SIGNAL(toggled(bool)), this, SLOT(ShowStyle(bool)));
connect(mUI.mActionShowErrors, SIGNAL(toggled(bool)), this, SLOT(ShowErrors(bool))); connect(mUI.mActionShowErrors, SIGNAL(toggled(bool)), this, SLOT(ShowErrors(bool)));
@ -431,6 +432,22 @@ void MainWindow::ClearResults()
mUI.mActionSave->setEnabled(false); mUI.mActionSave->setEnabled(false);
} }
void MainWindow::OpenXML()
{
QString selectedFilter;
QString filter(tr("XML files (*.xml)"));
QString selectedFile = QFileDialog::getOpenFileName(this,
tr("Open the report file"),
QString(),
filter,
&selectedFilter);
if (!selectedFile.isEmpty())
{
mUI.mResults->ReadErrorsXml(selectedFile);
}
}
void MainWindow::EnableCheckButtons(bool enable) void MainWindow::EnableCheckButtons(bool enable)
{ {
mUI.mActionStop->setEnabled(!enable); mUI.mActionStop->setEnabled(!enable);

View File

@ -67,6 +67,12 @@ public slots:
*/ */
void ClearResults(); void ClearResults();
/**
* @brief Slot to open XML report file
*
*/
void OpenXML();
/** /**
* @brief Show errors with type "style" * @brief Show errors with type "style"
* @param checked Should errors be shown (true) or hidden (false) * @param checked Should errors be shown (true) or hidden (false)

View File

@ -17,6 +17,7 @@
*/ */
#include <QFile> #include <QFile>
#include "erroritem.h"
#include "report.h" #include "report.h"
Report::Report(const QString &filename, QObject * parent) : Report::Report(const QString &filename, QObject * parent) :
@ -41,6 +42,17 @@ bool Report::Create()
return succeed; return succeed;
} }
bool Report::Open()
{
bool succeed = false;
if (!mFile.isOpen())
{
mFile.setFileName(mFilename);
succeed = mFile.open(QIODevice::ReadOnly | QIODevice::Text);
}
return succeed;
}
void Report::Close() void Report::Close()
{ {
if (mFile.isOpen()) if (mFile.isOpen())

View File

@ -23,6 +23,7 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QFile> #include <QFile>
#include "erroritem.h"
/// @addtogroup GUI /// @addtogroup GUI
/// @{ /// @{
@ -50,6 +51,12 @@ public:
*/ */
virtual bool Create(); virtual bool Create();
/**
* @brief Open the existing report (file).
* @return true if succeeded, false if file could not be created.
*/
virtual bool Open();
/** /**
* @brief Close the report (file). * @brief Close the report (file).
*/ */
@ -67,10 +74,9 @@ public:
/** /**
* @brief Write error to report. * @brief Write error to report.
* @param error Error data.
*/ */
virtual void WriteError(const QStringList &files, const QStringList &lines, virtual void WriteError(const ErrorItem &error) = 0;
const QString &id, const QString &severity,
const QString &msg) = 0;
protected: protected:

View File

@ -24,14 +24,15 @@
#include <QDir> #include <QDir>
#include <QMessageBox> #include <QMessageBox>
#include <QFileInfo> #include <QFileInfo>
#include <QFileDialog>
#include <QClipboard> #include <QClipboard>
#include "erroritem.h"
#include "resultstree.h" #include "resultstree.h"
#include "xmlreport.h" #include "xmlreport.h"
ResultsTree::ResultsTree(QWidget * parent) : ResultsTree::ResultsTree(QWidget * parent) :
QTreeView(parent), QTreeView(parent),
mContextItem(0), mContextItem(0),
mCheckPath(""),
mVisibleErrors(false) mVisibleErrors(false)
{ {
for (int i = 0; i < SHOW_NONE; i++) for (int i = 0; i < SHOW_NONE; i++)
@ -67,28 +68,21 @@ QStandardItem *ResultsTree::CreateItem(const QString &name)
return item; return item;
} }
void ResultsTree::AddErrorItem(const QString &file, void ResultsTree::AddErrorItem(const ErrorItem &item)
const QString &severity,
const QString &message,
const QStringList &files,
const QVariantList &lines,
const QString &id)
{ {
Q_UNUSED(file); if (item.files.isEmpty())
if (files.isEmpty())
{ {
return; return;
} }
QString realfile = StripPath(files[0], false); QString realfile = StripPath(item.files[0], false);
if (realfile.isEmpty()) if (realfile.isEmpty())
{ {
realfile = tr("Undefined file"); realfile = tr("Undefined file");
} }
bool hide = !mShowTypes[SeverityToShowType(severity)]; bool hide = !mShowTypes[SeverityToShowType(item.severity)];
//if there is at least one error that is not hidden, we have a visible error //if there is at least one error that is not hidden, we have a visible error
if (!hide) if (!hide)
@ -96,48 +90,49 @@ void ResultsTree::AddErrorItem(const QString &file,
mVisibleErrors = true; mVisibleErrors = true;
} }
ErrorLine line;
line.file = realfile;
line.id = item.id;
line.line = QString::number(item.lines[0]);
line.msg = item.msg;
line.severity = item.severity;
//Create the base item for the error and ensure it has a proper //Create the base item for the error and ensure it has a proper
//file item as a parent //file item as a parent
QStandardItem *item = AddBacktraceFiles(EnsureFileItem(files[0], hide), QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, hide),
realfile, line,
lines[0].toInt(), hide,
severity, SeverityToIcon(line.severity));
message,
hide,
SeverityToIcon(severity));
if (!item) if (!stditem)
return; return;
//Add user data to that item //Add user data to that item
QMap<QString, QVariant> data; QMap<QString, QVariant> data;
data["severity"] = SeverityToShowType(severity); data["severity"] = SeverityToShowType(item.severity);
data["message"] = message; data["message"] = item.msg;
data["file"] = files[0]; data["file"] = item.files[0];
data["line"] = lines[0]; data["line"] = QString::number(item.lines[0]);
data["id"] = id; data["id"] = item.id;
item->setData(QVariant(data)); stditem->setData(QVariant(data));
//Add backtrace files as children //Add backtrace files as children
for (int i = 1; i < files.size() && i < lines.size(); i++) for (int i = 1; i < item.files.size() && i < item.lines.size(); i++)
{ {
line.file = StripPath(item.files[i], false);
line.line = item.lines[i];
QStandardItem *child_item; QStandardItem *child_item;
child_item = AddBacktraceFiles(stditem,
child_item = AddBacktraceFiles(item, line,
StripPath(files[i], false),
lines[i].toInt(),
severity,
message,
hide, hide,
":images/go-down.png"); ":images/go-down.png");
//Add user data to that item //Add user data to that item
QMap<QString, QVariant> child_data; QMap<QString, QVariant> child_data;
child_data["severity"] = SeverityToShowType(severity); child_data["severity"] = SeverityToShowType(line.severity);
child_data["message"] = message; child_data["message"] = line.msg;
child_data["file"] = files[i]; child_data["file"] = item.files[i];
child_data["line"] = lines[i]; child_data["line"] = line.line;
child_data["id"] = id; child_data["id"] = line.id;
child_item->setData(QVariant(child_data)); child_item->setData(QVariant(child_data));
} }
@ -150,10 +145,7 @@ void ResultsTree::AddErrorItem(const QString &file,
} }
QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent, QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent,
const QString &file, const ErrorLine &item,
const int line,
const QString &severity,
const QString &message,
const bool hide, const bool hide,
const QString &icon) const QString &icon)
@ -164,12 +156,12 @@ QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent,
} }
QList<QStandardItem*> list; QList<QStandardItem*> list;
list << CreateItem(file); list << CreateItem(item.file);
list << CreateItem(tr(severity.toLatin1())); list << CreateItem(tr(item.severity.toLatin1()));
list << CreateItem(QString("%1").arg(line)); list << CreateItem(QString("%1").arg(item.line));
//TODO message has parameter names so we'll need changes to the core //TODO message has parameter names so we'll need changes to the core
//cppcheck so we can get proper translations //cppcheck so we can get proper translations
list << CreateItem(tr(message.toLatin1())); list << CreateItem(tr(item.msg.toLatin1()));
// Check for duplicate rows and don't add them if found // Check for duplicate rows and don't add them if found
for (int i = 0; i < parent->rowCount(); i++) for (int i = 0; i < parent->rowCount(); i++)
@ -452,7 +444,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
void ResultsTree::StartApplication(QStandardItem *target, int application) void ResultsTree::StartApplication(QStandardItem *target, int application)
{ {
//If there are now application's specified, tell the user about it //If there are no applications specified, tell the user about it
if (mApplications->GetApplicationCount() == 0) if (mApplications->GetApplicationCount() == 0)
{ {
QMessageBox msg(QMessageBox::Information, QMessageBox msg(QMessageBox::Information,
@ -476,6 +468,34 @@ void ResultsTree::StartApplication(QStandardItem *target, int application)
//Replace (file) with filename //Replace (file) with filename
QString file = data["file"].toString(); QString file = data["file"].toString();
QFileInfo info(file);
if (!info.exists())
{
if (info.isAbsolute())
{
QMessageBox msgbox(this);
msgbox.setWindowTitle("Cppcheck");
msgbox.setText(tr("Could not find the file!"));
msgbox.setIcon(QMessageBox::Critical);
msgbox.exec();
}
else
{
QDir checkdir(mCheckPath);
if (checkdir.isAbsolute() && checkdir.exists())
{
file = mCheckPath + "/" + file;
}
else
{
QString dir = AskFileDir(file);
dir += '/';
file = dir + file;
}
}
}
if (file.indexOf(" ") > -1) if (file.indexOf(" ") > -1)
{ {
file.insert(0, "\""); file.insert(0, "\"");
@ -506,6 +526,22 @@ void ResultsTree::StartApplication(QStandardItem *target, int application)
} }
} }
QString ResultsTree::AskFileDir(const QString &file)
{
QString text = tr("Could not find file:\n%1\nPlease select the directory where file is located.").arg(file);
QMessageBox msgbox(this);
msgbox.setWindowTitle("Cppcheck");
msgbox.setText(text);
msgbox.setIcon(QMessageBox::Warning);
msgbox.exec();
QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"),
"",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
mCheckPath = dir;
return dir;
}
void ResultsTree::CopyFilename() void ResultsTree::CopyFilename()
{ {
CopyPath(mContextItem, false); CopyPath(mContextItem, false);
@ -601,8 +637,6 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
return; return;
} }
//qDebug() << item->text() << "has" << item->rowCount() << "errors";
for (int i = 0; i < item->rowCount(); i++) for (int i = 0; i < item->rowCount(); i++)
{ {
QStandardItem *error = item->child(i, 0); QStandardItem *error = item->child(i, 0);
@ -622,17 +656,15 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
//Convert it to QVariantMap //Convert it to QVariantMap
QVariantMap data = userdata.toMap(); QVariantMap data = userdata.toMap();
QString severity = ShowTypeToString(VariantToShowType(data["severity"])); ErrorItem item;
QString message = data["message"].toString(); item.severity = ShowTypeToString(VariantToShowType(data["severity"]));
QString id = data["id"].toString(); item.msg = data["message"].toString();
item.id = data["id"].toString();
QString file = StripPath(data["file"].toString(), true); QString file = StripPath(data["file"].toString(), true);
QString line = data["line"].toString(); unsigned int line = data["line"].toUInt();
QStringList files; item.files << file;
QStringList lines; item.lines << line;
files << file;
lines << line;
for (int j = 0; j < error->rowCount(); j++) for (int j = 0; j < error->rowCount(); j++)
{ {
@ -643,13 +675,13 @@ void ResultsTree::SaveErrors(Report *report, QStandardItem *item)
QVariantMap child_data = child_userdata.toMap(); QVariantMap child_data = child_userdata.toMap();
file = StripPath(child_data["file"].toString(), true); file = StripPath(child_data["file"].toString(), true);
line = child_data["line"].toString(); line = child_data["line"].toUInt();
files << file; item.files << file;
lines << line; item.lines << line;
} }
report->WriteError(files, lines, id, severity, message); report->WriteError(item);
} }
} }

View File

@ -25,11 +25,13 @@
#include <QStandardItem> #include <QStandardItem>
#include <QSettings> #include <QSettings>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QTextStream>
#include "common.h" #include "common.h"
#include "applicationlist.h" #include "applicationlist.h"
#include <QTextStream>
class Report; class Report;
class ErrorItem;
class ErrorLine;
/// @addtogroup GUI /// @addtogroup GUI
/// @{ /// @{
@ -50,19 +52,9 @@ public:
/** /**
* @brief Add a new item to the tree * @brief Add a new item to the tree
* *
* @param file filename * @param item Error item data
* @param severity error severity
* @param message error message
* @param files list of files affected by the error
* @param lines list of file line numers affected by the error
* @param id error id
*/ */
void AddErrorItem(const QString &file, void AddErrorItem(const ErrorItem &item);
const QString &severity,
const QString &message,
const QStringList &files,
const QVariantList &lines,
const QString &id);
/** /**
* @brief Clear all errors from the tree * @brief Clear all errors from the tree
@ -224,19 +216,13 @@ protected:
* @brief Add a new error item beneath a file or a backtrace item beneath an error * @brief Add a new error item beneath a file or a backtrace item beneath an error
* *
* @param parent Parent for the item. Either a file item or an error item * @param parent Parent for the item. Either a file item or an error item
* @param file Filename of the error * @param item Error line data
* @param line Line numer
* @param severity Error severity
* @param message Error message
* @param hide Should this be hidden (true) or shown (false) * @param hide Should this be hidden (true) or shown (false)
* @param icon Should a default backtrace item icon be added * @param icon Should a default backtrace item icon be added
* @return newly created QStandardItem * * @return newly created QStandardItem *
*/ */
QStandardItem *AddBacktraceFiles(QStandardItem *parent, QStandardItem *AddBacktraceFiles(QStandardItem *parent,
const QString &file, const ErrorLine &item,
const int line,
const QString &severity,
const QString &message,
const bool hide, const bool hide,
const QString &icon); const QString &icon);
@ -276,6 +262,12 @@ protected:
*/ */
void LoadSettings(); void LoadSettings();
/**
* @brief Ask directory where file is located.
* @param file File name.
* @return Directory user chose.
*/
QString AskFileDir(const QString &file);
/** /**
* @brief Create a new QStandardItem * @brief Create a new QStandardItem

View File

@ -70,11 +70,19 @@ void ResultsView::Error(const QString &file,
const QString &severity, const QString &severity,
const QString &message, const QString &message,
const QStringList &files, const QStringList &files,
const QVariantList &lines, const QList<unsigned int> &lines,
const QString &id) const QString &id)
{ {
mErrorsFound = true; mErrorsFound = true;
mUI.mTree->AddErrorItem(file, severity, message, files, lines, id); ErrorItem item;
item.file = file;
item.files = files;
item.id = id;
item.lines = lines;
item.msg = message;
item.severity = severity;
mUI.mTree->AddErrorItem(item);
emit GotResults(); emit GotResults();
} }
@ -217,3 +225,38 @@ void ResultsView::DisableProgressbar()
{ {
mUI.mProgress->setEnabled(false); mUI.mProgress->setEnabled(false);
} }
void ResultsView::ReadErrorsXml(const QString &filename)
{
XmlReport *report = new XmlReport(filename, this);
QList<ErrorLine> errors;
if (report)
{
if (report->Open())
errors = report->Read();
else
{
QMessageBox msgBox;
msgBox.setText(tr("Failed to read the report."));
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
}
delete report;
report = NULL;
}
else
{
QMessageBox msgBox;
msgBox.setText(tr("Failed to read the report."));
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
}
ErrorLine line;
foreach(line, errors)
{
ErrorItem item(line);
mUI.mTree->AddErrorItem(item);
}
mUI.mTree->SetCheckDirectory("");
}

View File

@ -129,6 +129,14 @@ public:
void Translate(); void Translate();
void DisableProgressbar(); void DisableProgressbar();
/**
* @brief Read errors from report XML file.
* @param filename Report file to read.
*
*/
void ReadErrorsXml(const QString &filename);
signals: signals:
/** /**
@ -161,7 +169,7 @@ public slots:
const QString &severity, const QString &severity,
const QString &message, const QString &message,
const QStringList &files, const QStringList &files,
const QVariantList &lines, const QList<unsigned int> &lines,
const QString &id); const QString &id);
/** /**

View File

@ -145,13 +145,13 @@ void ThreadHandler::Initialize(ResultsView *view)
const QString &, const QString &,
const QString &, const QString &,
const QStringList &, const QStringList &,
const QVariantList &, const QList<unsigned int> &,
const QString &)), const QString &)),
view, SLOT(Error(const QString &, view, SLOT(Error(const QString &,
const QString &, const QString &,
const QString &, const QString &,
const QStringList &, const QStringList &,
const QVariantList &, const QList<unsigned int> &,
const QString &))); const QString &)));
} }

View File

@ -47,7 +47,7 @@ void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg)
{ {
QMutexLocker locker(&mutex); QMutexLocker locker(&mutex);
QVariantList lines; QList<unsigned int> lines;
QStringList files; QStringList files;
for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator tok = msg._callStack.begin(); for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator tok = msg._callStack.begin();

View File

@ -98,7 +98,7 @@ signals:
const QString &severity, const QString &severity,
const QString &message, const QString &message,
const QStringList &files, const QStringList &files,
const QVariantList &lines, const QList<unsigned int> &lines,
const QString &id); const QString &id);
protected: protected:

View File

@ -51,11 +51,8 @@ void TxtReport::WriteFooter()
// No footer for txt report // No footer for txt report
} }
void TxtReport::WriteError(const QStringList &files, const QStringList &lines, void TxtReport::WriteError(const ErrorItem &error)
const QString &id, const QString &severity, const QString &msg)
{ {
Q_UNUSED(id);
/* /*
Error example from the core program in text Error example from the core program in text
[gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k [gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k
@ -63,21 +60,21 @@ void TxtReport::WriteError(const QStringList &files, const QStringList &lines,
QString line; QString line;
for (int i = 0; i < lines.size(); i++) for (int i = 0; i < error.lines.size(); i++)
{ {
line += QString("[%1:%2]").arg(files[i]).arg(lines[i]); line += QString("[%1:%2]").arg(error.files[i]).arg(error.lines[i]);
if (i < lines.size() - 1 && lines.size() > 0) if (i < error.lines.size() - 1 && error.lines.size() > 0)
{ {
line += " -> "; line += " -> ";
} }
if (i == lines.size() - 1) if (i == error.lines.size() - 1)
{ {
line += ": "; line += ": ";
} }
} }
line += QString("(%1) %2").arg(severity).arg(msg); line += QString("(%1) %2").arg(error.severity).arg(error.msg);
mTxtWriter << line << endl; mTxtWriter << line << endl;
} }

View File

@ -58,10 +58,9 @@ public:
/** /**
* @brief Write error to report. * @brief Write error to report.
* @param error Error data.
*/ */
virtual void WriteError(const QStringList &files, const QStringList &lines, virtual void WriteError(const ErrorItem &error);
const QString &id, const QString &severity,
const QString &msg);
private: private:

View File

@ -18,15 +18,29 @@
#include <QFile> #include <QFile>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <qdebug>
#include "erroritem.h"
#include "xmlreport.h" #include "xmlreport.h"
static const char ResultElementName[] = "results";
static const char ErrorElementName[] = "error";
static const char FilenameAttribute[] = "file";
static const char LineAttribute[] = "line";
static const char IdAttribute[] = "id";
static const char SeverityAttribute[] = "severity";
static const char MsgAttribute[] = "msg";
XmlReport::XmlReport(const QString &filename, QObject * parent) : XmlReport::XmlReport(const QString &filename, QObject * parent) :
Report(filename, parent) Report(filename, parent),
mXmlReader(NULL),
mXmlWriter(NULL)
{ {
} }
XmlReport::~XmlReport() XmlReport::~XmlReport()
{ {
delete mXmlReader;
delete mXmlWriter;
Close(); Close();
} }
@ -35,7 +49,18 @@ bool XmlReport::Create()
bool success = false; bool success = false;
if (Report::Create()) if (Report::Create())
{ {
mXmlWriter.setDevice(Report::GetFile()); mXmlWriter = new QXmlStreamWriter(Report::GetFile());
success = true;
}
return success;
}
bool XmlReport::Open()
{
bool success = false;
if (Report::Open())
{
mXmlReader = new QXmlStreamReader(Report::GetFile());
success = true; success = true;
} }
return success; return success;
@ -43,19 +68,18 @@ bool XmlReport::Create()
void XmlReport::WriteHeader() void XmlReport::WriteHeader()
{ {
mXmlWriter.setAutoFormatting(true); mXmlWriter->setAutoFormatting(true);
mXmlWriter.writeStartDocument(); mXmlWriter->writeStartDocument();
mXmlWriter.writeStartElement("results"); mXmlWriter->writeStartElement(ResultElementName);
} }
void XmlReport::WriteFooter() void XmlReport::WriteFooter()
{ {
mXmlWriter.writeEndElement(); mXmlWriter->writeEndElement();
mXmlWriter.writeEndDocument(); mXmlWriter->writeEndDocument();
} }
void XmlReport::WriteError(const QStringList &files, const QStringList &lines, void XmlReport::WriteError(const ErrorItem &error)
const QString &id, const QString &severity, const QString &msg)
{ {
/* /*
Error example from the core program in xml Error example from the core program in xml
@ -63,11 +87,73 @@ void XmlReport::WriteError(const QStringList &files, const QStringList &lines,
The callstack seems to be ignored here aswell, instead last item of the stack is used The callstack seems to be ignored here aswell, instead last item of the stack is used
*/ */
mXmlWriter.writeStartElement("error"); mXmlWriter->writeStartElement(ErrorElementName);
mXmlWriter.writeAttribute("file", files[files.size() - 1]); mXmlWriter->writeAttribute(FilenameAttribute, error.files[error.files.size() - 1]);
mXmlWriter.writeAttribute("line", lines[lines.size() - 1]); const QString line = QString::number(error.lines[error.lines.size() - 1]);
mXmlWriter.writeAttribute("id", id); mXmlWriter->writeAttribute(LineAttribute, line);
mXmlWriter.writeAttribute("severity", severity); mXmlWriter->writeAttribute(IdAttribute, error.id);
mXmlWriter.writeAttribute("msg", msg); mXmlWriter->writeAttribute(SeverityAttribute, error.severity);
mXmlWriter.writeEndElement(); mXmlWriter->writeAttribute(MsgAttribute, error.msg);
mXmlWriter->writeEndElement();
}
QList<ErrorLine> XmlReport::Read()
{
QList<ErrorLine> errors;
bool insideResults = false;
if (!mXmlReader)
{
qDebug() << "You must Open() the file before reading it!";
return errors;
}
while (!mXmlReader->atEnd())
{
switch (mXmlReader->readNext())
{
case QXmlStreamReader::StartElement:
if (mXmlReader->name() == ResultElementName)
insideResults = true;
// Read error element from inside result element
if (insideResults && mXmlReader->name() == ErrorElementName)
{
ErrorLine line = ReadError(mXmlReader);
errors.append(line);
}
break;
case QXmlStreamReader::EndElement:
if (mXmlReader->name() == ResultElementName)
insideResults = false;
break;
// Not handled
case QXmlStreamReader::NoToken:
case QXmlStreamReader::Invalid:
case QXmlStreamReader::StartDocument:
case QXmlStreamReader::EndDocument:
case QXmlStreamReader::Characters:
case QXmlStreamReader::Comment:
case QXmlStreamReader::DTD:
case QXmlStreamReader::EntityReference:
case QXmlStreamReader::ProcessingInstruction:
break;
}
}
return errors;
}
ErrorLine XmlReport::ReadError(QXmlStreamReader *reader)
{
ErrorLine line;
if (reader->name().toString() == ErrorElementName)
{
QXmlStreamAttributes attribs = reader->attributes();
line.file = attribs.value("", FilenameAttribute).toString();
line.line = attribs.value("", LineAttribute).toString();
line.id = attribs.value("", IdAttribute).toString();
line.severity = attribs.value("", SeverityAttribute).toString();
line.msg = attribs.value("", MsgAttribute).toString();
}
return line;
} }

View File

@ -23,6 +23,7 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QFile> #include <QFile>
#include <QXmlStreamReader>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include "report.h" #include "report.h"
@ -47,6 +48,11 @@ public:
*/ */
virtual bool Create(); virtual bool Create();
/**
* @brief Open existing report file.
*/
bool Open();
/** /**
* @brief Write report header. * @brief Write report header.
*/ */
@ -59,16 +65,32 @@ public:
/** /**
* @brief Write error to report. * @brief Write error to report.
* @param error Error data.
*/ */
virtual void WriteError(const QStringList &files, const QStringList &lines, virtual void WriteError(const ErrorItem &error);
const QString &id, const QString &severity, const QString &msg);
/**
* @brief Read contents of the report file.
*/
QList<ErrorLine> Read();
protected:
/**
* @brief Read and parse error item from XML stream.
* @param reader XML stream reader to use.
*/
ErrorLine ReadError(QXmlStreamReader *reader);
private: private:
/**
* @brief XML stream reader for reading the report in XML format.
*/
QXmlStreamReader *mXmlReader;
/** /**
* @brief XML stream writer for writing the report in XML format. * @brief XML stream writer for writing the report in XML format.
*/ */
QXmlStreamWriter mXmlWriter; QXmlStreamWriter *mXmlWriter;
}; };
/// @} /// @}
#endif // XML_REPORT_H #endif // XML_REPORT_H