mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-24 16:04:16 +02:00
650e318e02
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).
170 lines
5.3 KiB
C++
170 lines
5.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 TERMINALSTRIPMODEL_H
|
|
#define TERMINALSTRIPMODEL_H
|
|
|
|
#include <QAbstractTableModel>
|
|
#include <QObject>
|
|
#include <QPointer>
|
|
#include <QStyledItemDelegate>
|
|
#include <QHash>
|
|
#include <QColor>
|
|
|
|
#include "../terminalstrip.h"
|
|
#include "modelTerminalData.h"
|
|
|
|
//Code to use QColor as key for QHash
|
|
inline size_t qHash(const QColor &key, size_t seed = 0) {
|
|
return qHash(key.rgba(), seed);
|
|
}
|
|
|
|
//needed to use QPointer<Element> as key of QHash
|
|
inline uint qHash(const QPointer<Element> &key, uint seed) {
|
|
if (key)
|
|
return qHash(key->uuid(), seed);
|
|
else
|
|
return qHash(QUuid(), seed);
|
|
}
|
|
|
|
class TerminalStrip;
|
|
|
|
class TerminalStripModel : public QAbstractTableModel
|
|
{
|
|
public:
|
|
enum Column {
|
|
Pos = 0,
|
|
Level = 1,
|
|
Level0 = 2,
|
|
Level1 = 3,
|
|
Level2 = 4,
|
|
Level3 = 5,
|
|
Label = 6,
|
|
Conductor = 7,
|
|
XRef = 8,
|
|
Cable = 9,
|
|
CableWire = 10,
|
|
CableTarget = 11,
|
|
Type = 12,
|
|
Function = 13,
|
|
Led = 14,
|
|
Shield = 15,
|
|
Color = 16,
|
|
Section = 17,
|
|
Width = 18,
|
|
Separator = 19,
|
|
Invalid = 99
|
|
};
|
|
|
|
static int levelForColumn(TerminalStripModel::Column column);
|
|
static TerminalStripModel::Column columnTypeForIndex(const QModelIndex &index);
|
|
|
|
///Role of the Width column : the label of the terminal chosen in the catalog.
|
|
///setData() with this role takes a QVariantMap {"mm": width, "entry": label}
|
|
static constexpr int CatalogEntryRole = Qt::UserRole + 1;
|
|
|
|
Q_OBJECT
|
|
public:
|
|
TerminalStripModel(TerminalStrip *terminal_strip, QObject *parent = nullptr);
|
|
void setTerminalStrip(TerminalStrip *terminal_strip);
|
|
|
|
virtual int rowCount (const QModelIndex &parent = QModelIndex()) const override;
|
|
virtual int columnCount (const QModelIndex &parent = QModelIndex()) const override;
|
|
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
virtual bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
|
virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
|
virtual Qt::ItemFlags flags (const QModelIndex &index) const override;
|
|
QVector<modelRealTerminalData> modifiedmodelRealTerminalData() const;
|
|
|
|
QVector<modelPhysicalTerminalData> modelPhysicalTerminalDataForIndex(QModelIndexList index_list) const;
|
|
QVector<modelRealTerminalData> modelRealTerminalDataForIndex(QModelIndexList index_list) const;
|
|
modelRealTerminalData modelRealTerminalDataForIndex(const QModelIndex &index) const;
|
|
|
|
void buildBridgePixmap(const QSize &pixmap_size);
|
|
|
|
void reload();
|
|
|
|
private:
|
|
void fillPhysicalTerminalData();
|
|
modelRealTerminalData dataAtRow(int row) const;
|
|
void replaceDataAtRow(modelRealTerminalData data, int row);
|
|
modelPhysicalTerminalData physicalDataAtIndex(int index) const;
|
|
modelRealTerminalData realDataAtIndex(int index) const;
|
|
QPixmap bridgePixmapFor(const QModelIndex &index) const;
|
|
|
|
private:
|
|
//Where the data of one row of the table sit in m_physical_data.
|
|
//The view asks for every cell of every row, over and over (paint,
|
|
//flags, row height), so looking a row up must be a lookup and not
|
|
//a walk through the whole strip each time.
|
|
struct RowPlace
|
|
{
|
|
int physical_; //index in m_physical_data
|
|
int real_; //index in the real_data of that physical terminal
|
|
};
|
|
|
|
QPointer<TerminalStrip> m_terminal_strip;
|
|
//Modified cells of each real terminal (spare terminals have no element)
|
|
QHash<const RealTerminal *, QVector<bool>> m_modified_cell;
|
|
QVector<modelPhysicalTerminalData> m_physical_data;
|
|
//One RowPlace by row, filled with m_physical_data (see fillPhysicalTerminalData)
|
|
QVector<RowPlace> m_row_index;
|
|
//Number of rows held in m_row_index, so rowCount() needs no walk
|
|
int m_row_count = 0;
|
|
struct BridgePixmap
|
|
{
|
|
QPixmap top_,
|
|
middle_,
|
|
bottom_,
|
|
none_;
|
|
};
|
|
|
|
QHash<QColor, BridgePixmap> m_bridges_pixmaps;
|
|
|
|
};
|
|
|
|
class TerminalStripModelDelegate : public QStyledItemDelegate
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
TerminalStripModelDelegate(QObject *parent = Q_NULLPTR);
|
|
|
|
QWidget *createEditor(
|
|
QWidget *parent,
|
|
const QStyleOptionViewItem &option,
|
|
const QModelIndex &index) const override;
|
|
void setEditorData(
|
|
QWidget *editor,
|
|
const QModelIndex &index) const override;
|
|
void setModelData(
|
|
QWidget *editor,
|
|
QAbstractItemModel *model,
|
|
const QModelIndex &index) const override;
|
|
bool eventFilter(QObject *object, QEvent *event) override;
|
|
|
|
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
|
|
|
void setManufacturer(const QString &manufacturer);
|
|
|
|
private:
|
|
///Manufacturer of the terminals proposed in the Width column, empty = all
|
|
QString m_manufacturer;
|
|
};
|
|
|
|
#endif // TERMINALSTRIPMODEL_H
|