0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-23 16:22:58 +03:00
LimeReport/limereport/serializators/lrxmlwriter.cpp
Андрей Лухнов 0fca7169d3 Define code style and format all source file using clang-format-14
except those placed in 3rdparty directories.
2024-09-19 21:09:38 +03:00

312 lines
12 KiB
C++

/***************************************************************************
* This file is part of the Lime Report project *
* Copyright (C) 2021 by Alexander Arin *
* arin_a@bk.ru *
* *
** GNU General Public License Usage **
* *
* This library 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. *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
** GNU Lesser General Public License **
* *
* This library is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
* This library 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. *
****************************************************************************/
#include "lrxmlwriter.h"
#include "lrbasedesignintf.h"
#include "lrcollection.h"
#include "lrreporttranslation.h"
#include "serializators/lrxmlserializatorsfactory.h"
#include <QDebug>
namespace LimeReport {
XMLWriter::XMLWriter(): m_doc(new QDomDocument) { init(); }
XMLWriter::XMLWriter(QSharedPointer<QDomDocument> doc): m_doc(doc) { init(); }
void XMLWriter::init()
{
m_rootElement = m_doc->createElement("Report");
QDomNode xmlNode
= m_doc->createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF8\"");
m_doc->insertBefore(xmlNode, m_doc->firstChild());
m_doc->appendChild(m_rootElement);
}
void XMLWriter::putItem(QObject* item)
{
QDomElement node = putQObjectItem(item->metaObject()->className(), item);
if (!replaceNode(node, item))
m_rootElement.appendChild(node);
}
QString XMLWriter::extractClassName(QObject* item)
{
BaseDesignIntf* baseItem = dynamic_cast<BaseDesignIntf*>(item);
if (baseItem)
return baseItem->storageTypeName();
else
return item->metaObject()->className();
}
void XMLWriter::putChildQObjectItem(QString name, QObject* item, QDomElement* parentNode)
{
QDomElement itemNode = m_doc->createElement(name);
itemNode.setAttribute("ClassName", extractClassName(item));
itemNode.setAttribute("Type", "Object");
if (parentNode)
parentNode->appendChild(itemNode);
saveProperties(item, &itemNode);
}
bool XMLWriter::setContent(QString fileName)
{
QFile xmlFile(fileName);
if (xmlFile.open(QFile::ReadOnly)) {
m_doc->setContent(&xmlFile);
return true;
}
return false;
}
bool XMLWriter::saveToFile(QString fileName)
{
if ((m_doc->childNodes().count() == 0) || fileName.isEmpty())
return false;
QFile xmlFile(fileName);
if (xmlFile.open(QFile::WriteOnly)) {
QTextStream buffer(&xmlFile);
m_doc->save(buffer, 2);
xmlFile.close();
return true;
}
return false;
}
QString XMLWriter::saveToString()
{
QString res;
QTextStream buffer(&res);
m_doc->save(buffer, 2);
return res;
}
QByteArray XMLWriter::saveToByteArray()
{
QByteArray res;
QTextStream buffer(&res);
m_doc->save(buffer, 2);
return res;
}
void XMLWriter::setPassPhrase(const QString& passPhrase) { m_passPhrase = passPhrase; }
QDomElement XMLWriter::putQObjectItem(QString name, QObject* item)
{
Q_UNUSED(name)
QDomElement itemNode = m_doc->createElement("object");
itemNode.setAttribute("ClassName", extractClassName(item));
itemNode.setAttribute("Type", "Object");
saveProperties(item, &itemNode);
return itemNode;
}
void XMLWriter::saveProperty(QString name, QObject* item, QDomElement* node)
{
QString typeName;
if (name.compare("itemIndexMethod") == 0)
typeName = item->metaObject()
->property(item->metaObject()->indexOfProperty(name.toLatin1()))
.typeName();
else
typeName = item->property(name.toLatin1()).typeName();
CreateSerializator creator = 0;
if (isCollection(name, item)) {
saveCollection(name, item, node);
return;
}
if (isTranslation(name, item)) {
saveTranslation(name, item, node);
return;
}
if (isQObject(name, item)) {
if (qvariant_cast<QObject*>(item->property(name.toLatin1())))
putQObjectProperty(name, qvariant_cast<QObject*>(item->property(name.toLatin1())),
node);
else {
qDebug() << "Warnig property can`t be casted to QObject" << name;
}
return;
}
if (enumOrFlag(name, item))
creator = XMLAbstractSerializatorFactory::instance().objectCreator("enumAndFlags");
else
try {
creator = XMLAbstractSerializatorFactory::instance().objectCreator(typeName);
} catch (LimeReport::ReportError& exception) {
qDebug() << "class name =" << item->metaObject()->className()
<< "property name=" << name << " property type=" << typeName
<< exception.what();
}
if (creator) {
QScopedPointer<SerializatorIntf> serializator(creator(m_doc.data(), node));
CryptedSerializator* cs = dynamic_cast<CryptedSerializator*>(serializator.data());
if (cs) {
cs->setPassPhrase(m_passPhrase);
}
serializator->save(item->property(name.toLatin1()), name);
}
}
void XMLWriter::saveProperties(QObject* item, QDomElement* node)
{
for (int i = 0; i < item->metaObject()->propertyCount(); i++) {
saveProperty(item->metaObject()->property(i).name(), item, node);
}
}
bool XMLWriter::enumOrFlag(QString name, QObject* item)
{
return item->metaObject()
->property(item->metaObject()->indexOfProperty(name.toLatin1()))
.isFlagType()
|| item->metaObject()
->property(item->metaObject()->indexOfProperty(name.toLatin1()))
.isEnumType();
}
bool XMLWriter::isCollection(QString propertyName, QObject* item)
{
QMetaProperty prop = item->metaObject()->property(
item->metaObject()->indexOfProperty(propertyName.toLatin1()));
// TODO: Migrate to QMetaType
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return QMetaType::fromName(prop.typeName()).id() == COLLECTION_TYPE_ID;
#else
return QMetaType::type(prop.typeName()) == COLLECTION_TYPE_ID;
#endif
}
bool XMLWriter::isTranslation(QString propertyName, QObject* item)
{
QMetaProperty prop = item->metaObject()->property(
item->metaObject()->indexOfProperty(propertyName.toLatin1()));
// TODO: Migrate to QMetaType
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return QMetaType::fromName(prop.typeName()).id() == TRANSLATION_TYPE_ID;
#else
return QMetaType::type(prop.typeName()) == TRANSLATION_TYPE_ID;
#endif
}
void XMLWriter::saveCollection(QString propertyName, QObject* item, QDomElement* node)
{
ICollectionContainer* collection = dynamic_cast<ICollectionContainer*>(item);
QDomElement collectionNode = m_doc->createElement(propertyName);
collectionNode.setAttribute("Type", "Collection");
for (int i = 0; i < collection->elementsCount(propertyName); i++) {
putCollectionItem(collection->elementAt(propertyName, i), &collectionNode);
}
node->appendChild(collectionNode);
}
void XMLWriter::saveTranslation(QString propertyName, QObject* item, QDomElement* node)
{
ITranslationContainer* translationsContainer = dynamic_cast<ITranslationContainer*>(item);
if (translationsContainer) {
QDomElement translationsNode = m_doc->createElement(propertyName);
translationsNode.setAttribute("Type", "Translation");
Translations* translations = translationsContainer->translations();
foreach (QLocale::Language language, translations->keys()) {
QDomElement languageNode
= m_doc->createElement(QLocale::languageToString(language).replace(' ', '_'));
languageNode.setAttribute("Value", QString::number(language));
translationsNode.appendChild(languageNode);
ReportTranslation* curTranslation = translations->value(language);
foreach (PageTranslation* page, curTranslation->pagesTranslation()) {
QDomElement pageNode = m_doc->createElement(page->pageName);
languageNode.appendChild(pageNode);
foreach (ItemTranslation* item, page->itemsTranslation) {
QDomElement itemNode = m_doc->createElement(item->itemName);
foreach (PropertyTranslation* property, item->propertyesTranslation) {
if (property->sourceValue.compare(property->value) != 0) {
QDomElement propertyNode = m_doc->createElement(property->propertyName);
propertyNode.setAttribute("Value", property->value);
propertyNode.setAttribute("SourceValue", property->sourceValue);
propertyNode.setAttribute("Checked", property->checked ? "Y" : "N");
itemNode.appendChild(propertyNode);
}
}
if (!itemNode.childNodes().isEmpty())
pageNode.appendChild(itemNode);
}
}
}
node->appendChild(translationsNode);
}
}
bool XMLWriter::isQObject(QString propertyName, QObject* item)
{
QMetaProperty prop = item->metaObject()->property(
item->metaObject()->indexOfProperty(propertyName.toLatin1()));
// TODO: Migrate to QMetaType
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return QMetaType::fromName(prop.typeName()).id() == QMetaType::QObjectStar;
#else
return QMetaType::type(prop.typeName()) == QMetaType::QObjectStar;
#endif
}
bool XMLWriter::replaceNode(QDomElement node, QObject* item)
{
QDomElement element = m_rootElement.firstChildElement(item->metaObject()->className());
while (!element.isNull()) {
QDomElement objectName = element.firstChildElement(QLatin1String("objectName"));
if (!objectName.isNull() && (objectName.text() == item->objectName())) {
QDomElement removeElement = element;
element = element.nextSiblingElement(item->metaObject()->className());
m_rootElement.replaceChild(node, removeElement);
return true;
} else
element = element.nextSiblingElement(item->metaObject()->className());
}
return false;
}
void XMLWriter::putCollectionItem(QObject* item, QDomElement* parentNode)
{
putChildQObjectItem("item", item, parentNode);
}
void XMLWriter::putQObjectProperty(QString propertyName, QObject* item, QDomElement* parentNode)
{
putChildQObjectItem(propertyName, item, parentNode);
}
} // namespace LimeReport