Merge pull request #1320 from bhangart/feature/free-text-width

Let free texts keep a width they wrap to
This commit is contained in:
Laurent Trinques
2026-10-06 16:18:25 +02:00
committed by GitHub
9 changed files with 356 additions and 4 deletions
+8 -3
View File
@@ -1248,6 +1248,8 @@ void projectDataBase::addDrawingItem(QGraphicsItem *item)
}
else if (auto text = qobject_cast<IndependentTextItem *>(object)) {
connect(text, &IndependentTextItem::uuidChanged, this, &projectDataBase::drawingItemChanged, unique);
//Also changes the height of the text, kept in the row
connect(text, &IndependentTextItem::textWidthChanged, this, &projectDataBase::drawingItemChanged, unique);
//Sent by the document, not the item: drawingItemChanged() walks
//back up to the item. It is the one signal that catches every way
//the text changes -- typing, undo, a script's setTextContent().
@@ -1424,6 +1426,9 @@ bool projectDataBase::writeDrawingItem(QObject *object)
query = &m_insert_independent_text_query;
query->bindValue(QStringLiteral(":text"), text->toPlainText());
query->bindValue(QStringLiteral(":rotation"), text->rotation());
//NULL for the automatic width
query->bindValue(QStringLiteral(":text_width"), text->textWidth() > 0
? QVariant(text->textWidth()) : QVariant());
}
else if (auto image = qobject_cast<DiagramImageItem *>(object))
{
@@ -1667,7 +1672,7 @@ bool projectDataBase::createDataBase()
"type VARCHAR(20), color VARCHAR(20), fill VARCHAR(20), "
"FOREIGN KEY (diagram_uuid) REFERENCES diagram (uuid))",
QStringLiteral("CREATE TABLE independent_text (") + drawing_columns +
"text TEXT, rotation REAL, "
"text TEXT, rotation REAL, text_width REAL, "
"FOREIGN KEY (diagram_uuid) REFERENCES diagram (uuid))",
QStringLiteral("CREATE TABLE image (") + drawing_columns +
"pixel_width INTEGER, pixel_height INTEGER, "
@@ -2123,8 +2128,8 @@ void projectDataBase::prepareQuery()
", :type, :color, :fill)");
m_insert_independent_text_query = QSqlQuery(m_data_base);
m_insert_independent_text_query.prepare("INSERT OR REPLACE INTO independent_text (" + drawing_columns +
", text, rotation) VALUES (" + drawing_values +
", :text, :rotation)");
", text, rotation, text_width) VALUES (" + drawing_values +
", :text, :rotation, :text_width)");
m_insert_image_query = QSqlQuery(m_data_base);
m_insert_image_query.prepare("INSERT OR REPLACE INTO image (" + drawing_columns +
", pixel_width, pixel_height) VALUES (" + drawing_values +
+3 -1
View File
@@ -269,7 +269,9 @@ void DiagramTextItem::setHtml(const QString &text)
block = block.next();
}
if (m_non_left_alignment) {
//Room for centred or right-aligned lines, unless the user has
//given this text a width of its own
if (m_non_left_alignment && !hasUserTextWidth()) {
document()->setTextWidth(document()->idealWidth() + 40.0);
}
}
@@ -110,6 +110,8 @@ class DiagramTextItem : public QGraphicsTextItem
void prepareAlignment();
void finishAlignment();
virtual bool hasUserTextWidth() const {return false;}
protected:
bool
@@ -26,7 +26,9 @@
#include "../utils/qetutils.h"
#include <QDomElement>
#include <QScopedPointer>
#include <QSettings>
#include <QtCore/qnumeric.h>
/**
Constructeur
@@ -36,6 +38,7 @@ IndependentTextItem::IndependentTextItem() :
DiagramTextItem(nullptr)
{
ShownKinds::tag(this, ShownKinds::FreeTexts);
wrapAtWords();
//Start from the font last applied to a text item this session,
//falling back to the app-wide Preferences default otherwise.
setFont(LastUsedStyle::hasTextFont() ? LastUsedStyle::textFont()
@@ -53,6 +56,19 @@ IndependentTextItem::IndependentTextItem(const QString &text) :
DiagramTextItem(text, nullptr)
{
ShownKinds::tag(this, ShownKinds::FreeTexts);
wrapAtWords();
}
/**
@brief IndependentTextItem::wrapAtWords
A text with a width wraps between words only: a word longer than the
width goes past it rather than being cut, as for the texts of symbols.
*/
void IndependentTextItem::wrapAtWords()
{
QTextOption option = document()->defaultTextOption();
option.setWrapMode(QTextOption::WordWrap);
document()->setDefaultTextOption(option);
}
/// Destructeur
@@ -78,6 +94,10 @@ void IndependentTextItem::fromXml(const QDomElement &e) {
QETUtils::fontFromString(font, e.attribute("font"));
setFont(font);
}
//Optional: absent for a text with the automatic width, the only
//kind older versions know (they show such a text unwrapped).
//Read after the text, setHtml() sets a width of its own.
setTextWidth(e.attribute(QStringLiteral("text_width"), QStringLiteral("-1")).toDouble());
}
/**
@@ -93,10 +113,41 @@ QDomElement IndependentTextItem::toXml(QDomDocument &document) const
result.setAttribute("text", toHtml());
result.setAttribute("rotation", QString::number(QET::correctAngle(rotation())));
result.setAttribute("font", QETUtils::fontToString(font()));
//Only when set, so a text with the automatic width is saved as before
if (m_text_width > 0)
result.setAttribute("text_width", QString::number(m_text_width));
return(result);
}
/**
@brief IndependentTextItem::setTextWidth
Set the width of this text (-1 = automatic width): the text wraps to
it, its top-left corner stays in place.
@param width
*/
void IndependentTextItem::setTextWidth(qreal width)
{
if (!qIsFinite(width) || width <= 0)
width = -1;
if (qFuzzyCompare(width, m_text_width))
return;
qreal document_width = width;
//The automatic width of a text with centred or right-aligned
//lines, as setHtml() gives it
if (width < 0 && m_non_left_alignment)
{
QScopedPointer<QTextDocument> natural(document()->clone());
natural->setTextWidth(-1);
document_width = natural->idealWidth() + 40.0;
}
document()->setTextWidth(document_width);
m_text_width = width;
emit textWidthChanged(width);
}
void IndependentTextItem::focusOutEvent(QFocusEvent *event)
{
DiagramTextItem::focusOutEvent(event);
@@ -29,10 +29,13 @@
class IndependentTextItem : public DiagramTextItem
{
Q_OBJECT
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth NOTIFY textWidthChanged)
// constructors, destructor
signals:
void uuidChanged();
void textWidthChanged(qreal width);
public:
IndependentTextItem();
@@ -49,11 +52,23 @@ class IndependentTextItem : public DiagramTextItem
QUuid uuid() const {return m_uuid;}
void setUuid(const QUuid &uuid) {m_uuid = uuid; emit uuidChanged();}
void newUuid() {setUuid(QUuid::createUuid());} //create new uuid for this item
//Hide QGraphicsTextItem::textWidth()/setTextWidth(), which are not
//virtual: called through a QGraphicsTextItem or DiagramTextItem
//pointer they would change the document only, and the width would
//be neither saved nor shown in the properties. Use these, or the
//"textWidth" property.
qreal textWidth() const {return m_text_width;}
void setTextWidth(qreal width);
protected:
void focusOutEvent(QFocusEvent *event) override;
bool hasUserTextWidth() const override {return m_text_width > 0;}
private:
void wrapAtWords();
QUuid m_uuid = QUuid::createUuid();
qreal m_text_width = -1;
};
#endif