1-Use the "implicite shared" of Qt for the QPicture and QPixmap of element (https://doc.qt.io/qt-5/implicit-sharing.html).

This avoid to parse the same element definition each time user drop the same element in the diagram.
Only the first element build the picture, all other get the created picture which is shared.

2- For use the "implicite shared" QPicture and QPixmap of element, now this isn't the element who build her picture, but a dedicated class who made only this job : build the QPicture and QPixmap of elements.

3- With the two previous novelty, the class CustomElement and GhostElement are became useless, and so was removed.
Some few member function of CustomElement was moved to Element.


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5492 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2018-08-23 19:41:58 +00:00
parent 1d871e0625
commit e6d73977c1
30 changed files with 1250 additions and 1712 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef CUSTOM_ELEMENT_H
#define CUSTOM_ELEMENT_H
#include "element.h"
#include "nameslist.h"
#include "elementslocation.h"
#include <QPicture>
class Terminal;
/**
This class represents an electrical element; it may be used like a fixed
element, the difference being that the CustomElement reads its description
(names, drawing, behavior) from an XML document.
*/
class CustomElement : public Element
{
Q_OBJECT
// constructors, destructor
public:
CustomElement (const ElementsLocation &, QGraphicsItem * = nullptr, int * = nullptr);
~CustomElement() override;
private:
CustomElement(const CustomElement &);
// attributes
protected:
NamesList names;
ElementsLocation location_;
QPicture drawing;
QPicture low_zoom_drawing;
QList<Terminal *> m_terminals;
QList<DynamicElementTextItem *> m_dynamic_texts;
bool forbid_antialiasing;
QList<QLineF *> m_lines;
QList<QRectF *> m_rectangles;
QList<QRectF *> m_circles;
QList<QVector<QPointF> *> m_polygons;
QList<QVector<qreal> *> m_arcs;
// methods
public:
QList<Terminal *> terminals() const override;
QList<Conductor *> conductors() const override;
QList<QLineF *> lines() const override;
QList<QRectF *> rectangles() const override;
QList<QRectF *> circles() const override;
QList<QVector<QPointF> *> polygons() const override;
QList<QVector<qreal> *> arcs() const override;
void paint(QPainter *, const QStyleOptionGraphicsItem *) override;
QString typeId() const override;
ElementsLocation location() const;
QString name() const override;
protected:
virtual bool buildFromXml(const QDomElement &, int * = nullptr);
virtual bool parseElement(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseLine(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseRect(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseEllipse(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseCircle(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseArc(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parsePolygon(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseText(QDomElement &, QPainter &, bool addtolist = true);
virtual bool parseInput(QDomElement &);
virtual DynamicElementTextItem *parseDynamicText(QDomElement &);
virtual Terminal *parseTerminal(QDomElement &);
virtual void setQPainterAntiAliasing(QPainter &, bool);
virtual bool validOrientationAttribute(const QDomElement &);
virtual void setPainterStyle(QDomElement &, QPainter &);
};
/**
@return The element type ID; considering a CustomElement, this means the
@location of its XML description.
@see location()
*/
inline QString CustomElement::typeId() const {
return(location_.path());
}
/**
@return the location of the XML document describing this element.
*/
inline ElementsLocation CustomElement::location() const {
return(location_);
}
/**
@return The name of this element.
*/
inline QString CustomElement::name() const {
return(names.name(location_.baseName()));
}
#endif

View File

@@ -38,7 +38,7 @@ class DynamicElementTextItem : public DiagramTextItem
{
friend class DynamicTextItemDelegate;
friend class CompositeTextEditDialog;
friend class CustomElement;
friend class Element;
Q_OBJECT

View File

@@ -31,6 +31,8 @@
#include "changeelementinformationcommand.h"
#include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "elementpicturefactory.h"
#include "iostream"
class ElementXmlRetroCompatibility
{
@@ -62,15 +64,38 @@ class ElementXmlRetroCompatibility
};
/**
Constructeur pour un element sans scene ni parent
*/
Element::Element(QGraphicsItem *parent) :
* @brief Element::Element
* @param location, location of this element
* @param parent, parent graphics item
* @param state, state of the instanciation
*/
Element::Element(const ElementsLocation &location, QGraphicsItem *parent, int *state) :
QetGraphicsItem(parent),
must_highlight_(false),
m_mouse_over(false)
m_location (location)
{
if(! (location.isElement() && location.exist()))
{
if (state)
{
*state = 1;
return;
}
}
int elmt_state;
buildFromXml(location.xml(), &elmt_state);
if (state) {
*state = elmt_state;
}
if (elmt_state) {
return;
}
if (state) {
*state = 0;
}
setPrefix(autonum::elementPrefixForLocation(location));
m_link_type = Simple;
uuid_ = QUuid::createUuid();
m_uuid = QUuid::createUuid();
setZValue(10);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptHoverEvents(true);
@@ -85,11 +110,37 @@ Element::Element(QGraphicsItem *parent) :
}
/**
Destructeur
*/
* @brief Element::~Element
*/
Element::~Element()
{
qDeleteAll(m_dynamic_text_list);
qDeleteAll (m_dynamic_text_list);
qDeleteAll (m_terminals);
}
/**
* @brief Element::terminals
* @return the list of terminals of this element.
*/
QList<Terminal *> Element::terminals() const {
return m_terminals;
}
/**
* @brief Element::conductors
* @return The list of conductors docked to this element
* the list is sorted according to the position of the terminal where the conductor is docked
* from top to bottom, and left to right.
*/
QList<Conductor *> Element::conductors() const
{
QList<Conductor *> conductors;
for (Terminal *t : m_terminals) {
conductors << t -> conductors();
}
return(conductors);
}
void Element::editProperty()
@@ -106,20 +157,11 @@ void Element::editProperty()
}
}
/**
@return true si l'element est mis en evidence
*/
bool Element::isHighlighted() const {
return(must_highlight_);
}
/**
@param hl true pour mettre l'element en evidence, false sinon
*/
void Element::setHighlighted(bool hl) {
must_highlight_ = hl;
m_must_highlight = hl;
update();
}
@@ -142,14 +184,20 @@ void Element::displayHelpLine(bool b)
*/
void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *)
{
if (must_highlight_) drawHighlight(painter, options);
if (m_must_highlight) {
drawHighlight(painter, options);
}
//Draw the element himself
paint(painter, options);
if (options && options -> levelOfDetail < 1.0) {
painter->drawPicture(0, 0, m_low_zoom_picture);
} else {
painter->drawPicture(0, 0, m_picture);
}
//Draw the selection rectangle
if ( isSelected() || m_mouse_over ) drawSelection(painter, options);
if ( isSelected() || m_mouse_over ) {
drawSelection(painter, options);
}
}
/**
@@ -160,20 +208,20 @@ QRectF Element::boundingRect() const {
}
/**
Definit la taille de l'element sur le schema. Les tailles doivent etre
des multiples de 10 ; si ce n'est pas le cas, les dimensions indiquees
seront arrrondies aux dizaines superieures.
@param wid Largeur de l'element
@param hei Hauteur de l'element
@return La taille finale de l'element
*/
QSize Element::setSize(int wid, int hei) {
* @brief Element::setSize
* Define the size of the element.
* The size must be a multiple of 10.
* If not, the dimensions indicated will be arrrondies to higher tens.
* @param wid
* @param hei
*/
void Element::setSize(int wid, int hei)
{
prepareGeometryChange();
// chaque dimension indiquee est arrondie a la dizaine superieure
while (wid % 10) ++ wid;
while (hei % 10) ++ hei;
// les dimensions finales sont conservees et retournees
return(dimensions = QSize(wid, hei));
dimensions = QSize(wid, hei);
}
/**
@@ -209,25 +257,11 @@ QPoint Element::hotspot() const {
}
/**
Selectionne l'element
*/
void Element::select() {
setSelected(true);
}
/**
Deselectionne l'element
*/
void Element::deselect() {
setSelected(false);
}
/**
@return La pixmap de l'element
*/
* @brief Element::pixmap
* @return the pixmap of this element
*/
QPixmap Element::pixmap() {
if (preview.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
return(preview);
return ElementPictureFactory::instance()->pixmap(m_location);
}
/*** Methodes protegees ***/
@@ -301,20 +335,274 @@ void Element::drawHighlight(QPainter *painter, const QStyleOptionGraphicsItem *o
}
/**
Fonction initialisant et dessinant la pixmap de l'element.
*/
void Element::updatePixmap() {
// Pixmap transparente faisant la taille de base de l'element
preview = QPixmap(dimensions);
preview.fill(QColor(255, 255, 255, 0));
// QPainter sur la pixmap, avec antialiasing
QPainter p(&preview);
p.setRenderHint(QPainter::Antialiasing, true);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
// Translation de l'origine du repere de la pixmap
p.translate(hotspot_coord);
// L'element se dessine sur la pixmap
paint(&p, nullptr);
* @brief Element::buildFromXml
* Build this element from an xml description
* @param xml_def_elmt
* @param state
* Optional pointer which define the status of build
* 0 - evreything all right
* 4 - xml isn't a "definition"
* 5 - attribute of the definition isn't present or valid
* 6 - the definition is empty
* 7 - parsing of a xml node who describe a graphical part failed.
* 8 - No part of the drawing could be loaded
* @return
*/
bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state)
{
m_state = QET::GIBuildingFromXml;
if (xml_def_elmt.tagName() != "definition" || xml_def_elmt.attribute("type") != "element")
{
if (state) *state = 4;
m_state = QET::GIOK;
return(false);
}
//Check if the curent version can read the xml description
if (xml_def_elmt.hasAttribute("version"))
{
bool conv_ok;
qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok);
if (conv_ok && QET::version.toDouble() < element_version)
{
std::cerr << qPrintable(
QObject::tr("Avertissement : l'élément "
" a été enregistré avec une version"
" ultérieure de QElectroTech.")
) << std::endl;
}
}
//This attribute must be present and valid
int w, h, hot_x, hot_y;
if (
!QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("height"), &h) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_x"), &hot_x) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_y"), &hot_y)
) {
if (state) *state = 5;
m_state = QET::GIOK;
return(false);
}
setSize(w, h);
setHotspot(QPoint(hot_x, hot_y));
//the definition must have childs
if (xml_def_elmt.firstChild().isNull())
{
if (state) *state = 6;
m_state = QET::GIOK;
return(false);
}
//Extract the names
m_names.fromXml(xml_def_elmt);
setToolTip(name());
//load kind informations
m_kind_informations.fromXml(xml_def_elmt.firstChildElement("kindInformations"), "kindInformation");
//load element information
m_element_informations.fromXml(xml_def_elmt.firstChildElement("elementInformations"), "elementInformation");
//scroll of the Children of the Definition: Parts of the Drawing
int parsed_elements_count = 0;
for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling())
{
QDomElement elmts = node.toElement();
if (elmts.isNull())
continue;
if (elmts.tagName() == "description")
{
//Minor workaround to find if there is a "input" tagg as label.
//If not, we set the tagg "label" to the first "input.
QList <QDomElement> input_field;
bool have_label = false;
for (QDomElement input_node = node.firstChildElement("input") ; !input_node.isNull() ; input_node = input_node.nextSiblingElement("input"))
{
if (!input_node.isNull())
{
input_field << input_node;
if (input_node.attribute("tagg", "none") == "label")
have_label = true;
}
}
if(!have_label && !input_field.isEmpty())
input_field.first().setAttribute("tagg", "label");
//Parse the definition
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling())
{
QDomElement qde = n.toElement();
if (qde.isNull())
continue;
if (parseElement(qde)) {
++ parsed_elements_count;
}
else
{
if (state)
*state = 7;
m_state = QET::GIOK;
return(false);
}
}
}
}
ElementPictureFactory *epf = ElementPictureFactory::instance();
epf->getPictures(m_location, const_cast<QPicture&>(m_picture), const_cast<QPicture&>(m_low_zoom_picture));
if(!m_picture.isNull())
++ parsed_elements_count;
//They must be at least one parsed graphics part
if (!parsed_elements_count)
{
if (state)
*state = 8;
m_state = QET::GIOK;
return(false);
}
else
{
if (state)
*state = 0;
m_state = QET::GIOK;
return(true);
}
}
/**
* @brief Element::parseElement
* Parse the element of the xml description of this element
* @param dom
* @return
*/
bool Element::parseElement(const QDomElement &dom)
{
if (dom.tagName() == "terminal") return(parseTerminal(dom));
else if (dom.tagName() == "input") return(parseInput(dom));
else if (dom.tagName() == "dynamic_text") return(parseDynamicText(dom));
else return(true);
}
/**
* @brief Element::parseInput
* Parse the input (old text field)
* the parsed input are converted to dynamic text field, this function
* is only here to keep compatibility with old text.
* @param dom_element
* @return
*/
bool Element::parseInput(const QDomElement &dom_element)
{
qreal pos_x, pos_y;
int size;
if (
!QET::attributeIsAReal(dom_element, "x", &pos_x) ||\
!QET::attributeIsAReal(dom_element, "y", &pos_y) ||\
!QET::attributeIsAnInteger(dom_element, "size", &size)
) return(false);
else
{
DynamicElementTextItem *deti = new DynamicElementTextItem(this);
deti->setText(dom_element.attribute("text", "_"));
deti->setFontSize(dom_element.attribute("size", QString::number(9)).toInt());
deti->setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble());
if(dom_element.attribute("tagg", "none") != "none")
{
deti->setTextFrom(DynamicElementTextItem::ElementInfo);
deti->setInfoName(dom_element.attribute("tagg"));
}
//the origin transformation point of PartDynamicTextField is the top left corner, no matter the font size
//The origin transformation point of ElementTextItem is the middle of left edge, and so by definition, change with the size of the font
//We need to use a QMatrix to find the pos of this text from the saved pos of text item
QMatrix matrix;
//First make the rotation
matrix.rotate(dom_element.attribute("rotation", "0").toDouble());
QPointF pos = matrix.map(QPointF(0, -deti->boundingRect().height()/2));
matrix.reset();
//Second translate to the pos
QPointF p(dom_element.attribute("x", QString::number(0)).toDouble(),
dom_element.attribute("y", QString::number(0)).toDouble());
matrix.translate(p.x(), p.y());
deti->setPos(matrix.map(pos));
m_converted_text_from_xml_description.insert(deti, p);
return true;
}
return false;
}
/**
* @brief Element::parseDynamicText
* Create the dynamic text field describ in @dom_element
* @param dom_element
* @return
*/
DynamicElementTextItem *Element::parseDynamicText(const QDomElement &dom_element)
{
DynamicElementTextItem *deti = new DynamicElementTextItem(this);
//Because the xml description of a .elmt file is the same as how a dynamic text field is save to xml in a .qet file
//wa call fromXml, we just change the tagg name (.elmt = dynamic_text, .qet = dynamic_elmt_text)
//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());
dom.setTagName(DynamicElementTextItem::xmlTaggName());
deti->fromXml(dom);
deti->m_uuid = QUuid::createUuid();
this->addDynamicTextItem(deti);
return deti;
}
Terminal *Element::parseTerminal(const QDomElement &dom_element)
{
qreal terminalx, terminaly;
Qet::Orientation terminalo;
if (!QET::attributeIsAReal(dom_element, QString("x"), &terminalx)) {
return(nullptr);
}
if (!QET::attributeIsAReal(dom_element, QString("y"), &terminaly)) {
return(nullptr);
}
if (!dom_element.hasAttribute("orientation")) {
return(nullptr);
}
if (dom_element.attribute("orientation") == "n") {
terminalo = Qet::North;
}
else if (dom_element.attribute("orientation") == "s") {
terminalo = Qet::South;
}
else if (dom_element.attribute("orientation") == "e") {
terminalo = Qet::East;
}
else if (dom_element.attribute("orientation") == "w") {
terminalo = Qet::West;
}
else {
return(nullptr);
}
Terminal *new_terminal = new Terminal(terminalx, terminaly, terminalo, this);
m_terminals << new_terminal;
//Sort from top to bottom and left to rigth
std::sort(m_terminals.begin(), m_terminals.end(), [](Terminal *a, Terminal *b)
{
if(a->dockConductor().y() == b->dockConductor().y())
return (a->dockConductor().x() < b->dockConductor().x());
else
return (a->dockConductor().y() < b->dockConductor().y());
});
return(new_terminal);
}
/**
@@ -413,7 +701,7 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool
foreach (QDomElement qdo, uuid_list) tmp_uuids_link << qdo.attribute("uuid");
//uuid of this element
uuid_= QUuid(e.attribute("uuid", QUuid::createUuid().toString()));
m_uuid= QUuid(e.attribute("uuid", QUuid::createUuid().toString()));
//load prefix
m_prefix = e.attribute("prefix");
@@ -726,7 +1014,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table
QDomElement element = document.createElement("element");
// type
element.setAttribute("type", typeId());
element.setAttribute("type", m_location.path());
// uuid
element.setAttribute("uuid", uuid().toString());
@@ -1258,3 +1546,15 @@ void Element::freezeNewAddedElement() {
}
else return;
}
/**
* @brief Element::name
* @return the human name of this element
*/
QString Element::name() const {
return m_names.name(m_location.baseName());
}
ElementsLocation Element::location() const {
return m_location;
}

View File

@@ -22,13 +22,15 @@
#include "qetgraphicsitem.h"
#include "diagramcontext.h"
#include "assignvariables.h"
#include "elementslocation.h"
#include "nameslist.h"
#include <algorithm>
#include <QPicture>
class QETProject;
class Terminal;
class Conductor;
class NumerotationContext;
class DiagramTextItem;
class DynamicElementTextItem;
class ElementTextItemGroup;
@@ -43,7 +45,7 @@ class Element : public QetGraphicsItem
// constructors, destructor
public:
Element(QGraphicsItem * = nullptr);
Element(const ElementsLocation &location, QGraphicsItem * = nullptr, int *state = nullptr);
~Element() override;
private:
Element(const Element &);
@@ -68,54 +70,7 @@ class Element : public QetGraphicsItem
Master = 8,
Slave = 16,
Terminale = 32};
private:
QSize dimensions;
QPoint hotspot_coord;
QPixmap preview;
// methods
public:
/// @return the list of terminals for this element
virtual QList<Terminal *> terminals() const = 0;
/// @return the list of conductors attached to this element
virtual QList<Conductor *> conductors() const = 0;
/// @return the list of lines items in this element
virtual QList<QLineF *> lines() const = 0;
/// @return the list of rectangles items in this element
virtual QList<QRectF *> rectangles() const = 0;
/// @return the list of bounding rectangles for circles items in this element
virtual QList<QRectF *> circles() const = 0;
/// @return the list of polygons in this element
virtual QList<QVector<QPointF> *> polygons() const = 0;
/// @return the list of arcs in this element
virtual QList<QVector<qreal> *> arcs() const = 0;
QList <QPair <Terminal *, Terminal *> > AlignedFreeTerminals () const;
/**
*related method and attributes,
*about none graphic thing
*like the linked element or information about this element
*/
//METHODS related to linked element
public:
bool isFree () const;
virtual void linkToElement (Element *) {}
virtual void unlinkAllElements () {}
virtual void unlinkElement (Element *) {}
virtual void initLink (QETProject *);
QList<Element *> linkedElements ();
virtual kind linkType() const {return m_link_type;} // @return the linkable type
void newUuid() {uuid_ = QUuid::createUuid();} //create new uuid for this element
//ATTRIBUTES related to linked element
protected:
QList <Element *> connected_elements;
QList <QUuid> tmp_uuids_link;
QUuid uuid_;
kind m_link_type;
signals:
void linkedElementChanged(); //This signal is emited when the linked elements with this element change
void elementInfoChange(DiagramContext old_info, DiagramContext new_info);
@@ -126,8 +81,13 @@ class Element : public QetGraphicsItem
void textAddedToGroup(DynamicElementTextItem *text, ElementTextItemGroup *group);
void textRemovedFromGroup(DynamicElementTextItem *text, ElementTextItemGroup *group);
//METHODS related to information
public:
QList<Terminal *> terminals() const;
QList<Conductor *> conductors() const;
QList <QPair <Terminal *, Terminal *> > AlignedFreeTerminals () const;
//METHODS related to information
DiagramContext elementInformations ()const {return m_element_informations;}
virtual void setElementInformations (DiagramContext dc);
DiagramContext kindInformations () const {return m_kind_informations;} //@kind_information_ is used to store more information
@@ -136,56 +96,29 @@ class Element : public QetGraphicsItem
autonum::sequentialNumbers sequenceStruct () const {return m_autoNum_seq;}
autonum::sequentialNumbers& rSequenceStruct() {return m_autoNum_seq;}
void setUpFormula(bool code_letter = true);
void setPrefix(QString);
QString getPrefix() const;
void freezeLabel(bool freeze);
bool isFreezeLabel() const {return m_freeze_label;}
void freezeNewAddedElement();
//ATTRIBUTES
protected:
DiagramContext m_element_informations, m_kind_informations;
autonum::sequentialNumbers m_autoNum_seq;
bool m_freeze_label = false;
QString m_F_str;
public:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
/// @return This element type ID
virtual QString typeId() const = 0;
/// @return the human name for this element
QString name() const override = 0;
virtual bool isHighlighted() const;
QString name() const override;
ElementsLocation location() const;
virtual void setHighlighted(bool);
void displayHelpLine(bool b = true);
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override;
QRectF boundingRect() const override;
QSize setSize(int, int);
QSize size() const;
QPixmap pixmap();
// methods related to the hotspot
QPoint setHotspot(QPoint);
QPoint hotspot() const;
// selection-related methods
void select();
void deselect();
QPoint hotspot() const;
void editProperty() override;
// methods related to XML import/export
static bool valideXml(QDomElement &);
virtual bool fromXml(QDomElement &, QHash<int, Terminal *> &, bool = false);
virtual QDomElement toXml(QDomDocument &, QHash<Terminal *, int> &) const;
QUuid uuid() const;
// orientation-related methods
int orientation() const;
//METHODS related to texts
void addDynamicTextItem(DynamicElementTextItem *deti = nullptr);
void removeDynamicTextItem(DynamicElementTextItem *deti);
QList<DynamicElementTextItem *> dynamicTextItems() const;
@@ -196,16 +129,34 @@ class Element : public QetGraphicsItem
QList<ElementTextItemGroup *> textGroups() const;
bool addTextToGroup(DynamicElementTextItem *text, ElementTextItemGroup *group);
bool removeTextFromGroup(DynamicElementTextItem *text, ElementTextItemGroup *group);
//METHODS related to linked element
bool isFree () const;
virtual void linkToElement (Element *) {}
virtual void unlinkAllElements () {}
virtual void unlinkElement (Element *) {}
virtual void initLink (QETProject *);
QList<Element *> linkedElements ();
virtual kind linkType() const {return m_link_type;} // @return the linkable type
void newUuid() {m_uuid = QUuid::createUuid();} //create new uuid for this element
protected:
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
void setSize(int, int);
private:
bool must_highlight_;
void drawSelection(QPainter *, const QStyleOptionGraphicsItem *);
void drawHighlight(QPainter *, const QStyleOptionGraphicsItem *);
void updatePixmap();
bool buildFromXml(const QDomElement &, int * = nullptr);
bool parseElement(const QDomElement &dom);
bool parseInput(const QDomElement &dom_element);
DynamicElementTextItem *parseDynamicText(const QDomElement &dom_element);
Terminal *parseTerminal(const QDomElement &dom_element);
//Reimplemented from QGraphicsItem
public:
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override;
QRectF boundingRect() const override;
protected:
void mouseMoveEvent ( QGraphicsSceneMouseEvent *event ) override;
void mouseReleaseEvent ( QGraphicsSceneMouseEvent *event ) override;
@@ -217,8 +168,30 @@ class Element : public QetGraphicsItem
// are converted to dynamic text field, the QPointF is the original position of the text item, because the origin transformation point of text item
// and dynamic text item are not the same, so we must to keep a track of this value, to be use in the function element::fromXml
QHash <DynamicElementTextItem *, QPointF> m_converted_text_from_xml_description;
//ATTRIBUTES related to linked element
QList <Element *> connected_elements;
QList <QUuid> tmp_uuids_link;
QUuid m_uuid;
kind m_link_type;
//ATTRIBUTES related to informations
DiagramContext m_element_informations, m_kind_informations;
autonum::sequentialNumbers m_autoNum_seq;
bool m_freeze_label = false;
QString m_F_str;
ElementsLocation m_location;
NamesList m_names;
QList <Terminal *> m_terminals;
const QPicture m_picture;
const QPicture m_low_zoom_picture;
private:
bool m_mouse_over;
bool m_must_highlight = false;
QSize dimensions;
QPoint hotspot_coord;
bool m_mouse_over = false;
QString m_prefix;
QList <DynamicElementTextItem *> m_dynamic_text_list;
QList <ElementTextItemGroup *> m_texts_group;
@@ -248,7 +221,7 @@ inline int Element::orientation() const {
* @return the uuid of this element
*/
inline QUuid Element::uuid() const {
return uuid_;
return m_uuid;
}
/**

View File

@@ -1,185 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "ghostelement.h"
#include "qet.h"
#include "terminal.h"
#include "diagramcommands.h"
/**
Constructeur
@param location Emplacement de la definition d'element a utiliser
@param qgi Le QGraphicsItem parent de cet element
@param d Le schema affichant cet element
*/
GhostElement::GhostElement(
const ElementsLocation &location,
QGraphicsItem *qgi
) :
CustomElement(location, qgi)
{
QString tooltip_string = QString(
tr("<u>Élément manquant :</u> %1")
).arg(location_.toString());
setToolTip(tooltip_string);
}
/**
Destructeur
*/
GhostElement::~GhostElement() {
}
/**
@param e L'element XML a analyser.
@param table_id_adr Reference vers la table de correspondance entre les IDs
du fichier XML et les adresses en memoire. Si l'import reussit, il faut y
ajouter les bons couples (id, adresse).
@return true si l'import a reussi, false sinon
*/
bool GhostElement::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool handle_inputs_rotation) {
// instancie les bornes decrites dans l'element XML
terminalsFromXml(e, table_id_adr);
// instancie les champs de texte decrits dans l'element XML
foreach(QDomElement qde, QET::findInDomElement(e, "inputs", "input")) {
qde.setAttribute("size", 9); // arbitraire
CustomElement::parseInput(qde);
}
/*
maintenant que l'element fantome connait toutes les bornes et tous les
champs de texte, on peut determiner une taille appropriee
*/
QRect final_bounding_rect = minimalBoundingRect().united(childrenBoundingRect()).toAlignedRect();
setSize(final_bounding_rect.width(), final_bounding_rect.height());
setHotspot(QPoint() - final_bounding_rect.topLeft());
// on peut desormais confectionner le rendu de l'element
generateDrawings();
// position, selection
setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
// orientation
bool conv_ok;
int read_ori = e.attribute("orientation").toInt(&conv_ok);
if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = 0;
if (handle_inputs_rotation) {
setRotation(rotation() + (90*read_ori));
} else {
setRotation(90*read_ori);
}
return(true);
}
/**
@return le bounding rect minimum, utilise si l'element fantome n'a ni champ
de texte ni borne.
*/
QRectF GhostElement::minimalBoundingRect() const {
return(
QRectF(
QPointF(-10.0, -10.0),
QSizeF(20.0, 20.0)
)
);
}
/**
Gere l'import des bornes
@param e L'element XML a analyser.
@param table_id_adr Reference vers la table de correspondance entre les IDs
du fichier XML et les adresses en memoire. Si l'import reussit, il faut y
ajouter les bons couples (id, adresse).
@return true si l'import a reussi, false sinon
*/
bool GhostElement::terminalsFromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr) {
// instancie les bornes decrites dans l'element XML
foreach(QDomElement qde, QET::findInDomElement(e, "terminals", "terminal")) {
if (!Terminal::valideXml(qde)) continue;
// modifie certains attributs pour que l'analyse par la classe CustomElement reussisse
int previous_x_value = qde.attribute("x").toInt();
int previous_y_value = qde.attribute("y").toInt();
Qet::Orientation previous_ori_value = static_cast<Qet::Orientation>(qde.attribute("orientation").toInt());
qreal x_add = 0.0, y_add = 0.0;
if (previous_ori_value == Qet::North) y_add = -Terminal::terminalSize;
else if (previous_ori_value == Qet::East) x_add = Terminal::terminalSize;
else if (previous_ori_value == Qet::South) y_add = Terminal::terminalSize;
else if (previous_ori_value == Qet::West) x_add = -Terminal::terminalSize;
qde.setAttribute("x", previous_x_value + x_add);
qde.setAttribute("y", previous_y_value + y_add);
qde.setAttribute("orientation", previous_ori_value);
if (Terminal *new_terminal = CustomElement::parseTerminal(qde)) {
table_id_adr.insert(qde.attribute("id").toInt(), new_terminal);
}
// restaure les attributs modifies
qde.setAttribute("x", previous_x_value);
qde.setAttribute("y", previous_y_value);
qde.setAttribute("orientation", previous_ori_value);
}
return(true);
}
/**
Genere les rendus de l'element fantome : il s'agit d'un rectangle
representant grosso modo l'espace que devait prendre l'element initial.
En son centre est dessine un point d'interrogation. Une petite croix indique
le point de saisie de l'element.
*/
void GhostElement::generateDrawings() {
// style de dessin
QPen t(QBrush(Qt::black), 1.0);
// rendu normal
QPainter qp;
qp.begin(&drawing);
qp.setPen(t);
qp.setRenderHint(QPainter::Antialiasing, false);
generateDrawing(&qp);
qp.end();
// rendu low_zoom
QPainter low_zoom_qp;
low_zoom_qp.begin(&low_zoom_drawing);
t.setCosmetic(true);
low_zoom_qp.setRenderHint(QPainter::Antialiasing, false);
low_zoom_qp.setPen(t);
generateDrawing(&low_zoom_qp);
low_zoom_qp.end();
}
/**
Genere un rendu de l'element fantome
@see generateDrawings
*/
void GhostElement::generateDrawing(QPainter *painter) {
// une petite croix indique le point de saisie de l'element
painter -> drawLine(QLineF(-1.0, 0.0, 1.0, 0.0));
painter -> drawLine(QLineF(0.0, -1.0, 0.0, 1.0));
// rectangle avec un point d'interrogation au centre
QRectF drawn_rect = boundingRect().adjusted(4.0, 4.0, -4.0, -4.0);
painter -> drawRect(drawn_rect);
painter -> drawText(drawn_rect, Qt::AlignHCenter | Qt::AlignVCenter, "?");
}

View File

@@ -1,53 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef GHOST_ELEMENT_H
#define GHOST_ELEMENT_H
#include "customelement.h"
class QGraphicsItem;
class ElementsLocation;
class Terminal;
/**
The GhostElement class inherits CustomElement. A GhostElement aims at
visually replacing a CustomElement whose definition could not be loaded.
This way, instead of not loading an element, thus potentially losing its
position, its orientation, its child text items and conductors, one can
substitute a GhostElement. The GhostElement will extrapolate the position
of terminals and text items from the rest of the diagram. It is visually
rendered using a simple rectangle.
*/
class GhostElement : public CustomElement {
Q_OBJECT
// constructor, destructor
public:
GhostElement(const ElementsLocation &, QGraphicsItem * = nullptr);
~GhostElement() override;
// methods
public:
bool fromXml(QDomElement &, QHash<int, Terminal *> &, bool = false) override;
kind linkType() const override {return Simple;}
protected:
QRectF minimalBoundingRect() const;
bool terminalsFromXml(QDomElement &, QHash<int, Terminal *> &);
void generateDrawings();
void generateDrawing(QPainter *);
};
#endif

View File

@@ -30,7 +30,7 @@
* @param state int used to know if the creation of element have error
*/
MasterElement::MasterElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
Element(location, qgi, state)
{
m_link_type = Element::Master;
}
@@ -109,7 +109,7 @@ void MasterElement::unlinkElement(Element *elmt)
*/
void MasterElement::initLink(QETProject *project) {
//Create the link with other element if needed
CustomElement::initLink(project);
Element::initLink(project);
}
/**
@@ -132,7 +132,7 @@ QVariant MasterElement::itemChange(QGraphicsItem::GraphicsItemChange change, con
m_first_scene_change = false;
connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &MasterElement::xrefPropertiesChanged);
}
return CustomElement::itemChange(change, value);
return Element::itemChange(change, value);
}
void MasterElement::xrefPropertiesChanged()

View File

@@ -18,7 +18,7 @@
#ifndef MASTERELEMENT_H
#define MASTERELEMENT_H
#include "customelement.h"
#include "element.h"
class CrossRefItem;
@@ -28,7 +28,7 @@ class CrossRefItem;
* to be a master element. Master element can be linked with slave element
* and display a cross ref item for know with what other element he is linked
*/
class MasterElement : public CustomElement
class MasterElement : public Element
{
Q_OBJECT

View File

@@ -24,7 +24,7 @@
#include "dynamicelementtextitem.h"
ReportElement::ReportElement(const ElementsLocation &location, const QString& link_type,QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
Element(location, qgi, state)
{
link_type == "next_report"? m_link_type=NextReport : m_link_type=PreviousReport;
link_type == "next_report"? m_inverse_report=PreviousReport : m_inverse_report=NextReport;

View File

@@ -18,14 +18,14 @@
#ifndef REPORTELEMENT_H
#define REPORTELEMENT_H
#include "customelement.h"
#include "element.h"
/**
* @brief The ReportElement class
*this class represent an element that can be linked to an other ReportElement
* a folio report in a diagram is a element that show a wire go on an other folio
*/
class ReportElement : public CustomElement
class ReportElement : public Element
{
Q_OBJECT

View File

@@ -26,7 +26,7 @@
* @param state
*/
SimpleElement::SimpleElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
Element(location, qgi, state)
{
m_link_type = Simple;
}
@@ -43,5 +43,5 @@ SimpleElement::~SimpleElement() {}
* call update label for setup it.
*/
void SimpleElement::initLink(QETProject *project) {
CustomElement::initLink(project);
Element::initLink(project);
}

View File

@@ -18,7 +18,7 @@
#ifndef SIMPLEELEMENT_H
#define SIMPLEELEMENT_H
#include "customelement.h"
#include "element.h"
class QETProject;
@@ -26,7 +26,7 @@ class QETProject;
* @brief The SimpleElement class
*this class represente a simple element with no specific attribute
*/
class SimpleElement : public CustomElement {
class SimpleElement : public Element {
Q_OBJECT

View File

@@ -30,7 +30,7 @@
* @param state int used to know if the creation of element have error
*/
SlaveElement::SlaveElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
Element(location, qgi, state)
{
m_xref_item = nullptr;
m_link_type = Slave;

View File

@@ -18,10 +18,10 @@
#ifndef SLAVEELEMENT_H
#define SLAVEELEMENT_H
#include "customelement.h"
#include "element.h"
#include"properties/xrefproperties.h"
class SlaveElement : public CustomElement
class SlaveElement : public Element
{
Q_OBJECT
public:

View File

@@ -26,7 +26,7 @@
* @param state int used to know if the creation of element have error
*/
TerminalElement::TerminalElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) :
CustomElement(location, qgi, state)
Element(location, qgi, state)
{m_link_type = Terminale;}
TerminalElement::~TerminalElement() {}
@@ -36,6 +36,6 @@ TerminalElement::~TerminalElement() {}
* @param project
*/
void TerminalElement::initLink(QETProject *project) {
CustomElement::initLink(project);
Element::initLink(project);
}

View File

@@ -18,11 +18,12 @@
#ifndef TERMINALELEMENT_H
#define TERMINALELEMENT_H
#include "customelement.h"
#include "element.h"
class QETProject;
class TerminalElement : public CustomElement
class TerminalElement : public Element
{
Q_OBJECT
public: