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