From 9a6764ae081ba6f4b3c7847db10aa8da297c2136 Mon Sep 17 00:00:00 2001 From: blacksun Date: Thu, 31 Mar 2016 17:28:44 +0000 Subject: [PATCH] Remove the use of ElementsCollectionItem and ElementDefinition from qetelementeditor class git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4413 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- .../elementcollectionitem.h | 1 + .../elementscollectionwidget.cpp | 6 +- .../ElementsCollection/elementslocation.cpp | 66 +++- sources/ElementsCollection/elementslocation.h | 2 + .../xmlprojectelementcollectionitem.cpp | 6 + .../xmlprojectelementcollectionitem.h | 1 + sources/editor/qetelementeditor.cpp | 281 ++++++++---------- sources/editor/qetelementeditor.h | 2 +- sources/qetxml.cpp | 34 +++ sources/qetxml.h | 2 + 10 files changed, 243 insertions(+), 158 deletions(-) diff --git a/sources/ElementsCollection/elementcollectionitem.h b/sources/ElementsCollection/elementcollectionitem.h index 8f8b942fd..35d989a42 100644 --- a/sources/ElementsCollection/elementcollectionitem.h +++ b/sources/ElementsCollection/elementcollectionitem.h @@ -61,6 +61,7 @@ class ElementCollectionItem : public QObject int row() const; virtual QString name(); virtual QString collectionName() const; + virtual QString collectionPath() const {return QString();} virtual bool isDir() const; virtual bool isElement() const; diff --git a/sources/ElementsCollection/elementscollectionwidget.cpp b/sources/ElementsCollection/elementscollectionwidget.cpp index 4206aaca8..3e2738946 100644 --- a/sources/ElementsCollection/elementscollectionwidget.cpp +++ b/sources/ElementsCollection/elementscollectionwidget.cpp @@ -240,11 +240,9 @@ void ElementsCollectionWidget::editElement() { ElementCollectionItem *eci = elementCollectionItemForIndex(m_index_at_context_menu); - if (!eci || - !eci->isElement() || - (eci->type() != FileElementCollectionItem::Type)) return; + if ( !(eci && eci->isElement()) ) return; - ElementsLocation location(static_cast(eci)->collectionPath()); + ElementsLocation location(eci->collectionPath()); QETApp *app = QETApp::instance(); app->openElementLocations(QList() << location); diff --git a/sources/ElementsCollection/elementslocation.cpp b/sources/ElementsCollection/elementslocation.cpp index bc3d096a8..7b238da07 100644 --- a/sources/ElementsCollection/elementslocation.cpp +++ b/sources/ElementsCollection/elementslocation.cpp @@ -22,6 +22,7 @@ #include "elementscollectioncache.h" #include "elementfactory.h" #include "element.h" +#include "qetxml.h" // make this class usable with QVariant int ElementsLocation::MetaTypeId = qRegisterMetaType("ElementsLocation"); @@ -430,6 +431,24 @@ bool ElementsLocation::exist() const } } +/** + * @brief ElementsLocation::isWritable + * @return True if this element can be writable (can use set xml) + */ +bool ElementsLocation::isWritable() const +{ + if (m_project) + return !m_project->isReadOnly(); + else if (isFileSystem()) + { + if (fileSystemPath().startsWith(QETApp::commonElementsDirN())) + return false; + else + return true; + } + return false; +} + /** * @brief ElementsLocation::projectCollection * @return If this location represente a item in an embedded project collection, return this collection @@ -492,7 +511,7 @@ QDomElement ElementsLocation::xml() const QFile file (m_file_system_path); QDomDocument docu; if (docu.setContent(&file)) - return docu.documentElement().cloneNode().toElement(); + return docu.documentElement(); } else { @@ -512,6 +531,51 @@ QDomElement ElementsLocation::xml() const return QDomElement(); } +/** + * @brief ElementsLocation::setXml + * Replace the current xml description by @xml_element; + * The document element of @xml_document must have tagname "definition" to be written + * This definition must be writable + * @param xml_element + * @return true if success + */ +bool ElementsLocation::setXml(const QDomDocument &xml_document) const +{ + if (!isWritable()) + return false; + + if (xml_document.documentElement().tagName() != "definition") + { + qDebug() << "ElementsLocation::setXml : tag name of document element isn't 'definition'"; + return false; + } + + if (isFileSystem()) + { + QString error; + QETXML::writeXmlFile(xml_document, fileSystemPath(), &error); + + if (!error.isEmpty()) + { + qDebug() << "ElementsLocation::setXml error : " << error; + return false; + } + else + return true; + } + else if (isProject() && exist()) + { + QDomElement dom_element = xml(); + QDomNode parent_node = dom_element.parentNode(); + parent_node.removeChild(dom_element); + parent_node.appendChild(xml_document.documentElement().cloneNode(true)); + + return true; + } + + return false; +} + /** * @brief ElementsLocation::uuid * @return The uuid of the pointed element diff --git a/sources/ElementsCollection/elementslocation.h b/sources/ElementsCollection/elementslocation.h index 1218d18fd..9bf79c738 100644 --- a/sources/ElementsCollection/elementslocation.h +++ b/sources/ElementsCollection/elementslocation.h @@ -63,11 +63,13 @@ class ElementsLocation bool isFileSystem() const; bool isProject() const; bool exist() const; + bool isWritable() const; XmlElementCollection *projectCollection() const; NamesList nameList(); QDomElement xml() const; + bool setXml(const QDomDocument &xml_document) const; QUuid uuid() const; QIcon icon() const; QString name() const; diff --git a/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp b/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp index 608f32157..d812ef708 100644 --- a/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp +++ b/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp @@ -102,6 +102,12 @@ QVariant XmlProjectElementCollectionItem::data(int column, int role) } } +void XmlProjectElementCollectionItem::clearData() +{ + m_icon = QIcon(); + ElementCollectionItem::clearData(); +} + /** * @brief XmlProjectElementCollectionItem::mimeData * @return The mimedata of this item diff --git a/sources/ElementsCollection/xmlprojectelementcollectionitem.h b/sources/ElementsCollection/xmlprojectelementcollectionitem.h index 41b4caee6..44493e0ee 100644 --- a/sources/ElementsCollection/xmlprojectelementcollectionitem.h +++ b/sources/ElementsCollection/xmlprojectelementcollectionitem.h @@ -44,6 +44,7 @@ class XmlProjectElementCollectionItem : public ElementCollectionItem virtual int type() const {return Type;} virtual QVariant data(int column, int role); + virtual void clearData(); virtual QMimeData *mimeData(); virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column) const; virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column); diff --git a/sources/editor/qetelementeditor.cpp b/sources/editor/qetelementeditor.cpp index 3c6baf21b..aaed4f4fe 100644 --- a/sources/editor/qetelementeditor.cpp +++ b/sources/editor/qetelementeditor.cpp @@ -23,7 +23,6 @@ #include "customelementpart.h" #include "newelementwizard.h" #include "elementitemeditor.h" -#include "elementdefinition.h" #include "elementdialog.h" #include "recentfiles.h" #include "qeticons.h" @@ -107,17 +106,15 @@ QETElementEditor::~QETElementEditor() { } /** - @param el Le nouvel emplacement de l'element edite -*/ -void QETElementEditor::setLocation(const ElementsLocation &el) { + * @brief QETElementEditor::setLocation + * The new location to edit + * @param el + */ +void QETElementEditor::setLocation(const ElementsLocation &el) +{ location_ = el; opened_from_file = false; - // modifie le mode lecture seule si besoin - ElementsCollectionItem *item = QETApp::collectionItem(location_); - bool must_be_read_only = item && !item -> isWritable(); - if (isReadOnly() != must_be_read_only) { - setReadOnly(must_be_read_only); - } + setReadOnly(!location_.isWritable()); slot_updateTitle(); } @@ -845,42 +842,23 @@ bool QETElementEditor::toFile(const QString &fn) { return(writing); } + /** - Enregistre l'element vers un emplacement - @param location Emplacement de l'element a enregistrer - @return true en cas de reussite, false sinon -*/ -bool QETElementEditor::toLocation(const ElementsLocation &location) { - ElementsCollectionItem *item = QETApp::collectionItem(location); - ElementDefinition *element; - if (item) { - // l'element existe deja - element = qobject_cast(item); - } else { - // l'element n'existe pas encore, on demande sa creation - element = QETApp::createElement(location); - } - - if (!element) { - QET::QetMessageBox::critical( - this, - tr("Erreur", "message box title"), - tr("Impossible d'atteindre l'élément", "message box content") - ); + * @brief QETElementEditor::toLocation + * Save the element to Location + * @param location : location where we must save the current element + * @return true if succesfully saved + */ +bool QETElementEditor::toLocation(const ElementsLocation &location) +{ + if (!location.setXml(ce_scene->toXml())) + { + QET::QetMessageBox::critical(this, + tr("Erreur", "message box title"), + tr("Impossible d'enregistrer l'élément", "message box content")); return(false); } - - // enregistre l'element - element -> setXml(ce_scene -> toXml().documentElement()); - if (!element -> write()) { - QET::QetMessageBox::critical( - this, - tr("Erreur", "message box title"), - tr("Impossible d'enregistrer l'élément", "message box content") - ); - return(false); - } - + return(true); } @@ -1101,69 +1079,74 @@ void QETElementEditor::openElement(const QString &filepath) { } /** - Recharge l'element edite -*/ -void QETElementEditor::slot_reload() { - // s'il ya des modifications, on demande a l'utilisateur s'il est certain - // de vouloir recharger - if (!ce_scene -> undoStack().isClean()) { - QMessageBox::StandardButton answer = QET::QetMessageBox::question( - this, - tr("Recharger l'élément", "dialog title"), - tr("Vous avez efffectué des modifications sur cet élément. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'élément ?", "dialog content"), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, - QMessageBox::Cancel - ); + * @brief QETElementEditor::slot_reload + * Reload the element from the file or location + */ +void QETElementEditor::slot_reload() +{ + //If user already edit the element, ask confirmation to reload + if (!ce_scene -> undoStack().isClean()) + { + QMessageBox::StandardButton answer = QET::QetMessageBox::question(this, + tr("Recharger l'élément", "dialog title"), + tr("Vous avez efffectué des modifications sur cet élément. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'élément ?", "dialog content"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Cancel); if (answer != QMessageBox::Yes) return; } - - // recharge l'element - if (opened_from_file) { - // l'element a ete ouvert a partir d'un chemin de fichier - ce_scene -> reset(); + + //Reload the element + ce_scene -> reset(); + if (opened_from_file) fromFile(filename_); - } else { - // l'element a ete ouvert a partir d'un emplacement (ElementsLocation) - // il peut s'agir aussi bien d'un fichier que d'un element XML - if (ElementsCollectionItem *item = QETApp::collectionItem(location_)) { - item -> reload(); - ce_scene -> reset(); - fromLocation(location_); - } - } + else + fromLocation(location_); } /** - Enregistre l'element en cours d'edition. - Si le nom du fichier en cours n'est pas connu, cette methode equivaut a - l'action "Enregistrer sous" - @see slot_saveAs() -*/ -bool QETElementEditor::slot_save() { - // Check element befor writing - if (checkElement()) { - // si on ne connait pas le nom du fichier en cours, enregistrer revient a enregistrer sous - if (opened_from_file) { - if (filename_.isEmpty()) return(slot_saveAsFile()); - // sinon on enregistre dans le nom de fichier connu + * @brief QETElementEditor::slot_save + * Save the current editing element. + * If the filepath or location is unknow, use save_as instead + * @return true if save with success + */ +bool QETElementEditor::slot_save() +{ + // Check element befor writing + if (checkElement()) + { + //If we don't know the name of the current file, use save as instead + if (opened_from_file) + { + if (filename_.isEmpty()) + return(slot_saveAsFile()); + + //Else wa save to the file at filename_ path bool result_save = toFile(filename_); if (result_save) ce_scene -> undoStack().setClean(); return(result_save); - } else { - if (location_.isNull()) return(slot_saveAs()); - // sinon on enregistre a l'emplacement connu + } + else + { + if (location_.isNull()) + return(slot_saveAs()); + + //Else save to the known location bool result_save = toLocation(location_); if (result_save) ce_scene -> undoStack().setClean(); return(result_save); } } + QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); return false; } /** - Demande une localisation a l'utilisateur et enregistre l'element -*/ + * @brief QETElementEditor::slot_saveAs + * Ask a location to user and save the current edited element + * to this location + * @return true if save with success + */ bool QETElementEditor::slot_saveAs() { // Check element befor writing if (checkElement()) { @@ -1186,8 +1169,10 @@ bool QETElementEditor::slot_saveAs() { } /** - Demande un nom de fichier a l'utilisateur et enregistre l'element -*/ + * @brief QETElementEditor::slot_saveAsFile + * Ask a file to user and save the current edited element to this file + * @return true if save with success + */ bool QETElementEditor::slot_saveAsFile() { // Check element befor writing if (checkElement()) { @@ -1444,53 +1429,48 @@ QString QETElementEditor::getOpenElementFileName(QWidget *parent, const QString } /** - @param location Emplacement de l'element a editer -*/ -void QETElementEditor::fromLocation(const ElementsLocation &location) { - - // l'element doit exister - ElementsCollectionItem *item = QETApp::collectionItem(location); - ElementDefinition *element = 0; - if (!item) { - QET::QetMessageBox::critical( - this, - tr("Élément inexistant.", "message box title"), - tr("L'élément n'existe pas.", "message box content") - ); + * @brief QETElementEditor::fromLocation + * Location of the element to edit + * @param location + */ +void QETElementEditor::fromLocation(const ElementsLocation &location) +{ + if (!location.isElement()) + { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); return; } - - if (!item -> isElement() || !(element = qobject_cast(item)) || element -> isNull()) { - QET::QetMessageBox::critical( - this, - tr("Élément inexistant.", "message box title"), - tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content") - ); + if (!location.exist()) + { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("L'élément n'existe pas.", "message box content")); return; } - - // le fichier doit etre un document XML + + //The file must be an xml document QDomDocument document_xml; - QDomNode node = document_xml.importNode(element -> xml(), true); + QDomNode node = document_xml.importNode(location.xml(), true); document_xml.appendChild(node); - - // chargement de l'element + + //Load the element ce_scene -> fromXml(document_xml); slot_createPartsList(); - - // gestion de la lecture seule - if (!element -> isWritable()) { - QET::QetMessageBox::warning( - this, - tr("Édition en lecture seule", "message box title"), - tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content") - ); + + //location is read only + if (!location.isWritable()) + { + QET::QetMessageBox::warning(this, + tr("Édition en lecture seule", "message box title"), + tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content")); setReadOnly(true); - } else { + } + else { setReadOnly(false); } - - // memorise le fichier + setLocation(location); slot_updateMenus(); } @@ -1525,40 +1505,37 @@ void QETElementEditor::pasteFromFile() { } /** - Denande un element a l'utilisateur, met son contenu dans le presse-papiers, - et appelle ElementView::PasteInArea -*/ -void QETElementEditor::pasteFromElement() { - // demande le chemin virtuel de l'element a ouvrir a l'utilisateur + * @brief QETElementEditor::pasteFromElement + * Ask an element to user, copy the xml definition of the element + * to the clipboard and call ElementView::PasteInArea + */ +void QETElementEditor::pasteFromElement() +{ + //Ask for a location ElementsLocation location = ElementDialog::getOpenElementLocation(this); - if (location.isNull()) return; - - // verifie l'existence de l'element choisi - ElementsCollectionItem *item = QETApp::collectionItem(location); - ElementDefinition *element = 0; - if (!item) { - QET::QetMessageBox::critical( - this, - tr("Élément inexistant.", "message box title"), - tr("L'élément n'existe pas.", "message box content") - ); + if (location.isNull()) + return; + + if (!location.isElement()) + { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); return; } - - if (!item -> isElement() || !(element = qobject_cast(item)) || element -> isNull()) { - QET::QetMessageBox::critical( - this, - tr("Élément inexistant.", "message box title"), - tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content") - ); + if (!location.exist()) + { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("L'élément n'existe pas.", "message box content")); return; } - - // creation d'un document XML a partir de la description XML de l'element + + //Create an xml document from the location xml QDomDocument document_xml; - QDomNode node = document_xml.importNode(element -> xml(), true); + QDomNode node = document_xml.importNode(location.xml(), true); document_xml.appendChild(node); - + copyAndPasteXml(document_xml); } diff --git a/sources/editor/qetelementeditor.h b/sources/editor/qetelementeditor.h index 2e5381d7f..d98a7ada1 100644 --- a/sources/editor/qetelementeditor.h +++ b/sources/editor/qetelementeditor.h @@ -104,7 +104,7 @@ class QETElementEditor : public QETMainWindow { void fromFile(const QString &); void fromLocation(const ElementsLocation &); bool toFile(const QString &); - bool toLocation(const ElementsLocation &); + bool toLocation(const ElementsLocation &location); bool isEditing(const ElementsLocation &); bool isEditing(const QString &); ElementScene *elementScene() const; diff --git a/sources/qetxml.cpp b/sources/qetxml.cpp index e82258fd3..052645486 100644 --- a/sources/qetxml.cpp +++ b/sources/qetxml.cpp @@ -220,3 +220,37 @@ QDomElement QETXML::fileSystemElementToXmlCollectionElement(QDomDocument &docume else return QDomElement(); } + +/** + * @brief QETXML::writeXmlFile + * Export an XML document to an UTF-8 text file indented with 4 spaces, with LF end of lines and no BOM. + * @param xml_document : An XML document to be exported + * @param file_path : Path to the file to be written + * @param error_message : If non-zero, will contain an error message explaining what happened when this function returns false. + * @return false if an error occured, true otherwise + */ +bool QETXML::writeXmlFile(const QDomDocument &xml_document, const QString &file_path, QString *error_message) +{ + QFile file(file_path); + + // Note: we do not set QIODevice::Text to avoid generating CRLF end of lines + bool file_opening = file.open(QIODevice::WriteOnly); + if (!file_opening) + { + if (error_message) + { + *error_message = QString(QObject::tr("Impossible d'ouvrir le fichier %1 en écriture, erreur %2 rencontrée.", + "error message when attempting to write an XML file") + ).arg(file_path).arg(file.error()); + } + return(false); + } + + QTextStream out(&file); + out.setCodec("UTF-8"); + out.setGenerateByteOrderMark(false); + out << xml_document.toString(4); + file.close(); + + return(true); +} diff --git a/sources/qetxml.h b/sources/qetxml.h index 06cf38a92..c0dd0a417 100644 --- a/sources/qetxml.h +++ b/sources/qetxml.h @@ -39,6 +39,8 @@ namespace QETXML QDomElement fileSystemDirToXmlCollectionDir (QDomDocument &document, const QDir &dir, QString rename = QString()); QDomElement fileSystemElementToXmlCollectionElement (QDomDocument &document, QFile &file, QString rename = QString()); + bool writeXmlFile(const QDomDocument &xml_document, const QString &file_path, QString *error_message = nullptr); + } #endif // QETXML_H