Changeset View
Changeset View
Standalone View
Standalone View
src/widgets/channellist/channellistview.cpp
Show All 17 Lines | 1 | /* | |||
---|---|---|---|---|---|
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "channellistview.h" | 21 | #include "channellistview.h" | ||
22 | #include "ruqola.h" | 22 | #include "ruqola.h" | ||
23 | #include "ruqolawidgets_debug.h" | 23 | #include "ruqolawidgets_debug.h" | ||
24 | #include "rocketchataccount.h" | 24 | #include "rocketchataccount.h" | ||
25 | #include "channellistdelegate.h" | 25 | #include "channellistdelegate.h" | ||
26 | #include "model/roomfilterproxymodel.h" | 26 | #include "model/accountschannelsmodel.h" | ||
27 | #include "model/rocketchataccountmodel.h" | ||||
27 | 28 | | |||
28 | #include <KLocalizedString> | 29 | #include <KLocalizedString> | ||
29 | 30 | | |||
30 | #include <QAction> | 31 | #include <QAction> | ||
31 | #include <QContextMenuEvent> | 32 | #include <QContextMenuEvent> | ||
32 | #include <QMenu> | 33 | #include <QMenu> | ||
33 | 34 | | |||
34 | ChannelListView::ChannelListView(QWidget *parent) | 35 | ChannelListView::ChannelListView(QWidget *parent) | ||
35 | : QListView(parent) | 36 | : QTreeView(parent) | ||
36 | { | 37 | { | ||
38 | setUniformRowHeights(true); | ||||
39 | setHeaderHidden(true); | ||||
40 | | ||||
37 | auto *delegate = new ChannelListDelegate(this); | 41 | auto *delegate = new ChannelListDelegate(this); | ||
38 | setItemDelegate(delegate); | 42 | setItemDelegate(delegate); | ||
39 | setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 43 | setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | ||
40 | 44 | | |||
41 | connect(this, &ChannelListView::clicked, this, &ChannelListView::slotClicked); | 45 | connect(this, &ChannelListView::clicked, this, &ChannelListView::activateChannel); | ||
42 | } | | |||
43 | 46 | | |||
44 | ChannelListView::~ChannelListView() | 47 | auto model = new AccountsChannelsModel(this); | ||
45 | { | 48 | auto syncCurrentIndex = [this, model]{ | ||
46 | } | 49 | if (model->isFiltered()) | ||
47 | 50 | return; // We don't keep in sync when filtering | |||
48 | RoomFilterProxyModel *ChannelListView::model() const | 51 | | ||
49 | { | 52 | const auto index = model->findRoomById(mCurrentChannelId); | ||
50 | return qobject_cast<RoomFilterProxyModel *>(QListView::model()); | 53 | selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); | ||
54 | }; | ||||
55 | | ||||
56 | connect(model, &AccountsChannelsModel::modelChanged, this, syncCurrentIndex); | ||||
57 | connect(this, &ChannelListView::channelActivated, this, syncCurrentIndex); | ||||
58 | QTreeView::setModel(model); | ||||
51 | } | 59 | } | ||
52 | 60 | | |||
53 | void ChannelListView::setModel(QAbstractItemModel *model) | 61 | ChannelListView::~ChannelListView() | ||
54 | { | 62 | { | ||
55 | if (!qobject_cast<RoomFilterProxyModel *>(model)) { | | |||
56 | qCWarning(RUQOLAWIDGETS_LOG) << "Need to pass a RoomFilterProxyModel instance!"; | | |||
57 | return; | | |||
58 | } | | |||
59 | | ||||
60 | QListView::setModel(model); | | |||
61 | } | 63 | } | ||
62 | 64 | | |||
63 | void ChannelListView::slotClicked(const QModelIndex &index) | 65 | void ChannelListView::setModel(QAbstractItemModel *) | ||
64 | { | 66 | { | ||
65 | if (index.isValid()) { | 67 | Q_ASSERT_X(false, "", "Cannot change the channel list view model"); | ||
66 | channelSelected(index); | | |||
67 | } | | |||
68 | } | 68 | } | ||
69 | 69 | | |||
70 | void ChannelListView::contextMenuEvent(QContextMenuEvent *event) | 70 | void ChannelListView::contextMenuEvent(QContextMenuEvent *event) | ||
71 | { | 71 | { | ||
72 | const QModelIndex index = indexAt(event->pos()); | 72 | const QModelIndex index = indexAt(event->pos()); | ||
73 | if (!index.isValid()) { | 73 | if (!index.isValid()) { | ||
74 | return; | 74 | return; | ||
75 | } | 75 | } | ||
Show All 24 Lines | 93 | if (roomType == QLatin1String("c") || roomType == QLatin1String("p")) { //Not direct channel | |||
100 | }); | 100 | }); | ||
101 | menu.addAction(quitChannel); | 101 | menu.addAction(quitChannel); | ||
102 | } | 102 | } | ||
103 | if (!menu.actions().isEmpty()) { | 103 | if (!menu.actions().isEmpty()) { | ||
104 | menu.exec(event->globalPos()); | 104 | menu.exec(event->globalPos()); | ||
105 | } | 105 | } | ||
106 | } | 106 | } | ||
107 | 107 | | |||
108 | void ChannelListView::channelSelected(const QModelIndex &index) | 108 | AccountsChannelsModel *ChannelListView::rooms() const | ||
109 | { | 109 | { | ||
110 | Q_ASSERT(qobject_cast<AccountsChannelsModel*>(QTreeView::model())); | ||||
111 | return static_cast<AccountsChannelsModel*>(QTreeView::model()); | ||||
112 | } | ||||
113 | | ||||
114 | void ChannelListView::activateChannel(const QModelIndex &index) | ||||
115 | { | ||||
116 | if (!index.isValid()) | ||||
117 | return; | ||||
118 | | ||||
119 | if (!index.parent().isValid()) | ||||
120 | { | ||||
121 | // This is an account index, activate last selected room | ||||
122 | if (auto account = index.data(RocketChatAccountModel::Account).value<RocketChatAccount*>()) | ||||
123 | activateChannelById(account->settings()->lastSelectedRoom()); | ||||
124 | return; | ||||
125 | } | ||||
126 | | ||||
110 | const QString roomId = index.data(RoomModel::RoomID).toString(); | 127 | const QString roomId = index.data(RoomModel::RoomID).toString(); | ||
111 | const QString roomType = index.data(RoomModel::RoomType).toString(); | 128 | const QString roomType = index.data(RoomModel::RoomType).toString(); | ||
112 | Q_EMIT roomSelected(roomId, roomType); | 129 | const QString acct = rooms()->accountForIndex(index); | ||
130 | mCurrentChannelId = roomId; | ||||
131 | Q_EMIT channelActivated(acct, roomId, roomType); | ||||
113 | } | 132 | } | ||
114 | 133 | | |||
115 | void ChannelListView::slotHideChannel(const QModelIndex &index, const QString &roomType) | 134 | void ChannelListView::slotHideChannel(const QModelIndex &index, const QString &roomType) | ||
116 | { | 135 | { | ||
117 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | 136 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | ||
118 | const QString roomId = index.data(RoomModel::RoomID).toString(); | 137 | const QString roomId = index.data(RoomModel::RoomID).toString(); | ||
119 | rcAccount->hideRoom(roomId, roomType); | 138 | rcAccount->hideRoom(roomId, roomType); | ||
120 | } | 139 | } | ||
121 | 140 | | |||
122 | void ChannelListView::slotLeaveChannel(const QModelIndex &index, const QString &roomType) | 141 | void ChannelListView::slotLeaveChannel(const QModelIndex &index, const QString &roomType) | ||
123 | { | 142 | { | ||
124 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | 143 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | ||
125 | const QString roomId = index.data(RoomModel::RoomID).toString(); | 144 | const QString roomId = index.data(RoomModel::RoomID).toString(); | ||
126 | rcAccount->leaveRoom(roomId, roomType); | 145 | rcAccount->leaveRoom(roomId, roomType); | ||
127 | } | 146 | } | ||
128 | 147 | | |||
129 | void ChannelListView::slotChangeFavorite(const QModelIndex &index, bool isFavorite) | 148 | void ChannelListView::slotChangeFavorite(const QModelIndex &index, bool isFavorite) | ||
130 | { | 149 | { | ||
131 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | 150 | auto *rcAccount = Ruqola::self()->rocketChatAccount(); | ||
132 | const QString roomId = index.data(RoomModel::RoomID).toString(); | 151 | const QString roomId = index.data(RoomModel::RoomID).toString(); | ||
133 | rcAccount->changeFavorite(roomId, !isFavorite); | 152 | rcAccount->changeFavorite(roomId, !isFavorite); | ||
134 | } | 153 | } | ||
135 | 154 | | |||
136 | void ChannelListView::selectChannelRequested(const QString &channelId) | 155 | void ChannelListView::activateChannelById(const QString &channelId) | ||
137 | { | 156 | { | ||
138 | if (channelId.isEmpty()) { | 157 | activateChannel(rooms()->findRoomById(channelId)); | ||
139 | return; | | |||
140 | } | 158 | } | ||
141 | RoomFilterProxyModel *filterModel = model(); | 159 | | ||
142 | Q_ASSERT(filterModel); | 160 | bool ChannelListView::activateChannelByRoomName(const QString &selectedRoomName) | ||
143 | const int nRooms = filterModel->rowCount(); | 161 | { | ||
144 | if (nRooms == 0) { | 162 | const auto roomIdx = rooms()->findRoomByName(selectedRoomName); | ||
145 | return; // too early, next chance when accountInitialized is emitted | 163 | if (!roomIdx.isValid()) | ||
146 | } | 164 | return false; | ||
147 | for (int roomIdx = 0; roomIdx < nRooms; ++roomIdx) { | 165 | | ||
148 | const auto roomModelIndex = filterModel->index(roomIdx, 0); | 166 | activateChannel(roomIdx); | ||
149 | const auto roomId = roomModelIndex.data(RoomModel::RoomID).toString(); | 167 | return true; | ||
150 | if (roomId == channelId) { | 168 | } | ||
151 | channelSelected(roomModelIndex); | 169 | | ||
152 | selectionModel()->setCurrentIndex(filterModel->index(roomIdx, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); | 170 | void ChannelListView::moveSelectionDown() | ||
153 | return; | 171 | { | ||
172 | const auto index = [&]() -> QModelIndex { | ||||
173 | const auto current = currentIndex().isValid() ? currentIndex() : rooms()->index(0, 0); | ||||
174 | if (!current.isValid()) | ||||
175 | return {}; | ||||
176 | | ||||
177 | const auto useParent = current.parent(); | ||||
178 | if (useParent.isValid()) | ||||
179 | { | ||||
180 | const auto room = current.sibling(current.row() + 1, 0); | ||||
181 | if (room.isValid()) | ||||
182 | return room; | ||||
154 | } | 183 | } | ||
184 | | ||||
185 | auto account = useParent.isValid() ? useParent.sibling(useParent.row() + 1, 0) : current; | ||||
186 | while (account.isValid()) | ||||
187 | { | ||||
188 | if (rooms()->hasChildren(account)) | ||||
189 | return rooms()->index(0, 0, account); | ||||
190 | account = account.sibling(account.row() + 1, account.column()); | ||||
155 | } | 191 | } | ||
156 | qCWarning(RUQOLAWIDGETS_LOG) << "Room not found:" << channelId; | 192 | return {}; | ||
193 | }(); | ||||
194 | | ||||
195 | if (index.isValid()) | ||||
196 | selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); | ||||
157 | } | 197 | } | ||
158 | 198 | | |||
159 | bool ChannelListView::selectChannelByRoomNameRequested(const QString &selectedRoomName) | 199 | void ChannelListView::moveSelectionUp() | ||
160 | { | 200 | { | ||
161 | if (selectedRoomName.isEmpty()) { | 201 | const auto index = [&]() -> QModelIndex { | ||
162 | return false; | 202 | const auto current = [&]{ | ||
203 | if (currentIndex().isValid()) | ||||
204 | return currentIndex(); | ||||
205 | | ||||
206 | const auto lastParent = rooms()->index(rooms()->rowCount() - 1, 0); | ||||
207 | if (!lastParent.isValid()) | ||||
208 | return lastParent; | ||||
209 | | ||||
210 | const auto lastChild = rooms()->index(rooms()->rowCount(lastParent) - 1, 0, lastParent); | ||||
211 | return lastChild.isValid() ? lastChild : lastParent; | ||||
212 | }(); | ||||
213 | if (!current.isValid()) | ||||
214 | return {}; | ||||
215 | | ||||
216 | const auto useParent = current.parent(); | ||||
217 | if (useParent.isValid()) | ||||
218 | { | ||||
219 | const auto room = current.sibling(current.row() - 1, 0); | ||||
220 | if (room.isValid()) | ||||
221 | return room; | ||||
163 | } | 222 | } | ||
164 | RoomFilterProxyModel *filterModel = model(); | 223 | | ||
165 | for (int roomIdx = 0, nRooms = filterModel->rowCount(); roomIdx < nRooms; ++roomIdx) { | 224 | auto account = useParent.isValid() ? useParent.sibling(useParent.row() - 1, 0) : current; | ||
166 | const auto roomModelIndex = filterModel->index(roomIdx, 0); | 225 | while (account.isValid()) | ||
167 | const auto roomName = roomModelIndex.data(RoomModel::RoomName).toString(); | 226 | { | ||
168 | if (roomName == selectedRoomName) { | 227 | if (rooms()->hasChildren(account)) | ||
169 | channelSelected(roomModelIndex); | 228 | return rooms()->index(rooms()->rowCount(account) - 1, 0, account); | ||
170 | selectionModel()->setCurrentIndex(filterModel->index(roomIdx, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); | 229 | account = account.sibling(account.row() - 1, account.column()); | ||
171 | return true; | | |||
172 | } | 230 | } | ||
231 | | ||||
232 | return {}; | ||||
233 | }(); | ||||
234 | | ||||
235 | if (index.isValid()) | ||||
236 | selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); | ||||
173 | } | 237 | } | ||
174 | return false; | 238 | | ||
239 | void ChannelListView::setFilterString(const QString &filter) | ||||
240 | { | ||||
241 | rooms()->setFilterString(filter); | ||||
175 | } | 242 | } |