summaryrefslogtreecommitdiffstats
path: root/src/library/basesqltablemodel.h
blob: 3a5e3df2b611fe99193d2675085cfdd1b96c09c9 (plain)
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
155
156
#pragma once

#include <QHash>
#include <QtSql>

#include "library/basetrackcache.h"
#include "library/dao/trackdao.h"
#include "library/basetracktablemodel.h"
#include "library/columncache.h"
#include "util/class.h"

class TrackCollectionManager;

// BaseSqlTableModel is a custom-written SQL-backed table which aggressively
// caches the contents of the table and supports lightweight updates.
class BaseSqlTableModel : public BaseTrackTableModel {
    Q_OBJECT
  public:
    BaseSqlTableModel(
            QObject* parent,
            TrackCollectionManager* pTrackCollectionManager,
            const char* settingsNamespace);
    ~BaseSqlTableModel() override;

    // Returns true if the BaseSqlTableModel has been initialized. Calling data
    // access methods on a BaseSqlTableModel which is not initialized is likely
    // to cause instability / crashes.
    bool initialized() const {
        return m_bInitialized;
    }

    void setSearch(const QString& searchText, const QString& extraFilter = QString());
    void setSort(int column, Qt::SortOrder order);

    ///////////////////////////////////////////////////////////////////////////
    // Inherited from QAbstractItemModel
    ///////////////////////////////////////////////////////////////////////////
    int rowCount(const QModelIndex& parent = QModelIndex()) const final;
    int columnCount(const QModelIndex& parent = QModelIndex()) const final;

    void sort(int column, Qt::SortOrder order) final;

    ///////////////////////////////////////////////////////////////////////////
    // Inherited from TrackModel
    ///////////////////////////////////////////////////////////////////////////
    int fieldIndex(const QString& fieldName) const final;

    TrackPointer getTrack(const QModelIndex& index) const override;
    TrackId getTrackId(const QModelIndex& index) const override;
    QString getTrackLocation(const QModelIndex& index) const override;

    const QVector<int> getTrackRows(TrackId trackId) const override {
        return m_trackIdToRows.value(trackId);
    }

    void search(const QString& searchText, const QString& extraFilter = QString()) override;
    const QString currentSearch() const override;

    TrackModel::SortColumnId sortColumnIdFromColumnIndex(int column) override;
    int columnIndexFromSortColumnId(TrackModel::SortColumnId sortColumn) override;

    void hideTracks(const QModelIndexList& indices) override;

    void select() override;

    ///////////////////////////////////////////////////////////////////////////
    // Inherited from BaseTrackTableModel
    ///////////////////////////////////////////////////////////////////////////
    int fieldIndex(
            ColumnCache::Column column) const final;

  protected:
    ///////////////////////////////////////////////////////////////////////////
    // Inherited from BaseTrackTableModel
    ///////////////////////////////////////////////////////////////////////////
    QVariant rawValue(
            const QModelIndex& index) const override;

    bool setTrackValueForColumn(
            const TrackPointer& pTrack,
            int column,
            const QVariant& value,
            int role) final;

    void setTable(const QString& tableName, const QString& trackIdColumn,
                  const QStringList& tableColumns,
                  QSharedPointer<BaseTrackCache> trackSource);
    void initHeaderProperties() override;
    virtual void initSortColumnMapping();

    TrackCollectionManager* const m_pTrackCollectionManager;

  protected:
    QList<TrackRef> getTrackRefs(const QModelIndexList& indices) const;

    QSqlDatabase m_database;

    QString m_tableOrderBy;
    int m_columnIndexBySortColumnId[NUM_SORTCOLUMNIDS];
    QMap<int, TrackModel::SortColumnId> m_sortColumnIdByColumnIndex;

  private slots:
    void tracksChanged(QSet<TrackId> trackIds);

  private:
    BaseCoverArtDelegate* doCreateCoverArtDelegate(
            QTableView* pTableView) const final;

    void setTrackValueForColumn(
            TrackPointer pTrack, int column, QVariant value);

    // Set the columns used for searching. Names must correspond to the column
    // names in the table provided to setTable. Must be called after setTable is
    // called.
    QString orderByClause() const;

    struct RowInfo {
        TrackId trackId;
        int order;
        QVector<QVariant> metadata;

        bool operator<(const RowInfo& other) const {
            // -1 is greater than anything
            if (order == -1) {
                return false;
            } else if (other.order == -1) {
                return true;
            }
            return order < other.order;
        }
    };

    typedef QHash<TrackId, QVector<int>> TrackId2Rows;

    void clearRows();
    void replaceRows(
            QVector<RowInfo>&& rows,
            TrackId2Rows&& trackIdToRows);

    QVector<RowInfo> m_rowInfo;

    QString m_tableName;
    QString m_idColumn;
    QSharedPointer<BaseTrackCache> m_trackSource;
    QStringList m_tableColumns;
    QList<SortColumn> m_sortColumns;
    bool m_bInitialized;
    QHash<TrackId, int> m_trackSortOrder;
    TrackId2Rows m_trackIdToRows;
    QString m_currentSearch;
    QString m_currentSearchFilter;
    QVector<QHash<int, QVariant> > m_headerInfo;
    QString m_trackSourceOrderBy;

    DISALLOW_COPY_AND_ASSIGN(BaseSqlTableModel);
};