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
157
|
// SPDX-FileCopyrightText: 2021 Nheko Contributors
// SPDX-FileCopyrightText: 2022 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QAbstractListModel>
#include <QHash>
#include <QSortFilterProxyModel>
#include <QString>
#include <QStringList>
#include <mtx/responses/sync.hpp>
#include "CacheStructs.h"
class CommunitiesModel;
class FilteredCommunitiesModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent = nullptr);
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
};
class CommunitiesModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QString currentTagId READ currentTagId WRITE setCurrentTagId NOTIFY
currentTagIdChanged RESET resetCurrentTagId)
Q_PROPERTY(QStringList tags READ tags NOTIFY tagsChanged)
Q_PROPERTY(QStringList tagsWithDefault READ tagsWithDefault NOTIFY tagsChanged)
Q_PROPERTY(bool containsSubspaces READ containsSubspaces NOTIFY containsSubspacesChanged)
public:
enum Roles
{
AvatarUrl = Qt::UserRole,
DisplayName,
Tooltip,
Collapsed,
Collapsible,
Hidden,
Parent,
Depth,
Id,
};
struct FlatTree
{
struct Elem
{
QString name;
int depth = 0;
bool collapsed = false;
};
std::vector<Elem> tree;
int size() const { return static_cast<int>(tree.size()); }
int indexOf(const QString &s) const
{
for (int i = 0; i < size(); i++)
if (tree[i].name == s)
return i;
return -1;
}
int lastChild(int index) const
{
if (index >= size() || index < 0)
return index;
const auto depth = tree[index].depth;
int i = index + 1;
for (; i < size(); i++)
if (tree[i].depth <= depth)
break;
return i - 1;
}
int parent(int index) const
{
if (index >= size() || index < 0)
return -1;
const auto depth = tree[index].depth;
if (depth == 0)
return -1;
int i = index - 1;
for (; i >= 0; i--)
if (tree[i].depth < depth)
break;
return i;
}
void storeCollapsed();
void restoreCollapsed();
};
CommunitiesModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
(void)parent;
return 2 + tags_.size() + spaceOrder_.size();
}
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool containsSubspaces() const
{
for (const auto &e : spaceOrder_.tree)
if (e.depth > 0)
return true;
return false;
}
public slots:
void initializeSidebar();
void sync(const mtx::responses::Sync &sync_);
void clear();
QString currentTagId() const { return currentTagId_; }
void setCurrentTagId(QString tagId);
void resetCurrentTagId()
{
currentTagId_.clear();
emit currentTagIdChanged(currentTagId_);
}
QStringList tags() const { return tags_; }
QStringList tagsWithDefault() const
{
QStringList tagsWD = tags_;
tagsWD.prepend(QStringLiteral("m.lowpriority"));
tagsWD.prepend(QStringLiteral("m.favourite"));
tagsWD.removeOne(QStringLiteral("m.server_notice"));
tagsWD.removeDuplicates();
return tagsWD;
}
void toggleTagId(QString tagId);
FilteredCommunitiesModel *filtered() { return new FilteredCommunitiesModel(this, this); }
signals:
void currentTagIdChanged(QString tagId);
void hiddenTagsChanged();
void tagsChanged();
void containsSubspacesChanged();
private:
QStringList tags_;
QString currentTagId_;
QStringList hiddentTagIds_;
FlatTree spaceOrder_;
std::map<QString, RoomInfo> spaces_;
friend class FilteredCommunitiesModel;
};
|