First step for the dynamic element text : Now user can add directly from the diagram editor an editable text of an element.

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5005 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2017-08-03 17:36:08 +00:00
parent 0df5391491
commit 3ef55906a4
33 changed files with 2222 additions and 863 deletions

View File

@@ -27,10 +27,7 @@
*/
DiagramTextItem::DiagramTextItem(QGraphicsItem *parent) :
QGraphicsTextItem(parent),
m_mouse_hover(false),
previous_text_(),
rotation_angle_(0.0),
m_first_move (true)
m_rotation_angle(0.0)
{ build(); }
/**
@@ -41,8 +38,8 @@ DiagramTextItem::DiagramTextItem(QGraphicsItem *parent) :
DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent) :
QGraphicsTextItem(text, parent),
m_mouse_hover(false),
previous_text_(text),
rotation_angle_(0.0)
m_previous_html_text(text),
m_rotation_angle(0.0)
{ build(); }
/**
@@ -83,7 +80,7 @@ QDomElement DiagramTextItem::toXml(QDomDocument &) const {
@return l'angle de rotation actuel de ce texte
*/
qreal DiagramTextItem::rotationAngle() const {
return(rotation_angle_);
return(m_rotation_angle);
}
/**
@@ -94,8 +91,8 @@ qreal DiagramTextItem::rotationAngle() const {
*/
void DiagramTextItem::setRotationAngle(const qreal &rotation) {
qreal applied_rotation = QET::correctAngle(rotation);
applyRotation(applied_rotation - rotation_angle_);
rotation_angle_ = applied_rotation;
applyRotation(applied_rotation - m_rotation_angle);
m_rotation_angle = applied_rotation;
}
/**
@@ -106,7 +103,7 @@ void DiagramTextItem::setRotationAngle(const qreal &rotation) {
*/
void DiagramTextItem::rotateBy(const qreal &added_rotation) {
qreal applied_added_rotation = QET::correctAngle(added_rotation);
rotation_angle_ = QET::correctAngle(rotation_angle_ + applied_added_rotation);
m_rotation_angle = QET::correctAngle(m_rotation_angle + applied_added_rotation);
applyRotation(applied_added_rotation);
}
@@ -186,8 +183,25 @@ QPointF DiagramTextItem::mapMovementFromParent(const QPointF &movement) const {
return(local_movement_point - local_origin);
}
void DiagramTextItem::setFontSize(int &s) {
setFont(QETApp::diagramTextsFont(s));
void DiagramTextItem::setFontSize(int s)
{
setFont(QETApp::diagramTextsFont(s));
emit fontSizeChanged(s);
}
int DiagramTextItem::fontSize() const
{
return font().pointSize();
}
void DiagramTextItem::setColor(QColor color)
{
setDefaultTextColor(color);
emit colorChanged(color);
}
QColor DiagramTextItem::color() const {
return defaultTextColor();
}
/**
@@ -226,42 +240,39 @@ void DiagramTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
}
/**
Gere la prise de focus du champ de texte
@param e Objet decrivant la prise de focus
*/
void DiagramTextItem::focusInEvent(QFocusEvent *e) {
QGraphicsTextItem::focusInEvent(e);
// empeche le deplacement du texte pendant son edition
* @brief DiagramTextItem::focusInEvent
* @param e
*/
void DiagramTextItem::focusInEvent(QFocusEvent *event)
{
QGraphicsTextItem::focusInEvent(event);
setFlag(QGraphicsItem::ItemIsMovable, false);
// memorise le texte avant que l'utilisateur n'y touche
previous_text_ = toHtml();
// cela permettra de determiner si l'utilisateur a modifie le texte a la fin de l'edition
m_previous_html_text = toHtml();
m_previous_text = toPlainText();
}
/**
Gere la perte de focus du champ de texte
@param e Objet decrivant la perte de focus
*/
void DiagramTextItem::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
* @brief DiagramTextItem::focusOutEvent
* @param event
*/
void DiagramTextItem::focusOutEvent(QFocusEvent *event)
{
QGraphicsTextItem::focusOutEvent(event);
if (toHtml() != m_previous_html_text)
emit(diagramTextChanged(this, m_previous_html_text, toHtml()));
if(toPlainText() != m_previous_text)
emit textEdited(m_previous_text, toPlainText());
// signale la modification du texte si besoin
if (toPlainText() != previous_text_) {
emit(diagramTextChanged(this, previous_text_, toHtml()));
previous_text_ = toHtml();
}
// deselectionne le texte
QTextCursor cursor = textCursor();
cursor.clearSelection();
setTextCursor(cursor);
// hack a la con pour etre re-entrant
//Bad hack to be re-entrant
setTextInteractionFlags(Qt::NoTextInteraction);
// autorise de nouveau le deplacement du texte
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsTextItem::ItemIsFocusable, false);
}
@@ -271,7 +282,7 @@ void DiagramTextItem::focusOutEvent(QFocusEvent *e) {
@param event un QGraphicsSceneMouseEvent decrivant le double-clic
*/
void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
if (!(textInteractionFlags() & Qt::TextEditable) && !no_editable) {
if (!(textInteractionFlags() & Qt::TextEditable) && !m_no_editable) {
// rend le champ de texte editable
setTextInteractionFlags(Qt::TextEditorInteraction);

View File

@@ -32,6 +32,13 @@ class QDomDocument;
class DiagramTextItem : public QGraphicsTextItem
{
Q_OBJECT
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
signals:
void fontSizeChanged(int size);
void colorChanged(QColor color);
public:
DiagramTextItem(QGraphicsItem * = 0);
@@ -42,7 +49,7 @@ class DiagramTextItem : public QGraphicsTextItem
public:
enum { Type = UserType + 1004 };
virtual int type() const { return Type; }
virtual int type() const override { return Type; }
Diagram *diagram() const;
virtual void fromXml(const QDomElement &) = 0;
@@ -57,35 +64,43 @@ class DiagramTextItem : public QGraphicsTextItem
QPointF mapMovementToParent (const QPointF &) const;
QPointF mapMovementFromParent (const QPointF &) const;
void setFontSize(int &s);
void setNoEditable(bool e = true) {no_editable = e;}
void setFontSize(int s);
int fontSize()const;
void setColor(QColor color);
QColor color() const;
void setNoEditable(bool e = true) {m_no_editable = e;}
protected:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
virtual void focusInEvent(QFocusEvent *);
virtual void focusOutEvent(QFocusEvent *);
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override;
virtual void focusInEvent(QFocusEvent *) override;
virtual void focusOutEvent(QFocusEvent *) override;
virtual void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event);
virtual void mousePressEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override;
virtual void mousePressEvent (QGraphicsSceneMouseEvent *event) override;
virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override;
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override;
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *);
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *) override;
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *) override;
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *) override;
virtual void applyRotation(const qreal &);
signals:
/// signal emitted after text was changed
void diagramTextChanged(DiagramTextItem *, const QString &, const QString &);
void textEdited(const QString &old_str, const QString &new_str);
protected:
bool m_mouse_hover;
QString previous_text_;
qreal rotation_angle_;
bool no_editable;
bool m_first_move;
bool m_mouse_hover = false,
m_first_move = true,
m_no_editable;
QString m_previous_html_text,
m_previous_text;
qreal m_rotation_angle;
QPointF m_mouse_to_origin_movement;
};
#endif

