Files
qelectrotech-source-mirror/sources/factory/elementpicturefactory.h
T
ispyisail 592cbdbf0b Keep the texts of turned symbols horizontal, per project (#1335)
A project can now keep the texts drawn in its symbols, and the names of
their terminals, horizontal when a symbol is turned: Project properties >
General, "Garder horizontaux les textes des symboles pivotés". The box of
each text turns with the symbol; the text does not, and reads as it does
in the symbol itself.

It is a project setting, saved as <symbol_texts upright="true"/> and
only when on. A new project starts with it on; a project saved without
it (every existing one) reads with it off, so it looks and saves exactly
as before, and looks the same on every computer. The MCP server's new
projects start with it on too.

It builds on the mirror of #1354, which already redraws the texts of a
mirrored symbol readable: what the symbol does to its texts is now its
mirrors and, with the setting on, its turn (Element::symbolTextsTransform()).
ElementPictureFactory caches one drawing per such transform, terminal
names undo it the same way, and the DXF export places the texts alike.

The fields of a symbol (label, comment...) already keep their angle with
"Garder la rotation visuelle" and are left as they are.

Known limit: two texts stacked in a symbol end up side by side when it is
turned, and can overlap when kept horizontal; the setting can be turned
off for such a project.

Test: tst_uprightsymboltexts turns the symbols of a folio and checks the
angle of each motor's "M" in the DXF, with the setting off and on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:43:04 +13:00

130 lines
4.3 KiB
C++

/*
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/>.
*/
#ifndef ELEMENTPICTUREFACTORY_H
#define ELEMENTPICTUREFACTORY_H
#include <QMutex>
#include <QSharedPointer>
#include <QHash>
#include <QPair>
#include <QTransform>
class ElementsLocation;
class QPicture;
class QUuid;
class QDomElement;
class QPainter;
class QGraphicsSimpleTextItem;
/**
@brief The ElementPictureFactory class
This class is singleton factory, use
to create and get the picture use by elements
*/
class ElementPictureFactory
{
public :
struct primitives
{
QList<QLineF> m_lines;
QList<QRectF> m_rectangles;
QList<QRectF> m_circles;
QList<QVector<QPointF>> m_polygons;
QList<QVector<qreal>> m_arcs;
QList<QGraphicsSimpleTextItem*> m_texts;
};
/**
@brief instance
@return The instance of the factory
*/
static ElementPictureFactory* instance()
{
static QMutex mutex;
if (!m_factory)
{
mutex.lock();
if (!m_factory) {
m_factory = new ElementPictureFactory();
}
mutex.unlock();
}
return m_factory;
}
/**
@brief dropInstance
Drop the instance of factory
*/
static void dropInstance()
{
static QMutex mutex;
if (m_factory)
{
mutex.lock();
delete m_factory;
m_factory = nullptr;
mutex.unlock();
}
}
void getPictures(const ElementsLocation &location, QPicture &picture, QPicture &low_picture);
void getReadablePictures(const ElementsLocation &location, const QTransform &texts_transform,
QPicture &picture, QPicture &low_picture);
QPixmap pixmap(const ElementsLocation &location);
ElementPictureFactory::primitives getPrimitives(const ElementsLocation &location);
void dropCache(const ElementsLocation &location);
private:
ElementPictureFactory() {}
ElementPictureFactory (const ElementPictureFactory &);
ElementPictureFactory operator= (const ElementPictureFactory &);
~ElementPictureFactory();
static QUuid cacheKey(const ElementsLocation &location);
static int readableKey(const QTransform &texts_transform);
bool build(const ElementsLocation &location, QPicture *picture=nullptr, QPicture *low_picture=nullptr,
const QTransform &texts_transform=QTransform());
void parseElement(const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseLine (const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseRect (const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseEllipse(const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseCircle (const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseArc (const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parsePolygon(const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parseText (const QDomElement &dom, QPainter &painter, primitives &prim) const;
void parsePlcTable(const QDomElement &dom, const QDomElement &plc_data, QPainter &painter) const;
void setPainterStyle(const QDomElement &dom, QPainter &painter) const;
QHash<QUuid, QPicture> m_pictures_H;
QHash<QUuid, QPicture> m_low_pictures_H;
/// Drawings whose texts read normally once an element has
/// mirrored or turned them, by element and readableKey(), see
/// getReadablePictures()
QHash<QPair<QUuid, int>, QPicture> m_readable_pictures_H;
QHash<QPair<QUuid, int>, QPicture> m_readable_low_pictures_H;
/// What build() undoes on each text, read by parseText()
QTransform m_build_texts_undo;
QHash<QUuid, QPixmap> m_pixmap_H;
QHash<QUuid, primitives> m_primitives_H;
static ElementPictureFactory* m_factory;
};
#endif // ELEMENTPICTUREFACTORY_H