1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
/*
XmlSerialization.cpp
This file is part of Charm, a task-based time tracking application.
Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Mirko Boehm <mirko.boehm@kdab.com>
Author: Frank Osterfeld <frank.osterfeld@kdab.com>
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 2 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 "XmlSerialization.h"
#include "CharmConstants.h"
#include "CharmExceptions.h"
#include "Configuration.h"
#include <QDateTime>
#include <QFile>
static QHash<QString, QString> readMetadata(const QDomElement &metadata)
{
QHash<QString, QString> l;
const QDomNodeList cs = metadata.childNodes();
for (int i = 0; i < cs.count(); ++i) {
QDomElement e = cs.at(i).toElement();
if (e.isNull())
continue;
l.insert(e.tagName(), e.text());
}
return l;
}
namespace XmlSerialization {
QString reportTagName()
{
return QStringLiteral("charmreport");
}
QString reportTypeAttribute()
{
return QStringLiteral("type");
}
QDomDocument createXmlTemplate(const QString &docClass)
{
QDomDocument doc(reportTagName());
// root element:
QDomElement root = doc.createElement(reportTagName());
root.setAttribute(reportTypeAttribute(), docClass);
doc.appendChild(root);
// metadata:
{
QDomElement metadata = doc.createElement(QStringLiteral("metadata"));
root.appendChild(metadata);
QDomElement username = doc.createElement(QStringLiteral("username"));
metadata.appendChild(username);
QDomText text = doc.createTextNode(Configuration::instance().user.name());
username.appendChild(text);
QDomElement creationTime = doc.createElement(QStringLiteral("creation-time"));
metadata.appendChild(creationTime);
QDomText time = doc.createTextNode(
QDateTime::currentDateTimeUtc().toString(Qt::ISODate));
creationTime.appendChild(time);
// FIXME installation id and stuff are probably necessary
}
QDomElement report = doc.createElement(QStringLiteral("report"));
root.appendChild(report);
return doc;
}
QDomElement reportElement(const QDomDocument &document)
{
QDomElement root = document.documentElement();
return root.firstChildElement(QStringLiteral("report"));
}
QDomElement metadataElement(const QDomDocument &document)
{
QDomElement root = document.documentElement();
return root.firstChildElement(QStringLiteral("metadata"));
}
QDateTime creationTime(const QDomElement &metaDataElement)
{
QDomElement creationTimeElement
= metaDataElement.firstChildElement(QStringLiteral("creation-time"));
if (!creationTimeElement.isNull()) {
return QDateTime::fromString(creationTimeElement.text(), Qt::ISODate);
} else {
return QDateTime();
}
}
QString userName(const QDomElement &metaDataElement)
{
QDomElement usernameElement = metaDataElement.firstChildElement(QStringLiteral("username"));
return usernameElement.text();
}
}
QString TaskExport::reportType()
{
return QStringLiteral("taskdefinitions");
}
void TaskExport::writeTo(const QString &filename, const TaskList &tasks)
{
QDomDocument document = XmlSerialization::createXmlTemplate(reportType());
QDomElement report = XmlSerialization::reportElement(document);
// write tasks
{
QDomElement tasksElement = Task::makeTasksElement(document, tasks);
report.appendChild(tasksElement);
}
// all done, write to file:
QFile file(filename);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
document.save(stream, 4);
} else {
throw XmlSerializationException(QObject::tr("Cannot write to file: %1").arg(
file.errorString()));
}
}
void TaskExport::readFrom(const QString &filename)
{
// load the time sheet:
QFile file(filename);
if (!file.exists())
throw XmlSerializationException(QObject::tr("File does not exist."));
// load the XML into a DOM tree:
if (!file.open(QIODevice::ReadOnly))
throw XmlSerializationException(QObject::tr("Cannot open file for reading: %1").arg(file.
errorString()));
return readFrom(&file);
}
void TaskExport::readFrom(QIODevice *device)
{
QDomDocument document;
QString errorMessage;
int errorLine = 0;
int errorColumn = 0;
if (!document.setContent(device, &errorMessage, &errorLine, &errorColumn)) {
throw XmlSerializationException(QObject::tr("Invalid XML: [%1:%2] %3").arg(QString::number(
errorLine),
QString::number(
errorColumn),
errorMessage));
}
// now read and check for the correct report type
QDomElement rootElement = document.documentElement();
const QString tagName = rootElement.tagName();
const QString typeAttribute = rootElement.attribute(XmlSerialization::reportTypeAttribute());
if (tagName != XmlSerialization::reportTagName() || typeAttribute != reportType())
throw XmlSerializationException(QObject::tr(
"This file is not a Charm task definition file. Please double-check."));
QDomElement metadata = XmlSerialization::metadataElement(document);
QDomElement report = XmlSerialization::reportElement(document);
m_metadata = readMetadata(metadata);
// from metadata, read the export time stamp:
m_exportTime = XmlSerialization::creationTime(metadata);
// from report, read tasks:
QDomElement tasksElement = report.firstChildElement(Task::taskListTagName());
m_tasks = Task::readTasksElement(tasksElement, CHARM_DATABASE_VERSION);
}
TaskList TaskExport::tasks() const
{
return m_tasks;
}
QDateTime TaskExport::exportTime() const
{
return m_exportTime;
}
QString TaskExport::metadata(const QString &key) const
{
return m_metadata.value(key, QString());
}
|