mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-03 10:34:14 +02:00
68ffacc9e6
QFont::fromString() of Qt 5.x and Qt <= 6.10 rejects the >= 19 field descriptions QFont::toString() emits since Qt 6.11, silently leaving a broken font at every read site. Add QETUtils::fontFromString(): try the native parser first, and on failure re-compose the legacy 10/11 field form from the known Qt 6.11 field layout (OpenType weight mapped back to the legacy scale) so no font information stored in existing files is lost. Also salvage the 21 field double-serialized descriptions left behind by some historical builds (a complete legacy description embedded as the family name of a second one) by taking the embedded leading description, matching what the lenient parser of Qt 6.11+ resolves them to. All font read sites now go through the helper; on failure the default font of the caller is left untouched instead of a cleared family. Verified end to end on a Qt 5.15 build: a project whose 53 font attributes were rewritten into the 19 field Qt 6.11 format loads and autosaves byte-identical to the original legacy file (family, sizes, bold/italic/underline, style name all preserved), and a mixed file containing the exact 21 field string from the issue comes back normalized as "Caladea,9,-1,5,75,1,0,0,0,0,Bold Italic". See issue #553.
1520 lines
49 KiB
C++
1520 lines
49 KiB
C++
/*
|
|
Copyright 2006-2026 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 "../qetproject.h"
|
|
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
|
#include "../diagram.h"
|
|
#include "../qetapp.h"
|
|
#include "../qetgraphicsitem/conductor.h"
|
|
#include "../qetgraphicsitem/terminal.h"
|
|
#include "../qetinformation.h"
|
|
#include "../utils/qetutils.h"
|
|
#include "crossrefitem.h"
|
|
#include "element.h"
|
|
#include "elementtextitemgroup.h"
|
|
#include <QTimer>
|
|
#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::dynamicTextsItemFont());
|
|
setText(tr("Texte"));
|
|
setParentItem(parent_element);
|
|
QSettings settings;
|
|
setRotation(settings.value("dynamic_text_rotation", 0).toInt());
|
|
setKeepVisualRotation(true);
|
|
setTextWidth(settings.value("dynamic_text_width", -1).toInt());
|
|
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);
|
|
}
|
|
});
|
|
|
|
//Option when text is displayed in multiple line
|
|
QTextOption option = document()->defaultTextOption();
|
|
option.setAlignment(Qt::AlignHCenter);
|
|
option.setWrapMode(QTextOption::WordWrap);
|
|
document()->setDefaultTextOption(option);
|
|
}
|
|
|
|
DynamicElementTextItem::~DynamicElementTextItem()
|
|
{}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::textFromMetaEnum
|
|
@return The QMetaEnum of the enum TextFrom
|
|
*/
|
|
QMetaEnum DynamicElementTextItem::textFromMetaEnum()
|
|
{
|
|
DynamicElementTextItem deti;
|
|
return deti.metaObject()->enumerator(deti.metaObject()->indexOfEnumerator("TextFrom"));
|
|
}
|
|
|
|
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(xmlTagName());
|
|
|
|
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("uuid", m_uuid.toString());
|
|
root_element.setAttribute("frame", m_frame? "true" : "false");
|
|
root_element.setAttribute("text_width", QString::number(m_text_width));
|
|
root_element.setAttribute("font", QETUtils::fontToString(font()));
|
|
root_element.setAttribute("keep_visual_rotation", m_keep_visual_rotation ? "true" : "false");
|
|
|
|
QMetaEnum me = textFromMetaEnum();
|
|
root_element.setAttribute("text_from", me.valueToKey(m_text_from));
|
|
|
|
me = QMetaEnum::fromType<Qt::Alignment>();
|
|
if(this->alignment() &Qt::AlignRight)
|
|
root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignRight));
|
|
else if(this->alignment() &Qt::AlignLeft)
|
|
root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignLeft));
|
|
else if(this->alignment() &Qt::AlignHCenter)
|
|
root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignHCenter));
|
|
|
|
if(this->alignment() &Qt::AlignBottom)
|
|
root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignBottom));
|
|
else if(this->alignment() & Qt::AlignTop)
|
|
root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignTop));
|
|
else if(this->alignment() &Qt::AlignVCenter)
|
|
root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignVCenter));
|
|
|
|
|
|
QDomElement dom_text = dom_doc.createElement("text");
|
|
dom_text.appendChild(dom_doc.createTextNode(toPlainText()));
|
|
root_element.appendChild(dom_text);
|
|
|
|
//Info name
|
|
if(!m_info_name.isEmpty())
|
|
{
|
|
QDomElement dom_info_name = dom_doc.createElement("info_name");
|
|
dom_info_name.appendChild(dom_doc.createTextNode(m_info_name));
|
|
root_element.appendChild(dom_info_name);
|
|
}
|
|
|
|
//Composite text
|
|
if(!m_composite_text.isEmpty())
|
|
{
|
|
QDomElement dom_comp_text = dom_doc.createElement("composite_text");
|
|
dom_comp_text.appendChild(dom_doc.createTextNode(m_composite_text));
|
|
root_element.appendChild(dom_comp_text);
|
|
}
|
|
|
|
//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() != xmlTagName()) {
|
|
qDebug() << "DynamicElementTextItem::fromXml : Wrong tagg name";
|
|
return;
|
|
}
|
|
|
|
QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble());
|
|
setKeepVisualRotation(dom_elmt.attribute("keep_visual_rotation", "true") == "true"? true : false);
|
|
|
|
if (dom_elmt.hasAttribute("font"))
|
|
{
|
|
QFont font;
|
|
QETUtils::fontFromString(font, dom_elmt.attribute("font"));
|
|
setFont(font);
|
|
}
|
|
else //Retrocompatibility during the 0.7 dev because the font property was added lately. TODO remove this part in futur
|
|
{
|
|
QFont font_(dom_elmt.attribute("font_family", font().family()),
|
|
dom_elmt.attribute("font_size", QString::number(9)).toInt());
|
|
font_.setStyleName(dom_elmt.attribute("dynamicitemstyle", font().styleName()));
|
|
setFont(font_);
|
|
}
|
|
|
|
m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString()));
|
|
setFrame(dom_elmt.attribute("frame", "false") == "true"? true : false);
|
|
setTextWidth(dom_elmt.attribute("text_width", QString::number(-1)).toDouble());
|
|
|
|
//Text from
|
|
QMetaEnum me = textFromMetaEnum();
|
|
setTextFrom(DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data())));
|
|
|
|
me = QMetaEnum::fromType<Qt::Alignment>();
|
|
if(dom_elmt.hasAttribute("Halignment"))
|
|
setAlignment(Qt::Alignment(me.keyToValue(dom_elmt.attribute("Halignment").toStdString().data())));
|
|
if(dom_elmt.hasAttribute(("Valignment")))
|
|
setAlignment(Qt::Alignment(me.keyToValue(dom_elmt.attribute("Valignment").toStdString().data())) | this->alignment());
|
|
|
|
//Text
|
|
QDomElement dom_text = dom_elmt.firstChildElement("text");
|
|
//Clear the current text.
|
|
setPlainText("");
|
|
if (!dom_text.isNull()) {
|
|
setText(dom_text.text());
|
|
}
|
|
|
|
//Info name
|
|
QDomElement dom_info_name = dom_elmt.firstChildElement("info_name");
|
|
if(!dom_info_name.isNull())
|
|
setInfoName(dom_info_name.text());
|
|
|
|
//Composite text
|
|
QDomElement dom_comp_text = dom_elmt.firstChildElement("composite_text");
|
|
if(!dom_comp_text.isNull())
|
|
setCompositeText(dom_comp_text.text());
|
|
|
|
//Color
|
|
QDomElement dom_color = dom_elmt.firstChildElement("color");
|
|
if(!dom_color.isNull())
|
|
setColor(QColor(dom_color.text()));
|
|
|
|
//Force the update of the displayed text
|
|
setTextFrom(m_text_from);
|
|
|
|
QGraphicsTextItem::setPos(dom_elmt.attribute("x", QString::number(0)).toDouble(),
|
|
dom_elmt.attribute("y", QString::number(0)).toDouble());
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::ParentElement
|
|
@return a pointer to the parent element. Note the pointer can be null.
|
|
Note that the text can return a parent element,
|
|
even if the text belong to a group of this same element.
|
|
*/
|
|
Element *DynamicElementTextItem::parentElement() const
|
|
{
|
|
return m_parent_element;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::parentGroup
|
|
@return The group where this text belong, if this item
|
|
is note in a group, return nullptr.
|
|
*/
|
|
ElementTextItemGroup *DynamicElementTextItem::parentGroup() const
|
|
{
|
|
if(parentItem())
|
|
{
|
|
if(ElementTextItemGroup *grp = dynamic_cast<ElementTextItemGroup *>(parentItem()))
|
|
return grp;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::elementUseForInfo
|
|
@return a pointer to the element we must use for the variable information.
|
|
If this text is owned by a simple element, the simple element is returned, this is the same element returned by the function parentElement().
|
|
If this text is owned by a master element, the master element is returned, this is the same element returned by the function parentElement().
|
|
If this text is owned by a report element, the report element is returned, this is the same element returned by the function parentElement().
|
|
If this text is owned by a terminal element, the terminal element is returned, this is the same element returned by the function parentElement().
|
|
If this text is owned by a slave element, we return the master element set as master of the parent slave element,
|
|
if the parent slave is not linked to a master, this function return a nullptr.
|
|
If this text have no parent element, return nullptr
|
|
*/
|
|
Element *DynamicElementTextItem::elementUseForInfo() const
|
|
{
|
|
Element *elmt = parentElement();
|
|
if(!elmt)
|
|
return nullptr;
|
|
|
|
switch (elmt->linkType())
|
|
{
|
|
case Element::Simple:
|
|
return elmt;
|
|
case Element::Thumbnail:
|
|
return elmt;
|
|
case Element::NextReport:
|
|
return elmt;
|
|
case Element::PreviousReport:
|
|
return elmt;
|
|
case Element::Master:
|
|
return elmt;
|
|
case Element::Slave:
|
|
{
|
|
if(elmt->linkedElements().isEmpty())
|
|
return nullptr;
|
|
else
|
|
return elmt->linkedElements().first();
|
|
}
|
|
case Element::Terminale:
|
|
return elmt;
|
|
default:
|
|
return elmt;
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::refreshLabelConnection
|
|
Refresh the connection of this text when the source of text is label,
|
|
or composite text, with a variable %{label}
|
|
*/
|
|
void DynamicElementTextItem::refreshLabelConnection()
|
|
{
|
|
if ((m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
|
|
{
|
|
if((m_parent_element.data()->linkType() & Element::AllReport) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition)
|
|
{
|
|
updateReportFormulaConnection();
|
|
updateReportText();
|
|
}
|
|
else
|
|
{
|
|
setupFormulaConnection();
|
|
updateLabel();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
@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)
|
|
{
|
|
if(m_text_from == text_from)
|
|
return;
|
|
|
|
setNoEditable(text_from == UserText? false : true);
|
|
clearFormulaConnection();
|
|
|
|
TextFrom old_text_from = m_text_from;
|
|
m_text_from = text_from;
|
|
|
|
if(m_text_from == UserText)
|
|
{
|
|
setPlainText(m_text);
|
|
disconnect(m_parent_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
|
|
}
|
|
else if (m_text_from == ElementInfo && elementUseForInfo())
|
|
{
|
|
if(m_info_name == "label")
|
|
{
|
|
setupFormulaConnection();
|
|
updateLabel();
|
|
}
|
|
else
|
|
setPlainText(elementUseForInfo()->elementInformations().value(m_info_name).toString());
|
|
|
|
if(old_text_from == UserText)
|
|
connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
|
|
}
|
|
else if (m_text_from == CompositeText && elementUseForInfo())
|
|
{
|
|
if(m_composite_text.contains("%{label}"))
|
|
{
|
|
setupFormulaConnection();
|
|
updateLabel();
|
|
}
|
|
else
|
|
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementUseForInfo()->elementInformations()));
|
|
|
|
if(old_text_from == UserText)
|
|
connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
|
|
}
|
|
|
|
if(m_parent_element.data()->linkType() == Element::Master ||
|
|
m_parent_element.data()->linkType() == Element::Slave)
|
|
updateXref();
|
|
|
|
emit textFromChanged(m_text_from);
|
|
}
|
|
|
|
/**
|
|
@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 text
|
|
*/
|
|
void DynamicElementTextItem::setText(const QString &text)
|
|
{
|
|
m_text = text;
|
|
if(m_text_from == DynamicElementTextItem::UserText)
|
|
setPlainText(m_text);
|
|
emit textChanged(m_text);
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::setInfoName
|
|
Set the information name of the parent element.
|
|
@param info_name
|
|
*/
|
|
void DynamicElementTextItem::setInfoName(const QString &info_name)
|
|
{
|
|
QString old_info_name = m_info_name;
|
|
m_info_name = info_name;
|
|
|
|
|
|
if(old_info_name == "label")
|
|
{
|
|
clearFormulaConnection();
|
|
updateXref();
|
|
}
|
|
|
|
if (m_parent_element && ((m_parent_element.data()->linkType() & Element::AllReport) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition)) //special treatment for report
|
|
{
|
|
if(old_info_name != info_name)
|
|
{
|
|
if(old_info_name == "label") {
|
|
removeConnectionForReportFormula(m_report_formula);
|
|
}
|
|
if(info_name == "label")
|
|
{
|
|
setConnectionForReportFormula(m_report_formula);
|
|
updateReportText();
|
|
}
|
|
else
|
|
conductorPropertiesChanged();
|
|
}
|
|
}
|
|
else if (m_info_name == "label" && elementUseForInfo())
|
|
{
|
|
setupFormulaConnection();
|
|
updateLabel();
|
|
updateXref();
|
|
}
|
|
else if(elementUseForInfo() && m_text_from == DynamicElementTextItem::ElementInfo) {
|
|
setPlainText(elementUseForInfo()->elementInformations().value(info_name).toString());
|
|
}
|
|
|
|
emit infoNameChanged(info_name);
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::infoName
|
|
@return the info name of this text
|
|
*/
|
|
QString DynamicElementTextItem::infoName() const
|
|
{
|
|
return m_info_name;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::setCompositeText
|
|
Set the composite text of this text item to text
|
|
@param text
|
|
*/
|
|
void DynamicElementTextItem::setCompositeText(const QString &text)
|
|
{
|
|
QString old_composite_text = m_composite_text;
|
|
m_composite_text = text;
|
|
|
|
if(old_composite_text.contains("%{label}"))
|
|
{
|
|
clearFormulaConnection();
|
|
updateXref();
|
|
}
|
|
|
|
if (m_parent_element && ((m_parent_element.data()->linkType() & Element::AllReport) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition)) //special treatment for report
|
|
{
|
|
/*
|
|
* May be in some case the old and new composite text both have the var %{label},
|
|
* and so we don't have to remove connection and after set connection,
|
|
* but for that we must do several checks and because I'm lazy,
|
|
* in every case I remove connection and set it after ;)
|
|
*/
|
|
if(old_composite_text.contains("%{label}"))
|
|
removeConnectionForReportFormula(m_report_formula);
|
|
if(m_composite_text.contains("%{label}"))
|
|
setConnectionForReportFormula(m_report_formula);
|
|
|
|
updateReportText();
|
|
}
|
|
else if (m_composite_text.contains("%{label}") && elementUseForInfo())
|
|
{
|
|
setupFormulaConnection();
|
|
updateLabel();
|
|
updateXref();
|
|
}
|
|
else if (m_text_from == DynamicElementTextItem::CompositeText)
|
|
{
|
|
DiagramContext dc;
|
|
if(elementUseForInfo())
|
|
dc = elementUseForInfo()->elementInformations();
|
|
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, dc));
|
|
}
|
|
|
|
emit compositeTextChanged(m_composite_text);
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::compositeText
|
|
@return
|
|
*/
|
|
QString DynamicElementTextItem::compositeText() const
|
|
{
|
|
return m_composite_text;
|
|
}
|
|
|
|
void DynamicElementTextItem::setFrame(const bool frame)
|
|
{
|
|
m_frame = frame;
|
|
update();
|
|
emit frameChanged(m_frame);
|
|
}
|
|
|
|
bool DynamicElementTextItem::frame() const
|
|
{
|
|
return m_frame;
|
|
}
|
|
|
|
QUuid DynamicElementTextItem::uuid() const
|
|
{
|
|
return m_uuid;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::mousePressEvent
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
//The text become selected, we set the real color, otherwise the editor will display the color of text as blue,
|
|
//but this is not the color set by the user.
|
|
if(m_user_color.isValid())
|
|
{
|
|
setDefaultTextColor(m_user_color);
|
|
m_user_color = QColor(); //m_user_color is now invalid
|
|
if(m_slave_Xref_item)
|
|
m_slave_Xref_item->setDefaultTextColor(Qt::black);
|
|
}
|
|
|
|
// Shift or no parent initiates movement of dynamic text, otherwise movement of parent element
|
|
if((event->modifiers() & Qt::ShiftModifier) || !m_parent_element)
|
|
{
|
|
m_move_parent = false;
|
|
DiagramTextItem::mousePressEvent(event);
|
|
} else {
|
|
m_move_parent = true;
|
|
parentElement()->mousePressEvent(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::mouseMoveEvent
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable))
|
|
{
|
|
if(m_move_parent)
|
|
{
|
|
parentElement()->mouseMoveEvent(event);
|
|
} else {
|
|
if(diagram() && m_first_move)
|
|
diagram()->elementTextsMover().beginMovement(diagram(), this);
|
|
|
|
if(m_first_move)
|
|
{
|
|
m_initial_position = pos();
|
|
if(parentElement())
|
|
parentElement()->setHighlighted(true);
|
|
}
|
|
|
|
QPointF current_parent_pos;
|
|
QPointF button_down_parent_pos;
|
|
current_parent_pos = mapToParent(mapFromScene(event->scenePos()));
|
|
button_down_parent_pos = mapToParent(mapFromScene(event->buttonDownScenePos(Qt::LeftButton)));
|
|
|
|
int diffx = qRound(current_parent_pos.x() - button_down_parent_pos.x());
|
|
int diffy = qRound(current_parent_pos.y() - button_down_parent_pos.y());
|
|
QPointF new_pos = m_initial_position + QPointF(diffx, diffy);
|
|
setPos(new_pos);
|
|
|
|
if(diagram())
|
|
diagram()->elementTextsMover().continueMovement(event);
|
|
}
|
|
} else {
|
|
event->ignore();
|
|
}
|
|
|
|
if(m_first_move)
|
|
m_first_move = false;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::mouseReleaseEvent
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if(m_move_parent)
|
|
{
|
|
parentElement()->mouseReleaseEvent(event);
|
|
} else {
|
|
if (m_parent_element)
|
|
m_parent_element->setHighlighted(false);
|
|
|
|
if(m_parent_element && m_parent_element->diagram())
|
|
m_parent_element.data()->diagram()->elementTextsMover().endMovement();
|
|
|
|
if(!(event->modifiers() & Qt::ControlModifier))
|
|
QGraphicsTextItem::mouseReleaseEvent(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::mouseDoubleClickEvent
|
|
Reimplemented functions, for add extra feature when this text is owned by a slave.
|
|
In this case if the parent slave element is linked to a master, and this text display the label of the master
|
|
(both if the 'text from' is 'element info' or 'composite text') the QGraphicsView go to master and select it.
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
DiagramTextItem::mouseDoubleClickEvent(event);
|
|
zoomToLinkedElement();
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::hoverEnterEvent
|
|
If the parent element of this text is a folio report or a slave element, the element is linked
|
|
and the text display the variable "label" we set the text blue for signal the user that the text act like
|
|
a link when we double click on.
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|
{
|
|
DiagramTextItem::hoverEnterEvent(event);
|
|
|
|
//If the text is selected we set the real color, otherwise the editor will display the color of text as blue,
|
|
//but this is not the color set by the user.
|
|
if(isSelected())
|
|
return;
|
|
|
|
if ((parentElement()->linkType() & Element::AllReport) && m_other_report)
|
|
{
|
|
if( (m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")) )
|
|
{
|
|
m_user_color = color();
|
|
setDefaultTextColor(Qt::blue);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::hoverLeaveEvent
|
|
@param event
|
|
*/
|
|
void DynamicElementTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|
{
|
|
DiagramTextItem::hoverLeaveEvent(event);
|
|
|
|
if(m_user_color.isValid())
|
|
{
|
|
setDefaultTextColor(m_user_color);
|
|
m_user_color = QColor(); //m_user_color is now invalid
|
|
}
|
|
|
|
}
|
|
|
|
void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
DiagramTextItem::paint(painter, option, widget);
|
|
|
|
if (m_frame)
|
|
{
|
|
painter->save();
|
|
painter->setFont(QETApp::dynamicTextsItemFont(font().pointSize()));
|
|
|
|
//Adjust the thickness according to the font size,
|
|
qreal w=0.3;
|
|
if(font().pointSize() >= 5)
|
|
{
|
|
w = font().pointSizeF()*0.1;
|
|
if(w > 2.5)
|
|
w = 2.5;
|
|
}
|
|
|
|
QPen pen;
|
|
pen.setColor(color());
|
|
pen.setWidthF(w);
|
|
painter->setPen(pen);
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
|
|
//Adjust the rounding of the rectangle according to the size of the font
|
|
qreal ro = font().pointSizeF()/3;
|
|
painter->drawRoundedRect(frameRect(), ro, ro);
|
|
|
|
painter->restore();
|
|
}
|
|
}
|
|
|
|
QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
|
|
{
|
|
//The first time this text is added to a scene, we make several checking and connection
|
|
//according to the link type of the parent element
|
|
if(change == QGraphicsItem::ItemSceneHasChanged && m_first_scene_change)
|
|
{
|
|
if(m_parent_element.isNull())
|
|
return QGraphicsObject::itemChange(change, value);
|
|
|
|
//If the parent is slave, we keep aware about the changement of master.
|
|
if(m_parent_element.data()->linkType() == Element::Slave)
|
|
{
|
|
connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::masterChanged);
|
|
//The parent is already linked, wa call master changed for init the connection
|
|
if(!m_parent_element.data()->linkedElements().isEmpty())
|
|
masterChanged();
|
|
}
|
|
else if((m_parent_element.data()->linkType() & Element::AllReport) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition)
|
|
{
|
|
//Get the report formula, and add connection to keep up to date the formula.
|
|
if (m_parent_element.data()->diagram() && m_parent_element.data()->diagram()->project())
|
|
{
|
|
m_report_formula = m_parent_element.data()->diagram()->project()->defaultReportProperties();
|
|
m_report_formula_con = connect(m_parent_element.data()->diagram()->project(), &QETProject::reportPropertiesChanged, this, &DynamicElementTextItem::reportFormulaChanged);
|
|
}
|
|
|
|
//Add connection to keep up to date the status of the element linked to the parent folio report of this text.
|
|
connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::reportChanged);
|
|
//The parent is already linked, we call reportChanged for init the connection
|
|
if(!m_parent_element.data()->linkedElements().isEmpty())
|
|
reportChanged();
|
|
|
|
if(m_parent_element.data()->terminals().size())
|
|
{
|
|
//Add connection to keep up date the conductors added or removed to the parent folio report element
|
|
connect(m_parent_element.data()->terminals().first(), &Terminal::conductorWasAdded, this, &DynamicElementTextItem::conductorWasAdded);
|
|
connect(m_parent_element.data()->terminals().first(), &Terminal::conductorWasRemoved, this, &DynamicElementTextItem::conductorWasRemoved);
|
|
}
|
|
//Get a conductor in the potential
|
|
setPotentialConductor();
|
|
}
|
|
else if(m_parent_element.data()->linkType() == Element::Master)
|
|
{
|
|
connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::updateXref);
|
|
if(m_parent_element.data()->diagram())
|
|
connect(m_parent_element.data()->diagram()->project(), &QETProject::XRefPropertiesChanged, this, &DynamicElementTextItem::updateXref);
|
|
if(!m_parent_element.data()->linkedElements().isEmpty())
|
|
updateXref();
|
|
}
|
|
|
|
m_first_scene_change = false;
|
|
return QGraphicsObject::itemChange(change, value);
|
|
}
|
|
else if (change == QGraphicsItem::ItemParentHasChanged)
|
|
{
|
|
updateXref();
|
|
updateXref();
|
|
}
|
|
|
|
return QGraphicsObject::itemChange(change, value);
|
|
}
|
|
|
|
bool DynamicElementTextItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
|
{
|
|
if(watched != m_slave_Xref_item)
|
|
return false;
|
|
|
|
if(event->type() == QEvent::GraphicsSceneHoverEnter) {
|
|
m_slave_Xref_item->setDefaultTextColor(Qt::blue);
|
|
return true;
|
|
}
|
|
else if(event->type() == QEvent::GraphicsSceneHoverLeave) {
|
|
m_slave_Xref_item->setDefaultTextColor(Qt::black);
|
|
return true;
|
|
}
|
|
else if(event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
|
|
zoomToLinkedElement();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void DynamicElementTextItem::elementInfoChanged()
|
|
{
|
|
DiagramContext dc;
|
|
Element *element = elementUseForInfo();
|
|
if(element) {
|
|
dc = element->elementInformations();
|
|
}
|
|
|
|
QString final_text;
|
|
|
|
|
|
if (m_text_from == ElementInfo)
|
|
{
|
|
//If the info is the label, then we must make some connection
|
|
//if the label is created from a formula
|
|
if(m_info_name == "label")
|
|
{
|
|
setupFormulaConnection();
|
|
|
|
if (element) {
|
|
final_text = element->actualLabel();
|
|
}
|
|
}
|
|
else {
|
|
final_text = dc.value(m_info_name).toString();
|
|
}
|
|
}
|
|
else if (m_text_from == CompositeText)
|
|
{
|
|
//If the composite have the label variable, we must make some
|
|
//connection if the label is created from a formula
|
|
if (m_composite_text.contains("%{label}"))
|
|
setupFormulaConnection();
|
|
|
|
final_text = autonum::AssignVariables::replaceVariable(m_composite_text, dc);
|
|
}
|
|
else if (m_text_from == UserText)
|
|
final_text = m_text;
|
|
|
|
setPlainText(final_text);
|
|
emit plainTextChanged();
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::masterChanged
|
|
This function is only use when the parent element is a slave.
|
|
Call when the master element linked to the parent slave element of this text change
|
|
*/
|
|
void DynamicElementTextItem::masterChanged()
|
|
{
|
|
//First we remove the old connection
|
|
if(!m_master_element.isNull() && (m_text_from == ElementInfo || m_text_from == CompositeText))
|
|
{
|
|
disconnect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
|
|
m_master_element.clear();
|
|
updateXref();
|
|
}
|
|
|
|
if(elementUseForInfo())
|
|
{
|
|
m_master_element = elementUseForInfo();
|
|
if(m_text_from == ElementInfo || m_text_from == CompositeText)
|
|
connect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
|
|
|
|
updateXref();
|
|
}
|
|
|
|
//Because master changed we update this text
|
|
elementInfoChanged();
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::reportChanged
|
|
This function is only use when parent element of this text is a folio report
|
|
The linked report of the parent element was changed
|
|
*/
|
|
void DynamicElementTextItem::reportChanged()
|
|
{
|
|
/*
|
|
* When the dynamic text are added by a drag & drop from the element panel,
|
|
* the connection below are made in the constructor.
|
|
* If the text are added at load of a .qet file, the text is not yet added to a diagram then the connection is not made.
|
|
* We make it now, because when the linked report changed, that mean this text is in a diagram
|
|
*/
|
|
if(!m_report_formula_con)
|
|
{
|
|
//Get the report formula, and add connection to keep up to date the formula.
|
|
if (parentElement()->diagram() && parentElement()->diagram()->project())
|
|
{
|
|
m_report_formula = parentElement()->diagram()->project()->defaultReportProperties();
|
|
m_report_formula_con = connect(parentElement()->diagram()->project(), &QETProject::reportPropertiesChanged, this, &DynamicElementTextItem::reportFormulaChanged);
|
|
}
|
|
}
|
|
|
|
bool text_have_label = false;
|
|
|
|
if((textFrom() == ElementInfo && m_info_name == "label") ||
|
|
(textFrom() == CompositeText && m_composite_text.contains("%{label}")))
|
|
text_have_label = true;
|
|
|
|
if(text_have_label)
|
|
removeConnectionForReportFormula(m_report_formula);
|
|
|
|
m_other_report.clear();
|
|
if(!m_parent_element.data()->linkedElements().isEmpty())
|
|
m_other_report = m_parent_element.data()->linkedElements().first();
|
|
|
|
//Because linked report was changed, we ensure there is a conductor watched
|
|
setPotentialConductor();
|
|
|
|
if(text_have_label)
|
|
{
|
|
setConnectionForReportFormula(m_report_formula);
|
|
updateReportText();
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::reportFormulaChanged
|
|
The report formula use in the project was changed
|
|
*/
|
|
void DynamicElementTextItem::reportFormulaChanged()
|
|
{
|
|
m_report_formula = parentElement()->diagram()->project()->defaultReportProperties();
|
|
|
|
if(m_text_from == ElementInfo && m_info_name == "label")
|
|
updateReportText();
|
|
}
|
|
|
|
void DynamicElementTextItem::setConnectionForReportFormula(const QString &formula)
|
|
{
|
|
if(m_other_report.isNull() || formula.isEmpty())
|
|
return;
|
|
|
|
Element *other_elmt = m_other_report.data();
|
|
QString string = formula;
|
|
Diagram *other_diagram = m_other_report.data()->diagram();
|
|
|
|
//Because the variable %F is a reference to another text which can contain variables,
|
|
//we must replace %F by the real text, to check if the real text contains the variable %id
|
|
if (other_diagram && string.contains("%F"))
|
|
{
|
|
m_F_str = other_diagram->border_and_titleblock.folio();
|
|
string.replace("%F", other_diagram->border_and_titleblock.folio());
|
|
connect(&other_diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateReportFormulaConnection);
|
|
}
|
|
|
|
if (other_diagram && (string.contains("%f") || string.contains("%id")))
|
|
{
|
|
connect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText);
|
|
connect(other_diagram->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateReportText);
|
|
}
|
|
if (string.contains("%l"))
|
|
connect(other_elmt, &Element::yChanged, this, &DynamicElementTextItem::updateReportText);
|
|
if (string.contains("%c"))
|
|
connect(other_elmt, &Element::xChanged, this, &DynamicElementTextItem::updateReportText);
|
|
}
|
|
|
|
void DynamicElementTextItem::removeConnectionForReportFormula(const QString &formula)
|
|
{
|
|
if(m_other_report.isNull() || formula.isEmpty())
|
|
return;
|
|
|
|
Element *other_element = m_other_report.data();
|
|
QString string = formula;
|
|
Diagram *other_diagram = m_other_report.data()->diagram();
|
|
|
|
//Because the variable %F is a reference to another text which can contain variables,
|
|
//we must replace %F with the real text, to check if the real text contains the variable %id
|
|
if (other_diagram && string.contains("%F"))
|
|
{
|
|
string.replace("%F", m_F_str);
|
|
disconnect(&other_diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateReportFormulaConnection);
|
|
}
|
|
|
|
if (other_diagram && (string.contains("%f") || string.contains("%id")))
|
|
disconnect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText);
|
|
if (string.contains("%l"))
|
|
disconnect(other_element, &Element::yChanged, this, &DynamicElementTextItem::updateReportText);
|
|
if (string.contains("%c"))
|
|
disconnect(other_element, &Element::xChanged, this, &DynamicElementTextItem::updateReportText);
|
|
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::setupFormulaConnection
|
|
Setup the required connection for the formula of the label.
|
|
*/
|
|
void DynamicElementTextItem::setupFormulaConnection()
|
|
{
|
|
if ((m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
|
|
{
|
|
clearFormulaConnection();
|
|
|
|
Element *element = elementUseForInfo();
|
|
if (!element)
|
|
return;
|
|
|
|
Diagram *diagram = element->diagram();
|
|
QString formula = element->elementInformations().value("formula").toString();
|
|
|
|
//Label is frozen, so we don't update it.
|
|
if (element->isFreezeLabel())
|
|
return;
|
|
|
|
if (diagram && formula.contains("%F"))
|
|
{
|
|
m_F_str = diagram->border_and_titleblock.folio();
|
|
formula.replace("%F", m_F_str);
|
|
m_formula_connection << connect(&diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateLabel);
|
|
}
|
|
|
|
if (diagram && (formula.contains("%f") || formula.contains("%id")))
|
|
{
|
|
m_formula_connection << connect(diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateLabel);
|
|
m_formula_connection << connect(diagram->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateLabel);
|
|
}
|
|
if (formula.contains("%l"))
|
|
m_formula_connection << connect(element, &Element::yChanged, this, &DynamicElementTextItem::updateLabel);
|
|
if (formula.contains("%c"))
|
|
m_formula_connection << connect(element, &Element::xChanged, this, &DynamicElementTextItem::updateLabel);
|
|
|
|
}
|
|
}
|
|
|
|
void DynamicElementTextItem::clearFormulaConnection()
|
|
{
|
|
for (const QMetaObject::Connection& con : m_formula_connection)
|
|
disconnect(con);
|
|
m_formula_connection.clear();
|
|
}
|
|
|
|
void DynamicElementTextItem::updateReportFormulaConnection()
|
|
{
|
|
if(!(m_parent_element.data()->linkType() & Element::AllReport) &&
|
|
m_parent_element.data()->linkType() != Element::ConductorDefinition)
|
|
return;
|
|
|
|
removeConnectionForReportFormula(m_report_formula);
|
|
setConnectionForReportFormula(m_report_formula);
|
|
updateReportText();
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::updateReportText
|
|
This function is only use when this text is owned by a report, and this text have for info the Label.
|
|
*/
|
|
void DynamicElementTextItem::updateReportText()
|
|
{
|
|
if(!(m_parent_element.data()->linkType() & Element::AllReport) &&
|
|
m_parent_element.data()->linkType() != Element::ConductorDefinition)
|
|
return;
|
|
|
|
if (m_text_from == ElementInfo && m_info_name == "label")
|
|
{
|
|
if(m_other_report)
|
|
{
|
|
Element *elmt = m_other_report.data();
|
|
QString label = m_report_formula;
|
|
label = autonum::AssignVariables::formulaToLabel(label, elmt->rSequenceStruct(), elmt->diagram(), elmt);
|
|
setPlainText(label);
|
|
}
|
|
else
|
|
{
|
|
setPlainText("");
|
|
}
|
|
}
|
|
else if (m_text_from == CompositeText) {
|
|
setPlainText(reportReplacedCompositeText());
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::updateLabel
|
|
Update the displayed text, when this dynamic text is based on the label of the parent element.
|
|
This function is notably use when the label itself is based from a formula.
|
|
If this dynamic text isn't based on label, this function do nothing.
|
|
*/
|
|
void DynamicElementTextItem::updateLabel()
|
|
{
|
|
if ((m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
|
|
{
|
|
DiagramContext dc;
|
|
Element *element = elementUseForInfo();
|
|
if(element) {
|
|
dc = element->elementInformations();
|
|
}
|
|
|
|
|
|
if(m_text_from == ElementInfo && element) {
|
|
setPlainText(element->actualLabel());
|
|
}
|
|
else if (m_text_from == CompositeText) {
|
|
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, dc));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::conductorWasAdded
|
|
Function only use when parent element is a folio report
|
|
@param conductor
|
|
*/
|
|
void DynamicElementTextItem::conductorWasAdded(Conductor *conductor)
|
|
{
|
|
Q_UNUSED(conductor)
|
|
QTimer::singleShot(100, this, [this]() {
|
|
setPotentialConductor();
|
|
conductorPropertiesChanged();
|
|
});
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::conductorWasRemoved
|
|
Function only use when parent element is a folio report
|
|
@param conductor
|
|
*/
|
|
void DynamicElementTextItem::conductorWasRemoved(Conductor *conductor)
|
|
{
|
|
if(m_watched_conductor.data() == conductor)
|
|
{
|
|
disconnect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged);
|
|
m_watched_conductor.clear();
|
|
setPotentialConductor();
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::setPotentialConductor
|
|
This function is only used when the parent element of this text is a report element
|
|
Get a conductor in the potential of the parent report
|
|
*/
|
|
void DynamicElementTextItem::setPotentialConductor()
|
|
{
|
|
if(parentElement() && ((parentElement()->linkType() & Element::AllReport) || (parentElement()->linkType() == Element::ConductorDefinition) ||
|
|
parentElement()->linkType() == Element::ConductorDefinition))
|
|
{
|
|
if(parentElement()->terminals().isEmpty())
|
|
return;
|
|
|
|
/*
|
|
* #First case, if m_watched_conductor is a conductor of the parent report, everything is ok
|
|
* #Second case, if the conductors list of parent report element is not empty,
|
|
* we set one of these conductor as m_watched_conductor, even if m_watched_conductor is already set,
|
|
* because that mean the conductor is a conductor of the linked report, and we prefer to set a conductor
|
|
* owned by the parent report element of this text.
|
|
* #third case, if m_watched_conductor is null, we set a conductor of the linked report, if any.
|
|
*/
|
|
QList<Conductor *> c_list = parentElement()->terminals().first()->conductors();
|
|
|
|
if(!c_list.isEmpty() && c_list.contains(m_watched_conductor.data()))
|
|
return;
|
|
else if(!c_list.isEmpty())
|
|
{
|
|
if(!m_watched_conductor.isNull())
|
|
disconnect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged);
|
|
|
|
m_watched_conductor = c_list.first();
|
|
connect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged);
|
|
}
|
|
else if(m_watched_conductor.isNull() && m_other_report)
|
|
{
|
|
if (!m_other_report.data()->terminals().first()->conductors().isEmpty())
|
|
{
|
|
m_watched_conductor = m_other_report.data()->terminals().first()->conductors().first();
|
|
connect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged);
|
|
}
|
|
}
|
|
conductorPropertiesChanged();
|
|
}
|
|
else //This text haven't got a parent element, then ther isn't a conductor in the potential
|
|
{
|
|
if(!m_watched_conductor.isNull())
|
|
disconnect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged);
|
|
|
|
m_watched_conductor.clear();
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::conductorPropertiesChanged
|
|
This function is only used when the parent element of this text is a report element
|
|
*/
|
|
void DynamicElementTextItem::conductorPropertiesChanged()
|
|
{
|
|
if(m_parent_element && ((m_parent_element.data()->linkType() & Element::AllReport) || (m_parent_element.data()->linkType() == Element::ConductorDefinition) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition))
|
|
{
|
|
if(m_text_from == ElementInfo)
|
|
{
|
|
if(m_info_name == QETInformation::COND_FUNCTION)
|
|
setPlainText(m_watched_conductor? m_watched_conductor.data()->properties().m_function : "");
|
|
else if (m_info_name == QETInformation::COND_TENSION_PROTOCOL)
|
|
setPlainText(m_watched_conductor? m_watched_conductor.data()->properties().m_tension_protocol : "");
|
|
else if (m_info_name == QETInformation::COND_COLOR)
|
|
setPlainText(m_watched_conductor? m_watched_conductor.data()->properties().m_wire_color : "");
|
|
else if (m_info_name == QETInformation::COND_SECTION)
|
|
setPlainText(m_watched_conductor? m_watched_conductor.data()->properties().m_wire_section : "");
|
|
}
|
|
else if (m_text_from == CompositeText) {
|
|
setPlainText(reportReplacedCompositeText());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::reportReplacedCompositeText
|
|
This function is only used when the parent element of this text is a report element
|
|
@return the composite text with the variable replaced by the real value.
|
|
If the parent element of this text is not a folio report, return a default QString.
|
|
*/
|
|
QString DynamicElementTextItem::reportReplacedCompositeText() const
|
|
{
|
|
QString string;
|
|
|
|
if((m_parent_element.data()->linkType() & Element::AllReport) || (m_parent_element.data()->linkType() == Element::ConductorDefinition) ||
|
|
m_parent_element.data()->linkType() == Element::ConductorDefinition)
|
|
{
|
|
string = m_composite_text;
|
|
|
|
if (string.contains("%{label}") && m_other_report)
|
|
{
|
|
Element *elmt = m_other_report.data();
|
|
QString label = m_report_formula;
|
|
label = autonum::AssignVariables::formulaToLabel(label, elmt->rSequenceStruct(), elmt->diagram(), elmt);
|
|
string.replace("%{label}", label);
|
|
}
|
|
// if element is not linked, replace an empty string
|
|
else
|
|
{
|
|
string.replace("%{label}", "");
|
|
}
|
|
|
|
if (m_watched_conductor)
|
|
{
|
|
if(string.contains("%{function}"))
|
|
string.replace("%{function}", m_watched_conductor.data()->properties().m_function);
|
|
if(string.contains("%{tension_protocol}"))
|
|
string.replace("%{tension_protocol}", m_watched_conductor.data()->properties().m_tension_protocol);
|
|
if(string.contains("%{conductor_color}"))
|
|
string.replace("%{conductor_color}", m_watched_conductor.data()->properties().m_wire_color);
|
|
if(string.contains("%{conductor_section}"))
|
|
string.replace("%{conductor_section}", m_watched_conductor.data()->properties().m_wire_section);
|
|
}
|
|
// if no conductor is connected, replace an empty String
|
|
else
|
|
{
|
|
if(string.contains("%{function}"))
|
|
string.replace("%{function}", "");
|
|
if(string.contains("%{tension_protocol}"))
|
|
string.replace("%{tension_protocol}", "");
|
|
if(string.contains("%{conductor_color}"))
|
|
string.replace("%{conductor_color}", "");
|
|
if(string.contains("%{conductor_section}"))
|
|
string.replace("%{conductor_section}", "");
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::zoomToLinkedElement
|
|
If the parent element is a folio report or a slave element,
|
|
and is linked, zoom to the linked element
|
|
*/
|
|
void DynamicElementTextItem::zoomToLinkedElement()
|
|
{
|
|
if(!parentElement())
|
|
return;
|
|
|
|
Element *zoomed_element = nullptr;
|
|
|
|
if(parentElement()->linkType() == Element::Slave && m_master_element)
|
|
{
|
|
if ((m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
|
|
zoomed_element = m_master_element.data();
|
|
}
|
|
if((parentElement()->linkType() & Element::AllReport) && m_other_report)
|
|
{
|
|
if((m_text_from == ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
|
|
zoomed_element = m_other_report.data();
|
|
}
|
|
|
|
if(zoomed_element)
|
|
{
|
|
//Unselect and ungrab mouse to prevent unwanted
|
|
//move when linked element is in the same scene of this.
|
|
setSelected(false);
|
|
ungrabMouse();
|
|
|
|
QetGraphicsItem::showItem(zoomed_element);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief DynamicElementTextItem::parentElementRotationChanged
|
|
* Called when the parent element is rotated
|
|
*/
|
|
void DynamicElementTextItem::parentElementRotationChanged()
|
|
{
|
|
if (m_parent_element && m_keep_visual_rotation)
|
|
{
|
|
//We temporally disconnect for not change m_visual_rotation value.
|
|
//We don't use block signal, because rotationChanged signal is used in other place.
|
|
disconnect(this, &DynamicElementTextItem::rotationChanged, this, &DynamicElementTextItem::thisRotationChanged);
|
|
this->setRotation(QET::correctAngle(m_visual_rotation_ref - m_parent_element->rotation(), true));
|
|
connect(this, &DynamicElementTextItem::rotationChanged, this, &DynamicElementTextItem::thisRotationChanged);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief DynamicElementTextItem::thisRotationChanged
|
|
* This function is called when user change the rotation of the text
|
|
* and "keep visual rotation" is to true
|
|
* to keep in memory the visual rotation wanted by the user.
|
|
*/
|
|
void DynamicElementTextItem::thisRotationChanged() {
|
|
m_visual_rotation_ref = this->rotation() + m_parent_element->rotation();
|
|
}
|
|
|
|
/**
|
|
@brief DynamicElementTextItem::updateXref
|
|
Create or delete the Xref according to the current properties of the project
|
|
*/
|
|
void DynamicElementTextItem::updateXref()
|
|
{
|
|
if(diagram())
|
|
{
|
|
if(m_parent_element.data()->linkType() == Element::Master)
|
|
{
|
|
XRefProperties xrp = diagram()->project()->defaultXRefProperties(m_parent_element.data()->kindInformations()["type"].toString());
|
|
|
|
if(m_text_from == DynamicElementTextItem::ElementInfo &&
|
|
m_info_name == "label" &&
|
|
!m_parent_element.data()->linkedElements().isEmpty() &&
|
|
xrp.snapTo() == XRefProperties::Label)
|
|
{
|
|
//For add a Xref, this text must not be in a group
|
|
if(!parentGroup())
|
|
{
|
|
if(!m_Xref_item)
|
|
m_Xref_item = new CrossRefItem(m_parent_element.data(), this);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if (m_parent_element.data()->linkType() == Element::Slave)
|
|
{
|
|
if(m_master_element && !parentGroup() &&
|
|
(
|
|
(m_text_from == DynamicElementTextItem::ElementInfo && m_info_name == "label") ||
|
|
(m_text_from == DynamicElementTextItem::CompositeText && m_composite_text.contains("%{label}"))
|
|
)
|
|
)
|
|
{
|
|
XRefProperties xrp = diagram()->project()->defaultXRefProperties(m_master_element.data()->kindInformations()["type"].toString());
|
|
QString xref_label = xrp.slaveLabel();
|
|
xref_label = autonum::AssignVariables::formulaToLabel(xref_label, m_master_element.data()->rSequenceStruct(), m_master_element.data()->diagram(), m_master_element.data());
|
|
|
|
if(!m_slave_Xref_item)
|
|
{
|
|
m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
|
|
m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
|
|
m_slave_Xref_item->setDefaultTextColor(Qt::black);
|
|
m_slave_Xref_item->installSceneEventFilter(this);
|
|
|
|
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::yChanged, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(diagram(), &Diagram::diagramInformationChanged, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateXref);
|
|
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &DynamicElementTextItem::updateXref);
|
|
}
|
|
else
|
|
m_slave_Xref_item->setPlainText(xref_label);
|
|
setXref_item(xrp.getXrefPos());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//There is no reason to have a xref, we delete it if exist
|
|
if(m_Xref_item)
|
|
{
|
|
delete m_Xref_item;
|
|
m_Xref_item = nullptr;
|
|
}
|
|
|
|
if(m_slave_Xref_item)
|
|
{
|
|
delete m_slave_Xref_item;
|
|
m_slave_Xref_item = nullptr;
|
|
m_update_slave_Xref_connection.clear();
|
|
}
|
|
}
|
|
|
|
void DynamicElementTextItem::setPlainText(const QString &text)
|
|
{
|
|
if (toPlainText() == text)
|
|
return;
|
|
|
|
|
|
bool update_alignment = true;
|
|
if (diagram() && (diagram()->project()->state() == QETProject::ProjectParsingRunning))
|
|
update_alignment = false;
|
|
if (m_parent_element.data()->state() == QET::GIBuildingFromXml ||
|
|
m_parent_element.data()->state() == QET::GILoadingFromXml)
|
|
update_alignment = false;
|
|
|
|
if (update_alignment) {
|
|
prepareAlignment();
|
|
}
|
|
|
|
DiagramTextItem::setPlainText(text);
|
|
|
|
//User define a text width
|
|
if (m_text_width > 0)
|
|
{
|
|
if (document()->size().width() > m_text_width)
|
|
{
|
|
document()->setTextWidth(m_text_width);
|
|
if (document()->size().width() > m_text_width)
|
|
{
|
|
document()->setTextWidth(document()->idealWidth());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (update_alignment) {
|
|
finishAlignment();
|
|
}
|
|
|
|
if (m_Xref_item) {
|
|
m_Xref_item->autoPos();
|
|
}
|
|
else if (m_slave_Xref_item)
|
|
{
|
|
|
|
XRefProperties xrp = diagram()->project()->defaultXRefProperties(m_master_element.data()->kindInformations()["type"].toString());
|
|
setXref_item(xrp.getXrefPos());
|
|
}
|
|
}
|
|
|
|
void DynamicElementTextItem::setTextWidth(qreal width)
|
|
{
|
|
this->document()->setTextWidth(width);
|
|
m_text_width = width;
|
|
emit textWidthChanged(width);
|
|
}
|
|
|
|
void DynamicElementTextItem::setXref_item(Qt::AlignmentFlag m_exHrefPos)
|
|
{
|
|
QRectF r = boundingRect();
|
|
QPointF pos;
|
|
//QPointF pos(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,r.top());
|
|
if (m_exHrefPos == Qt::AlignBottom)
|
|
{
|
|
pos = QPointF(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,r.bottom());
|
|
}
|
|
else if (m_exHrefPos == Qt::AlignTop)
|
|
{
|
|
pos = QPointF(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,r.top() - m_slave_Xref_item->boundingRect().height());
|
|
}
|
|
else if (m_exHrefPos == Qt::AlignLeft) //
|
|
{
|
|
pos = QPointF(r.left() - m_slave_Xref_item->boundingRect().width(),r.center().y() - m_slave_Xref_item->boundingRect().height()/2);
|
|
}
|
|
else if (m_exHrefPos == Qt::AlignRight) //
|
|
{
|
|
pos = QPointF(r.right() ,r.center().y() - m_slave_Xref_item->boundingRect().height()/2);
|
|
}
|
|
else if (m_exHrefPos == Qt::AlignBaseline) //
|
|
{
|
|
if(this->alignment() &Qt::AlignBottom)
|
|
{
|
|
pos = QPointF(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,r.bottom());
|
|
}
|
|
else if(this->alignment() &Qt::AlignTop)
|
|
{
|
|
pos = QPointF(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,r.top() - m_slave_Xref_item->boundingRect().height());
|
|
}
|
|
else if(this->alignment() &Qt::AlignLeft)
|
|
{
|
|
pos = QPointF(r.left() - m_slave_Xref_item->boundingRect().width(),r.center().y() - m_slave_Xref_item->boundingRect().height()/2);
|
|
}
|
|
else if(this->alignment() &Qt::AlignRight)
|
|
{
|
|
pos = QPointF(r.right() ,r.center().y() - m_slave_Xref_item->boundingRect().height()/2);
|
|
}
|
|
}
|
|
m_slave_Xref_item->setPos(pos);
|
|
|
|
return;
|
|
}
|
|
|
|
void DynamicElementTextItem::setKeepVisualRotation(bool set)
|
|
{
|
|
m_keep_visual_rotation = set;
|
|
emit keepVisualRotationChanged(set);
|
|
if (set) {
|
|
m_visual_rotation_ref = this->rotation() + m_parent_element->rotation();
|
|
connect(m_parent_element, &Element::rotationChanged, this, &DynamicElementTextItem::parentElementRotationChanged);
|
|
connect(this, &DynamicElementTextItem::rotationChanged, this, &DynamicElementTextItem::thisRotationChanged);
|
|
}
|
|
else {
|
|
disconnect(m_parent_element, &Element::rotationChanged, this, &DynamicElementTextItem::parentElementRotationChanged);
|
|
disconnect(this, &DynamicElementTextItem::rotationChanged, this, &DynamicElementTextItem::thisRotationChanged);
|
|
}
|
|
}
|
|
|
|
bool DynamicElementTextItem::keepVisualRotation() const {
|
|
return m_keep_visual_rotation;
|
|
}
|
|
|