File: spreadmodel.h

package info (click to toggle)
qt6-declarative 6.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 308,920 kB
  • sloc: cpp: 775,911; javascript: 514,247; xml: 10,855; python: 2,806; ansic: 2,253; java: 810; sh: 262; makefile: 41; php: 27
file content (154 lines) | stat: -rw-r--r-- 5,164 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// 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