View File

@@ -0,0 +1,255 @@
/*
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 "dynamicelementtextitem.h"
#include "qet.h"
#include "element.h"
#include "qetapp.h"
#include "diagram.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include <QDomDocument>
#include <QDomElement>
#include <QGraphicsSceneMouseEvent>
/**
* @brief DynamicElementTextItem::DynamicElementTextItem
* Constructor
* @param parent_element
*/
DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) :
m_parent_element(parent_element),
m_uuid(QUuid::createUuid())
{
setFont(QETApp::diagramTextsFont(9));
setText(tr("Texte"));
setParentItem(parent_element);
connect(this, &DynamicElementTextItem::textEdited, [this](const QString &old_str, const QString &new_str)
{
if(this->m_parent_element && this->m_parent_element->diagram())
{
QUndoCommand *undo = new QPropertyUndoCommand(this, "text", old_str, new_str);
undo->setText(tr("Éditer un texte d'élément"));
this->m_parent_element->diagram()->undoStack().push(undo);
}
});
}
DynamicElementTextItem::~DynamicElementTextItem()
{}
/**
* @brief DynamicElementTextItem::toXml
* Export this text to xml
* @param dom_doc
* @return
*/
QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const
{
QDomElement root_element = dom_doc.createElement(xmlTaggName());
root_element.setAttribute("x", QString::number(pos().x()));
root_element.setAttribute("y", QString::number(pos().y()));
root_element.setAttribute("rotation", QString::number(QET::correctAngle(rotation())));
root_element.setAttribute("font_size", font().pointSize());
root_element.setAttribute("uuid", m_uuid.toString());
QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("TextFrom"));
root_element.setAttribute("text_from", me.valueToKey(m_text_from));
QDomElement dom_text = dom_doc.createElement("text");
dom_text.appendChild(dom_doc.createTextNode(toPlainText()));
root_element.appendChild(dom_text);
//tagg
if (!m_tagg.isEmpty())
{
QDomElement dom_tagg = dom_doc.createElement("tagg");
dom_tagg.appendChild(dom_doc.createTextNode(m_tagg));
root_element.appendChild(dom_tagg);
}
//Color
if(color() != QColor(Qt::black))
{
QDomElement dom_color = dom_doc.createElement("color");
dom_color.appendChild(dom_doc.createTextNode(color().name()));
root_element.appendChild(dom_color);
}
return root_element;
}
/**
* @brief DynamicElementTextItem::fromXml
* Import this text from xml
* @param dom_elmt
*/
void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt)
{
if (dom_elmt.tagName() != xmlTaggName()) {
qDebug() << "DynamicElementTextItem::fromXml : Wrong tagg name";
return;
}
QGraphicsTextItem::setPos(dom_elmt.attribute("x", QString::number(0)).toDouble(),
dom_elmt.attribute("y", QString::number(0)).toDouble());
QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble());
setFont(QETApp::diagramTextsFont(dom_elmt.attribute("font_size", QString::number(9)).toInt()));
m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString()));
QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("TextFrom"));
m_text_from = DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data()));
setNoEditable(m_text_from == ElementInfo? true : false);
//Text
QDomElement dom_text = dom_elmt.firstChildElement("text");
if (!dom_text.isNull())
setPlainText(dom_text.text());
//tagg
QDomElement dom_tagg = dom_elmt.firstChildElement("tagg");
if (!dom_tagg.isNull())
m_tagg = dom_tagg.text();
//Color
QDomElement dom_color = dom_elmt.firstChildElement("color");
if(!dom_color.isNull())
setColor(QColor(dom_color.text()));
}
/**
* @brief DynamicElementTextItem::ParentElement
* @return a pointer to the parent element. Note the pointer can be null.
*/
Element *DynamicElementTextItem::ParentElement() const {
return m_parent_element;
}
/**
* @brief DynamicElementTextItem::textFrom
* @return what the final text is created from.
*/
DynamicElementTextItem::TextFrom DynamicElementTextItem::textFrom() const {
return m_text_from;
}
/**
* @brief DynamicElementTextItem::setTextFrom
* Set the final text is created from.
* @param text_from
*/
void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_from)
{
m_text_from = text_from;
setNoEditable(m_text_from == ElementInfo? true : false);
emit TextFromChanged(m_text_from);
}
/**
* @brief DynamicElementTextItem::tagg
* @return the tagg of this text
*/
QString DynamicElementTextItem::tagg() const {
return m_tagg;
}
/**
* @brief DynamicElementTextItem::setTagg
* set the taggof this text
* @param tagg
*/
void DynamicElementTextItem::setTagg(const QString &tagg)
{
m_tagg = tagg;
emit taggChanged(m_tagg);
}
/**
* @brief DynamicElementTextItem::text
* @return the text of this text
*/
QString DynamicElementTextItem::text() const {
return m_text;
}
/**
* @brief DynamicElementTextItem::setText
* Set the text of this text
* @param formula
*/
void DynamicElementTextItem::setText(const QString &text)
{
m_text = text;
setPlainText(m_text);
emit textChanged(m_text);
}
/**
* @brief DynamicElementTextItem::mouseMoveEvent
* @param event
*/
void DynamicElementTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
QPointF old_pos = pos(); //The old pos
QPointF movement = event->pos() - event->buttonDownPos(Qt::LeftButton); //The movement since the button down pos
QPointF new_pos = pos() + mapMovementToParent(movement); //The new pos with this event
event->modifiers() == Qt::ControlModifier ? setPos(new_pos) : setPos(Diagram::snapToGrid(new_pos));
if(m_parent_element && m_parent_element->diagram())
{
Diagram *diagram = m_parent_element->diagram();
if(m_first_move)
{
if(diagram->beginMoveElementTexts(this) == 1)
m_parent_element->setHighlighted(true);
}
//Because setPos() can be snaped to grid or not, we calcule the real movement
QPointF effective_movement = pos() - old_pos;
QPointF scene_effective_movement = mapMovementToScene(mapMovementFromParent(effective_movement));
diagram->continueMoveElementTexts(scene_effective_movement);
}
}
else
event->ignore();
if(m_first_move)
m_first_move = false;
}
/**
* @brief DynamicElementTextItem::mouseReleaseEvent
* @param event
*/
void DynamicElementTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (m_parent_element)
m_parent_element->setHighlighted(false);
if(m_parent_element && m_parent_element->diagram())
m_parent_element->diagram()->endMoveElementTexts();
if(!(event->modifiers() & Qt::ControlModifier))
QGraphicsTextItem::mouseReleaseEvent(event);
}

