diff --git a/include/lrreportengine.h b/include/lrreportengine.h index 108c4e7..64f01bb 100644 --- a/include/lrreportengine.h +++ b/include/lrreportengine.h @@ -107,6 +107,12 @@ public: bool resultIsEditable(); bool isBusy(); void setPassPharse(QString& passPharse); + + + QList aviableLanguages(); + bool addTranslationLanguage(QLocale::Language language); + bool setReportLanguage(QLocale::Language language); + signals: void renderStarted(); void renderFinished(); diff --git a/limereport/limereport.pri b/limereport/limereport.pri index 9cbb795..cf5c18e 100644 --- a/limereport/limereport.pri +++ b/limereport/limereport.pri @@ -97,7 +97,8 @@ SOURCES += \ $$REPORT_PATH/lritemscontainerdesignitf.cpp \ $$REPORT_PATH/lrcolorindicator.cpp \ $$REPORT_PATH/items/lrchartitem.cpp \ - $$REPORT_PATH/items/lrchartitemeditor.cpp + $$REPORT_PATH/items/lrchartitemeditor.cpp \ + $$REPORT_PATH/lrreporttranslation.cpp contains(CONFIG, staticlib){ SOURCES += $$REPORT_PATH/lrfactoryinitializer.cpp @@ -205,7 +206,8 @@ HEADERS += \ $$REPORT_PATH/lritemscontainerdesignitf.h \ $$REPORT_PATH/lrcolorindicator.h \ $$REPORT_PATH/items/lrchartitem.h \ - $$REPORT_PATH/items/lrchartitemeditor.h + $$REPORT_PATH/items/lrchartitemeditor.h \ + $$REPORT_PATH/lrreporttranslation.h contains(CONFIG, staticlib){ HEADERS += $$REPORT_PATH/lrfactoryinitializer.h diff --git a/limereport/lrbasedesignintf.cpp b/limereport/lrbasedesignintf.cpp index 8160db9..76e41f2 100644 --- a/limereport/lrbasedesignintf.cpp +++ b/limereport/lrbasedesignintf.cpp @@ -1423,6 +1423,21 @@ QList BaseDesignIntf::childBaseItems() return resList; } + +void BaseDesignIntf::addChildItems(QList* list){ + foreach(BaseDesignIntf* item, childBaseItems()){ + list->append(item); + item->addChildItems(list); + } +} + +QList BaseDesignIntf::allChildBaseItems() +{ + QList resList; + addChildItems(&resList); + return resList; +} + BaseDesignIntf *BaseDesignIntf::childByName(const QString &name) { foreach(BaseDesignIntf* item, childBaseItems()){ @@ -1539,11 +1554,8 @@ BaseDesignIntf *Marker::object() const return m_object; } +QMap BaseDesignIntf::getStringForTranslation(){ + return QMap(); +} + } //namespace LimeReport - - - - - - - diff --git a/limereport/lrbasedesignintf.h b/limereport/lrbasedesignintf.h index 8e77cc9..d9ce55d 100644 --- a/limereport/lrbasedesignintf.h +++ b/limereport/lrbasedesignintf.h @@ -237,6 +237,7 @@ public: virtual void beforeDelete(); QList childBaseItems(); + QList allChildBaseItems(); BaseDesignIntf* childByName(const QString& name); virtual QWidget *defaultEditor(); @@ -274,6 +275,7 @@ public: void setPatternName(const QString &patternName); BaseDesignIntf* patternItem() const; void setPatternItem(BaseDesignIntf* patternItem); + virtual QMap getStringForTranslation(); Q_INVOKABLE QString setItemWidth(qreal width); Q_INVOKABLE QString setItemHeight(qreal height); @@ -284,6 +286,7 @@ public: Q_INVOKABLE QString setItemPosX(qreal xValue); Q_INVOKABLE QString setItemPosY(qreal yValue); + protected: //ICollectionContainer @@ -344,6 +347,8 @@ protected: virtual void preparePopUpMenu(QMenu& menu){Q_UNUSED(menu)} virtual void processPopUpAction(QAction* action){Q_UNUSED(action)} + void addChildItems(QList* list); + private: void updateSelectionMarker(); int resizeDirectionFlags(QPointF position); @@ -400,6 +405,7 @@ private: ReportSettings* m_reportSettings; QString m_patternName; BaseDesignIntf* m_patternItem; + signals: void geometryChanged(QObject* object, QRectF newGeometry, QRectF oldGeometry); void posChanged(QObject* object, QPointF newPos, QPointF oldPos); diff --git a/limereport/lrcollection.h b/limereport/lrcollection.h index d5d5ffe..641ddff 100644 --- a/limereport/lrcollection.h +++ b/limereport/lrcollection.h @@ -45,7 +45,7 @@ Q_DECLARE_METATYPE(ACollectionProperty) namespace LimeReport{ -const int VARIABLE_IS_NOT_USED COLLECTION_TYPE_ID = qMetaTypeId(); +const int COLLECTION_TYPE_ID = qMetaTypeId(); class ICollectionContainer{ public: virtual QObject* createElement(const QString& collectionName,const QString& elementType)=0; diff --git a/limereport/lritemdesignintf.cpp b/limereport/lritemdesignintf.cpp index 5987086..a830c96 100644 --- a/limereport/lritemdesignintf.cpp +++ b/limereport/lritemdesignintf.cpp @@ -116,4 +116,10 @@ void ItemDesignIntf::initFlags() Spacer::Spacer(QObject *owner, QGraphicsItem *parent) :ItemDesignIntf("Spacer",owner,parent){} +QMap ContentItemDesignIntf::getStringForTranslation(){ + QMapmap; + map.insert("content",content()); + return map; +} + }// namespace LimeReport diff --git a/limereport/lritemdesignintf.h b/limereport/lritemdesignintf.h index a9c8d7a..f07fd9f 100644 --- a/limereport/lritemdesignintf.h +++ b/limereport/lritemdesignintf.h @@ -75,6 +75,7 @@ public: :ItemDesignIntf(xmlTypeName,owner,parent){} virtual QString content() const = 0; virtual void setContent(const QString& value) = 0; + QMap getStringForTranslation(); }; class LayoutDesignIntf : public ItemDesignIntf{ diff --git a/limereport/lrreportengine.cpp b/limereport/lrreportengine.cpp index 96a0da4..18af591 100644 --- a/limereport/lrreportengine.cpp +++ b/limereport/lrreportengine.cpp @@ -90,6 +90,11 @@ ReportEnginePrivate::~ReportEnginePrivate() } foreach(PageDesignIntf* page,m_pages) delete page; m_pages.clear(); + + foreach(ReportTranslation* translation, m_translations) + delete translation; + m_translations.clear(); + if (m_ownedSettings&&m_settings) delete m_settings; } @@ -178,10 +183,14 @@ void ReportEnginePrivate::clearReport() { foreach(PageDesignIntf* page,m_pages) delete page; m_pages.clear(); + foreach(ReportTranslation* reportTranslation, m_translations) + delete reportTranslation; + m_translations.clear(); m_datasources->clear(DataSourceManager::Owned); m_fileName=""; m_scriptEngineContext->clear(); m_reportSettings.setDefaultValues(); + emit cleared(); } @@ -379,7 +388,7 @@ bool ReportEnginePrivate::printToPDF(const QString &fileName) void ReportEnginePrivate::previewReport(PreviewHints hints) { - QTime start = QTime::currentTime(); +// QTime start = QTime::currentTime(); try{ dataManager()->setDesignTime(false); ReportPages pages = renderToPages(); @@ -733,11 +742,62 @@ QString ReportEnginePrivate::renderToString() }else return QString(); } +PageDesignIntf* ReportEnginePrivate::getPageByName(const QString& pageName) +{ + foreach(PageDesignIntf* page, m_pages){ + if ( page->objectName().compare(pageName, Qt::CaseInsensitive) == 0) + return page; + } + return 0; +} + void ReportEnginePrivate::setPassPhrase(const QString &passPhrase) { m_passPhrase = passPhrase; } +bool ReportEnginePrivate::addTranslationLanguage(QLocale::Language language) +{ + if (!m_translations.keys().contains(language)){ + ReportTranslation* translation = new ReportTranslation(language,m_pages); + m_translations.insert(language, translation); + return true; + } else { + m_lastError = tr("Language %1 already exists").arg(QLocale::languageToString(language)); + return false; + } +} + +bool ReportEnginePrivate::setReportLanguage(QLocale::Language language){ + if (!m_translations.keys().contains(language)) return false; + ReportTranslation* translation = m_translations.value(language); + + foreach(PageTranslation* pageTranslation, translation->pagesTranslation()){ + PageDesignIntf* page = getPageByName(pageTranslation->pageName); + if (page){ + foreach(ItemTranslation itemTranslation, pageTranslation->itemsTranslation){ + BaseDesignIntf* item = page->pageItem()->childByName(itemTranslation.itemName); + if (item) { + foreach(PropertyTranslation propertyTranslation, itemTranslation.propertyesTranslation){ + item->setProperty(propertyTranslation.propertyName.toLatin1(),propertyTranslation.value); + } + } + } + } + } + return true; +} + +QList ReportEnginePrivate::aviableLanguages() +{ + return m_translations.keys(); +} + +ReportTranslation*ReportEnginePrivate::reportTranslation(QLocale::Language language) +{ + return m_translations.value(language); +} + bool ReportEnginePrivate::resultIsEditable() const { return m_resultIsEditable; @@ -934,6 +994,24 @@ void ReportEngine::setPassPharse(QString &passPharse) d->setPassPhrase(passPharse); } +QList ReportEngine::aviableLanguages() +{ + Q_D(ReportEngine); + return d->aviableLanguages(); +} + +bool ReportEngine::addTranslationLanguage(QLocale::Language language) +{ + Q_D(ReportEngine); + return d->addTranslationLanguage(language); +} + +bool ReportEngine::setReportLanguage(QLocale::Language language) +{ + Q_D(ReportEngine); + return d->setReportLanguage(language); +} + void ReportEngine::setShowProgressDialog(bool value) { Q_D(ReportEngine); @@ -1046,6 +1124,5 @@ ReportEngine::ReportEngine(ReportEnginePrivate &dd, QObject *parent) connect(d, SIGNAL(renderFinished()), this, SIGNAL(renderFinished())); } +}// namespace LimeReport - -} diff --git a/limereport/lrreportengine.h b/limereport/lrreportengine.h index 108c4e7..64f01bb 100644 --- a/limereport/lrreportengine.h +++ b/limereport/lrreportengine.h @@ -107,6 +107,12 @@ public: bool resultIsEditable(); bool isBusy(); void setPassPharse(QString& passPharse); + + + QList aviableLanguages(); + bool addTranslationLanguage(QLocale::Language language); + bool setReportLanguage(QLocale::Language language); + signals: void renderStarted(); void renderFinished(); diff --git a/limereport/lrreportengine_p.h b/limereport/lrreportengine_p.h index 0c65284..c31e019 100644 --- a/limereport/lrreportengine_p.h +++ b/limereport/lrreportengine_p.h @@ -41,6 +41,7 @@ #include "lrreportrender.h" #include "serializators/lrstorageintf.h" #include "lrscriptenginemanager.h" +#include "lrreporttranslation.h" class QFileSystemWatcher; @@ -52,7 +53,7 @@ class ReportDesignWindow; //TODO: Add on render callback -class ReportEnginePrivate : public QObject, public ICollectionContainer +class ReportEnginePrivate : public QObject, public ICollectionContainer, public ITranslationContainer { Q_OBJECT Q_DECLARE_PUBLIC(ReportEngine) @@ -60,6 +61,8 @@ class ReportEnginePrivate : public QObject, public ICollectionContainer Q_PROPERTY(QObject* datasourcesManager READ dataManager) Q_PROPERTY(QObject* scriptContext READ scriptContext) Q_PROPERTY(bool suppressFieldAndVarError READ suppressFieldAndVarError WRITE setSuppressFieldAndVarError) + Q_PROPERTY(ATranslationProperty translation READ fakeTranslationReader) + friend class PreviewReportWidget; public: static void printReport(ItemsReaderIntf::Ptr reader, QPrinter &printer); @@ -128,6 +131,10 @@ public: void setResultEditable(bool value); void setPassPhrase(const QString &passPhrase); + bool addTranslationLanguage(QLocale::Language language); + bool setReportLanguage(QLocale::Language language); + QList aviableLanguages(); + ReportTranslation* reportTranslation(QLocale::Language language); signals: void pagesLoadFinished(); @@ -157,8 +164,13 @@ private: void saveError(QString message); void showError(QString message); //ICollectionContainer + //ITranslationContainer + Translations* translations(){ return &m_translations;} + //ITranslationContainer ReportPages renderToPages(); QString renderToString(); + PageDesignIntf* getPageByName(const QString& pageName); + ATranslationProperty fakeTranslationReader(){ return ATranslationProperty();} private: QList m_pages; DataSourceManager* m_datasources; @@ -182,6 +194,7 @@ private: bool m_resultIsEditable; QString m_passPhrase; QFileSystemWatcher *m_fileWatcher; + Translations m_translations; }; } diff --git a/limereport/lrreporttranslation.cpp b/limereport/lrreporttranslation.cpp new file mode 100644 index 0000000..bc8717a --- /dev/null +++ b/limereport/lrreporttranslation.cpp @@ -0,0 +1,70 @@ +#include "lrreporttranslation.h" + +#include "lrbasedesignintf.h" +#include "lrpagedesignintf.h" + +namespace LimeReport{ + +ReportTranslation::ReportTranslation(QLocale::Language language, QList pages) + : m_language(language) +{ + foreach (PageDesignIntf* page, pages){ + m_pagesTranslation.append(createPageTranslation(page)); + } +} + +ReportTranslation::ReportTranslation(const ReportTranslation& reportTranslation) + :m_language(reportTranslation.m_language) +{ + foreach(PageTranslation* pageTranslation, reportTranslation.m_pagesTranslation){ + m_pagesTranslation.append(pageTranslation); + } +} + +ReportTranslation::~ReportTranslation() +{ + foreach(PageTranslation* page, m_pagesTranslation){ + delete page; + } + m_pagesTranslation.clear(); +} + +PageTranslation* ReportTranslation::createPageTranslation(PageDesignIntf* page) +{ + PageTranslation* pageTranslation = new PageTranslation; + pageTranslation->pageName = page->objectName(); + foreach(BaseDesignIntf* item, page->pageItem()->allChildBaseItems()){ + QMap stringsForTranslation = item->getStringForTranslation(); + if (!stringsForTranslation.isEmpty()){ + ItemTranslation itemTranslation; + itemTranslation.itemName = item->objectName(); + foreach(QString propertyName, stringsForTranslation.keys()){ + PropertyTranslation propertyTranslation; + propertyTranslation.propertyName = propertyName; + propertyTranslation.value = stringsForTranslation.value(propertyName); + itemTranslation.propertyesTranslation.append(propertyTranslation); + } + pageTranslation->itemsTranslation.append(itemTranslation); + } + } + return pageTranslation; +} + +QList ReportTranslation::pagesTranslation() const +{ + return m_pagesTranslation; +} + +PageTranslation*ReportTranslation::createEmptyPageTranslation() +{ + PageTranslation* pageTranslation = new PageTranslation; + m_pagesTranslation.append(pageTranslation); + return pageTranslation; +} + +QLocale::Language ReportTranslation::language() const +{ + return m_language; +} + +} //namespace LimeReport diff --git a/limereport/lrreporttranslation.h b/limereport/lrreporttranslation.h new file mode 100644 index 0000000..8af2de7 --- /dev/null +++ b/limereport/lrreporttranslation.h @@ -0,0 +1,67 @@ +#ifndef REPORTTRANSLATION_H +#define REPORTTRANSLATION_H + +#include +#include +#include +#include + +#include "lrpagedesignintf.h" + + +class ATranslationProperty{ +public: + ATranslationProperty(){} + ATranslationProperty(const ACollectionProperty& ){} + virtual ~ATranslationProperty(){} +}; + +Q_DECLARE_METATYPE(ATranslationProperty) +const int TRANSLATION_TYPE_ID = qMetaTypeId(); + +namespace LimeReport{ + +struct PropertyTranslation{ + QString propertyName; + QString value; +}; + +struct ItemTranslation{ + QString itemName; + QList propertyesTranslation; +}; + +struct PageTranslation{ + QString pageName; + QList itemsTranslation; +}; + +class ReportTranslation{ +public: + ReportTranslation(QLocale::Language language) :m_language(language){} + ReportTranslation(QLocale::Language language, QList pages); + ReportTranslation(const ReportTranslation& reportTranslation); + ~ReportTranslation(); + QLocale::Language language() const; + QList pagesTranslation() const; + PageTranslation* createEmptyPageTranslation(); +private: + PageTranslation* createPageTranslation(PageDesignIntf* page); +private: + QLocale::Language m_language; + QList m_pagesTranslation; +}; + + +typedef QMap Translations; + +class ITranslationContainer{ +public: + virtual Translations* translations() = 0; +}; + +} // namespace LimeReport + +//Q_DECLARE_METATYPE(ReportTranslation) + +#endif // REPORTTRANSLATION_H diff --git a/limereport/serializators/lrxmlreader.cpp b/limereport/serializators/lrxmlreader.cpp index 2e791cd..3cf11ad 100644 --- a/limereport/serializators/lrxmlreader.cpp +++ b/limereport/serializators/lrxmlreader.cpp @@ -33,6 +33,7 @@ #include "lrbasedesignintf.h" #include "lrdesignelementsfactory.h" #include "lrcollection.h" +#include "lrreporttranslation.h" #include @@ -112,11 +113,12 @@ void XMLReader::readItemFromNode(QObject* item,QDomElement *node) QDomElement currentNode =node->childNodes().at(i).toElement(); if (currentNode.attribute("Type")=="Object"){ readQObject(item,¤tNode); - }else if (currentNode.attribute("Type")=="Collection") + } else if (currentNode.attribute("Type")=="Collection") { readCollection(item,¤tNode); - } - else readProperty(item,¤tNode); + } else if (currentNode.attribute("Type")=="Translation"){ + readTranslation(item,¤tNode); + } else readProperty(item,¤tNode); } if (lf) lf->objectLoadFinished(); @@ -191,7 +193,7 @@ void XMLReader::readCollection(QObject *item, QDomElement *node) ICollectionContainer* collection = dynamic_cast(item); if (collection){ QString collectionName = node->nodeName(); - for(int i=0;ichildNodes().count();i++){ + for(int i = 0; i < node->childNodes().count(); ++i){ QDomElement currentNode =node->childNodes().at(i).toElement(); QObject* obj = collection->createElement(collectionName,currentNode.attribute("ClassName")); if (obj) @@ -201,6 +203,37 @@ void XMLReader::readCollection(QObject *item, QDomElement *node) } } +void XMLReader::readTranslation(QObject* item, QDomElement* node) +{ + ITranslationContainer* tranclationContainer = dynamic_cast(item); + if (tranclationContainer){ + Translations* translations = tranclationContainer->translations(); + for (int langIndex = 0; langIndexchildNodes().count(); ++langIndex){ + QDomElement languageNode = node->childNodes().at(langIndex).toElement(); + ReportTranslation* curTranslation = new ReportTranslation((QLocale::Language)(languageNode.attributeNode("Value").value().toInt())); + for (int pageIndex = 0; pageIndex < languageNode.childNodes().count(); ++pageIndex){ + QDomElement pageNode = languageNode.childNodes().at(pageIndex).toElement(); + PageTranslation* pageTranslation = curTranslation->createEmptyPageTranslation(); + pageTranslation->pageName = pageNode.nodeName(); + for (int itemIndex = 0; itemIndex < pageNode.childNodes().count(); ++itemIndex){ + QDomElement itemNode = pageNode.childNodes().at(itemIndex).toElement(); + ItemTranslation itemTranslation; + itemTranslation.itemName = itemNode.nodeName(); + for (int propertyIndex = 0; propertyIndex < itemNode.childNodes().count(); ++propertyIndex){ + QDomElement propertyNode = itemNode.childNodes().at(propertyIndex).toElement(); + PropertyTranslation propertyTranslation; + propertyTranslation.propertyName = propertyNode.nodeName(); + propertyTranslation.value = propertyNode.attribute("Value"); + itemTranslation.propertyesTranslation.append(propertyTranslation); + } + pageTranslation->itemsTranslation.append(itemTranslation); + } + } + translations->insert(curTranslation->language(),curTranslation); + } + } +} + FileXMLReader::FileXMLReader(QString fileName) : m_fileName(fileName) { diff --git a/limereport/serializators/lrxmlreader.h b/limereport/serializators/lrxmlreader.h index c0f3508..3dbbc5c 100644 --- a/limereport/serializators/lrxmlreader.h +++ b/limereport/serializators/lrxmlreader.h @@ -61,6 +61,7 @@ protected: void readProperty(QObject *item, QDomElement *node); void readQObject(QObject *item, QDomElement *node); void readCollection(QObject *item, QDomElement *node); + void readTranslation(QObject *item, QDomElement *node); QVariant getValue(QDomElement *node); protected: diff --git a/limereport/serializators/lrxmlwriter.cpp b/limereport/serializators/lrxmlwriter.cpp index 3038373..b0f0bee 100644 --- a/limereport/serializators/lrxmlwriter.cpp +++ b/limereport/serializators/lrxmlwriter.cpp @@ -31,6 +31,7 @@ #include "lrbasedesignintf.h" #include "serializators/lrxmlserializatorsfactory.h" #include "lrcollection.h" +#include "lrreporttranslation.h" #include namespace LimeReport{ @@ -137,7 +138,9 @@ void XMLWriter::saveProperty(QString name, QObject* item, QDomElement *node) typeName = item->property(name.toLatin1()).typeName(); CreateSerializator creator=0; - if (isCollection(name,item)) { saveCollection(name,item,node); return;} + 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(item->property(name.toLatin1()))) putQObjectProperty(name,qvariant_cast(item->property(name.toLatin1())),node); @@ -193,9 +196,15 @@ bool XMLWriter::isCollection(QString propertyName, QObject* item) return QMetaType::type(prop.typeName())==COLLECTION_TYPE_ID; } +bool XMLWriter::isTranslation(QString propertyName, QObject* item) +{ + QMetaProperty prop=item->metaObject()->property(item->metaObject()->indexOfProperty(propertyName.toLatin1())); + return QMetaType::type(prop.typeName())==TRANSLATION_TYPE_ID; +} + void XMLWriter::saveCollection(QString propertyName, QObject *item, QDomElement *node) { - ICollectionContainer * collection=dynamic_cast(item); + ICollectionContainer * collection = dynamic_cast(item); QDomElement collectionNode=m_doc->createElement(propertyName); collectionNode.setAttribute("Type","Collection"); @@ -206,6 +215,37 @@ void XMLWriter::saveCollection(QString propertyName, QObject *item, QDomElement node->appendChild(collectionNode); } +void XMLWriter::saveTranslation(QString propertyName, QObject* item, QDomElement* node) +{ + ITranslationContainer* translationsContainer = dynamic_cast(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)); + 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); + pageNode.appendChild(itemNode); + foreach(PropertyTranslation property, item.propertyesTranslation){ + QDomElement propertyNode = m_doc->createElement(property.propertyName); + propertyNode.setAttribute("Value",property.value); + itemNode.appendChild(propertyNode); + } + } + } + } + node->appendChild(translationsNode); + } + +} + bool XMLWriter::isQObject(QString propertyName, QObject *item) { QMetaProperty prop=item->metaObject()->property(item->metaObject()->indexOfProperty(propertyName.toLatin1())); diff --git a/limereport/serializators/lrxmlwriter.h b/limereport/serializators/lrxmlwriter.h index 0259a75..05d47a7 100644 --- a/limereport/serializators/lrxmlwriter.h +++ b/limereport/serializators/lrxmlwriter.h @@ -62,7 +62,9 @@ private: bool enumOrFlag(QString name, QObject* item); QString extractClassName(QObject* item); bool isCollection(QString propertyName, QObject *item); + bool isTranslation(QString propertyName, QObject *item); void saveCollection(QString propertyName, QObject *item, QDomElement *node); + void saveTranslation(QString propertyName, QObject *item, QDomElement *node); bool isQObject(QString propertyName, QObject *item); bool replaceNode(QDomElement node, QObject *item); private: