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