src: Yearly copyright bump
[quassel.git] / src / client / coreaccountmodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2019 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 bool CoreAccountModel::operator!=(const CoreAccountModel &other) const
159 {
160     return !(*this == other);
161 }
162
163
164 // TODO with Qt 4.6, use QAbstractItemModel move semantics to properly do this
165 AccountId CoreAccountModel::createOrUpdateAccount(const CoreAccount &newAcc)
166 {
167     CoreAccount acc = newAcc;
168
169     if (acc.uuid().isNull())
170         acc.setUuid(QUuid::createUuid());
171
172     if (!acc.accountId().isValid()) {
173         // find free Id
174         AccountId newId = 0;
175         const QList<AccountId> &ids = accountIds();
176         for (int i = 1;; i++) {
177             if (!_removedAccounts.contains(i) && !ids.contains(i)) {
178                 newId = i;
179                 break;
180             }
181         }
182         acc.setAccountId(newId);
183         insertAccount(acc);
184     }
185     else {
186         int idx = findAccountIdx(acc.accountId());
187         if (idx >= 0) {
188             if (acc.accountName() == accounts().at(idx).accountName()) {
189                 _accounts[idx] = acc;
190                 emit dataChanged(index(idx, 0), index(idx, 0));
191             }
192             else {
193                 takeAccount(acc.accountId());
194                 insertAccount(acc);
195             }
196         }
197         else
198             insertAccount(acc);
199     }
200     return acc.accountId();
201 }
202
203
204 void CoreAccountModel::insertAccount(const CoreAccount &acc)
205 {
206     if (acc.isInternal()) {
207         if (internalAccount().isValid()) {
208             qWarning() << "Trying to insert a second internal account in CoreAccountModel, ignoring";
209             return;
210         }
211         _internalAccount = acc.accountId();
212     }
213
214     // check for Quuid
215     int idx = 0;
216     while (idx<_accounts.count() && acc.accountName()> _accounts.at(idx).accountName() && !acc.isInternal())
217         ++idx;
218
219     beginInsertRows(QModelIndex(), idx, idx);
220     _accounts.insert(idx, acc);
221     endInsertRows();
222 }
223
224
225 CoreAccount CoreAccountModel::takeAccount(AccountId accId)
226 {
227     int idx = findAccountIdx(accId);
228     if (idx < 0)
229         return CoreAccount();
230
231     beginRemoveRows(QModelIndex(), idx, idx);
232     CoreAccount acc = _accounts.takeAt(idx);
233     endRemoveRows();
234
235     if (acc.isInternal())
236         _internalAccount = 0;
237
238     return acc;
239 }
240
241
242 void CoreAccountModel::removeAccount(AccountId accId)
243 {
244     takeAccount(accId);
245     _removedAccounts.insert(accId);
246 }
247
248
249 QModelIndex CoreAccountModel::accountIndex(AccountId accId) const
250 {
251     for (int i = 0; i < _accounts.count(); i++) {
252         if (_accounts.at(i).accountId() == accId)
253             return index(i, 0);
254     }
255     return QModelIndex();
256 }
257
258
259 int CoreAccountModel::findAccountIdx(AccountId id) const
260 {
261     QModelIndex idx = accountIndex(id);
262     return idx.isValid() ? idx.row() : -1;
263 }