qtdeclarative/examples/quickcontrols/spreadsheets/Spreadsheets/spreadmodel.h

155 lines
5.0 KiB
C++

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef SPREADMODEL_H
#define SPREADMODEL_H
#include "datamodel.h"
#include <QQmlEngine>
#include <QAbstractTableModel>
#include <QItemSelectionModel>
#include <QMutex>
class DataModel;
class SpreadModel;
class Formula;
class SpreadModel final : public QAbstractTableModel
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_DISABLE_COPY_MOVE(SpreadModel)
friend class SpreadSelectionModel;
friend class SpreadCell;
friend struct Formula;
protected:
explicit SpreadModel(QObject *parent = nullptr) : QAbstractTableModel(parent) { }
public:
int rowCount() const { return rowCount(QModelIndex{}); }
int columnCount() const { return columnCount(QModelIndex{}); }
const DataModel *dataModel() { return &m_dataModel; }
int columnNumberFromName(const QString &text);
int rowNumberFromName(const QString &text);
// returns nullptr if it's not been created yet.
static SpreadModel *instance();
static SpreadModel *create(QQmlEngine *, QJSEngine *);
protected:
Q_INVOKABLE void update(int row, int column);
Q_INVOKABLE void clearHighlight();
Q_INVOKABLE void setHighlight(const QModelIndex &index, bool highlight);
Q_INVOKABLE bool clearItemData(const QModelIndexList &indexes);
Q_INVOKABLE bool removeColumns(QModelIndexList indexes);
Q_INVOKABLE bool removeRows(QModelIndexList indexes);
Q_INVOKABLE void mapColumn(int model, int view);
Q_INVOKABLE void mapRow(int model, int view);
Q_INVOKABLE void resetColumnMapping() { m_viewColumns.clear(); }
Q_INVOKABLE void resetRowMapping() { m_viewRows.clear(); }
// QAbstractItemModel interface
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Q_INVOKABLE bool clearItemData(const QModelIndex &index) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QHash<int, QByteArray> roleNames() const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex{}) override;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex{}) override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
private:
Formula parseFormulaString(const QString &text);
QString formulaValueText(const Formula &formula);
int getViewColumn(int modelColumn) const;
int getModelColumn(int viewColumn) const;
int getViewRow(int modelRow) const;
int getModelRow(int viewRow) const;
private:
std::pair<int, int> m_size {1000, 26}; // rows:1-1000, columns:A-Z
DataModel m_dataModel;
QMap<int, int> m_viewColumns;
QMap<int, int> m_viewRows;
QMutex m_updateMutex;
static inline SpreadModel *s_instance {nullptr};
};
class SpreadSelectionModel : public QItemSelectionModel
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(Behavior behavior READ getBehavior WRITE setBehavior NOTIFY behaviorChanged FINAL)
public:
enum Behavior {
DisabledBehavior,
SelectCells,
SelectColumns,
SelectRows,
};
Q_ENUM(Behavior)
public:
Q_INVOKABLE void toggleColumn(int column);
Q_INVOKABLE void deselectColumn(int column);
Q_INVOKABLE void selectColumn(int column, bool clear = true);
Q_INVOKABLE void toggleRow(int row);
Q_INVOKABLE void deselectRow(int row);
Q_INVOKABLE void selectRow(int row, bool clear = true);
protected:
Behavior getBehavior() const { return m_behavior; }
protected slots:
void setBehavior(Behavior);
signals:
void behaviorChanged();
private:
Behavior m_behavior = Behavior::DisabledBehavior;
};
class HeaderSelectionModel : public QItemSelectionModel
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(SpreadSelectionModel* selectionModel READ getSelectionModel WRITE setSelectionModel NOTIFY selectionModelChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ getOrientation WRITE setOrientation NOTIFY orientationChanged FINAL)
protected:
Q_INVOKABLE void setCurrent(int current = -1);
SpreadSelectionModel *getSelectionModel() { return m_selectionModel; }
Qt::Orientation getOrientation() const { return m_orientation; }
protected slots:
void setSelectionModel(SpreadSelectionModel *selectionModel);
void setOrientation(Qt::Orientation orientation);
private slots:
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
signals:
void selectionModelChanged();
void orientationChanged();
private:
SpreadSelectionModel *m_selectionModel = nullptr;
Qt::Orientation m_orientation = Qt::Horizontal;
};
#endif // SPREADMODEL_H