View File

@@ -0,0 +1,87 @@
/*
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 DYNAMICELEMENTTEXTITEM_H
#define DYNAMICELEMENTTEXTITEM_H
#include "diagramtextitem.h"
#include <QUuid>
class Element;
/**
* @brief The DynamicElementTextItem class
* This class provide a simple text field of element who can be added or removed directly from the diagram editor.
* This text is created to compensate a big lack of the ElementTextItem : ElementTextItem can't be added or removed directly in the diagram editor
*
*/
class DynamicElementTextItem : public DiagramTextItem
{
Q_OBJECT
Q_PROPERTY(QString tagg READ tagg WRITE setTagg NOTIFY taggChanged)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(TextFrom textFrom READ textFrom WRITE setTextFrom NOTIFY TextFromChanged)
public:
Q_ENUMS(TextFrom)
enum TextFrom {
UserText,
ElementInfo
};
enum {Type = UserType + 1010};
virtual int type() const override {return Type;}
signals:
void taggChanged(QString tagg);
void textChanged(QString text);
void TextFromChanged(DynamicElementTextItem::TextFrom text_from);
public:
DynamicElementTextItem(Element *parent_element);
virtual ~DynamicElementTextItem() override;
private:
DynamicElementTextItem(const DynamicElementTextItem &);
public:
virtual QDomElement toXml(QDomDocument &dom_doc) const override;
virtual void fromXml(const QDomElement &dom_elmt) override;
Element *ParentElement() const;
DynamicElementTextItem::TextFrom textFrom() const;
void setTextFrom (DynamicElementTextItem::TextFrom text_from);
QString tagg() const;
void setTagg(const QString &tagg);
QString text() const;
void setText(const QString &text);
static QString xmlTaggName() {return QString("dynamic_elmt_text");}
protected:
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
Element *m_parent_element = nullptr;
QString m_tagg,
m_text,
m_elmt_info_name;
DynamicElementTextItem::TextFrom m_text_from = UserText;
QUuid m_uuid;
};
#endif // DYNAMICELEMENTTEXTITEM_H

