From 1b18b980a97db7575150da41b982806cd1475096 Mon Sep 17 00:00:00 2001 From: blacksun Date: Sat, 30 Dec 2017 14:41:25 +0000 Subject: [PATCH] User can export / import the configuration of the texts and texts group of an element. git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5195 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- sources/elementtextpattern.cpp | 250 ++++++++++++++++++ sources/elementtextpattern.h | 56 ++++ sources/qet.h | 2 +- sources/qetgraphicsitem/element.cpp | 62 ++--- .../qetgraphicsitem/elementtextitemgroup.cpp | 17 +- .../qetgraphicsitem/elementtextitemgroup.h | 2 +- sources/ui/dynamicelementtextitemeditor.cpp | 14 +- sources/ui/dynamicelementtextitemeditor.h | 2 + sources/ui/dynamicelementtextitemeditor.ui | 67 +++-- sources/undocommand/addelementtextcommand.cpp | 26 ++ sources/undocommand/addelementtextcommand.h | 4 + 11 files changed, 429 insertions(+), 73 deletions(-) create mode 100644 sources/elementtextpattern.cpp create mode 100644 sources/elementtextpattern.h diff --git a/sources/elementtextpattern.cpp b/sources/elementtextpattern.cpp new file mode 100644 index 000000000..1562ff2d4 --- /dev/null +++ b/sources/elementtextpattern.cpp @@ -0,0 +1,250 @@ +/* + Copyright 2006-2017 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech 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. + + QElectroTech 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 QElectroTech. If not, see . +*/ +#include "elementtextpattern.h" +#include "qetapp.h" +#include "element.h" +#include "qet.h" +#include "dynamicelementtextitem.h" +#include "elementtextitemgroup.h" +#include "addelementtextcommand.h" +#include "diagram.h" + +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief ExportElementTextPattern::ExportElementTextPattern + * Constructor + * @param elmt + */ +ExportElementTextPattern::ExportElementTextPattern(Element *elmt) : + m_element(elmt) +{ + //Create the conf dir if not yet. + QDir dir(QETApp::configDir()+ "/element_texts_pattern"); + if(!dir.exists()) + { + dir.cdUp(); + dir.mkdir("element_texts_pattern"); + dir.cd("element_texts_pattern"); + } + + //Get the name of conf + bool ok; + m_name = getName(ok); + if(ok == false) + return; + + //Check if a conf with the same name already exist + if (QFileInfo::exists(dir.absoluteFilePath(m_name + ".xml"))) + { + bool r = QMessageBox::question(parentWidget(), + QObject::tr("Configuration de textes"), + QObject::tr("Une configuration de textes nommé << %1 >> existe déjà.\n" + "Voulez-vous la remplacer ?").arg(m_name)); + + if(r == false) + return; + } + + QDomDocument doc = xmlConf(); + QET::writeXmlFile(doc, dir.absoluteFilePath(m_name + ".xml")); +} + +/** + * @brief ExportElementTextConf::getName + * Open a dialog to let user set the name of the conf and return it + * @return + */ +QString ExportElementTextPattern::getName(bool &ok) const +{ + QString text = QInputDialog::getText(parentWidget(), + QObject::tr("Nom de la configuration"), + QObject::tr("Entrer le nom de la configuration à créer"), + QLineEdit::Normal, + QString(), + &ok); + + text.replace(" ", "_"); + text.replace(".",""); + return text; +} + +QWidget *ExportElementTextPattern::parentWidget() const +{ + QWidget *parent = nullptr; + if(m_element->scene() && !m_element->scene()->views().isEmpty()) + parent = m_element->scene()->views().first(); + + return parent; +} + +QDomDocument ExportElementTextPattern::xmlConf() const +{ + QDomDocument doc; + QDomElement root = doc.createElement("Element_texts_pattern"); + root.setAttribute("name", m_name); + doc.appendChild(root); + + QHash H; + QDomElement elmt = m_element->toXml(doc, H); + QDomElement texts = elmt.firstChildElement("dynamic_texts"); + QDomElement groups = elmt.firstChildElement("texts_groups"); + + if(texts.tagName() == "dynamic_texts") + root.appendChild(texts); + if(groups.tagName() == "texts_groups") + root.appendChild(groups); + + return doc; +} + +//*******************// +//******IMPORT*******// +//*******************// + +ImportElementTextPattern::ImportElementTextPattern(Element *elmt): + m_element(elmt) +{ + bool exist = true; + QDir dir(QETApp::configDir()+ "/element_texts_pattern"); + + if(!dir.exists()) + exist = false; + + QStringList entry = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); + QStringList result = entry.filter(".xml"); + if(result.isEmpty()) + exist = false; + + if(!exist) + { + QMessageBox::information(parentWidget(), + QObject::tr("Configurtaion de textes"), + QObject::tr("Aucune configuration de textes existante.")); + return; + } + + bool ok=false; + //Remove the .xml extention of the files + result.replaceInStrings(".xml", ""); + QString name = getName(result, ok); + + if(!ok || name.isEmpty()) + return; + else + apply(name); +} + +/** + * @brief ImportElementTextPattern::getName + * Open a dialog to let user select a conf + * @param ok + * @return + */ +QString ImportElementTextPattern::getName(QStringList list, bool &ok) const +{ + return QInputDialog::getItem(parentWidget(), + QObject::tr("Séléctionner une configuration de textes"), + QObject::tr("Séléctionner la configuration de textes à ajouter à l'élément"), + list, + 0, + false, + &ok); +} + +QWidget *ImportElementTextPattern::parentWidget() const +{ + QWidget *parent = nullptr; + if(m_element->scene() && !m_element->scene()->views().isEmpty()) + parent = m_element->scene()->views().first(); + + return parent; +} + +/** + * @brief ImportElementTextPattern::apply + * Apply the user choice + * @param name : the name of the selected pattern + */ +void ImportElementTextPattern::apply(QString name) const +{ + if(!name.endsWith(".xml")) + name.append(".xml"); + + QFile conf_file(QETApp::configDir() + "/element_texts_pattern/" + name); + if(!conf_file.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + + //Load the content of the xml file + QDomDocument xml_conf; + if(!xml_conf.setContent(&conf_file)) + return; + + QDomElement root = xml_conf.firstChildElement("Element_texts_pattern"); + + //Get the text + QList texts = QET::findInDomElement(root, "dynamic_texts", "dynamic_elmt_text"); + if (texts.isEmpty()) + return; + + //Replace the original uuid of texts in the xml description, by a new one for every texts + QHash uuid_hash; + for(QDomElement text : texts) + { + QUuid original_uuid(text.attribute("uuid")); + QUuid new_uuid = QUuid::createUuid(); + text.setAttribute("uuid", new_uuid.toString()); + + uuid_hash.insert(original_uuid, new_uuid); + } + + //In each group of the xml description, replace the original uuids, by the news created upper. + QList groups = QET::findInDomElement(root, "texts_groups", "texts_group"); + for(QDomElement group : groups) + { + for(QDomElement text : QET::findInDomElement(group, "texts", "text")) + { + QUuid original_uuid(text.attribute("uuid")); + QUuid new_uuid = uuid_hash.value(original_uuid); + if(!new_uuid.isNull()) + text.setAttribute("uuid", new_uuid.toString()); + } + } + + QUndoStack &undo_stack = m_element->diagram()->undoStack(); + undo_stack.beginMacro(QObject::tr("Importer la configuration de texte : %1").arg(name.remove(".xml"))); + + //Add the texts to element + for(QDomElement text : texts) + { + DynamicElementTextItem *deti = new DynamicElementTextItem(m_element); + undo_stack.push(new AddElementTextCommand(m_element, deti)); + deti->fromXml(text); + } + //Add the groups to element + for(QDomElement xml_group : groups) + undo_stack.push(new AddTextsGroupCommand(m_element, xml_group)); + + undo_stack.endMacro(); +} diff --git a/sources/elementtextpattern.h b/sources/elementtextpattern.h new file mode 100644 index 000000000..17079aa10 --- /dev/null +++ b/sources/elementtextpattern.h @@ -0,0 +1,56 @@ +/* + Copyright 2006-2017 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech 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. + + QElectroTech 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 QElectroTech. If not, see . +*/ +#ifndef ELEMENTTEXTPATTERN_H +#define ELEMENTTEXTPATTERN_H + +#include +#include + +class Element; +class QWidget; + +class ExportElementTextPattern +{ + public: + ExportElementTextPattern(Element *elmt); + + private: + QString getName(bool &ok) const; + QWidget *parentWidget() const; + QDomDocument xmlConf() const; + + private: + Element *m_element = nullptr; + QString m_name; +}; + +class ImportElementTextPattern +{ + public: + ImportElementTextPattern(Element *elmt); + + private: + QString getName(QStringList list, bool &ok) const; + QWidget *parentWidget() const; + void apply(QString name) const; + + private: + Element *m_element = nullptr; +}; + +#endif // ELEMENTTEXTCONFIGURATION_H diff --git a/sources/qet.h b/sources/qet.h index 5352e9844..86bf0e26f 100644 --- a/sources/qet.h +++ b/sources/qet.h @@ -160,7 +160,7 @@ namespace QET { qreal correctAngle(const qreal &); bool compareCanonicalFilePaths(const QString &, const QString &); QString titleBlockColumnLengthToString(const TitleBlockColumnLength &); - bool writeXmlFile(QDomDocument &, const QString &, QString * = nullptr); + bool writeXmlFile(QDomDocument &xml_doc, const QString &filepath, QString * error_message= nullptr); QPointF graphicsSceneEventPos(QEvent *); bool eachStrIsEqual (const QStringList &qsl); } diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 8390db12e..3fe9ed69c 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -488,16 +488,16 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool for(DynamicElementTextItem *deti : m_dynamic_text_list) delete deti; m_dynamic_text_list.clear(); - + //************************// //***Dynamic texts item***// //************************// - for(QDomElement qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTaggName())) - { - DynamicElementTextItem *deti = new DynamicElementTextItem(this); - addDynamicTextItem(deti); - deti->fromXml(qde); - } + for (QDomElement qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTaggName())) + { + DynamicElementTextItem *deti = new DynamicElementTextItem(this); + addDynamicTextItem(deti); + deti->fromXml(qde); + } //************************// @@ -584,7 +584,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool } } - for (QDomElement qde : QET::findInDomElement(e, "texts_group", ElementTextItemGroup::xmlTaggName())) + for (QDomElement qde : QET::findInDomElement(e, "texts_groups", ElementTextItemGroup::xmlTaggName())) { ElementTextItemGroup *group = addTextGroup("loaded_from_xml_group"); group->fromXml(qde); @@ -626,7 +626,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool } } } - + return(true); } @@ -658,7 +658,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table QDomElement seq = m_autoNum_seq.toXml(document); if (seq.hasChildNodes()) element.appendChild(seq); - + // position, selection et orientation element.setAttribute("x", QString("%1").arg(pos().x())); element.setAttribute("y", QString("%1").arg(pos().y())); @@ -674,7 +674,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table } id_terminal = max_id_t + 1; } - + // enregistrement des bornes de l'appareil QDomElement xml_terminals = document.createElement("terminals"); // pour chaque enfant de l'element @@ -686,7 +686,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table xml_terminals.appendChild(terminal); } element.appendChild(xml_terminals); - + // enregistrement des champ de texte de l'appareil QDomElement inputs = document.createElement("inputs"); foreach(ElementTextItem *eti, texts()) { @@ -706,21 +706,21 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table element.appendChild(links_uuids); } - //save information of this element + //save information of this element if (! m_element_informations.keys().isEmpty()) { QDomElement infos = document.createElement("elementInformations"); m_element_informations.toXml(infos, "elementInformation"); element.appendChild(infos); } - - //Dynamic texts - QDomElement dyn_text = document.createElement("dynamic_texts"); - for(DynamicElementTextItem *deti : m_dynamic_text_list) - dyn_text.appendChild(deti->toXml(document)); + + //Dynamic texts + QDomElement dyn_text = document.createElement("dynamic_texts"); + for (DynamicElementTextItem *deti : m_dynamic_text_list) + dyn_text.appendChild(deti->toXml(document)); - QDomElement texts_group = document.createElement("texts_group"); + QDomElement texts_group = document.createElement("texts_groups"); - //Dynamic texts owned by groups + //Dynamic texts owned by groups for(ElementTextItemGroup *group : m_texts_group) { //temporarily remove the texts from group to get the pos relative to element and not group. @@ -735,7 +735,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table group->removeFromGroup(deti); //Save the texts to xml - for(DynamicElementTextItem *deti : deti_list) + for (DynamicElementTextItem *deti : deti_list) dyn_text.appendChild(deti->toXml(document)); //Re add texts to group @@ -754,7 +754,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table //Append the texts group to element element.appendChild(texts_group); - return(element); + return(element); } /** @@ -765,18 +765,18 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table */ void Element::addDynamicTextItem(DynamicElementTextItem *deti) { - if (deti && !m_dynamic_text_list.contains(deti)) + if (deti && !m_dynamic_text_list.contains(deti)) { - m_dynamic_text_list.append(deti); + m_dynamic_text_list.append(deti); deti->setParentItem(this); emit textAdded(deti); } - else - { - DynamicElementTextItem *text = new DynamicElementTextItem(this); - m_dynamic_text_list.append(text); + else + { + DynamicElementTextItem *text = new DynamicElementTextItem(this); + m_dynamic_text_list.append(text); emit textAdded(text); - } + } } /** @@ -787,9 +787,9 @@ void Element::addDynamicTextItem(DynamicElementTextItem *deti) */ void Element::removeDynamicTextItem(DynamicElementTextItem *deti) { - if (m_dynamic_text_list.contains(deti)) + if (m_dynamic_text_list.contains(deti)) { - m_dynamic_text_list.removeOne(deti); + m_dynamic_text_list.removeOne(deti); deti->setParentItem(nullptr); emit textRemoved(deti); return; diff --git a/sources/qetgraphicsitem/elementtextitemgroup.cpp b/sources/qetgraphicsitem/elementtextitemgroup.cpp index 80b09d799..98e210e41 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.cpp +++ b/sources/qetgraphicsitem/elementtextitemgroup.cpp @@ -179,13 +179,10 @@ void ElementTextItemGroup::updateAlignment() */ void ElementTextItemGroup::setVerticalAdjustment(int v) { - if(m_vertical_adjustment != v) - { - prepareGeometryChange(); - m_vertical_adjustment = v; - updateAlignment(); - emit verticalAdjustmentChanged(v); - } + prepareGeometryChange(); + m_vertical_adjustment = v; + updateAlignment(); + emit verticalAdjustmentChanged(v); } /** @@ -278,12 +275,12 @@ void ElementTextItemGroup::fromXml(QDomElement &dom_element) return; } - m_name = dom_element.attribute("name", "no name"); + setName(dom_element.attribute("name", "no name")); QMetaEnum me = QMetaEnum::fromType(); - m_alignment = Qt::Alignment(me.keyToValue(dom_element.attribute("alignment").toStdString().data())); + setAlignment(Qt::Alignment(me.keyToValue(dom_element.attribute("alignment").toStdString().data()))); setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble()); - m_vertical_adjustment = dom_element.attribute("vertical_adjustment").toInt(); + setVerticalAdjustment(dom_element.attribute("vertical_adjustment").toInt()); if(parentElement()) { diff --git a/sources/qetgraphicsitem/elementtextitemgroup.h b/sources/qetgraphicsitem/elementtextitemgroup.h index 0b03c4bdc..55432edde 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.h +++ b/sources/qetgraphicsitem/elementtextitemgroup.h @@ -67,7 +67,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup QDomElement toXml(QDomDocument &dom_document) const; void fromXml(QDomElement &dom_element); - static QString xmlTaggName() {return QString("text_group");} + static QString xmlTaggName() {return QString("texts_group");} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; QRectF boundingRect() const override; diff --git a/sources/ui/dynamicelementtextitemeditor.cpp b/sources/ui/dynamicelementtextitemeditor.cpp index b6fd32cf0..34de13311 100644 --- a/sources/ui/dynamicelementtextitemeditor.cpp +++ b/sources/ui/dynamicelementtextitemeditor.cpp @@ -26,6 +26,7 @@ #include "QPropertyUndoCommand/qpropertyundocommand.h" #include "elementtextitemgroup.h" #include "deleteqgraphicsitemcommand.h" +#include "elementtextpattern.h" #include #include @@ -40,9 +41,6 @@ DynamicElementTextItemEditor::DynamicElementTextItemEditor(Element *element, QWi ui->m_tree_view->installEventFilter(this); ui->m_remove_selection->setDisabled(true); - ui->m_export_pb->hide(); - ui->m_import_pb->hide(); - setElement(element); } @@ -256,3 +254,13 @@ void DynamicElementTextItemEditor::on_m_tree_view_clicked(const QModelIndex &ind else ui->m_remove_selection->setDisabled(true); } + +void DynamicElementTextItemEditor::on_m_export_pb_clicked() +{ + ExportElementTextPattern eetp(m_element); +} + +void DynamicElementTextItemEditor::on_m_import_pb_clicked() +{ + ImportElementTextPattern ietp(m_element); +} diff --git a/sources/ui/dynamicelementtextitemeditor.h b/sources/ui/dynamicelementtextitemeditor.h index a47baaad9..807da9083 100644 --- a/sources/ui/dynamicelementtextitemeditor.h +++ b/sources/ui/dynamicelementtextitemeditor.h @@ -53,6 +53,8 @@ class DynamicElementTextItemEditor : public AbstractElementPropertiesEditorWidge void on_m_remove_selection_clicked(); void on_m_add_group_clicked(); void on_m_tree_view_clicked(const QModelIndex &index); + void on_m_export_pb_clicked(); + void on_m_import_pb_clicked(); private: Ui::DynamicElementTextItemEditor *ui; diff --git a/sources/ui/dynamicelementtextitemeditor.ui b/sources/ui/dynamicelementtextitemeditor.ui index ed379f75a..66a326d4f 100644 --- a/sources/ui/dynamicelementtextitemeditor.ui +++ b/sources/ui/dynamicelementtextitemeditor.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 226 + 234 @@ -17,7 +17,35 @@ - + + + Exporter l'actuelle configuration des textes + + + ... + + + + :/ico/16x16/document-save.png:/ico/16x16/document-save.png + + + + + + + Importer une configuration de texte + + + ... + + + + :/ico/16x16/folder-open.png:/ico/16x16/folder-open.png + + + + + Qt::Horizontal @@ -30,40 +58,40 @@ - + Ajouter un texte - Texte + ... - :/ico/16x16/list-add.png:/ico/16x16/list-add.png + :/ico/22x22/textfield.png:/ico/22x22/textfield.png - + Ajouter un groupe de textes - Groupe + ... - :/ico/16x16/list-add.png:/ico/16x16/list-add.png + :/ico/16x16/object-group.png:/ico/16x16/object-group.png - + Supprimer la sélection - + ... @@ -93,22 +121,7 @@ - - - - - Exporter - - - - - - - Importer - - - - + diff --git a/sources/undocommand/addelementtextcommand.cpp b/sources/undocommand/addelementtextcommand.cpp index 2fb575668..a5e84b973 100644 --- a/sources/undocommand/addelementtextcommand.cpp +++ b/sources/undocommand/addelementtextcommand.cpp @@ -75,6 +75,20 @@ AddTextsGroupCommand::AddTextsGroupCommand(Element *element, QString groupe_name setText(QObject::tr("Ajouter un groupe de textes d'élément")); } +/** + * @brief AddTextsGroupCommand::AddTextsGroupCommand + * @param element : The element to add a new group + * @param dom_element : the first time the group is created, we call the function fromXml of the group, and give @dom_element has argument. + * @param parent : parent undo + */ +AddTextsGroupCommand::AddTextsGroupCommand(Element *element, QDomElement dom_element, QUndoCommand *parent) : + QUndoCommand(parent), + m_element(element), + m_dom_element(dom_element) +{ + setText(QObject::tr("Ajouter un groupe de textes d'élément")); +} + /** * @brief AddTextsGroupCommand::~AddTextsGroupCommand * Destructor @@ -95,10 +109,22 @@ void AddTextsGroupCommand::redo() if(m_first_undo) { m_group = m_element.data()->addTextGroup(m_name); + if(!m_dom_element.isNull()) + { + m_group.data()->fromXml(m_dom_element); + //We get the list of texts (if any) because when undo is called, all child text will be removed + //from the group, and reparented to m_elemeny. + //Then the next time redo is called, the texts will be added to the group + m_deti_list = m_group.data()->texts(); + } m_first_undo = false; } else if(m_group) + { m_element.data()->addTextGroup(m_group.data()); + for(DynamicElementTextItem *deti : m_deti_list) + m_element.data()->addTextToGroup(deti, m_group.data()); + } } } diff --git a/sources/undocommand/addelementtextcommand.h b/sources/undocommand/addelementtextcommand.h index 9ff375cbc..67b4112ac 100644 --- a/sources/undocommand/addelementtextcommand.h +++ b/sources/undocommand/addelementtextcommand.h @@ -20,6 +20,7 @@ #include #include +#include class Element; class DynamicElementTextItem; @@ -51,6 +52,7 @@ class AddTextsGroupCommand : public QUndoCommand { public: AddTextsGroupCommand(Element *element, QString groupe_name, QUndoCommand *parent = nullptr); + AddTextsGroupCommand(Element *element, QDomElement dom_element, QUndoCommand *parent = nullptr); ~AddTextsGroupCommand() override; void undo() override; @@ -59,6 +61,8 @@ class AddTextsGroupCommand : public QUndoCommand private: QPointer m_element; QPointer m_group; + QList m_deti_list; + QDomElement m_dom_element; QString m_name; bool m_first_undo = true; };