Feature: Add terminal name label display in element editor

This commit is contained in:
Kellermorph
2026-07-09 14:02:27 +02:00
parent 99ad9aa459
commit c884d32dbe
8 changed files with 753 additions and 82 deletions
+229 -1
View File
@@ -17,6 +17,8 @@
*/
#include "partterminal.h"
#include "../elementscene.h"
#include "../../QPropertyUndoCommand/qpropertyundocommand.h"
#include "../../qetgraphicsitem/terminal.h"
/**
@@ -100,6 +102,60 @@ void PartTerminal::paint(
if (m_hovered)
drawShadowShape(painter);
if (d->m_show_name && !d->m_name.isEmpty()) {
painter->save();
painter->setFont(d->m_label_font);
painter->setPen(d->m_label_color);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::TextAntialiasing, true);
QPointF label_pos = d->m_label_pos;
QRectF text_rect;
QFontMetrics fm(d->m_label_font);
QSizeF text_size = fm.size(Qt::TextSingleLine, d->m_name);
auto compute_rect = [&]() {
qreal dx = 0, dy = 0;
if (d->m_label_halignment & Qt::AlignLeft) dx = 0;
else if (d->m_label_halignment & Qt::AlignHCenter) dx = -text_size.width() / 2.0;
else if (d->m_label_halignment & Qt::AlignRight) dx = -text_size.width();
if (d->m_label_valignment & Qt::AlignTop) dy = 0;
else if (d->m_label_valignment & Qt::AlignVCenter) dy = -text_size.height() / 2.0;
else if (d->m_label_valignment & Qt::AlignBottom) dy = -text_size.height();
return QRectF(label_pos + QPointF(dx, dy), text_size);
};
if (d->m_label_rotation != 0.0) {
painter->translate(label_pos);
painter->rotate(d->m_label_rotation);
text_rect = QRectF(-text_size.width()/2.0, -text_size.height()/2.0,
text_size.width(), text_size.height());
if (d->m_label_frame) {
painter->drawRect(text_rect.adjusted(-1, -1, 1, 1));
}
painter->drawText(text_rect, static_cast<int>(d->m_label_halignment | d->m_label_valignment), d->m_name);
} else {
text_rect = compute_rect();
if (d->m_label_frame) {
painter->drawRect(text_rect.adjusted(-1, -1, 1, 1));
}
painter->drawText(text_rect, static_cast<int>(Qt::AlignLeft | Qt::AlignTop), d->m_name);
}
if (isSelected() || m_hovered) {
QPen outline_pen(Qt::darkBlue, 0, Qt::DashLine);
painter->setPen(outline_pen);
painter->setBrush(Qt::NoBrush);
if (d->m_label_rotation != 0.0) {
painter->drawRect(text_rect.adjusted(-1, -1, 1, 1));
} else {
painter->drawRect(text_rect.adjusted(-1, -1, 1, 1));
}
}
painter->restore();
}
}
/**
@@ -114,7 +170,27 @@ QPainterPath PartTerminal::shape() const
QPainterPathStroker pps;
pps.setWidth(1);
return (pps.createStroke(shape));
QPainterPath path = pps.createStroke(shape);
if (d->m_show_name && !d->m_name.isEmpty()) {
path.addRect(labelRect());
}
return path;
}
/**
@brief PartTerminal::shadowShape
@return the hover outline shape (terminal line only, no label rect)
*/
QPainterPath PartTerminal::shadowShape() const
{
QPainterPath shape;
shape.lineTo(d -> m_second_point);
QPainterPathStroker pps;
pps.setWidth(1);
return pps.createStroke(shape);
}
/**
@@ -128,9 +204,40 @@ QRectF PartTerminal::boundingRect() const
qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
br.adjust(-adjust, -adjust, adjust, adjust);
if (d->m_show_name && !d->m_name.isEmpty()) {
br = br.united(labelRect());
}
return(br);
}
/**
@brief PartTerminal::labelRect
@return the rectangle of the label text (in item coordinates),
or an empty rect if the label is not shown
*/
QRectF PartTerminal::labelRect() const
{
if (!d->m_show_name || d->m_name.isEmpty())
return QRectF();
QFontMetrics fm(d->m_label_font);
QSizeF text_size = fm.size(Qt::TextSingleLine, d->m_name);
QPointF label_pos = d->m_label_pos;
qreal dx = 0, dy = 0;
if (d->m_label_halignment & Qt::AlignLeft) dx = 0;
else if (d->m_label_halignment & Qt::AlignHCenter) dx = -text_size.width() / 2.0;
else if (d->m_label_halignment & Qt::AlignRight) dx = -text_size.width();
if (d->m_label_valignment & Qt::AlignTop) dy = 0;
else if (d->m_label_valignment & Qt::AlignVCenter) dy = -text_size.height() / 2.0;
else if (d->m_label_valignment & Qt::AlignBottom) dy = -text_size.height();
return QRectF(label_pos + QPointF(dx, dy), text_size).adjusted(-3, -3, 3, 3);
}
/**
Definit l'orientation de la borne
@@ -282,6 +389,77 @@ void PartTerminal::setNewUuid()
d -> m_uuid = QUuid::createUuid();
}
void PartTerminal::setShowName(bool show)
{
if (d->m_show_name == show) return;
prepareGeometryChange();
d->m_show_name = show;
update();
emit showNameChanged();
}
void PartTerminal::setLabelPos(QPointF pos)
{
if (d->m_label_pos == pos) return;
prepareGeometryChange();
d->m_label_pos = pos;
update();
emit labelPosChanged();
}
void PartTerminal::setLabelFont(QFont font)
{
if (d->m_label_font == font) return;
prepareGeometryChange();
d->m_label_font = font;
update();
emit labelFontChanged();
}
void PartTerminal::setLabelRotation(qreal rotation)
{
if (qFuzzyCompare(d->m_label_rotation, rotation)) return;
prepareGeometryChange();
d->m_label_rotation = rotation;
update();
emit labelRotationChanged();
}
void PartTerminal::setLabelHAlignment(Qt::Alignment align)
{
if (d->m_label_halignment == align) return;
prepareGeometryChange();
d->m_label_halignment = align;
update();
emit labelHAlignmentChanged();
}
void PartTerminal::setLabelVAlignment(Qt::Alignment align)
{
if (d->m_label_valignment == align) return;
prepareGeometryChange();
d->m_label_valignment = align;
update();
emit labelVAlignmentChanged();
}
void PartTerminal::setLabelFrame(bool frame)
{
if (d->m_label_frame == frame) return;
prepareGeometryChange();
d->m_label_frame = frame;
update();
emit labelFrameChanged();
}
void PartTerminal::setLabelColor(QColor color)
{
if (d->m_label_color == color) return;
d->m_label_color = color;
update();
emit labelColorChanged();
}
/**
Updates the position of the second point according to the position
and orientation of the terminal.
@@ -338,3 +516,53 @@ void PartTerminal::handleUserTransformation(const QRectF &initial_selection_rect
initial_selection_rect, new_selection_rect, QList<QPointF>() << saved_position_).first();
setPos(mapped_point);
}
void PartTerminal::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton && d->m_show_name && !d->m_name.isEmpty()) {
QPointF local_click = event->pos();
// Only start label drag when click is on label AND NOT on terminal line
if (!shadowShape().contains(local_click) && labelRect().contains(local_click)) {
m_dragging_label = true;
m_original_label_pos = d->m_label_pos;
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
void PartTerminal::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (m_dragging_label) {
QPointF delta = event->pos() - event->buttonDownPos(Qt::LeftButton);
QPointF new_pos = m_original_label_pos + delta;
if (!(event->modifiers() & Qt::ControlModifier)) {
ElementScene *scene = elementScene();
if (scene) {
QPointF scene_pos = mapToScene(new_pos);
new_pos = mapFromScene(scene->snapToGrid(scene_pos));
}
}
setLabelPos(new_pos);
update();
event->accept();
return;
}
CustomElementGraphicPart::mouseMoveEvent(event);
}
void PartTerminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (m_dragging_label) {
m_dragging_label = false;
if (m_original_label_pos != d->m_label_pos) {
auto undo = new QPropertyUndoCommand(this, "label_pos",
QVariant(m_original_label_pos), QVariant(d->m_label_pos));
undo->setText(tr("Déplacer le label d'une borne"));
undo->enableAnimation();
elementScene()->undoStack().push(undo);
}
event->accept();
return;
}
CustomElementGraphicPart::mouseReleaseEvent(event);
}
+50 -1
View File
@@ -34,6 +34,14 @@ class PartTerminal : public CustomElementGraphicPart
Q_PROPERTY(Qet::Orientation orientation READ orientation WRITE setOrientation)
Q_PROPERTY(QString terminal_name READ terminalName WRITE setTerminalName)
Q_PROPERTY(TerminalData::Type terminal_type READ terminalType WRITE setTerminalType)
Q_PROPERTY(bool show_name READ showName WRITE setShowName)
Q_PROPERTY(QPointF label_pos READ labelPos WRITE setLabelPos)
Q_PROPERTY(QFont label_font READ labelFont WRITE setLabelFont)
Q_PROPERTY(qreal label_rotation READ labelRotation WRITE setLabelRotation)
Q_PROPERTY(Qt::Alignment label_halignment READ labelHAlignment WRITE setLabelHAlignment)
Q_PROPERTY(Qt::Alignment label_valignment READ labelVAlignment WRITE setLabelVAlignment)
Q_PROPERTY(bool label_frame READ labelFrame WRITE setLabelFrame)
Q_PROPERTY(QColor label_color READ labelColor WRITE setLabelColor)
public:
// constructors, destructor
@@ -46,6 +54,14 @@ class PartTerminal : public CustomElementGraphicPart
void orientationChanged();
void nameChanged();
void terminalTypeChanged();
void showNameChanged();
void labelPosChanged();
void labelFontChanged();
void labelRotationChanged();
void labelHAlignmentChanged();
void labelVAlignmentChanged();
void labelFrameChanged();
void labelColorChanged();
// methods
public:
@@ -64,7 +80,7 @@ class PartTerminal : public CustomElementGraphicPart
QWidget *) override;
QPainterPath shape() const override;
QPainterPath shadowShape() const override {return shape();}
QPainterPath shadowShape() const override;
QRectF boundingRect() const override;
bool isUseless() const override;
QRectF sceneGeometricRect() const override;
@@ -90,13 +106,46 @@ class PartTerminal : public CustomElementGraphicPart
TerminalData::Type terminalType() const {return d->m_type;}
void setTerminalType(TerminalData::Type type);
bool showName() const { return d->m_show_name; }
void setShowName(bool show);
QPointF labelPos() const { return d->m_label_pos; }
void setLabelPos(QPointF pos);
QFont labelFont() const { return d->m_label_font; }
void setLabelFont(QFont font);
qreal labelRotation() const { return d->m_label_rotation; }
void setLabelRotation(qreal rotation);
Qt::Alignment labelHAlignment() const { return d->m_label_halignment; }
void setLabelHAlignment(Qt::Alignment align);
Qt::Alignment labelVAlignment() const { return d->m_label_valignment; }
void setLabelVAlignment(Qt::Alignment align);
bool labelFrame() const { return d->m_label_frame; }
void setLabelFrame(bool frame);
QColor labelColor() const { return d->m_label_color; }
void setLabelColor(QColor color);
void setNewUuid();
QRectF labelRect() const;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
void updateSecondPoint();
TerminalData* d; // pointer to the terminal data
private:
QPointF saved_position_;
bool m_dragging_label = false;
QPointF m_original_label_pos;
};
#endif