mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 23:54:22 +01:00
Symbol texts: width and height, each fixed or not
In a symbol text's properties, "Width (fixed)" and the new "Height (fixed)" each carry a tick box. Not ticked, the field follows the text and shows the size it has now, ready to be fixed; ticked, it keeps the size beside the box. A fixed height is new: the field keeps it whatever is written, and the lines that do not fit are cut off, neither drawn nor picked, to shorten a text where room is short. It is saved as text_height on the text, only when set, and changed through an undoable property command like the width. Translations for all languages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -175,6 +175,8 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const
|
||||
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));
|
||||
if (m_text_height > 0)
|
||||
root_element.setAttribute(QStringLiteral("text_height"), QString::number(m_text_height));
|
||||
root_element.setAttribute("font", QETUtils::fontToString(font()));
|
||||
root_element.setAttribute("keep_visual_rotation", m_keep_visual_rotation ? "true" : "false");
|
||||
root_element.setAttribute("rotation_point_center", m_rotation_point_center ? "true" : "false");
|
||||
@@ -262,6 +264,7 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt)
|
||||
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());
|
||||
setTextHeight(dom_elmt.attribute(QStringLiteral("text_height"), QStringLiteral("-1")).toDouble());
|
||||
|
||||
//Text from
|
||||
QMetaEnum me = textFromMetaEnum();
|
||||
@@ -867,7 +870,15 @@ void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphics
|
||||
if (m_jump_highlight)
|
||||
painter->fillRect(boundingRect(), QColor(69, 137, 255, 90));
|
||||
|
||||
DiagramTextItem::paint(painter, option, widget);
|
||||
//A fixed height cuts off the lines that do not fit
|
||||
if (m_text_height > 0) {
|
||||
painter->save();
|
||||
painter->setClipRect(boundingRect(), Qt::IntersectClip);
|
||||
DiagramTextItem::paint(painter, option, widget);
|
||||
painter->restore();
|
||||
} else {
|
||||
DiagramTextItem::paint(painter, option, widget);
|
||||
}
|
||||
|
||||
if (m_frame)
|
||||
{
|
||||
@@ -2069,6 +2080,60 @@ void DynamicElementTextItem::setTextWidth(qreal width)
|
||||
emit textWidthChanged(width);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief DynamicElementTextItem::setTextHeight
|
||||
@param height : the height of the text field, -1 to follow the text.
|
||||
With a height set, the field keeps it whatever is written: the lines
|
||||
that do not fit are not drawn, to shorten a text where room is short.
|
||||
*/
|
||||
void DynamicElementTextItem::setTextHeight(qreal height)
|
||||
{
|
||||
if (height <= 0)
|
||||
height = -1;
|
||||
if (qFuzzyCompare(height + 2, m_text_height + 2))
|
||||
return;
|
||||
prepareGeometryChange();
|
||||
m_text_height = height;
|
||||
update();
|
||||
emit textHeightChanged(height);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief DynamicElementTextItem::boundingRect
|
||||
@return the text's own box, cut to the height set by the user
|
||||
*/
|
||||
QRectF DynamicElementTextItem::boundingRect() const
|
||||
{
|
||||
QRectF rect = DiagramTextItem::boundingRect();
|
||||
if (m_text_height > 0)
|
||||
rect.setHeight(m_text_height);
|
||||
return rect;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief DynamicElementTextItem::shape
|
||||
QGraphicsTextItem answers shape() and contains() from its own box, not
|
||||
from boundingRect(): cut both to the height set by the user, so that
|
||||
the lines cut off take no clicks either.
|
||||
*/
|
||||
QPainterPath DynamicElementTextItem::shape() const
|
||||
{
|
||||
QPainterPath path = DiagramTextItem::shape();
|
||||
if (m_text_height > 0) {
|
||||
QPainterPath cut;
|
||||
cut.addRect(boundingRect());
|
||||
path = path.intersected(cut);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool DynamicElementTextItem::contains(const QPointF &point) const
|
||||
{
|
||||
if (m_text_height > 0 && !boundingRect().contains(point))
|
||||
return false;
|
||||
return DiagramTextItem::contains(point);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief DynamicElementTextItem::fitAutoTextWidth
|
||||
With no width set by the user, a QTextDocument has no width to centre
|
||||
|
||||
@@ -51,6 +51,7 @@ class DynamicElementTextItem : public DiagramTextItem
|
||||
Q_PROPERTY(QString compositeText READ compositeText WRITE setCompositeText NOTIFY compositeTextChanged)
|
||||
Q_PROPERTY(bool frame READ frame WRITE setFrame NOTIFY frameChanged)
|
||||
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth NOTIFY textWidthChanged)
|
||||
Q_PROPERTY(qreal textHeight READ textHeight WRITE setTextHeight NOTIFY textHeightChanged)
|
||||
Q_PROPERTY(bool keepVisualRotation READ keepVisualRotation WRITE setKeepVisualRotation NOTIFY keepVisualRotationChanged)
|
||||
Q_PROPERTY(bool rotationPointCenter READ rotationPointCenter WRITE setRotationPointCenter NOTIFY rotationPointCenterChanged)
|
||||
public:
|
||||
@@ -72,6 +73,7 @@ class DynamicElementTextItem : public DiagramTextItem
|
||||
void frameChanged(bool frame);
|
||||
void plainTextChanged();
|
||||
void textWidthChanged(qreal width);
|
||||
void textHeightChanged(qreal height);
|
||||
void keepVisualRotationChanged(bool keep);
|
||||
void rotationPointCenterChanged(bool center);
|
||||
|
||||
@@ -122,6 +124,13 @@ class DynamicElementTextItem : public DiagramTextItem
|
||||
//centred or right-aligned, but the width is still "auto" (-1).
|
||||
qreal textWidth() const {return m_text_width;}
|
||||
void setTextWidth(qreal width);
|
||||
//A height set by the user, -1 for "auto": lines that do not
|
||||
//fit are cut off, as a text field of fixed size does
|
||||
qreal textHeight() const {return m_text_height;}
|
||||
void setTextHeight(qreal height);
|
||||
QRectF boundingRect() const override;
|
||||
QPainterPath shape() const override;
|
||||
bool contains(const QPointF &point) const override;
|
||||
void setXref_item(Qt::AlignmentFlag m_exHrefPos, int slave_offset = 0);
|
||||
|
||||
void setKeepVisualRotation(bool set);
|
||||
@@ -204,6 +213,7 @@ class DynamicElementTextItem : public DiagramTextItem
|
||||
QGraphicsTextItem *m_slave_Xref_item = nullptr;
|
||||
qreal m_text_width = -1;
|
||||
bool m_jump_highlight = false;
|
||||
qreal m_text_height = -1;
|
||||
/// The text was emptied with its alignment kept (setPlainText())
|
||||
bool m_emptied_aligned = false;
|
||||
QPointF m_initial_position;
|
||||
|
||||
@@ -48,11 +48,12 @@ static int font_txt_row = 5;
|
||||
static int color_txt_row = 6;
|
||||
static int frame_txt_row = 7;
|
||||
static int width_txt_row = 8;
|
||||
static int x_txt_row = 9;
|
||||
static int y_txt_row = 10;
|
||||
static int rot_txt_row = 11;
|
||||
static int keep_rot_row = 12;
|
||||
static int align_txt_row = 13;
|
||||
static int height_txt_row = 9;
|
||||
static int x_txt_row = 10;
|
||||
static int y_txt_row = 11;
|
||||
static int rot_txt_row = 12;
|
||||
static int keep_rot_row = 13;
|
||||
static int align_txt_row = 14;
|
||||
|
||||
static int align_grp_row = 0;
|
||||
static int x_grp_row = 1;
|
||||
@@ -96,6 +97,27 @@ DynamicElementTextModel::~DynamicElementTextModel()
|
||||
setConnection(group, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief setSizeItems
|
||||
Show the width and the height of @a deti: ticked with the size set
|
||||
when it is fixed, not ticked with the size the field has now when it
|
||||
follows the text, so that ticking it fixes what one sees.
|
||||
*/
|
||||
static void setSizeItems(QStandardItem *width, QStandardItem *height, DynamicElementTextItem *deti)
|
||||
{
|
||||
const QRectF box = deti->boundingRect();
|
||||
if (width) {
|
||||
const bool fixed = deti->textWidth() > 0;
|
||||
width->setCheckState(fixed ? Qt::Checked : Qt::Unchecked);
|
||||
width->setData(qRound(fixed ? deti->textWidth() : box.width()), Qt::EditRole);
|
||||
}
|
||||
if (height) {
|
||||
const bool fixed = deti->textHeight() > 0;
|
||||
height->setCheckState(fixed ? Qt::Checked : Qt::Unchecked);
|
||||
height->setData(qRound(fixed ? deti->textHeight() : box.height()), Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief DynamicElementTextModel::indexIsInGroup
|
||||
@param index
|
||||
@@ -281,20 +303,41 @@ QList<QStandardItem *> DynamicElementTextModel::itemsForText(
|
||||
qsi_list << frame << frame_a;
|
||||
qsi->appendRow(qsi_list);
|
||||
|
||||
//Width
|
||||
QStandardItem *width = new QStandardItem(tr("Width"));
|
||||
//Width and height: ticked, the field keeps the size given beside
|
||||
//it; not ticked, it follows the text, and the size shown is the
|
||||
//one it has now, ready to be fixed
|
||||
QStandardItem *width = new QStandardItem(tr("Width (fixed)"));
|
||||
width->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
width->setToolTip(tr("Ticked, the text field keeps this width and the text wraps inside it. Not ticked, it is as wide as the text."));
|
||||
|
||||
QStandardItem *width_a = new QStandardItem;
|
||||
width_a->setData(deti->textWidth(), Qt::EditRole);
|
||||
width_a->setCheckable(true);
|
||||
width_a->setData(DynamicElementTextModel::textWidth, Qt::UserRole+1);
|
||||
width_a->setFlags(Qt::ItemIsSelectable
|
||||
| Qt::ItemIsEnabled
|
||||
| Qt::ItemIsEditable);
|
||||
| Qt::ItemIsEditable
|
||||
| Qt::ItemIsUserCheckable);
|
||||
|
||||
qsi_list.clear();
|
||||
qsi_list << width << width_a;
|
||||
qsi->appendRow(qsi_list);
|
||||
|
||||
QStandardItem *height = new QStandardItem(tr("Height (fixed)"));
|
||||
height->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
height->setToolTip(tr("Ticked, the text field keeps this height and the lines that do not fit are cut off. Not ticked, it is as high as the text."));
|
||||
|
||||
QStandardItem *height_a = new QStandardItem;
|
||||
height_a->setCheckable(true);
|
||||
height_a->setData(DynamicElementTextModel::textHeight, Qt::UserRole+1);
|
||||
height_a->setFlags(Qt::ItemIsSelectable
|
||||
| Qt::ItemIsEnabled
|
||||
| Qt::ItemIsEditable
|
||||
| Qt::ItemIsUserCheckable);
|
||||
|
||||
qsi_list.clear();
|
||||
qsi_list << height << height_a;
|
||||
qsi->appendRow(qsi_list);
|
||||
setSizeItems(width_a, height_a, deti);
|
||||
|
||||
if(deti->parentGroup() == nullptr)
|
||||
{
|
||||
@@ -587,13 +630,24 @@ QUndoCommand *DynamicElementTextModel::undoForEditedText(
|
||||
quc->setText(tr("Modify the frame of an element text"));
|
||||
}
|
||||
|
||||
qreal text_width = text_qsi->child(width_txt_row, 1)->data(Qt::EditRole).toDouble();
|
||||
QStandardItem *width_item = text_qsi->child(width_txt_row, 1);
|
||||
qreal text_width = width_item->checkState() == Qt::Checked
|
||||
? width_item->data(Qt::EditRole).toDouble() : -1;
|
||||
if(text_width != deti->textWidth())
|
||||
{
|
||||
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "textWidth", QVariant(deti->textWidth()), QVariant(text_width), undo);
|
||||
quc->setAnimated(true, false);
|
||||
quc->setText(tr("Change the width of an element text"));
|
||||
}
|
||||
|
||||
QStandardItem *height_item = text_qsi->child(height_txt_row, 1);
|
||||
qreal text_height = height_item->checkState() == Qt::Checked
|
||||
? height_item->data(Qt::EditRole).toDouble() : -1;
|
||||
if(text_height != deti->textHeight())
|
||||
{
|
||||
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "textHeight", QVariant(deti->textHeight()), QVariant(text_height), undo);
|
||||
quc->setText(tr("Change the height of an element text"));
|
||||
}
|
||||
|
||||
//When text is in a group, they're isn't item for position of the text
|
||||
if(text_qsi->child(x_txt_row,1) && text_qsi->child(y_txt_row,1))
|
||||
@@ -1388,6 +1442,7 @@ void DynamicElementTextModel::setConnection(DynamicElementTextItem *deti, bool s
|
||||
connection_list << connect(deti, &DynamicElementTextItem::frameChanged, [deti,this](){this->updateDataFromText(deti, frame);});
|
||||
connection_list << connect(deti, &DynamicElementTextItem::rotationChanged, [deti,this](){this->updateDataFromText(deti, rotation);});
|
||||
connection_list << connect(deti, &DynamicElementTextItem::textWidthChanged,[deti,this](){this->updateDataFromText(deti, textWidth);});
|
||||
connection_list << connect(deti, &DynamicElementTextItem::textHeightChanged,[deti,this](){this->updateDataFromText(deti, textHeight);});
|
||||
connection_list << connect(deti, &DynamicElementTextItem::compositeTextChanged, [deti, this]() {this->updateDataFromText(deti, compositeText);});
|
||||
m_hash_text_connect.insert(deti, connection_list);
|
||||
}
|
||||
@@ -1525,15 +1580,16 @@ void DynamicElementTextModel::updateDataFromText(DynamicElementTextItem *deti,
|
||||
break;
|
||||
}
|
||||
case textWidth:
|
||||
case textHeight:
|
||||
{
|
||||
qsi->child(width_txt_row,1)->setData(deti->textWidth(), Qt::EditRole);
|
||||
setSizeItems(qsi->child(width_txt_row,1), qsi->child(height_txt_row,1), deti);
|
||||
break;
|
||||
}
|
||||
default:break;
|
||||
}
|
||||
|
||||
//Rotating or resizing the text moves its anchor point (Position X/Y)
|
||||
if ((type == rotation || type == textWidth)
|
||||
if ((type == rotation || type == textWidth || type == textHeight)
|
||||
&& qsi->child(x_txt_row,1) && qsi->child(y_txt_row,1))
|
||||
{
|
||||
qsi->child(x_txt_row,1)->setData(deti->anchorPos().x(), Qt::EditRole);
|
||||
@@ -1761,10 +1817,12 @@ QWidget *DynamicTextItemDelegate::createEditor(
|
||||
return sb;
|
||||
}
|
||||
case DynamicElementTextModel::textWidth:
|
||||
case DynamicElementTextModel::textHeight:
|
||||
{
|
||||
QSpinBox *sb = new QSpinBox(parent);
|
||||
sb->setObjectName("width_spinbox");
|
||||
sb->setRange(-1, 500);
|
||||
sb->setObjectName(index.data(Qt::UserRole+1).toInt() == DynamicElementTextModel::textWidth
|
||||
? "width_spinbox" : "height_spinbox");
|
||||
sb->setRange(1, 1000);
|
||||
sb->setFrame(false);
|
||||
sb->setSuffix(" px");
|
||||
return sb;
|
||||
|
||||
@@ -53,6 +53,7 @@ class DynamicElementTextModel : public QStandardItemModel
|
||||
rotation,
|
||||
keepVisualRotation,
|
||||
textWidth,
|
||||
textHeight,
|
||||
grpAlignment,
|
||||
grpPos,
|
||||
grpRotation,
|
||||
|
||||
Reference in New Issue
Block a user