Initialize new buffers in the UI with their activity
[quassel.git] / src / client / coreaccountmodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2016 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 "coreaccountmodel.h"
22
23 #include "clientsettings.h"
24 #include "quassel.h"
25
26 CoreAccountModel::CoreAccountModel(QObject *parent)
27     : QAbstractListModel(parent),
28     _internalAccount(0)
29 {
30 }
31
32
33 CoreAccountModel::CoreAccountModel(const CoreAccountModel *other, QObject *parent)
34     : QAbstractListModel(parent),
35     _internalAccount(0)
36 {
37     update(other);
38 }
39
40
41 void CoreAccountModel::update(const CoreAccountModel *other)
42 {
43     clear();
44     if (other->_accounts.count() > 0) {
45         beginInsertRows(QModelIndex(), 0, other->_accounts.count() -1);
46         _accounts = other->_accounts;
47         endInsertRows();
48     }
49     _internalAccount = other->internalAccount();
50     _removedAccounts = other->_removedAccounts;
51 }
52
53
54 void CoreAccountModel::load()
55 {
56     clear();
57     CoreAccountSettings s;
58     foreach(AccountId accId, s.knownAccounts()) {
59         QVariantMap map = s.retrieveAccountData(accId);
60         CoreAccount acc;
61         acc.fromVariantMap(map); // TODO Hook into kwallet/password saving stuff
62         insertAccount(acc);
63     }
64     if (Quassel::runMode() == Quassel::Monolithic && !internalAccount().isValid()) {
65         // Make sure we have an internal account in monolithic mode
66         CoreAccount intAcc;
67         intAcc.setInternal(true);
68         intAcc.setAccountName(tr("Internal Core"));
69         _internalAccount = createOrUpdateAccount(intAcc);
70     }
71 }
72
73
74 void CoreAccountModel::save()
75 {
76     CoreAccountSettings s;
77     foreach(AccountId id, _removedAccounts) {
78         s.removeAccount(id);
79     }
80     _removedAccounts.clear();
81     foreach(const CoreAccount &acc, accounts()) {
82         QVariantMap map = acc.toVariantMap(false); // TODO Hook into kwallet/password saving stuff
83         s.storeAccountData(acc.accountId(), map);
84     }
85 }
86
87
88 void CoreAccountModel::clear()
89 {
90     if (rowCount()) {
91         beginRemoveRows(QModelIndex(), 0, rowCount()-1);
92         _internalAccount = 0;
93         _accounts.clear();
94         endRemoveRows();
95     }
96 }
97
98
99 QVariant CoreAccountModel::data(const QModelIndex &index, int role) const
100 {
101     if (!index.isValid() || index.row() >= rowCount() || index.column() >= 1)
102         return QVariant();
103
104     const CoreAccount &acc = accounts().at(index.row());
105
106     switch (role) {
107     case Qt::DisplayRole:
108         return acc.accountName();
109     case AccountIdRole:
110         return QVariant::fromValue<AccountId>(acc.accountId());
111     case UuidRole:
112         return acc.uuid().toString();
113
114     default:
115         return QVariant();
116     }
117 }
118
119
120 CoreAccount CoreAccountModel::account(AccountId id) const
121 {
122     int idx = findAccountIdx(id);
123     if (idx >= 0)
124         return _accounts.value(idx);
125     return CoreAccount();
126 }
127
128
129 CoreAccount CoreAccountModel::account(const QModelIndex &idx) const
130 {
131     if (idx.isValid() && idx.row() < _accounts.count())
132         return _accounts.value(idx.row());
133     return CoreAccount();
134 }
135
136
137 QList<CoreAccount> CoreAccountModel::accounts() const
138 {
139     return _accounts;
140 }
141
142
143 QList<AccountId> CoreAccountModel::accountIds() const
144 {
145     QList<AccountId> list;
146     foreach(const CoreAccount &acc, accounts())
147     list << acc.accountId();
148     return list;
149 }
150
151
152 bool CoreAccountModel::operator==(const CoreAccountModel &other) const
153 {
154     return _accounts == other._accounts;
155 }
156
157
158 // TODO with Qt 4.6, use QAbstractItemModel move semantics to properly do this
159 AccountId CoreAccountModel::createOrUpdateAccount(const CoreAccount &newAcc)
160 {
161     CoreAccount acc = newAcc;
162
163     if (acc.uuid().isNull())
164         acc.setUuid(QUuid::createUuid());
165
166     if (!acc.accountId().isValid()) {
167         // find free Id
168         AccountId newId = 0;
169         const QList<AccountId> &ids = accountIds();
170         for (int i = 1;; i++) {
171             if (!_removedAccounts.contains(i) && !ids.contains(i)) {
172                 newId = i;
173                 break;
174             }
175         }
176         acc.setAccountId(newId);
177         insertAccount(acc);
178     }
179     else {
180         int idx = findAccountIdx(acc.accountId());
181         if (idx >= 0) {
182             if (acc.accountName() == accounts().at(idx).accountName()) {
183                 _accounts[idx] = acc;
184                 emit dataChanged(index(idx, 0), index(idx, 0));
185             }
186             else {
187                 takeAccount(acc.accountId());
188                 insertAccount(acc);
189             }
190         }
191         else
192             insertAccount(acc);
193     }
194     return acc.accountId();
195 }
196
197
198 void CoreAccountModel::insertAccount(const CoreAccount &acc)
199 {
200     if (acc.isInternal()) {
201         if (internalAccount().isValid()) {
202             qWarning() << "Trying to insert a second internal account in CoreAccountModel, ignoring";
203             return;
204         }
205         _internalAccount = acc.accountId();
206     }
207
208     // check for Quuid
209     int idx = 0;
210     while (idx<_accounts.count() && acc.accountName()> _accounts.at(idx).accountName() && !acc.isInternal())
211         ++idx;
212
213     beginInsertRows(QModelIndex(), idx, idx);
214     _accounts.insert(idx, acc);
215     endInsertRows();
216 }
217
218
219 CoreAccount CoreAccountModel::takeAccount(AccountId accId)
220 {
221     int idx = findAccountIdx(accId);
222     if (idx < 0)
223         return CoreAccount();
224
225     beginRemoveRows(QModelIndex(), idx, idx);
226     CoreAccount acc = _accounts.takeAt(idx);
227     endRemoveRows();
228
229     if (acc.isInternal())
230         _internalAccount = 0;
231
232     return acc;
233 }
234
235
236 void CoreAccountModel::removeAccount(AccountId accId)
237 {
238     takeAccount(accId);
239     _removedAccounts.insert(accId);
240 }
241
242
243 QModelIndex CoreAccountModel::accountIndex(AccountId accId) const
244 {
245     for (int i = 0; i < _accounts.count(); i++) {
246         if (_accounts.at(i).accountId() == accId)
247             return index(i, 0);
248     }
249     return QModelIndex();
250 }
251
252
253 int CoreAccountModel::findAccountIdx(AccountId id) const
254 {
255     QModelIndex idx = accountIndex(id);
256     return idx.isValid() ? idx.row() : -1;
257 }