1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 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 | } |
258 | |