Files
qelectrotech-source-mirror/sources/TerminalStrip/terminalstrip.h
T
Kellermorph 650e318e02 Answer the terminal strip editor without walking the whole strip
The editor asks its model for every cell of every row, over and over
(paint, flags, row height, resize to contents). Three answers used to
cost far more than the little they tell:

- a row was found by walking m_physical_data each time, which made a
  layout O(rows^2 * columns);
- the bridge cells walked to the head of the strip for each neighbour
  of each step, and every step filled the full row data, which reads
  the cables of the whole project (the target column of the terminal
  strip editor);
- without any bridge on the strip, that walk still ran to its end.

Rows are now found through an index filled once with m_physical_data,
the bridge walk steps from row to row and fills only the three fields
it reads (level, bridge, identity), and it is skipped when the strip
has no bridge at all.

Nothing about what the editor shows, edits or saves changes: the model
data, the bridge pixmaps and the strip order are the same, only the
time to answer is not. Measured on a 302 row strip with one bridge
(20 rounds, offscreen, off the UI): all flags 372 ms to 6.6 ms, all
display cells 1195 ms to 31 ms, all decoration 7623 ms to 106 ms
(a bridge cell 251 us to 2.5 us), about 65 times faster overall.

The full test suite passes (121/121).
2026-10-21 17:42:12 +02:00

144 lines
6.4 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 TERMINALSTRIP_H
#define TERMINALSTRIP_H
#include <QObject>
#include <QPointer>
#include <QColor>
#include "terminalstripdata.h"
#include "../properties/elementdata.h"
class Element;
class RealTerminal;
class QETProject;
class PhysicalTerminal;
class TerminalStripIndex;
class TerminalElement;
class TerminalStrip;
class TerminalStripBridge;
/**
* @brief The TerminalStrip class
* This class hold all the datas and configurations
* of a terminal strip (but the not the visual aspect).
* A terminal strip have some informations (name comment etc...)
* and is composed by one or several PhysicalTerminal.
*/
class TerminalStrip : public QObject
{
friend class TerminalStripModel;
friend class RealTerminalData;
Q_OBJECT
public:
signals:
void orderChanged(); //Emitted when the order of the physical terminal is changed
void bridgeChanged();
void bridgeColorChanged(QSharedPointer<TerminalStripBridge> bridge);
//Emitted when the data of the strip (name...) or of one of its
//terminals (width, color, type...) is changed : what is drawn changes
void dataChanged();
public:
TerminalStrip(QETProject *project);
TerminalStrip(const QString &installation,
const QString &location,
const QString &name,
QETProject *project);
void setInstallation(const QString &installation);
QString installation() const {return m_data.m_installation;}
void setLocation(const QString &location);
QString location() const {return m_data.m_location;}
void setName(const QString &name);
QString name() const {return m_data.m_name;}
void setComment(const QString &comment);
QString comment() const {return m_data.m_comment;}
void setDescription(const QString &description);
QString description() const {return m_data.m_description;}
///Manufacturer of the terminals proposed by the editor, empty = all
QString manufacturer() const {return m_data.m_manufacturer;}
QUuid uuid() const {return m_data.m_uuid;}
QETProject *project() const;
TerminalStripData data() const;
void setData(const TerminalStripData &data);
void terminalDataChanged();
bool addTerminal (QSharedPointer<RealTerminal> real_t);
void addTerminals (QVector<QSharedPointer<RealTerminal>> real_t_vector);
void addAndGroupTerminals (const QVector<QVector<QSharedPointer<RealTerminal>>> &real_t_vector);
bool removeTerminal (QSharedPointer<RealTerminal> real_t);
void removeTerminals (QVector<QSharedPointer<RealTerminal>> real_t_vector);
bool addTerminal (Element *terminal);
bool removeTerminal (Element *terminal);
bool addTerminal (QSharedPointer<PhysicalTerminal> phy_t);
void addTerminals (QVector<QSharedPointer<PhysicalTerminal>> phy_t_vector);
bool removeTerminal (QSharedPointer<PhysicalTerminal> phy_t);
void removeTerminals (QVector<QSharedPointer<PhysicalTerminal>> phy_t_vector);
QVector<QSharedPointer<PhysicalTerminal>> insertSpareTerminals(int pos, const QVector<QSharedPointer<RealTerminal>> &spare_terminals);
void insertTerminals(int pos, const QVector<QSharedPointer<PhysicalTerminal>> &phy_t_vector);
int pos(const QSharedPointer<PhysicalTerminal> &terminal) const;
int physicalTerminalCount() const;
QSharedPointer<PhysicalTerminal> physicalTerminal(int index) const;
QSharedPointer<PhysicalTerminal> physicalTerminal(const QUuid &uuid) const;
QVector<QSharedPointer<PhysicalTerminal>> physicalTerminal() const;
QSharedPointer<RealTerminal> realTerminalForUuid(const QUuid &uuid) const;
QVector<QSharedPointer<RealTerminal>> realTerminals() const;
bool setOrderTo(const QVector<QSharedPointer<PhysicalTerminal>> &sorted_vector);
bool groupTerminals(const QSharedPointer<PhysicalTerminal> &receiver_terminal, const QVector<QSharedPointer<RealTerminal>> &added_terminals);
void unGroupTerminals(const QVector<QSharedPointer<RealTerminal>> &terminals_to_ungroup);
bool setLevel(const QSharedPointer<RealTerminal> &real_terminal, int level);
bool isBridgeable(const QVector<QSharedPointer<RealTerminal>> &real_terminals) const;
bool isBridgeable(QSharedPointer<TerminalStripBridge> bridge, const QVector<QSharedPointer<RealTerminal>> &real_terminals) const;
bool setBridge(const QVector<QSharedPointer<RealTerminal>> &real_terminals);
bool setBridge(const QSharedPointer<TerminalStripBridge> &bridge, const QVector<QSharedPointer<RealTerminal>> &real_terminals);
void unBridge(const QVector<QSharedPointer<RealTerminal>> &real_terminals);
bool canUnBridge(const QVector <QSharedPointer<RealTerminal>> &real_terminals) const;
QSharedPointer<TerminalStripBridge> isBridged(const QSharedPointer<RealTerminal> real_terminal) const;
///True when at least one bridge joins terminals of this strip :
///the bridge cells of the terminal strip editor are the only thing
///drawn from them (see TerminalStripModel::bridgePixmapFor)
bool hasBridges() const { return !m_bridge.isEmpty(); }
QSharedPointer<TerminalStripBridge> bridgeFor (const QVector<QSharedPointer<RealTerminal>> &terminal_vector) const;
QSharedPointer<RealTerminal> previousTerminalInLevel(const QSharedPointer<RealTerminal> &real_terminal) const;
QSharedPointer<RealTerminal> nextTerminalInLevel(const QSharedPointer<RealTerminal> &real_terminal) const;
QSharedPointer<RealTerminal> previousRealTerminal(const QSharedPointer<RealTerminal> &real_terminal) const;
QSharedPointer<RealTerminal> nextRealTerminal(const QSharedPointer<RealTerminal> &real_terminal) const;
static QString xmlTagName() {return QStringLiteral("terminal_strip");}
QDomElement toXml(QDomDocument &parent_document);
bool fromXml(QDomElement &xml_element);
private:
TerminalStripData m_data;
QPointer<QETProject> m_project;
QVector<QSharedPointer<PhysicalTerminal>> m_physical_terminals;
QVector<QSharedPointer<TerminalStripBridge>> m_bridge;
};
#endif // TERMINALSTRIP_H