mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-07 04:04:14 +02:00
Merge pull request #1320 from bhangart/feature/free-text-width
Let free texts keep a width they wrap to
This commit is contained in:
@@ -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 +
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -389,6 +389,18 @@ target_link_libraries(tst_conductorselfretrace PRIVATE Qt::Test)
|
||||
target_compile_definitions(tst_conductorselfretrace PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
|
||||
|
||||
# A free text with a width keeps it when the project is saved again (the
|
||||
# attribute is written only when set) and is drawn wrapped to it.
|
||||
add_executable(
|
||||
tst_freetextwidth
|
||||
tst_freetextwidth.cpp)
|
||||
add_test(NAME tst_freetextwidth COMMAND tst_freetextwidth)
|
||||
set_tests_properties(tst_freetextwidth PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
||||
add_dependencies(tst_freetextwidth qelectrotech)
|
||||
target_link_libraries(tst_freetextwidth PRIVATE Qt::Test Qt::Gui Qt::Xml)
|
||||
target_compile_definitions(tst_freetextwidth PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
|
||||
|
||||
# The wiring list export (--export-cables) keeps every wire drawn to a folio
|
||||
# report when a report has several, joins only one-to-one report pairs, and
|
||||
# prints the folio number rather than its template. fixtures/wiring_list_arrows.qet
|
||||
@@ -531,6 +543,17 @@ if(QET_HAS_SCRIPTING)
|
||||
target_compile_definitions(tst_scriptlayoutreads PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
|
||||
|
||||
# The project database keeps the width of a free text (independent_text),
|
||||
# read with qet.query() on fixtures/free_text_width.qet.
|
||||
add_executable(
|
||||
tst_scriptfreetextwidth
|
||||
tst_scriptfreetextwidth.cpp)
|
||||
add_test(NAME tst_scriptfreetextwidth COMMAND tst_scriptfreetextwidth)
|
||||
add_dependencies(tst_scriptfreetextwidth qelectrotech)
|
||||
target_link_libraries(tst_scriptfreetextwidth PRIVATE Qt::Test)
|
||||
target_compile_definitions(tst_scriptfreetextwidth PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
|
||||
|
||||
# QET_SETTINGS_DIR moves the settings into an INI file there (#1178): a
|
||||
# script places a symbol only the folder's settings file can resolve.
|
||||
add_executable(
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<project title="Free text widths" uuid="{5b0f5e1c-8a43-4c1e-9e57-3f0d0f0a7a00}" version="0.200.1">
|
||||
<properties>
|
||||
<property name="saveddate" show="1">10/2/26</property>
|
||||
<property name="saveddate-eu" show="1">02-10-2026</property>
|
||||
<property name="saveddate-us" show="1">2026-10-02</property>
|
||||
<property name="savedfilename" show="1">free_text_width</property>
|
||||
<property name="savedtime" show="1">18:39</property>
|
||||
</properties>
|
||||
<usage enabled="true" time_spent="0"/>
|
||||
<newdiagrams>
|
||||
<border cols="17" colsize="60" displaycols="true" displayrows="true" rows="8" rowsize="80"/>
|
||||
<inset author="" auto_page_num="" date="null" displayAt="bottom" filename="" folio="" indexrev="" locmach="" plant="" title="" version=""/>
|
||||
<conductors bicolor="false" bus="" cable="" color2="#000000" condsize="1" conductor_color="" conductor_section="" dash-size="1" displaytext="1" formula="" function="" horizontal-alignment="AlignBottom" horizrotatetext="0" num="_" numsize="7" onetextperfolio="0" tension_protocol="" text_color="#000000" type="multi" vertical-alignment="AlignRight" vertirotatetext="270"/>
|
||||
<report label="%f-%l%c"/>
|
||||
<xrefs>
|
||||
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="coil" xrefpos="AlignBottom"/>
|
||||
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="commutator" xrefpos="AlignBottom"/>
|
||||
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="plc" xrefpos="AlignBottom"/>
|
||||
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="protection" xrefpos="AlignBottom"/>
|
||||
</xrefs>
|
||||
<conductors_autonums auto_break_conductors="false" current_autonum="" freeze_new_conductors="false"/>
|
||||
<folio_autonums/>
|
||||
<element_autonums current_autonum="" freeze_new_elements="false"/>
|
||||
<guides/>
|
||||
</newdiagrams>
|
||||
<diagram author="" auto_page_num="" cols="17" colsize="60" date="null" displayAt="bottom" displaycols="true" displayrows="true" filename="" folio="" freezeNewConductor="false" freezeNewElement="false" height="660" indexrev="" locmach="" order="1" plant="" rows="8" rowsize="80" title="" uuid="{5b0f5e1c-8a43-4c1e-9e57-3f0d0f0a7a01}" version="0.200.1-dev">
|
||||
<defaultconductor bicolor="false" bus="" cable="" color2="#000000" condsize="1" conductor_color="" conductor_section="" dash-size="1" displaytext="1" formula="" function="" horizontal-alignment="AlignBottom" horizrotatetext="0" num="_" numsize="7" onetextperfolio="0" tension_protocol="" text_color="#000000" type="multi" vertical-alignment="AlignRight" vertirotatetext="270"/>
|
||||
<inputs>
|
||||
<input font="Liberation Sans,9,-1,5,50,0,0,0,0,0,Regular" rotation="0" text="FreeAlpha FreeBeta FreeGamma FreeDelta FreeEpsilon" text_width="70" uuid="{5b0f5e1c-8a43-4c1e-9e57-3f0d0f0a7a03}" x="100" y="100"/>
|
||||
<input font="Liberation Sans,9,-1,5,50,0,0,0,0,0,Regular" rotation="0" text="OpenAlpha OpenBeta OpenGamma OpenDelta OpenEpsilon" uuid="{5b0f5e1c-8a43-4c1e-9e57-3f0d0f0a7a04}" x="100" y="400"/>
|
||||
<input font="Liberation Sans,9,-1,5,50,0,0,0,0,0,Regular" rotation="0" text="<p align="center">CentAlpha CentBeta CentGamma</p>" text_width="120" uuid="{5b0f5e1c-8a43-4c1e-9e57-3f0d0f0a7a08}" x="400" y="100"/>
|
||||
</inputs>
|
||||
</diagram>
|
||||
<collection>
|
||||
<category name="import">
|
||||
<names>
|
||||
<name lang="en">Imported elements</name>
|
||||
</names>
|
||||
</category>
|
||||
</collection>
|
||||
</project>
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 <QtTest>
|
||||
#include <QDomDocument>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTextDocument>
|
||||
|
||||
/// Run the qelectrotech binary with arguments, without a display.
|
||||
static bool runQet(const QStringList &arguments)
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("offscreen"));
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(env);
|
||||
proc.start(QStringLiteral(QET_TEST_BINARY_PATH), arguments);
|
||||
return proc.waitForFinished(60000)
|
||||
&& proc.exitStatus() == QProcess::NormalExit
|
||||
&& proc.exitCode() == 0;
|
||||
}
|
||||
|
||||
/// The number of lines the words starting with prefix are drawn on.
|
||||
static int drawnLines(const QString &svg, const QString &prefix)
|
||||
{
|
||||
const QRegularExpression text_re(
|
||||
QStringLiteral("<text[^>]*\\by=\"([^\"]+)\"[^>]*>\\s*%1").arg(prefix));
|
||||
QSet<QString> lines;
|
||||
auto it = text_re.globalMatch(svg);
|
||||
while (it.hasNext())
|
||||
lines.insert(it.next().captured(1));
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
/**
|
||||
A free text with a width (text_width on its <input>) keeps it when the
|
||||
project is saved again, and wraps to it. A text without a width is saved
|
||||
without the attribute, as before, so older versions read it unchanged.
|
||||
*/
|
||||
class tst_freetextwidth : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase()
|
||||
{
|
||||
QVERIFY2(QFile::exists(QStringLiteral(QET_TEST_BINARY_PATH)), "qelectrotech binary not found");
|
||||
m_fixture = QFINDTESTDATA("fixtures/free_text_width.qet");
|
||||
QVERIFY2(!m_fixture.isEmpty(), "fixture project not found");
|
||||
QVERIFY(m_dir.isValid());
|
||||
}
|
||||
|
||||
void widthIsSavedOnlyWhenSet()
|
||||
{
|
||||
const QString out = m_dir.filePath(QStringLiteral("resaved.qet"));
|
||||
QVERIFY2(runQet({QStringLiteral("--resave"), m_fixture, out}), "--resave failed");
|
||||
|
||||
QFile file(out);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly));
|
||||
QDomDocument document;
|
||||
QVERIFY(document.setContent(&file));
|
||||
|
||||
QMap<QString, QString> widths; // first word -> text_width
|
||||
const QDomNodeList inputs = document.elementsByTagName(QStringLiteral("input"));
|
||||
for (int i = 0 ; i < inputs.size() ; ++i) {
|
||||
const QDomElement input = inputs.at(i).toElement();
|
||||
QTextDocument text;
|
||||
text.setHtml(input.attribute(QStringLiteral("text")));
|
||||
const QString first_word = text.toPlainText().section(QLatin1Char(' '), 0, 0);
|
||||
widths.insert(first_word, input.hasAttribute(QStringLiteral("text_width"))
|
||||
? input.attribute(QStringLiteral("text_width"))
|
||||
: QStringLiteral("none"));
|
||||
}
|
||||
|
||||
QCOMPARE(widths.value(QStringLiteral("FreeAlpha")), QStringLiteral("70"));
|
||||
QCOMPARE(widths.value(QStringLiteral("OpenAlpha")), QStringLiteral("none"));
|
||||
//Centred lines: the width of the user, not the one setHtml() gives
|
||||
QCOMPARE(widths.value(QStringLiteral("CentAlpha")), QStringLiteral("120"));
|
||||
}
|
||||
|
||||
void textWrapsToItsWidth()
|
||||
{
|
||||
QVERIFY2(runQet({QStringLiteral("--export-svg"), m_fixture, m_dir.path()}), "--export-svg failed");
|
||||
QFile file(m_dir.filePath(QStringLiteral("01_diagram.svg")));
|
||||
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
|
||||
const QString svg = QString::fromUtf8(file.readAll());
|
||||
|
||||
QVERIFY(drawnLines(svg, QStringLiteral("Free")) > 1);
|
||||
QCOMPARE(drawnLines(svg, QStringLiteral("Open")), 1);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_fixture;
|
||||
QTemporaryDir m_dir;
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_freetextwidth)
|
||||
#include "tst_freetextwidth.moc"
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
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 <QtTest>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
/**
|
||||
The project database keeps the width of a free text (text_width in the
|
||||
independent_text table, NULL for the automatic width), read here with
|
||||
qet.query() from a script run on fixtures/free_text_width.qet.
|
||||
*/
|
||||
class tst_scriptfreetextwidth : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QTemporaryDir m_dir;
|
||||
|
||||
/// The rows of the independent_text table, by the first word of the text.
|
||||
QHash<QString, QJsonObject> rows()
|
||||
{
|
||||
const QString path = m_dir.filePath(QStringLiteral("probe.js"));
|
||||
const QString home = m_dir.filePath(QStringLiteral("home"));
|
||||
QDir().mkpath(home);
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::WriteOnly)) return {};
|
||||
f.write("qet.log('PROBE ' + JSON.stringify(qet.query("
|
||||
"'SELECT text, text_width, width, height FROM independent_text')));\n");
|
||||
f.close();
|
||||
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("offscreen"));
|
||||
env.insert(QStringLiteral("QET_ENABLE_SCRIPTING"), QStringLiteral("1"));
|
||||
env.insert(QStringLiteral("HOME"), home);
|
||||
env.insert(QStringLiteral("XDG_CONFIG_HOME"), home + QStringLiteral("/config"));
|
||||
env.insert(QStringLiteral("XDG_DATA_HOME"), home + QStringLiteral("/data"));
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(env);
|
||||
proc.start(QStringLiteral(QET_TEST_BINARY_PATH),
|
||||
{QStringLiteral("--run"), path, QFINDTESTDATA("fixtures/free_text_width.qet")});
|
||||
if (!proc.waitForFinished(60000)) return {};
|
||||
|
||||
const QString out = QString::fromUtf8(proc.readAllStandardOutput() + proc.readAllStandardError());
|
||||
const QString mark = QStringLiteral("PROBE ");
|
||||
QHash<QString, QJsonObject> result;
|
||||
for (const QString &line : out.split(QLatin1Char('\n'))) {
|
||||
const int i = line.indexOf(mark);
|
||||
if (i < 0) continue;
|
||||
const QJsonArray array = QJsonDocument::fromJson(line.mid(i + mark.size()).toUtf8()).array();
|
||||
for (const QJsonValue &row : array)
|
||||
result.insert(row.toObject().value(QStringLiteral("text")).toString().section(QLatin1Char(' '), 0, 0),
|
||||
row.toObject());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void initTestCase()
|
||||
{
|
||||
QVERIFY(m_dir.isValid());
|
||||
QVERIFY(QFile::exists(QStringLiteral(QET_TEST_BINARY_PATH)));
|
||||
QVERIFY(!QFINDTESTDATA("fixtures/free_text_width.qet").isEmpty());
|
||||
}
|
||||
|
||||
void widthIsInTheDatabase()
|
||||
{
|
||||
const QHash<QString, QJsonObject> r = rows();
|
||||
QCOMPARE(r.size(), 3);
|
||||
|
||||
QCOMPARE(r.value(QStringLiteral("FreeAlpha")).value(QStringLiteral("text_width")).toDouble(), 70.0);
|
||||
QCOMPARE(r.value(QStringLiteral("CentAlpha")).value(QStringLiteral("text_width")).toDouble(), 120.0);
|
||||
//The automatic width is NULL
|
||||
const QJsonValue open = r.value(QStringLiteral("OpenAlpha")).value(QStringLiteral("text_width"));
|
||||
QVERIFY2(open.isNull() || open.toString().isEmpty(), qPrintable(open.toVariant().toString()));
|
||||
|
||||
//The box of the row is the wrapped one: taller than one line
|
||||
QVERIFY(r.value(QStringLiteral("FreeAlpha")).value(QStringLiteral("height")).toDouble()
|
||||
> 2 * r.value(QStringLiteral("OpenAlpha")).value(QStringLiteral("height")).toDouble());
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_scriptfreetextwidth)
|
||||
#include "tst_scriptfreetextwidth.moc"
|
||||
Reference in New Issue
Block a user