save/load QetGraphicsTableItem to/from .qet file

This commit is contained in:
Claveau Joshua 2020-04-17 18:40:28 +02:00
parent 851265844f
commit 908d79925c
16 changed files with 600 additions and 117 deletions

View File

@ -37,6 +37,9 @@
#include "elementtextitemgroup.h" #include "elementtextitemgroup.h"
#include "undocommand/addelementtextcommand.h" #include "undocommand/addelementtextcommand.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "qetgraphicstableitem.h"
#include "qetxml.h"
#include "elementprovider.h"
int Diagram::xGrid = 10; int Diagram::xGrid = 10;
int Diagram::yGrid = 10; int Diagram::yGrid = 10;
@ -614,31 +617,31 @@ QDomDocument Diagram::toXml(bool whole_content) {
QDomDocument document; QDomDocument document;
// racine de l'arbre XML // racine de l'arbre XML
QDomElement racine = document.createElement("diagram"); auto dom_root = document.createElement("diagram");
// add the application version number // add the application version number
racine.setAttribute("version", QET::version); dom_root.setAttribute("version", QET::version);
// proprietes du schema // proprietes du schema
if (whole_content) { if (whole_content) {
border_and_titleblock.titleBlockToXml(racine); border_and_titleblock.titleBlockToXml(dom_root);
border_and_titleblock.borderToXml(racine); border_and_titleblock.borderToXml(dom_root);
// Default conductor properties // Default conductor properties
QDomElement default_conductor = document.createElement("defaultconductor"); QDomElement default_conductor = document.createElement("defaultconductor");
defaultConductorProperties.toXml(default_conductor); defaultConductorProperties.toXml(default_conductor);
racine.appendChild(default_conductor); dom_root.appendChild(default_conductor);
// Conductor autonum // Conductor autonum
if (!m_conductors_autonum_name.isEmpty()) { if (!m_conductors_autonum_name.isEmpty()) {
racine.setAttribute("conductorAutonum", m_conductors_autonum_name); dom_root.setAttribute("conductorAutonum", m_conductors_autonum_name);
} }
//Default New Element //Default New Element
racine.setAttribute("freezeNewElement", m_freeze_new_elements ? "true" : "false"); dom_root.setAttribute("freezeNewElement", m_freeze_new_elements ? "true" : "false");
//Default New Conductor //Default New Conductor
racine.setAttribute("freezeNewConductor", m_freeze_new_conductors_ ? "true" : "false"); dom_root.setAttribute("freezeNewConductor", m_freeze_new_conductors_ ? "true" : "false");
//Element Folio Sequential Variables //Element Folio Sequential Variables
if (!m_elmt_unitfolio_max.isEmpty() || !m_elmt_tenfolio_max.isEmpty() || !m_elmt_hundredfolio_max.isEmpty()) { if (!m_elmt_unitfolio_max.isEmpty() || !m_elmt_tenfolio_max.isEmpty() || !m_elmt_hundredfolio_max.isEmpty()) {
@ -658,7 +661,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
folioSequentialsToXml(&m_elmt_hundredfolio_max, &elmtfolioseq, "seqhf_", "hundredfolioseq", &document); folioSequentialsToXml(&m_elmt_hundredfolio_max, &elmtfolioseq, "seqhf_", "hundredfolioseq", &document);
elmtfoliosequential.appendChild(elmtfolioseq); elmtfoliosequential.appendChild(elmtfolioseq);
} }
racine.appendChild(elmtfoliosequential); dom_root.appendChild(elmtfoliosequential);
} }
//Conductor Folio Sequential Variables //Conductor Folio Sequential Variables
if (!m_cnd_unitfolio_max.isEmpty() || !m_cnd_tenfolio_max.isEmpty() || !m_cnd_hundredfolio_max.isEmpty()) { if (!m_cnd_unitfolio_max.isEmpty() || !m_cnd_tenfolio_max.isEmpty() || !m_cnd_hundredfolio_max.isEmpty()) {
@ -679,101 +682,125 @@ QDomDocument Diagram::toXml(bool whole_content) {
folioSequentialsToXml(&m_cnd_hundredfolio_max, &cndfolioseq, "seqhf_", "hundredfolioseq", &document); folioSequentialsToXml(&m_cnd_hundredfolio_max, &cndfolioseq, "seqhf_", "hundredfolioseq", &document);
cndfoliosequential.appendChild(cndfolioseq); cndfoliosequential.appendChild(cndfolioseq);
} }
racine.appendChild(cndfoliosequential); dom_root.appendChild(cndfoliosequential);
} }
} }
else { else {
//this method with whole_content to false, //this method with whole_content to false,
//is often use to copy and paste the current selection //is often use to copy and paste the current selection
//so we add the id of the project where copy occur. //so we add the id of the project where copy occur.
racine.setAttribute("projectId", QETApp::projectId(m_project)); dom_root.setAttribute("projectId", QETApp::projectId(m_project));
} }
document.appendChild(racine); document.appendChild(dom_root);
// si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML if (items().isEmpty())
if (items().isEmpty()) return(document); return(document);
// creation de trois listes : une qui contient les elements, une qui contient les conducteurs, une qui contient les champs de texte QVector<Element *> list_elements;
QList<Element *> list_elements; QVector<Conductor *> list_conductors;
QList<Conductor *> list_conductors; QVector<DiagramTextItem *> list_texts;
QList<DiagramTextItem *> list_texts; QVector<DiagramImageItem *> list_images;
QList<DiagramImageItem *> list_images; QVector<QetShapeItem *> list_shapes;
QList<QetShapeItem *> list_shapes; QVector<QetGraphicsTableItem *> table_vector;
QList<QGraphicsItem *> list_items = items(); //Ckeck graphics item to "XMLise"
; for(QGraphicsItem *qgi : items())
// Determine les elements a "XMLiser" {
foreach(QGraphicsItem *qgi, list_items) { switch (qgi->type())
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) { {
if (whole_content) list_elements << elmt; case Element::Type: {
else if (elmt -> isSelected()) list_elements << elmt; auto elmt = static_cast<Element *>(qgi);
} else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) { if (whole_content || elmt->isSelected())
if (whole_content) list_conductors << f; list_elements << elmt;
// lorsqu'on n'exporte pas tout le diagram, il faut retirer les conducteurs non selectionnes break;
// et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas selectionne }
else if (f -> terminal1 -> parentItem() -> isSelected() && f -> terminal2 -> parentItem() -> isSelected()) { case Conductor::Type: {
list_conductors << f; auto cond = static_cast<Conductor *>(qgi);
if (whole_content)
list_conductors << cond;
//When we did not export the whole diagram, we must to remove the non selected conductors.
//At this step that mean a conductor which one of these two element are not selected
else if (cond->terminal1->parentItem()->isSelected() && cond->terminal2->parentItem()->isSelected())
list_conductors << cond;
break;
}
case DiagramImageItem::Type: {
auto image = static_cast<DiagramImageItem *>(qgi);
if (whole_content || image->isSelected())
list_images << image;
break;
}
case IndependentTextItem::Type: {
auto indi_text = static_cast<IndependentTextItem *>(qgi);
if (whole_content || indi_text->isSelected())
list_texts << indi_text;
break;
}
case QetShapeItem::Type: {
auto shape = static_cast<QetShapeItem *>(qgi);
if (whole_content || shape->isSelected())
list_shapes << shape;
break;
}
case QetGraphicsTableItem::Type: {
auto table = static_cast<QetGraphicsTableItem *>(qgi);
if (whole_content || table->isSelected())
table_vector << table;
} }
} else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(qgi)) {
if (whole_content) list_texts << iti;
else if (iti -> isSelected()) list_texts << iti;
} else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(qgi)) {
if (whole_content) list_images << dii;
else if (dii -> isSelected()) list_images << dii;
} else if (QetShapeItem *dsi = qgraphicsitem_cast<QetShapeItem *>(qgi)) {
if (whole_content) list_shapes << dsi;
else if (dsi -> isSelected()) list_shapes << dsi;
} }
} }
// table de correspondance entre les adresses des bornes et leurs ids // table de correspondance entre les adresses des bornes et leurs ids
QHash<Terminal *, int> table_adr_id; QHash<Terminal *, int> table_adr_id;
// enregistrement des elements
if (!list_elements.isEmpty()) { if (!list_elements.isEmpty()) {
QDomElement elements = document.createElement("elements"); auto dom_elements = document.createElement("elements");
foreach(Element *elmt, list_elements) { for (auto elmt : list_elements) {
elements.appendChild(elmt -> toXml(document, table_adr_id)); dom_elements.appendChild(elmt->toXml(document, table_adr_id));
} }
racine.appendChild(elements); dom_root.appendChild(dom_elements);
} }
// enregistrement des conducteurs
if (!list_conductors.isEmpty()) { if (!list_conductors.isEmpty()) {
QDomElement conductors = document.createElement("conductors"); auto dom_conductors = document.createElement("conductors");
foreach(Conductor *cond, list_conductors) { for (auto cond : list_conductors) {
conductors.appendChild(cond -> toXml(document, table_adr_id)); dom_conductors.appendChild(cond->toXml(document, table_adr_id));
} }
racine.appendChild(conductors); dom_root.appendChild(dom_conductors);
} }
// enregistrement des champs de texte
if (!list_texts.isEmpty()) { if (!list_texts.isEmpty()) {
QDomElement inputs = document.createElement("inputs"); auto dom_texts = document.createElement("inputs");
foreach(DiagramTextItem *dti, list_texts) { for (auto dti : list_texts) {
inputs.appendChild(dti -> toXml(document)); dom_texts.appendChild(dti->toXml(document));
} }
racine.appendChild(inputs); dom_root.appendChild(dom_texts);
} }
// save of images
if (!list_images.isEmpty()) { if (!list_images.isEmpty()) {
QDomElement images = document.createElement("images"); auto dom_images = document.createElement("images");
foreach (DiagramImageItem *dii, list_images) { for (auto dii : list_images) {
images.appendChild(dii -> toXml(document)); dom_images.appendChild(dii->toXml(document));
} }
racine.appendChild(images); dom_root.appendChild(dom_images);
} }
// save of basic shapes
if (!list_shapes.isEmpty()) { if (!list_shapes.isEmpty()) {
QDomElement shapes = document.createElement("shapes"); auto dom_shapes = document.createElement("shapes");
foreach (QetShapeItem *dii, list_shapes) { for (auto dii : list_shapes) {
shapes.appendChild(dii -> toXml(document)); dom_shapes.appendChild(dii -> toXml(document));
} }
racine.appendChild(shapes); dom_root.appendChild(dom_shapes);
} }
// on retourne le document XML ainsi genere
if (table_vector.size()) {
auto tables = document.createElement("tables");
for (auto table : table_vector) {
tables.appendChild(table->toXml(document));
}
dom_root.appendChild(tables);
}
return(document); return(document);
} }
@ -970,7 +997,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf
} }
} }
// Load text // Load text
QList<IndependentTextItem *> added_texts; QList<IndependentTextItem *> added_texts;
foreach (QDomElement text_xml, QET::findInDomElement(root, "inputs", "input")) { foreach (QDomElement text_xml, QET::findInDomElement(root, "inputs", "input")) {
IndependentTextItem *iti = new IndependentTextItem(); IndependentTextItem *iti = new IndependentTextItem();
@ -979,7 +1006,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf
added_texts << iti; added_texts << iti;
} }
// Load image // Load image
QList<DiagramImageItem *> added_images; QList<DiagramImageItem *> added_images;
foreach (QDomElement image_xml, QET::findInDomElement(root, "images", "image")) { foreach (QDomElement image_xml, QET::findInDomElement(root, "images", "image")) {
DiagramImageItem *dii = new DiagramImageItem (); DiagramImageItem *dii = new DiagramImageItem ();
@ -988,7 +1015,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf
added_images << dii; added_images << dii;
} }
// Load shape // Load shape
QList<QetShapeItem *> added_shapes; QList<QetShapeItem *> added_shapes;
foreach (QDomElement shape_xml, QET::findInDomElement(root, "shapes", "shape")) { foreach (QDomElement shape_xml, QET::findInDomElement(root, "shapes", "shape")) {
QetShapeItem *dii = new QetShapeItem (QPointF(0,0)); QetShapeItem *dii = new QetShapeItem (QPointF(0,0));
@ -1026,39 +1053,52 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf
else qDebug() << "Diagram::fromXml() : Le chargement du conducteur" << id_p1 << id_p2 << "a echoue"; else qDebug() << "Diagram::fromXml() : Le chargement du conducteur" << id_p1 << id_p2 << "a echoue";
} }
//Translate items if a new position was given in parameter //Load tables
if (position != QPointF()) { QVector<QetGraphicsTableItem *> added_tables;
for (auto dom_table : QETXML::subChild(root, "tables", QetGraphicsTableItem::xmlTagName()))
{
auto table = new QetGraphicsTableItem();
addItem(table);
table->fromXml(dom_table);
added_tables << table;
}
QList<QGraphicsItem *> added_items; //Translate items if a new position was given in parameter
foreach (Element *added_element, added_elements ) added_items << added_element; if (position != QPointF())
foreach (Conductor *added_cond, added_conductors) added_items << added_cond; {
foreach (QetShapeItem *added_shape, added_shapes ) added_items << added_shape; QVector <QGraphicsItem *> added_items;
foreach (DiagramTextItem *added_text, added_texts ) added_items << added_text; for (auto element : added_elements ) added_items << element;
foreach (DiagramImageItem *added_image, added_images ) added_items << added_image; for (auto cond : added_conductors) added_items << cond;
for (auto shape : added_shapes ) added_items << shape;
for (auto text : added_texts ) added_items << text;
for (auto image : added_images ) added_items << image;
for (auto table : added_tables ) added_items << table;
//Get the top left corner of the rectangle that contain all added items //Get the top left corner of the rectangle that contain all added items
QRectF items_rect; QRectF items_rect;
foreach (QGraphicsItem *item, added_items) { for (auto item : added_items) {
items_rect = items_rect.united(item -> mapToScene(item -> boundingRect()).boundingRect()); items_rect = items_rect.united(item->mapToScene(item->boundingRect()).boundingRect());
} }
QPointF point_ = items_rect.topLeft(); QPointF point_ = items_rect.topLeft();
QPointF pos_ = Diagram::snapToGrid(QPointF (position.x() - point_.x(), QPointF pos_ = Diagram::snapToGrid(QPointF (position.x() - point_.x(),
position.y() - point_.y())); position.y() - point_.y()));
//Translate all added items //Translate all added items
foreach (QGraphicsItem *qgi, added_items) for (auto qgi : added_items)
qgi -> setPos( qgi -> pos() += pos_); qgi->setPos(qgi->pos() += pos_);
} }
// remplissage des listes facultatives //Filling of falculatory lists
if (content_ptr) { if (content_ptr) {
content_ptr -> m_elements = added_elements; content_ptr -> m_elements = added_elements;
content_ptr -> m_conductors_to_move = added_conductors; content_ptr -> m_conductors_to_move = added_conductors;
content_ptr -> m_text_fields = added_texts.toSet(); content_ptr -> m_text_fields = added_texts.toSet();
content_ptr -> m_images = added_images.toSet(); content_ptr -> m_images = added_images.toSet();
content_ptr -> m_shapes = added_shapes.toSet(); content_ptr -> m_shapes = added_shapes.toSet();
content_ptr -> m_tables = added_tables;
} }
adjustSceneRect(); adjustSceneRect();
return(true); return(true);
} }
@ -1096,6 +1136,8 @@ void Diagram::folioSequentialsFromXml(const QDomElement &root, QHash<QString, QS
*/ */
void Diagram::refreshContents() void Diagram::refreshContents()
{ {
ElementProvider provider_(this);
for (Element *elmt : elements()) for (Element *elmt : elements())
{ {
elmt->initLink(project()); elmt->initLink(project());
@ -1105,6 +1147,9 @@ void Diagram::refreshContents()
for (Conductor *conductor : conductors()) for (Conductor *conductor : conductors())
conductor->refreshText(); conductor->refreshText();
for (auto table : provider_.table())
table->initLink();
} }
/** /**

View File

@ -19,6 +19,7 @@
#define DIAGRAM_CONTENT_H #define DIAGRAM_CONTENT_H
#include <QSet> #include <QSet>
#include <QVector>
class QGraphicsItem; class QGraphicsItem;
class Conductor; class Conductor;
@ -30,6 +31,7 @@ class DynamicElementTextItem;
class ElementTextItemGroup; class ElementTextItemGroup;
class Diagram; class Diagram;
class DiagramTextItem; class DiagramTextItem;
class QetGraphicsTableItem;
/** /**
This class provides a container that makes the transmission of diagram content This class provides a container that makes the transmission of diagram content
@ -60,8 +62,9 @@ class DiagramContent
AnyConductor = 112, AnyConductor = 112,
Shapes = 128, Shapes = 128,
TextGroup = 256, TextGroup = 256,
All = 511, Tables = 512,
SelectedOnly = 512 All = 1023,
SelectedOnly = 1024
}; };
QList<Element *> m_elements; QList<Element *> m_elements;
@ -75,6 +78,8 @@ class DiagramContent
QSet<DynamicElementTextItem *> m_element_texts; QSet<DynamicElementTextItem *> m_element_texts;
QSet<ElementTextItemGroup *> m_texts_groups; QSet<ElementTextItemGroup *> m_texts_groups;
QList<QGraphicsItem *> m_selected_items; QList<QGraphicsItem *> m_selected_items;
QVector<QetGraphicsTableItem *> m_tables;
QList<DiagramTextItem *> selectedTexts() const; QList<DiagramTextItem *> selectedTexts() const;
QList<ElementTextItemGroup *> selectedTextsGroup() const; QList<ElementTextItemGroup *> selectedTextsGroup() const;

View File

@ -156,3 +156,17 @@ QVector<QetGraphicsTableItem *> ElementProvider::table(QetGraphicsTableItem *tab
return v_; return v_;
} }
/**
* @brief ElementProvider::tableFromUuid
* @param uuid
* @return the table with uuid @uuid or nullptr if not found
*/
QetGraphicsTableItem *ElementProvider::tableFromUuid(const QUuid &uuid)
{
for (auto table : this->table())
if (table->uuid() == uuid)
return table;
return nullptr;
}

View File

@ -42,6 +42,7 @@ class ElementProvider
QList <Element *> fromUuids(QList <QUuid>) const; QList <Element *> fromUuids(QList <QUuid>) const;
QList <Element *> find(const int filter) const; QList <Element *> find(const int filter) const;
QVector <QetGraphicsTableItem *> table(QetGraphicsTableItem *table = nullptr, QAbstractItemModel *model = nullptr); QVector <QetGraphicsTableItem *> table(QetGraphicsTableItem *table = nullptr, QAbstractItemModel *model = nullptr);
QetGraphicsTableItem *tableFromUuid(const QUuid &uuid);
private: private:
QList <Diagram *> m_diagram_list; QList <Diagram *> m_diagram_list;

View File

@ -18,6 +18,7 @@
#include "nomenclaturemodel.h" #include "nomenclaturemodel.h"
#include "qetapp.h" #include "qetapp.h"
#include "qetproject.h" #include "qetproject.h"
#include "qetxml.h"
#include <QModelIndex> #include <QModelIndex>
#include <QFont> #include <QFont>
@ -202,6 +203,47 @@ void NomenclatureModel::autoHeaders()
} }
} }
/**
* @brief NomenclatureModel::toXml
* Save the model to xml,since model can have unlimited data we only save few data.
* The query and all header data. All other data are not saved.
* @param document
* @return
*/
QDomElement NomenclatureModel::toXml(QDomDocument &document) const
{
auto dom_element = document.createElement(xmlTagName());
//query
auto dom_query = document.createElement("query");
auto dom_query_txt = document.createTextNode(m_query);
dom_query.appendChild(dom_query_txt);
dom_element.appendChild(dom_query);
//header data
QHash<int, QList<int>> horizontal_;
for (auto key : m_header_data.keys()) {
horizontal_.insert(key, m_header_data.value(key).keys()); }
dom_element.appendChild(QETXML::modelHeaderDataToXml(document, this, horizontal_, QHash<int, QList<int>>()));
return dom_element;
}
/**
* @brief NomenclatureModel::fromXml
* Restore the model from xml
* @param element
*/
void NomenclatureModel::fromXml(const QDomElement &element)
{
if (element.tagName() != xmlTagName())
return;
query(element.firstChildElement("query").text());
QETXML::modelHeaderDataFromXml(element.firstChildElement("header_data"), this);
}
/** /**
* @brief NomenclatureModel::dataBaseUpdated * @brief NomenclatureModel::dataBaseUpdated
* slot called when the project database is updated * slot called when the project database is updated
@ -214,9 +256,9 @@ void NomenclatureModel::dataBaseUpdated()
//befor any element, column count return 0, so in this case we emit column inserted //befor any element, column count return 0, so in this case we emit column inserted
if (new_record.size() != m_record.size()) if (new_record.size() != m_record.size())
{ {
emit beginInsertColumns(index(0,0), 0, m_record.size()-1); emit beginResetModel();
m_record = new_record; m_record = new_record;
emit endInsertColumns(); emit endResetModel();
} }
else else
{ {

View File

@ -1,4 +1,4 @@
/* /*
Copyright 2006-2020 QElectroTech Team Copyright 2006-2020 QElectroTech Team
This file is part of QElectroTech. This file is part of QElectroTech.
@ -20,6 +20,7 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QPointer> #include <QPointer>
#include <QDomElement>
class QETProject; class QETProject;
@ -45,6 +46,10 @@ class NomenclatureModel : public QAbstractTableModel
QETProject *project() const; QETProject *project() const;
void autoHeaders(); void autoHeaders();
QDomElement toXml(QDomDocument &document) const;
void fromXml(const QDomElement &element);
static QString xmlTagName() {return QString("nomenclature_model");}
private: private:
void dataBaseUpdated(); void dataBaseUpdated();

View File

@ -17,6 +17,7 @@
*/ */
#include "qetgraphicsheaderitem.h" #include "qetgraphicsheaderitem.h"
#include "qabstractitemmodel.h" #include "qabstractitemmodel.h"
#include "qetxml.h"
#include <QFontMetrics> #include <QFontMetrics>
#include <QPainter> #include <QPainter>
@ -209,6 +210,34 @@ void QetGraphicsHeaderItem::setMargins(const QMargins &margins)
headerDataChanged(Qt::Horizontal, 0,1); headerDataChanged(Qt::Horizontal, 0,1);
} }
/**
* @brief QetGraphicsHeaderItem::toXml
* save the header to xml
* @param document
* @return
*/
QDomElement QetGraphicsHeaderItem::toXml(QDomDocument &document) const
{
auto dom_element = document.createElement(xmlTagName());
dom_element.appendChild(QETXML::marginsToXml(document, m_margin));
return dom_element;
}
/**
* @brief QetGraphicsHeaderItem::fromXml
* Restore the header from xml
* @param element
*/
void QetGraphicsHeaderItem::fromXml(const QDomElement &element)
{
if (element.tagName() != xmlTagName()) {
return;
}
m_margin = QETXML::marginsFromXml(element.firstChildElement("margins"));
}
/** /**
* @brief QetGraphicsHeaderItem::setUpMinimumSectionsSize * @brief QetGraphicsHeaderItem::setUpMinimumSectionsSize
* Setup the minimum section size and height of the item. * Setup the minimum section size and height of the item.

View File

@ -59,6 +59,10 @@ class QetGraphicsHeaderItem : public QGraphicsObject
QVector<int> minimumSectionWidth() const {return m_sections_minimum_width;} QVector<int> minimumSectionWidth() const {return m_sections_minimum_width;}
int minimumWidth() const {return m_minimum_width;} int minimumWidth() const {return m_minimum_width;}
QDomElement toXml (QDomDocument &document) const;
void fromXml(const QDomElement &element);
static QString xmlTagName() {return QString("graphics_header");}
signals: signals:
void sectionResized(int logicalIndex, int size); void sectionResized(int logicalIndex, int size);
void heightResized(); void heightResized();

View File

@ -1,4 +1,4 @@
/* /*
Copyright 2006-2020 QElectroTech Team Copyright 2006-2020 QElectroTech Team
This file is part of QElectroTech. This file is part of QElectroTech.
@ -19,6 +19,9 @@
#include "diagram.h" #include "diagram.h"
#include "qetgraphicsheaderitem.h" #include "qetgraphicsheaderitem.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "qetxml.h"
#include "nomenclaturemodel.h"
#include "elementprovider.h"
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QFontMetrics> #include <QFontMetrics>
@ -55,6 +58,8 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
connect(m_header_item, &QetGraphicsHeaderItem::heightResized, this, [this]() { connect(m_header_item, &QetGraphicsHeaderItem::heightResized, this, [this]() {
m_header_item->setPos(0, 0-m_header_item->rect().height()); m_header_item->setPos(0, 0-m_header_item->rect().height());
}); });
//Init the size of table without a model
setModel();
} }
QetGraphicsTableItem::~QetGraphicsTableItem() QetGraphicsTableItem::~QetGraphicsTableItem()
@ -86,6 +91,10 @@ void QetGraphicsTableItem::setModel(QAbstractItemModel *model)
connect(m_model, &QAbstractItemModel::dataChanged, this, &QetGraphicsTableItem::dataChanged); connect(m_model, &QAbstractItemModel::dataChanged, this, &QetGraphicsTableItem::dataChanged);
connect(m_model, &QAbstractItemModel::modelReset, this, &QetGraphicsTableItem::modelReseted); connect(m_model, &QAbstractItemModel::modelReset, this, &QetGraphicsTableItem::modelReseted);
} }
if (m_next_table) {
m_next_table->setModel(m_model);
}
} }
/** /**
@ -141,7 +150,7 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
painter->restore(); painter->restore();
return; return;
} }
painter->setFont(m_model->data(model()->index(0,0), Qt::FontRole).value<QFont>()); painter->setFont(m_model->data(m_model->index(0,0), Qt::FontRole).value<QFont>());
//Draw vertical lines //Draw vertical lines
auto offset= 0; auto offset= 0;
@ -213,6 +222,7 @@ void QetGraphicsTableItem::setMargins(const QMargins &margins)
*/ */
void QetGraphicsTableItem::setSize(const QSize &size) void QetGraphicsTableItem::setSize(const QSize &size)
{ {
qDebug() << "ici";
auto new_size = size; auto new_size = size;
if (new_size.width() < minimumSize().width()) { if (new_size.width() < minimumSize().width()) {
new_size.setWidth(minimumSize().width()); new_size.setWidth(minimumSize().width());
@ -296,7 +306,8 @@ int QetGraphicsTableItem::displayNRow() const {
*/ */
void QetGraphicsTableItem::setPreviousTable(QetGraphicsTableItem *table) void QetGraphicsTableItem::setPreviousTable(QetGraphicsTableItem *table)
{ {
if (m_previous_table == table) { if (m_previous_table == table ||
this == table) {
return; return;
} }
@ -316,13 +327,6 @@ void QetGraphicsTableItem::setPreviousTable(QetGraphicsTableItem *table)
old_previous_table->nextTable() == this) { old_previous_table->nextTable() == this) {
old_previous_table->setNextTable(nullptr); old_previous_table->setNextTable(nullptr);
} }
//Set the m_model to every next table
auto next_ = m_next_table;
while (next_) {
next_->setModel(m_model);
next_ = next_->nextTable();
}
} }
/** /**
@ -333,7 +337,8 @@ void QetGraphicsTableItem::setPreviousTable(QetGraphicsTableItem *table)
*/ */
void QetGraphicsTableItem::setNextTable(QetGraphicsTableItem *table) void QetGraphicsTableItem::setNextTable(QetGraphicsTableItem *table)
{ {
if (m_next_table == table) { if (m_next_table == table ||
this == table) {
return; return;
} }
@ -393,6 +398,119 @@ void QetGraphicsTableItem::setToMinimumHeight()
setSize(size_); setSize(size_);
} }
void QetGraphicsTableItem::initLink()
{
if (!m_pending_previous_table_uuid.isNull())
{
ElementProvider provider_(this->diagram());
if (auto previous_table = provider_.tableFromUuid(m_pending_previous_table_uuid)) {
setPreviousTable(previous_table);
}
m_pending_previous_table_uuid = QUuid(); //Set to null in case initLink is called again
}
setSize(m_pending_size);
}
/**
* @brief QetGraphicsTableItem::toXml
* Save the table to xml
* @param dom_document : parent document
* @return the dom_element that describe the table
*/
QDomElement QetGraphicsTableItem::toXml(QDomDocument &dom_document) const
{
auto dom_table = dom_document.createElement(xmlTagName());
dom_table.setAttribute("x", QString::number(pos().x()));
dom_table.setAttribute("y", QString::number(pos().y()));
dom_table.setAttribute("width", QString::number(m_current_size.width()));
dom_table.setAttribute("height", QString::number(m_current_size.height()));
dom_table.setAttribute("uuid", m_uuid.toString());
dom_table.setAttribute("name", m_name);
dom_table.setAttribute("display_n_row", QString::number(m_number_of_displayed_row));
//Add the header xml
dom_table.appendChild(m_header_item->toXml(dom_document));
//Add previous table, the model is save by the previous table
if (m_previous_table)
{
auto dom_previous_table = dom_document.createElement("previous_table");
dom_previous_table.setAttribute("uuid", m_previous_table->m_uuid.toString());
dom_table.appendChild(dom_previous_table);
}
else if (m_model) //There is not a previous table, we need to save the model
{
//Add cell properties
auto dom_cell = dom_document.createElement("cell");
dom_cell.setAttribute("font", m_model->data(m_model->index(0,0), Qt::FontRole).toString());
auto me = QMetaEnum::fromType<Qt::Alignment>();
dom_cell.setAttribute("alignment", me.valueToKey(m_model->data(m_model->index(0,0), Qt::TextAlignmentRole).toInt()));
dom_cell.appendChild(QETXML::marginsToXml(dom_document, m_margin));
dom_table.appendChild(dom_cell);
//Add model
auto dom_model = dom_document.createElement("model");
auto nomenclature_model = static_cast<NomenclatureModel *>(m_model);
dom_model.appendChild(nomenclature_model->toXml(dom_document));
dom_table.appendChild(dom_model);
}
return dom_table;
}
/**
* @brief QetGraphicsTableItem::fromXml
* Restore the table from xml.
* Make this item is already in a diagram to
* @param dom_element
*/
void QetGraphicsTableItem::fromXml(const QDomElement &dom_element)
{
if (dom_element.tagName() != xmlTagName()) {
return;
}
this->setPos(dom_element.attribute("x", QString::number(10)).toDouble(),
dom_element.attribute("y", QString::number(10)).toDouble());
//Size is not set now because will change during the whole process of opening a project from the xml
m_pending_size = QSize(dom_element.attribute("width", QString::number(no_model_width)).toInt(),
dom_element.attribute("height", QString::number(no_model_height)).toInt());
m_uuid = QUuid(dom_element.attribute("uuid", QUuid::createUuid().toString()));
m_name = dom_element.attribute("name");
m_number_of_displayed_row = dom_element.attribute("display_n_row", QString::number(0)).toInt();
m_margin = QETXML::marginsFromXml(dom_element.firstChildElement("margins"));
auto vector_ = QETXML::directChild(dom_element, "previous_table");
if (vector_.size()) { //Table have a previous table
m_pending_previous_table_uuid = QUuid(vector_.first().attribute("uuid"));
}
else if (this->diagram()) //The table haven't got a previous table, so there should be a model save to xml
{
//Get table
auto model_ = new NomenclatureModel(this->diagram()->project(), this->diagram()->project());
model_->fromXml(dom_element.firstChildElement("model").firstChildElement(NomenclatureModel::xmlTagName()));
this->setModel(model_);
//Get cell properties
auto dom_cell = dom_element.firstChildElement("cell");
//font
QFont font_;
font_.fromString(dom_cell.attribute("font"));
m_model->setData(m_model->index(0,0), font_, Qt::FontRole);
//alignment
auto me = QMetaEnum::fromType<Qt::Alignment>();
m_model->setData(m_model->index(0,0), me.keyToValue(dom_cell.attribute("alignment").toStdString().data()));
dom_cell.setAttribute("alignment", me.valueToKey(m_model->data(m_model->index(0,0), Qt::TextAlignmentRole).toInt()));
//margins
m_margin = QETXML::marginsFromXml(dom_cell.firstChildElement("margins"));
}
//Restore the header from xml
m_header_item->fromXml(dom_element.firstChildElement(QetGraphicsHeaderItem::xmlTagName()));
}
/** /**
* @brief QetGraphicsTableItem::hoverEnterEvent * @brief QetGraphicsTableItem::hoverEnterEvent
* Reimplemented from QetGraphicsItem * Reimplemented from QetGraphicsItem

View File

@ -74,6 +74,12 @@ class QetGraphicsTableItem : public QetGraphicsItem
QetGraphicsTableItem *previousTable() const; QetGraphicsTableItem *previousTable() const;
QetGraphicsTableItem *nextTable() const; QetGraphicsTableItem *nextTable() const;
void setToMinimumHeight(); void setToMinimumHeight();
void initLink();
QUuid uuid() const {return m_uuid;}
QDomElement toXml(QDomDocument &dom_document) const;
void fromXml(const QDomElement &dom_element);
static QString xmlTagName() {return QString("graphics_table");}
protected: protected:
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
@ -103,7 +109,8 @@ class QetGraphicsTableItem : public QetGraphicsItem
int m_minimum_row_height; int m_minimum_row_height;
int m_number_of_displayed_row = 0; int m_number_of_displayed_row = 0;
QSize m_current_size, QSize m_current_size,
m_old_size; m_old_size,
m_pending_size;
int m_br_margin= 10; int m_br_margin= 10;
QRectF m_bounding_rect; QRectF m_bounding_rect;
@ -115,6 +122,8 @@ class QetGraphicsTableItem : public QetGraphicsItem
*m_next_table = nullptr; *m_next_table = nullptr;
QString m_name; QString m_name;
QUuid m_uuid = QUuid::createUuid(),
m_pending_previous_table_uuid;
}; };
#endif // QetGraphicsTableItem_H #endif // QetGraphicsTableItem_H

View File

@ -86,7 +86,7 @@ DynamicElementTextItem::DynamicElementTextItem()
*/ */
QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const
{ {
QDomElement root_element = dom_doc.createElement(xmlTaggName()); QDomElement root_element = dom_doc.createElement(xmlTagName());
root_element.setAttribute("x", QString::number(pos().x())); root_element.setAttribute("x", QString::number(pos().x()));
root_element.setAttribute("y", QString::number(pos().y())); root_element.setAttribute("y", QString::number(pos().y()));
@ -153,7 +153,7 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const
*/ */
void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt)
{ {
if (dom_elmt.tagName() != xmlTaggName()) { if (dom_elmt.tagName() != xmlTagName()) {
qDebug() << "DynamicElementTextItem::fromXml : Wrong tagg name"; qDebug() << "DynamicElementTextItem::fromXml : Wrong tagg name";
return; return;
} }

View File

@ -91,7 +91,7 @@ class DynamicElementTextItem : public DiagramTextItem
void setTextFrom (DynamicElementTextItem::TextFrom text_from); void setTextFrom (DynamicElementTextItem::TextFrom text_from);
QString text() const; QString text() const;
void setText(const QString &text); void setText(const QString &text);
static QString xmlTaggName() {return QString("dynamic_elmt_text");} static QString xmlTagName() {return QString("dynamic_elmt_text");}
void setInfoName(const QString &info_name); void setInfoName(const QString &info_name);
QString infoName() const; QString infoName() const;
void setCompositeText(const QString &text); void setCompositeText(const QString &text);

View File

@ -555,7 +555,7 @@ DynamicElementTextItem *Element::parseDynamicText(const QDomElement &dom_element
//and the uuid (because the uuid, is the uuid of the descritpion and not the uuid of instantiated dynamic text field) //and the uuid (because the uuid, is the uuid of the descritpion and not the uuid of instantiated dynamic text field)
QDomElement dom(dom_element.cloneNode(true).toElement()); QDomElement dom(dom_element.cloneNode(true).toElement());
dom.setTagName(DynamicElementTextItem::xmlTaggName()); dom.setTagName(DynamicElementTextItem::xmlTagName());
deti->fromXml(dom); deti->fromXml(dom);
deti->m_uuid = QUuid::createUuid(); deti->m_uuid = QUuid::createUuid();
this->addDynamicTextItem(deti); this->addDynamicTextItem(deti);
@ -741,7 +741,7 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool
//************************// //************************//
//***Dynamic texts item***// //***Dynamic texts item***//
//************************// //************************//
for (const QDomElement& qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTaggName())) for (const QDomElement& qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTagName()))
{ {
DynamicElementTextItem *deti = new DynamicElementTextItem(this); DynamicElementTextItem *deti = new DynamicElementTextItem(this);
addDynamicTextItem(deti); addDynamicTextItem(deti);

View File

@ -1391,6 +1391,9 @@ void QETProject::readDiagramsXml(QDomDocument &xml_project)
"Mise en place des références croisées" "Mise en place des références croisées"
"</p>")); "</p>"));
} }
m_data_base.updateDB(); //All diagrams and items are created we need to update the database
for(Diagram *d : diagrams()) for(Diagram *d : diagrams())
{ {
if(dlgWaiting) if(dlgWaiting)

View File

@ -17,8 +17,10 @@
*/ */
#include "qetxml.h" #include "qetxml.h"
#include "nameslist.h" #include "nameslist.h"
#include <QPen> #include <QPen>
#include <QDir> #include <QDir>
#include <QFont>
/** /**
* @brief QETXML::penToXml * @brief QETXML::penToXml
@ -72,8 +74,10 @@ QPen QETXML::penFromXml(const QDomElement &element)
else if (style == "DotLine") pen.setStyle(Qt::DotLine); else if (style == "DotLine") pen.setStyle(Qt::DotLine);
else if (style == "DashDotLine") pen.setStyle(Qt::DashDotLine); else if (style == "DashDotLine") pen.setStyle(Qt::DashDotLine);
else if (style == "DashDotDotLine") pen.setStyle(Qt::DashDotDotLine); else if (style == "DashDotDotLine") pen.setStyle(Qt::DashDotDotLine);
else if (style == "CustomDashLine") pen.setStyle(Qt::CustomDashLine), else if (style == "CustomDashLine") {
pen.setDashPattern( QVector<qreal>() << 10 << 10 ); pen.setStyle(Qt::CustomDashLine);
pen.setDashPattern( QVector<qreal>() << 10 << 10 );
}
else pen.setStyle(Qt::DashLine); else pen.setStyle(Qt::DashLine);
pen.setColor(QColor(element.attribute("color", "#000000"))); pen.setColor(QColor(element.attribute("color", "#000000")));
@ -274,3 +278,197 @@ QDomElement QETXML::textToDomElement(QDomDocument &document, const QString& tag_
element.appendChild(text); element.appendChild(text);
return element; return element;
} }
/**
* @brief QETXML::directChild
* @param element
* @param tag_name
* @return All direct child of @element with the tag name @tag_name
*/
QVector<QDomElement> QETXML::directChild(const QDomElement &element, const QString &tag_name)
{
QVector<QDomElement> return_list;
for (QDomNode node = element.firstChild() ; !node.isNull() ; node = node.nextSibling())
{
if (!node.isElement()) continue;
QDomElement element = node.toElement();
if (element.isNull() || element.tagName() != tag_name) continue;
return_list << element;
}
return(return_list);
}
/**
* @brief QETXML::subChild
* @param element
* @param parent_tag_name
* @param children_tag_name
* @return When given an xml dom element @element,
* returns a vector of all children dom_elements tagged @children_tag_name
* nested in the parent dom elements tagged parent_tag_name, themselves children of the dom element @element.
*/
QVector<QDomElement> QETXML::subChild(const QDomElement &element, const QString parent_tag_name, const QString &children_tag_name)
{
QVector<QDomElement> return_list;
for (QDomNode child = element.firstChild() ; !child.isNull() ; child = child.nextSibling())
{
QDomElement parents = child.toElement();
if (parents.isNull() || parents.tagName() != parent_tag_name)
continue;
for (QDomNode node_children = parents.firstChild() ; !node_children.isNull() ; node_children = node_children.nextSibling())
{
QDomElement n_children = node_children.toElement();
if (!n_children.isNull() && n_children.tagName() == children_tag_name)
return_list.append(n_children);
}
}
return(return_list);
}
/**
* @brief QETXML::marginsToXml
* Save a QMargins to xml. the xml tag name is 'margins'
* @param parent_document
* @param margins
* @return
*/
QDomElement QETXML::marginsToXml(QDomDocument &parent_document, const QMargins &margins)
{
auto dom_ = parent_document.createElement("margins");
auto text_ = parent_document.createTextNode(QString::number(margins.left()) + QString(";") +
QString::number(margins.top()) + QString(";") +
QString::number(margins.right()) + QString(";") +
QString::number(margins.bottom()));
dom_.appendChild(text_);
return dom_;
}
/**
* @brief QETXML::marginsFromXml
* @param element
* @return a QMargins from an xml description.
* The tag name must ne 'margins'
*/
QMargins QETXML::marginsFromXml(const QDomElement &element)
{
if (element.tagName() != "margins") {
return QMargins();
}
auto margins_ = element.text().split(";");
if (margins_.size() == 4) {
return QMargins(margins_.at(0).toInt(), margins_.at(1).toInt(), margins_.at(2).toInt(), margins_.at(3).toInt());
} else {
return QMargins();
}
}
/**
* @brief QETXML::modelHeaderDataToXml
* Save to xml element all header data specified by @horizontal_section_role and @vertical_section_role
* @param parent_document
* @param model
* @param horizontal_section_role : key as header section and value as list of roles to save in xml
* @param vertical_section_role :key as header section and value as list of roles to save in xml
* @return
*/
QDomElement QETXML::modelHeaderDataToXml(QDomDocument &parent_document, const QAbstractItemModel *model, QHash<int, QList<int>> horizontal_section_role, QHash<int, QList<int>> vertical_section_role)
{
auto dom_element = parent_document.createElement("header_data");
auto orientation_ = Qt::Horizontal;
auto data_hash = horizontal_section_role;
auto meta_enum_ori = QMetaEnum::fromType<Qt::Orientation>();
auto meta_enum_role = QMetaEnum::fromType<Qt::ItemDataRole>();
//Iterate twice, first for horizontal header and second to vertical header
while (true)
{
for (auto section : data_hash.keys())
{
for (auto role : data_hash.value(section))
{
auto variant = model->headerData(section, orientation_, role);
if (variant.isValid())
{
auto dom_data = parent_document.createElement("data");
dom_data.setAttribute("section", QString::number(section));
dom_data.setAttribute("orientation", meta_enum_ori.valueToKey(orientation_));
dom_data.setAttribute("role", meta_enum_role.valueToKey(role));
auto text_node = parent_document.createTextNode("");
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole || role == Qt::StatusTipRole || role == Qt::WhatsThisRole)
{
text_node.setData(variant.toString());
}
else if (role == Qt::FontRole)
{
auto font = variant.value<QFont>();
text_node.setData(font.toString());
}
else if (role == Qt::TextAlignmentRole)
{
auto me = QMetaEnum::fromType<Qt::Alignment>();
text_node.setData(me.valueToKey(variant.toInt()));
}
dom_data.appendChild(text_node);
dom_element.appendChild(dom_data);
}
}
}
if(orientation_ == Qt::Vertical) {
break;
} else {
data_hash = vertical_section_role;
orientation_ = Qt::Vertical;
}
}
return dom_element;
}
/**
* @brief QETXML::modelHeaderDataFromXml
* Restore from xml modele header data
* @param element
* @param model
*/
void QETXML::modelHeaderDataFromXml(const QDomElement &element, QAbstractItemModel *model)
{
if (element.tagName() != "header_data")
return;
auto meta_enum_orientation = QMetaEnum::fromType<Qt::Orientations>();
auto meta_enum_role = QMetaEnum::fromType<Qt::ItemDataRole>();
for (auto child : QETXML::directChild(element, "data"))
{
auto section_ = child.attribute("section", "-1").toInt();
auto orientation_ = Qt::Orientation(meta_enum_orientation.keyToValue(child.attribute("orientation", "Horizontal").toStdString().data()));
auto role_ = meta_enum_role.keyToValue(child.attribute("role", "DisplayRole").toStdString().data());
auto text_ = child.text();
QVariant data_;
if (role_ == Qt::DisplayRole || role_ == Qt::EditRole || role_ == Qt::ToolTipRole || role_ == Qt::StatusTipRole || role_ == Qt::WhatsThisRole) {
data_ = text_;
}
else if (role_ == Qt::FontRole)
{
QFont font;
font.fromString(text_);
data_ = font;
}
else if (role_ == Qt::TextAlignmentRole)
{
auto me = QMetaEnum::fromType<Qt::Alignment>();
data_ = me.keyToValue(text_.toStdString().data());
}
model->setHeaderData(section_, orientation_, data_, role_);
}
}

View File

@ -1,4 +1,4 @@
/* /*
Copyright 2006-2019 The QElectroTech Team Copyright 2006-2019 The QElectroTech Team
This file is part of QElectroTech. This file is part of QElectroTech.
@ -24,6 +24,7 @@
class QDomDocument; class QDomDocument;
class QDir; class QDir;
class QFile; class QFile;
class QAbstractItemModel;
/** /**
*This namespace contain some function to use xml with QET. *This namespace contain some function to use xml with QET.
@ -42,6 +43,15 @@ namespace QETXML
bool writeXmlFile(const QDomDocument &xml_document, const QString &file_path, QString *error_message = nullptr); bool writeXmlFile(const QDomDocument &xml_document, const QString &file_path, QString *error_message = nullptr);
QDomElement textToDomElement (QDomDocument &document, const QString& tag_name, const QString& value); QDomElement textToDomElement (QDomDocument &document, const QString& tag_name, const QString& value);
QVector <QDomElement> directChild(const QDomElement &element, const QString &tag_name);
QVector <QDomElement> subChild(const QDomElement &element, const QString parent_tag_name, const QString &children_tag_name);
QDomElement marginsToXml (QDomDocument &parent_document, const QMargins &margins);
QMargins marginsFromXml(const QDomElement &element);
QDomElement modelHeaderDataToXml(QDomDocument &parent_document, const QAbstractItemModel *model, QHash<int, QList<int>> horizontal_section_role, QHash<int, QList<int>> vertical_section_role);
void modelHeaderDataFromXml(const QDomElement &element, QAbstractItemModel *model);
} }
#endif // QETXML_H #endif // QETXML_H