Merge branch 'master' into fix/bugtracker-243-copy-from-readonly

This commit is contained in:
ispyisail
2026-09-12 23:06:47 +12:00
284 changed files with 80693 additions and 35501 deletions
+40 -30
View File
@@ -16,6 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editorcommands.h"
#include "../diagram.h"
/**
@brief ElementEditionCommand::ElementEditionCommand
@@ -276,14 +277,7 @@ void ChangeZValueCommand::applyRaise(const QList<QGraphicsItem *> &items_list) {
for (int i = my_items_list.count() - 2 ; i >= 0 ; -- i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i +1] -> isSelected()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) // ### Qt 6: remove
my_items_list.swap(i, i + 1);
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 5.13 or later")
#endif
my_items_list.swapItemsAt(i, i + 1);
#endif
}
}
}
@@ -301,14 +295,7 @@ void ChangeZValueCommand::applyLower(const QList<QGraphicsItem *> &items_list) {
for (int i = 1 ; i < my_items_list.count() ; ++ i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i - 1] -> isSelected()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) // ### Qt 6: remove
my_items_list.swap(i, i - 1);
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 5.13 or later")
#endif
my_items_list.swapItemsAt(i, i - 1);
#endif
}
}
}
@@ -680,10 +667,32 @@ void RotateFineElementsCommand::redo()
}
/**
@brief selectionCenter
@param items
@return the center of the united scene bounding rect of items,
snapped to the nearest half of the diagram grid. Mirroring across a
half-grid line keeps points that were on the grid on the grid.
*/
static QPointF selectionCenter(const QList<QGraphicsItem *> &items)
{
QRectF bounding;
for (auto *item : items) {
bounding = bounding.united(item->sceneBoundingRect());
}
QPointF center = bounding.center();
const qreal half_x = Diagram::xGrid / 2.0;
const qreal half_y = Diagram::yGrid / 2.0;
center.setX(qRound(center.x() / half_x) * half_x);
center.setY(qRound(center.y() / half_y) * half_y);
return center;
}
MirrorElementsCommand::MirrorElementsCommand(ElementScene *scene, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("Miroir de sélection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
m_axis_x = selectionCenter(m_items).x();
}
/**
@@ -694,28 +703,28 @@ void MirrorElementsCommand::redo()
foreach (auto *item, m_items) {
if (item->type() == PartText::Type) {
PartText* staticText = qgraphicsitem_cast<PartText*>(item);
staticText->mirror();
staticText->mirror(m_axis_x);
} else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->mirror();
dyntext->mirror(m_axis_x);
} else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->mirror();
arc->mirror(m_axis_x);
} else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->mirror();
ellipse->mirror(m_axis_x);
} else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->mirror();
line->mirror(m_axis_x);
} else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->mirror();
poly->mirror(m_axis_x);
} else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->mirror();
rect->mirror(m_axis_x);
} else if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
term->mirror();
term->mirror(m_axis_x);
}
}
}
@@ -732,6 +741,7 @@ FlipElementsCommand::FlipElementsCommand(ElementScene *scene, QUndoCommand *pare
ElementEditionCommand(QObject::tr("Retourner la sélection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
m_axis_y = selectionCenter(m_items).y();
}
/**
@@ -742,28 +752,28 @@ void FlipElementsCommand::redo()
foreach (auto *item, m_items) {
if (item->type() == PartText::Type) {
PartText* staticText = qgraphicsitem_cast<PartText*>(item);
staticText->flip();
staticText->flip(m_axis_y);
} else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->flip();
dyntext->flip(m_axis_y);
} else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->flip();
arc->flip(m_axis_y);
} else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->flip();
ellipse->flip(m_axis_y);
} else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->flip();
line->flip(m_axis_y);
} else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->flip();
poly->flip(m_axis_y);
} else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->flip();
rect->flip(m_axis_y);
} else if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
term->flip();
term->flip(m_axis_y);
}
}
}
+14
View File
@@ -279,6 +279,12 @@ private:
};
/**
@brief The MirrorElementsCommand class
Mirror the selected parts horizontally (left <-> right) across the
vertical line through the center of the selection, so the selection
keeps its place in the scene.
*/
class MirrorElementsCommand : public ElementEditionCommand
{
public:
@@ -288,8 +294,15 @@ public:
private:
ElementScene *m_scene =nullptr;
QList<QGraphicsItem*> m_items;
qreal m_axis_x = 0;
};
/**
@brief The FlipElementsCommand class
Flip the selected parts vertically (top <-> bottom) across the
horizontal line through the center of the selection, so the selection
keeps its place in the scene.
*/
class FlipElementsCommand : public ElementEditionCommand
{
public:
@@ -299,6 +312,7 @@ public:
private:
ElementScene *m_scene =nullptr;
QList<QGraphicsItem*> m_items;
qreal m_axis_y = 0;
};
#endif
+6 -1
View File
@@ -121,7 +121,7 @@ void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
if (m_event_interface) {
if (m_event_interface -> mouseMoveEvent(e)) {
emit mouseMoved(e -> scenePos());
emit mouseMoved(snapToGrid(e->scenePos()));
if (m_event_interface->isFinish()) {
delete m_event_interface;
m_event_interface = nullptr;
@@ -479,8 +479,13 @@ const QDomDocument ElementScene::toXml(bool all_parts)
root.appendChild(m_element_data.kindInfoToXml(xml_document));
}
//Slave is in this list because the element editor offers the
//Informations tab for it, including the PLC-specific rows
//populateTree() adds for a PLC slave. Without it the editor would
//accept that data and silently drop it on save.
if (type_ == ElementData::Simple ||
type_ == ElementData::Master ||
type_ == ElementData::Slave ||
type_ == ElementData::Terminal ||
type_ == ElementData::Thumbnail)
{
+21 -25
View File
@@ -100,13 +100,30 @@ void ElementView::setSelectionMode()
emit(modeChanged());
}
/**
Applique un facteur d'echelle a la vue en bornant l'echelle resultante
entre m_min_zoom et m_max_zoom. Sans cette borne, un zoom repete (molette)
finit par faire deborder la transformation de la vue et fait planter
l'editeur (issue #798).
@param factor facteur d'echelle a appliquer
*/
void ElementView::scaleClamped(qreal factor)
{
const qreal current = transform().m11();
const qreal target = current * factor;
if (target < m_min_zoom || target > m_max_zoom) {
return;
}
scale(factor, factor);
}
/**
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
*/
void ElementView::zoomIn()
{
adjustSceneRect();
scale(4.0/3.0, 4.0/3.0);
scaleClamped(4.0/3.0);
}
/**
@@ -115,7 +132,7 @@ void ElementView::zoomIn()
void ElementView::zoomOut()
{
adjustSceneRect();
scale(0.75, 0.75);
scaleClamped(0.75);
}
/**
@@ -123,7 +140,7 @@ void ElementView::zoomOut()
*/
void ElementView::zoomInSlowly()
{
scale(1.02, 1.02);
scaleClamped(1.02);
}
/**
@@ -131,7 +148,7 @@ void ElementView::zoomInSlowly()
*/
void ElementView::zoomOutSlowly()
{
scale(0.98, 0.98);
scaleClamped(0.98);
}
/**
@@ -372,14 +389,7 @@ ElementContent ElementView::pasteWithOffset(const QDomDocument &xml_document) {
*/
void ElementView::mousePressEvent(QMouseEvent* e)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 1) // ### Qt 6: remove
if (e->button() == Qt::MidButton)
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 6 or later")
#endif
if (e->button() == Qt::MiddleButton)
#endif
{
setCursor( (Qt::ClosedHandCursor));
reference_view_ = e->pos();
@@ -394,14 +404,7 @@ void ElementView::mousePressEvent(QMouseEvent* e)
*/
void ElementView::mouseMoveEvent(QMouseEvent* e)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 1) // ### Qt 6: remove
if (e->buttons() == Qt::MidButton)
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 6 or later")
#endif
if (e->buttons() == Qt::MiddleButton)
#endif
{
QScrollBar *h = horizontalScrollBar();
QScrollBar *v = verticalScrollBar();
@@ -420,14 +423,7 @@ void ElementView::mouseMoveEvent(QMouseEvent* e)
*/
void ElementView::mouseReleaseEvent(QMouseEvent* e)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 1) // ### Qt 6: remove
if (e->button() == Qt::MidButton)
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 6 or later")
#endif
if (e->button() == Qt::MiddleButton)
#endif
{
setCursor(Qt::ArrowCursor);
adjustSceneRect();
+7
View File
@@ -53,6 +53,13 @@ class ElementView : public QGraphicsView {
private:
QRectF applyMovement(const QRectF &, const QPointF &);
void scaleClamped(qreal factor);
/// Lowest and highest allowed value of the view transform scale (m11).
/// Prevents the wheel-zoom from driving the transform to overflow, which
/// crashes the editor (bugtracker / GitHub issue #798).
static constexpr qreal m_min_zoom = 0.1;
static constexpr qreal m_max_zoom = 200.0;
public slots:
void setVisualisationMode();
@@ -521,14 +521,7 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde)
resetStyles();
//Get the list of pair style/value
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // ### Qt 6: remove
QStringList styles = qde.attribute("style").split(";", QString::SkipEmptyParts);
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 5.14 or later")
#endif
QStringList styles = qde.attribute("style").split(";", Qt::SkipEmptyParts);
#endif
//Check each pair of style
QRegularExpression rx("^\\s*([a-z-]+)\\s*:\\s*([a-zA-Z-]+)\\s*$");
+4 -4
View File
@@ -197,13 +197,13 @@ qreal PartArc::rotation() const {
return qRound(m_rot * 100.0) / 100.0;
}
void PartArc::flip() {
void PartArc::flip(qreal axis_y) {
m_start_angle = (-1) * m_start_angle;
m_span_angle = (-1) * m_span_angle;
while (m_start_angle < 0) { m_start_angle += (360*16); }
while (m_start_angle >= (360*16)) { m_start_angle -= (360*16); }
auto p1 = mapToScene(m_rect.x(),m_rect.y());
p1.setY(((-1.0) * p1.y()) - m_rect.height());
p1.setY(2 * axis_y - p1.y() - m_rect.height());
p1 = mapFromScene(p1.x(),p1.y());
m_rect = QRectF(m_rect.x(), p1.y(), m_rect.width(), m_rect.height());
prepareGeometryChange();
@@ -211,13 +211,13 @@ void PartArc::flip() {
emit rectChanged();
}
void PartArc::mirror() {
void PartArc::mirror(qreal axis_x) {
m_start_angle = (180.0 * 16) - m_start_angle;
m_span_angle = (-1) * m_span_angle;
while (m_start_angle < 0) { m_start_angle += (360*16); }
while (m_start_angle >= (360*16)) { m_start_angle -= (360*16); }
auto p1 = mapToScene(m_rect.x(),m_rect.y());
p1.setX(((-1.0) * p1.x()) - m_rect.width());
p1.setX(2 * axis_x - p1.x() - m_rect.width());
p1 = mapFromScene(p1.x(), p1.y());
m_rect = QRectF(p1.x(), m_rect.y(), m_rect.width(), m_rect.height());
prepareGeometryChange();
+2 -2
View File
@@ -62,8 +62,8 @@ class PartArc : public AbstractPartEllipse
QRectF sceneGeometricRect() const override;
void setRotation(qreal angle);
qreal rotation() const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
void addHandler() override;
void removeHandler() override;
@@ -74,19 +74,19 @@ void PartDynamicTextField::setRotation(qreal angle) {
setPos(QTransform().rotate(diffAngle).map(pos()));
}
void PartDynamicTextField::mirror() {
void PartDynamicTextField::mirror(qreal axis_x) {
// at first: rotate the text:
QGraphicsObject::setRotation(QET::correctAngle(360-rotation(), true));
// then see, where we need to re-position depending on the angle!
qreal rot = qRound(QET::correctAngle(rotation(), true));
qreal c = qCos(qDegreesToRadians(rot));
qreal s = qSin(qDegreesToRadians(rot));
qreal x = (-1) * pos().x() - c * boundingRect().width();
qreal x = 2 * axis_x - pos().x() - c * boundingRect().width();
qreal y = pos().y() - s * boundingRect().width();
setPos(x, y);
}
void PartDynamicTextField::flip() {
void PartDynamicTextField::flip(qreal axis_y) {
// at first: rotate the text:
QGraphicsObject::setRotation(QET::correctAngle(360-rotation(), true));
// then see, where we need to re-position depending on the angle!
@@ -94,7 +94,7 @@ void PartDynamicTextField::flip() {
qreal c = qCos(qDegreesToRadians(rot));
qreal s = qSin(qDegreesToRadians(rot));
qreal x = pos().x() + s * boundingRect().height();
qreal y = (-1) * pos().y() - c * boundingRect().height();
qreal y = 2 * axis_y - pos().y() - c * boundingRect().height();
setPos(x, y);
}
@@ -106,8 +106,8 @@ class PartDynamicTextField : public QGraphicsTextItem, public CustomElementPart
bool rotationPointCenter() const;
void setRotation(qreal angle);
void mirror();
void flip();
void mirror(qreal axis_x = 0);
void flip(qreal axis_y = 0);
protected:
+4 -4
View File
@@ -256,9 +256,9 @@ qreal PartEllipse::rotation() const {
return qRound(m_rot * 100.0) / 100.0;
}
void PartEllipse::flip() {
void PartEllipse::flip(qreal axis_y) {
auto p1 = mapToScene(m_rect.x(), m_rect.y());
p1.setY(((-1.0) * p1.y()) - m_rect.height());
p1.setY(2 * axis_y - p1.y() - m_rect.height());
p1 = mapFromScene(p1.x(), p1.y());
m_rect = QRectF(p1.x(), p1.y(), m_rect.width(), m_rect.height());
prepareGeometryChange();
@@ -266,9 +266,9 @@ void PartEllipse::flip() {
emit rectChanged();
}
void PartEllipse::mirror() {
void PartEllipse::mirror(qreal axis_x) {
auto p1 = mapToScene(m_rect.x(), m_rect.y());
p1.setX(((-1.0) * p1.x()) - m_rect.width());
p1.setX(2 * axis_x - p1.x() - m_rect.width());
p1 = mapFromScene(p1.x(), p1.y());
m_rect = QRectF(p1.x(), p1.y(), m_rect.width(), m_rect.height());
prepareGeometryChange();
+2 -2
View File
@@ -62,8 +62,8 @@ class PartEllipse : public AbstractPartEllipse
void setRect(const QRectF &rect) override {AbstractPartEllipse::setRect(rect); adjustHandlerPos();}
void setRotation(qreal angle);
qreal rotation() const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
void addHandler() override;
void removeHandler() override;
+6 -6
View File
@@ -590,11 +590,11 @@ qreal PartLine::rotation() const {
return qRound(m_rot * 100.0) / 100.0;
}
void PartLine::flip() {
void PartLine::flip(qreal axis_y) {
auto p1 = mapToScene(m_line.p1());
auto p2 = mapToScene(m_line.p2());
p1 = QPointF(p1.x(), (-1) * p1.y());
p2 = QPointF(p2.x(), (-1) * p2.y());
p1 = QPointF(p1.x(), 2 * axis_y - p1.y());
p2 = QPointF(p2.x(), 2 * axis_y - p2.y());
m_line.setP1(mapFromScene(p1));
m_line.setP2(mapFromScene(p2));
setLine(m_line);
@@ -603,11 +603,11 @@ void PartLine::flip() {
emit lineChanged();
}
void PartLine::mirror() {
void PartLine::mirror(qreal axis_x) {
auto p1 = mapToScene(m_line.p1());
auto p2 = mapToScene(m_line.p2());
p1 = QPointF((-1) * p1.x(), p1.y());
p2 = QPointF((-1) * p2.x(), p2.y());
p1 = QPointF(2 * axis_x - p1.x(), p1.y());
p2 = QPointF(2 * axis_x - p2.x(), p2.y());
m_line.setP1(mapFromScene(p1));
m_line.setP2(mapFromScene(p2));
setLine(m_line);
+2 -2
View File
@@ -96,8 +96,8 @@ class PartLine : public CustomElementGraphicPart
void setSecondEndLength(const qreal &l);
void setRotation(qreal angle);
qreal rotation() const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
void addHandler() override;
void removeHandler() override;
+4 -4
View File
@@ -307,10 +307,10 @@ qreal PartPolygon::rotation() const {
return qRound(m_rot * 100.0) / 100.0;
}
void PartPolygon::flip() {
void PartPolygon::flip(qreal axis_y) {
for (auto &pt : m_polygon) {
pt = mapToScene(pt.x(), pt.y());
pt = QPointF(pt.x(), (-1) * pt.y());
pt = QPointF(pt.x(), 2 * axis_y - pt.y());
pt = mapFromScene(pt.x(), pt.y());
}
setPolygon(m_polygon);
@@ -319,10 +319,10 @@ void PartPolygon::flip() {
emit polygonChanged();
}
void PartPolygon::mirror() {
void PartPolygon::mirror(qreal axis_x) {
for (auto &pt : m_polygon) {
pt = mapToScene(pt.x(), pt.y());
pt = QPointF((-1) * pt.x(), pt.y());
pt = QPointF(2 * axis_x - pt.x(), pt.y());
pt = mapFromScene(pt.x(), pt.y());
}
setPolygon(m_polygon);
+2 -2
View File
@@ -89,8 +89,8 @@ class PartPolygon : public CustomElementGraphicPart
void setRotation (qreal angle);
qreal rotation () const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
void addHandler() override;
void removeHandler() override;
@@ -187,11 +187,11 @@ qreal PartRectangle::rotation() const {
return qRound(m_rot * 100.0) / 100.0;
}
void PartRectangle::flip() {
void PartRectangle::flip(qreal axis_y) {
auto height = m_rect.height();
auto p1 = mapToScene(m_rect.x(),m_rect.y());
qreal x = p1.x();
qreal y = ((-1.0) * p1.y()) - height;
qreal y = 2 * axis_y - p1.y() - height;
p1 = mapFromScene(x, y);
m_rect.setX(p1.x());
m_rect.setY(p1.y());
@@ -201,10 +201,10 @@ void PartRectangle::flip() {
emit rectChanged();
}
void PartRectangle::mirror() {
void PartRectangle::mirror(qreal axis_x) {
auto width = m_rect.width();
auto p1 = mapToScene(m_rect.x(),m_rect.y());
qreal x = ((-1.0) * p1.x()) - width;
qreal x = 2 * axis_x - p1.x() - width;
qreal y = p1.y();
p1 = mapFromScene(x, y);
m_rect.setX(p1.x());
+2 -2
View File
@@ -73,8 +73,8 @@ class PartRectangle : public CustomElementGraphicPart
void setYRadius(qreal Y);
void setRotation(qreal angle);
qreal rotation() const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
QRectF sceneGeometricRect() const override;
virtual QPointF sceneTopLeft() const;
+4 -4
View File
@@ -293,9 +293,9 @@ qreal PartTerminal::rotation() const {
@brief PartTerminal::flip
turn part upside down
*/
void PartTerminal::flip() {
void PartTerminal::flip(qreal axis_y) {
d->m_pos.setX( pos().x());
d->m_pos.setY((-1.0) * pos().y());
d->m_pos.setY(2 * axis_y - pos().y());
switch (d->m_orientation) {
case Qet::North : setOrientation(Qet::South);
break;
@@ -314,8 +314,8 @@ void PartTerminal::flip() {
@brief PartTerminal::mirror
turn part from left to right
*/
void PartTerminal::mirror() {
d->m_pos.setX((-1.0) * pos().x());
void PartTerminal::mirror(qreal axis_x) {
d->m_pos.setX(2 * axis_x - pos().x());
d->m_pos.setY( pos().y());
switch (d->m_orientation) {
case Qet::North : break;
+2 -2
View File
@@ -96,8 +96,8 @@ class PartTerminal : public CustomElementGraphicPart
void setRotation(qreal angle);
qreal rotation() const;
void flip();
void mirror();
void flip(qreal axis_y = 0);
void mirror(qreal axis_x = 0);
void nextOrientation();
void previousOrientation();
+12 -4
View File
@@ -75,7 +75,7 @@ void PartText::setRotation(qreal angle) {
setPos(QTransform().rotate(diffAngle).map(pos()));
}
void PartText::mirror() {
void PartText::mirror(qreal axis_x) {
// at first: rotate the text:
QGraphicsObject::setRotation(QET::correctAngle((360-rotation()), true));
// then see, where we need to re-position depending on text, font ...
@@ -86,12 +86,12 @@ void PartText::mirror() {
qreal c = qCos(qDegreesToRadians(rot));
qreal s = qSin(qDegreesToRadians(rot));
// Now: Move!
qreal x = (-1) * pos().x() - c * (textwidth);
qreal x = 2 * axis_x - pos().x() - c * (textwidth);
qreal y = pos().y() - s * (textwidth);
setPos(x, y);
}
void PartText::flip() {
void PartText::flip(qreal axis_y) {
// at first: rotate the text:
QGraphicsObject::setRotation(QET::correctAngle((360-rotation()), true));
// then see, where we need to re-position depending on text, font ...
@@ -103,7 +103,7 @@ void PartText::flip() {
qreal s = qSin(qDegreesToRadians(rot));
// Now: Move!
qreal x = pos().x() - s * (textheight);
qreal y = (-1) * pos().y() + c * (textheight);
qreal y = 2 * axis_y - pos().y() + c * (textheight);
setPos(x, y);
}
@@ -440,6 +440,14 @@ void PartText::setFont(const QFont &font) {
// at a different spot after save/reopen (the position recomputes from
// the saved font on load). See #158.
adjustItemPosition();
// Keep real_font_size_ in sync with the actual font. It's the base
// size startUserTransformation()/handleUserTransformation() scale
// from when the user drags a resize handle, and flip() also reads it
// to reposition the item. Left stale here, either one computes from
// whatever size the item had when it was first created, ignoring any
// size set since (toolbar, property editor, or loaded from XML) -
// found investigating #158.
real_font_size_ = font.pointSize();
emit fontChanged(font);
}
}
+2 -2
View File
@@ -64,8 +64,8 @@ class PartText : public QGraphicsTextItem, public CustomElementPart {
void fromXml(const QDomElement &) override;
const QDomElement toXml(QDomDocument &) const override;
void setRotation(qreal angle);
void mirror();
void flip();
void mirror(qreal axis_x = 0);
void flip(qreal axis_y = 0);
bool isUseless() const override;
QRectF sceneGeometricRect() const override;
void startUserTransformation(const QRectF &) override;
+21 -4
View File
@@ -31,6 +31,7 @@
#include <QColorDialog>
#include <QGraphicsItem>
#include <QPointer>
#include <QSignalBlocker>
DynamicTextFieldEditor::DynamicTextFieldEditor(QETElementEditor *editor,
PartDynamicTextField *text_field,
@@ -141,9 +142,20 @@ void DynamicTextFieldEditor::updateForm()
ui -> m_size_sb -> setValue(m_text_field.data() -> font().pointSize());
ui->m_keep_visual_rotation_cb->setChecked(m_text_field.data()->keepVisualRotation());
ui->m_rotation_point_center_cb->setChecked(m_text_field.data()->rotationPointCenter());
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
m_color_kpb -> setColor(m_text_field.data() -> color());
//Block signals while loading the colour into the button.
//KColorButton::changed fires on a programmatic setColor() as well
//as on user interaction, and m_color_kpb_changed() applies the new
//colour to *every* selected part -- so merely showing the first
//part's colour would overwrite the colour of all the others.
//The other widgets above are immune because they are wired to
//user-only signals (editingFinished, clicked), which setValue()
//and setChecked() do not emit.
{
const QSignalBlocker blocker(m_color_kpb);
m_color_kpb -> setColor(m_text_field.data() -> color());
}
#endif
ui -> m_width_sb -> setValue(m_text_field.data() -> textWidth());
ui -> m_font_pb -> setText(m_text_field -> font().family());
@@ -170,7 +182,7 @@ void DynamicTextFieldEditor::updateForm()
void DynamicTextFieldEditor::setupWidget()
{
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
m_color_kpb = new KColorButton(this);
m_color_kpb->setObjectName(QString::fromUtf8("m_color_kpb"));
@@ -233,7 +245,8 @@ void DynamicTextFieldEditor::fillInfoComboBox()
else {
strl = QETInformation::elementInfoKeys();
bool is_plc_slave = (type == ElementData::Slave
bool is_slave = (type == ElementData::Slave);
bool is_plc_slave = (is_slave
&& ed.m_slave_type == ElementData::PLCSlave);
if (is_plc_slave) {
@@ -262,6 +275,10 @@ void DynamicTextFieldEditor::fillInfoComboBox()
strl.removeAll(QETInformation::ELMT_PLC_T3);
strl.removeAll(QETInformation::ELMT_PLC_T4);
}
if (is_slave) {
strl.prepend(QETInformation::ELMT_XREF);
}
}
for (int i=0; i<strl.size();++i) {
+2 -2
View File
@@ -21,7 +21,7 @@
#include "../elementitemeditor.h"
#include "../graphicspart/partdynamictextfield.h"
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
# include <KColorButton>
#endif
@@ -79,7 +79,7 @@ class DynamicTextFieldEditor : public ElementItemEditor {
QList<PartDynamicTextField*> m_parts;
QList<QMetaObject::Connection> m_connection_list;
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
KColorButton* m_color_kpb = nullptr;
#endif
@@ -292,7 +292,7 @@ void ElementPropertiesEditorWidget::updateTree()
ui->m_tree->setEnabled(true);
break;
case ElementData::Slave:
ui->m_tree->setDisabled(true);
ui->m_tree->setEnabled(true);
break;
case ElementData::Terminal:
ui->m_tree->setEnabled(true);
@@ -371,7 +371,7 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>();
//If the checkbox is checked, save the number; otherwise, -1 (infinity)
if (ui->max_slaves_checkbox->isVisible() && ui->max_slaves_checkbox->isChecked()) {
if ((m_data.m_master_type == ElementData::Coil || m_data.m_master_type == ElementData::Protection || m_data.m_master_type == ElementData::Commutator) && ui->max_slaves_checkbox->isChecked()) {
m_data.m_max_slaves = ui->max_slaves_spinbox->value();
} else {
m_data.m_max_slaves = -1;
@@ -423,11 +423,11 @@ void ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged(int in
ui->m_master_gb->setVisible(master);
ui->m_terminal_gb->setVisible(terminal);
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
ui->tabWidget->setTabVisible(1,
(type_ == ElementData::Simple ||
type_ == ElementData::Master));
#endif
type_ == ElementData::Master ||
type_ == ElementData::Slave ||
type_ == ElementData::Terminal));
updateTree();
}
@@ -454,6 +454,9 @@ void ElementPropertiesEditorWidget::on_m_slave_groups_checkbox_toggled(bool chec
if (checked && !ui->max_slaves_checkbox->isChecked()) {
ui->max_slaves_checkbox->setChecked(true);
if (!m_data.m_slave_contact_groups.isEmpty()) {
ui->max_slaves_spinbox->setValue(m_data.m_slave_contact_groups.size());
}
}
if (checked) {
@@ -689,7 +692,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
m_plc_table->horizontalHeader()->resizeSection(2, 150);
m_plc_table->horizontalHeader()->resizeSection(3, 150);
m_plc_table->horizontalHeader()->resizeSection(4, 100);
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectItems);
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectRows);
m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_plc_table->setMinimumHeight(200);
m_plc_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+32 -7
View File
@@ -55,6 +55,7 @@
#include <QActionGroup>
#include <QFileDialog>
#include <QSvgGenerator>
#include <QHBoxLayout>
/**
* @brief QETElementEditor::QETElementEditor
@@ -77,8 +78,9 @@ QETElementEditor::QETElementEditor(QWidget *parent) :
//ui->m_display_menu->insertMenu(ui->m_zoom_in_action, menu);
setWindowState(Qt::WindowMaximized);
readSettings();
readSettings(); // restoreGeometry before show()
show();
readSettingsState(); // restoreState() must be called after show() in Qt6
}
/**
@@ -950,16 +952,28 @@ void QETElementEditor::readSettings()
restoreGeometry(geometry.toByteArray());
}
QVariant state = settings.value("elementeditor/state");
if (state.isValid()) {
restoreState(state.toByteArray());
}
auto data = m_elmt_scene->elementData();
data.m_drawing_information = settings.value("elementeditor/default-informations", "").toString();
m_elmt_scene->setElementData(data);
}
/**
* @brief QETElementEditor::readSettingsState
* Restore the window state (docks, toolbars).
* Must be called AFTER show() in Qt6 for restoreState() to work correctly.
*/
void QETElementEditor::readSettingsState()
{
QSettings settings;
QVariant state = settings.value("elementeditor/state");
if (state.isValid()) {
if (!restoreState(state.toByteArray())) {
settings.remove("elementeditor/state");
}
}
}
/**
* @brief QETElementEditor::writeSettings
* Write some setting of this widget in the
@@ -1210,7 +1224,18 @@ void QETElementEditor::initGui()
//Live cursor position readout, in the same scene coordinates as the parts' X/Y properties
m_position_label = new QLabel(this);
m_position_label->setMinimumWidth(120);
statusBar()->addPermanentWidget(m_position_label);
// Layout
QHBoxLayout *coordDisplayLayout = new QHBoxLayout();
coordDisplayLayout->setContentsMargins(0, 0, 0, 0);
coordDisplayLayout->addWidget(m_position_label);
coordDisplayLayout->addStretch();
// Widget
QWidget *coordDisplay = new QWidget;
coordDisplay->setLayout(coordDisplayLayout);
statusBar()->addPermanentWidget(coordDisplay);
connect(m_elmt_scene, &ElementScene::mouseMoved, this, [this](const QPointF &pos) {
m_position_label->setText(tr("X: %1 Y: %2")
.arg(pos.x(), 0, 'f', 1)
+1
View File
@@ -116,6 +116,7 @@ class QETElementEditor : public QMainWindow
private:
bool canClose();
void readSettings();
void readSettingsState();
void writeSettings() const;
void setupActions();
void updateAction();
+3 -3
View File
@@ -40,7 +40,7 @@ TerminalEditor::TerminalEditor(QETElementEditor *editor, QWidget *parent) :
{
ui->setupUi(this);
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
m_color_pb = new QPushButton(this);
m_color_pb->setMinimumSize(40, 24);
connect(m_color_pb, &QPushButton::clicked, this, &TerminalEditor::labelColorClicked);
@@ -93,7 +93,7 @@ void TerminalEditor::updateForm()
ui->m_label_rotation_sb->setValue(static_cast<int>(m_part->labelRotation()));
ui->m_label_frame_cb->setChecked(m_part->labelFrame());
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
QPixmap px(16, 16);
px.fill(m_part->labelColor());
m_color_pb->setIcon(QIcon(px));
@@ -410,7 +410,7 @@ void TerminalEditor::labelColorClicked()
if (m_locked) return;
m_locked = true;
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
QColor new_color = QColorDialog::getColor(m_part->labelColor(), this);
if (new_color.isValid() && m_part->labelColor() != new_color) {
auto undo = new QPropertyUndoCommand(m_part, "label_color", m_part->labelColor(), new_color);
+2 -2
View File
@@ -21,7 +21,7 @@
#include <QWidget>
#include "../elementitemeditor.h"
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#include <QPushButton>
#else
#include <KColorButton>
@@ -78,7 +78,7 @@ class TerminalEditor : public ElementItemEditor
m_change_connections;
PartTerminal *m_part = nullptr;
bool m_locked = false;
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
QPushButton *m_color_pb;
#else
KColorButton *m_color_pb;
+2 -2
View File
@@ -63,7 +63,7 @@ void TextEditor::updateForm()
m_rotation_sb -> setValue(m_text -> rotation());
m_size_sb -> setValue(m_text -> font().pointSize());
m_font_pb -> setText(m_text -> font().family());
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
m_color_pb -> setColor(m_text -> defaultTextColor());
#endif
@@ -346,7 +346,7 @@ void TextEditor::setUpWidget(QWidget *parent)
m_line_edit->setPlaceholderText(tr("Entrer votre texte ici"));
gridLayout->addWidget(m_line_edit, 0, 0, 1, 6);
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
m_color_pb = new KColorButton(parent);
m_color_pb->setObjectName(QString::fromUtf8("m_color_pb"));
+2 -2
View File
@@ -25,7 +25,7 @@
#include <QSpinBox>
#include <QLineEdit>
#include <QPushButton>
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
#include <KColorButton>
#endif
@@ -65,7 +65,7 @@ class TextEditor : public ElementItemEditor {
QSpinBox *m_size_sb;
QLineEdit *m_line_edit;
QPushButton *m_font_pb;
#ifdef BUILD_WITHOUT_KF5
#ifdef BUILD_WITHOUT_KF
#else
KColorButton *m_color_pb;
#endif