uisupport: Provide helpers for dealing with widget changes
[quassel.git] / src / client / buffermodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "buffermodel.h"
22
23 #include <QAbstractItemView>
24
25 #include "client.h"
26 #include "networkmodel.h"
27 #include "quassel.h"
28
29 BufferModel::BufferModel(NetworkModel *parent)
30     : QSortFilterProxyModel(parent),
31     _selectionModelSynchronizer(this)
32 {
33     setSourceModel(parent);
34     if (Quassel::isOptionSet("debugbufferswitches")) {
35         connect(_selectionModelSynchronizer.selectionModel(), &QItemSelectionModel::currentChanged,
36             this, &BufferModel::debug_currentChanged);
37     }
38     connect(Client::instance(), &Client::networkCreated, this, &BufferModel::newNetwork);
39     connect(this, &QAbstractItemModel::rowsInserted, this, &BufferModel::newBuffers);
40 }
41
42
43 bool BufferModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const
44 {
45     Q_UNUSED(sourceRow);
46     // only networks and buffers are allowed
47     if (!parent.isValid())
48         return true;
49     if (parent.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType)
50         return true;
51
52     return false;
53 }
54
55
56 void BufferModel::newNetwork(NetworkId id)
57 {
58     const Network *net = Client::network(id);
59     Q_ASSERT(net);
60     connect(net, &Network::connectionStateSet,
61         this, &BufferModel::networkConnectionChanged);
62 }
63
64
65 void BufferModel::networkConnectionChanged(Network::ConnectionState state)
66 {
67     switch (state) {
68     case Network::Connecting:
69     case Network::Initializing:
70         if (currentIndex().isValid())
71             return;
72         {
73             auto *net = qobject_cast<Network *>(sender());
74             Q_ASSERT(net);
75             setCurrentIndex(mapFromSource(Client::networkModel()->networkIndex(net->networkId())));
76         }
77         break;
78     default:
79         return;
80     }
81 }
82
83
84 void BufferModel::synchronizeView(QAbstractItemView *view)
85 {
86     _selectionModelSynchronizer.synchronizeSelectionModel(view->selectionModel());
87 }
88
89
90 void BufferModel::setCurrentIndex(const QModelIndex &newCurrent)
91 {
92     _selectionModelSynchronizer.selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::Current);
93     _selectionModelSynchronizer.selectionModel()->select(newCurrent, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
94 }
95
96
97 void BufferModel::switchToBuffer(const BufferId &bufferId)
98 {
99     QModelIndex source_index = Client::networkModel()->bufferIndex(bufferId);
100     setCurrentIndex(mapFromSource(source_index));
101 }
102
103
104 void BufferModel::switchToBufferIndex(const QModelIndex &bufferIdx)
105 {
106     // we accept indexes that directly belong to us or our parent - nothing else
107     if (bufferIdx.model() == this) {
108         setCurrentIndex(bufferIdx);
109         return;
110     }
111
112     if (bufferIdx.model() == sourceModel()) {
113         setCurrentIndex(mapFromSource(bufferIdx));
114         return;
115     }
116
117     qWarning() << "BufferModel::switchToBufferIndex(const QModelIndex &):" << bufferIdx << "does not belong to BufferModel or NetworkModel";
118 }
119
120
121 void BufferModel::switchToOrJoinBuffer(NetworkId networkId, const QString &name, bool isQuery)
122 {
123     BufferId bufId = Client::networkModel()->bufferId(networkId, name);
124     if (bufId.isValid()) {
125         QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId);
126         switchToBuffer(bufId);
127         if (!targetIdx.data(NetworkModel::ItemActiveRole).toBool()) {
128             qDebug() << "switchToOrJoinBuffer failed to switch even though bufId:" << bufId << "is valid.";
129             Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name));
130         }
131     }
132     else {
133         _bufferToSwitchTo = qMakePair(networkId, name);
134         Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name));
135     }
136 }
137
138
139 void BufferModel::debug_currentChanged(QModelIndex current, QModelIndex previous)
140 {
141     Q_UNUSED(previous);
142     qDebug() << "Switched current Buffer: " << current << current.data().toString() << "Buffer:" << current.data(NetworkModel::BufferIdRole).value<BufferId>();
143 }
144
145
146 void BufferModel::newBuffers(const QModelIndex &parent, int start, int end)
147 {
148     if (parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType)
149         return;
150
151     for (int row = start; row <= end; row++) {
152         QModelIndex child = parent.child(row, 0);
153         newBuffer(child.data(NetworkModel::BufferIdRole).value<BufferId>());
154     }
155 }
156
157
158 void BufferModel::newBuffer(BufferId bufferId)
159 {
160     BufferInfo bufferInfo = Client::networkModel()->bufferInfo(bufferId);
161     if (_bufferToSwitchTo.first == bufferInfo.networkId()
162         && _bufferToSwitchTo.second == bufferInfo.bufferName()) {
163         _bufferToSwitchTo.first = 0;
164         _bufferToSwitchTo.second.clear();
165         switchToBuffer(bufferId);
166     }
167 }
168
169
170 void BufferModel::switchToBufferAfterCreation(NetworkId network, const QString &name)
171 {
172     _bufferToSwitchTo = qMakePair(network, name);
173 }