View File

@@ -29,6 +29,7 @@
#include "numerotationcontextcommands.h"
#include "diagramcontext.h"
#include "changeelementinformationcommand.h"
#include "dynamicelementtextitem.h"
class ElementXmlRetroCompatibility
{
@@ -77,7 +78,9 @@ Element::Element(QGraphicsItem *parent) :
/**
Destructeur
*/
Element::~Element() {
Element::~Element()
{
qDeleteAll(m_dynamic_text_list);
}
void Element::editProperty()
@@ -529,6 +532,15 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool
} else {
applyRotation(90*read_ori);
}
//Dynamic texts
for (QDomElement qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTaggName()))
{
DynamicElementTextItem *deti = new DynamicElementTextItem(this);
addDynamicTextItem(deti);
deti->fromXml(qde);
}
return(true);
}
@@ -608,14 +620,59 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &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));
element.appendChild(dyn_text);
return(element);
return(element);
}
/**
* @brief Element::addDynamiqueTextItem
* Add @deti as a dynamic text item of this element
* If @deti is null, a new DynamicElementTextItem is created and added to this element.
* @param deti
*/
void Element::addDynamicTextItem(DynamicElementTextItem *deti)
{
if (deti && !m_dynamic_text_list.contains(deti))
{
m_dynamic_text_list.append(deti);
}
else
{
DynamicElementTextItem *text = new DynamicElementTextItem(this);
m_dynamic_text_list.append(text);
}
}
/**
* @brief Element::removeDynamicTextItem
* Remove @deti as dynamic text item of this element.
* The parent item of deti stay this item.
* @param deti
*/
void Element::removeDynamicTextItem(DynamicElementTextItem *deti)
{
if (m_dynamic_text_list.contains(deti))
m_dynamic_text_list.removeOne(deti);
}
/**
* @brief Element::dynamicTextItems
* @return all dynamic text items of this element
*/
QList<DynamicElementTextItem *> Element::dynamicTextItems() const {
return m_dynamic_text_list;
}
/**

View File

@@ -30,6 +30,7 @@ class Terminal;
class Conductor;
class NumerotationContext;
class DiagramTextItem;
class DynamicElementTextItem;
/**
This is the base class for electrical elements.
@@ -158,9 +159,6 @@ class Element : public QetGraphicsItem
bool m_freeze_label = false;
QString m_F_str;
/**
Draw this element
*/
public:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
/// @return This element type ID
@@ -177,25 +175,29 @@ class Element : public QetGraphicsItem
QSize size() const;
QPixmap pixmap();
// methods related to the hotspot
QPoint setHotspot(QPoint);
QPoint hotspot() const;
// selection-related methods
void select();
void deselect();
virtual void rotateBy(const qreal &);
virtual void editProperty();
// 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 the hotspot
QPoint setHotspot(QPoint);
QPoint hotspot() const;
// selection-related methods
void select();
void deselect();
virtual void rotateBy(const qreal &);
virtual void editProperty();
// 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;
void addDynamicTextItem(DynamicElementTextItem *deti = nullptr);
void removeDynamicTextItem(DynamicElementTextItem *deti);
QList<DynamicElementTextItem *> dynamicTextItems() const;
protected:
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
@@ -216,6 +218,7 @@ class Element : public QetGraphicsItem
private:
bool m_mouse_over;
QString m_prefix;
QList <DynamicElementTextItem *> m_dynamic_text_list;
};