File indexing completed on 2024-05-05 17:04:25
0001 /* This file is part of the KDE project 0002 * Copyright 2014 Dan Leinir Turthra Jensen <admin@leinir.dk> 0003 * 0004 * This program is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU General Public License as 0006 * published by the Free Software Foundation; either version 2 of 0007 * the License or (at your option) version 3 or any later version 0008 * accepted by the membership of KDE e.V. (or its successor approved 0009 * by the membership of KDE e.V.), which shall act as a proxy 0010 * defined in Section 14 of version 3 of the license. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License 0018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 * 0020 */ 0021 0022 #include "CloudAccountsModel.h" 0023 #include "PropertyContainer.h" 0024 0025 #include <QDebug> 0026 #include <QByteArray> 0027 #include <QDataStream> 0028 #include <QVariant> 0029 #include <QMetaObject> 0030 #include <QMetaProperty> 0031 #include <QFile> 0032 #include <QStandardPaths> 0033 0034 struct AccountEntry { 0035 public: 0036 AccountEntry(QObject* parent) 0037 : selected(false) 0038 , accountDetails(new PropertyContainer("", parent)) 0039 {} 0040 QString text; 0041 bool selected; 0042 QString accountType; 0043 QString stackComponent; 0044 QObject* accountDetails; 0045 0046 QByteArray serialize() { 0047 // selected is not serialised, because that would be silly 0048 QByteArray ba; 0049 QDataStream stream(&ba, QIODevice::WriteOnly); 0050 stream << text; 0051 stream << accountType; 0052 stream << stackComponent; 0053 Q_FOREACH(const QByteArray &name, accountDetails->dynamicPropertyNames()) { 0054 stream << name << accountDetails->property(name); 0055 } 0056 for(int i = accountDetails->metaObject()->propertyOffset(); i < accountDetails->metaObject()->propertyCount(); ++i) { 0057 stream << accountDetails->metaObject()->property(i).name() << accountDetails->metaObject()->property(i).read(accountDetails); 0058 } 0059 return ba; 0060 } 0061 0062 static AccountEntry* fromByteArray(QByteArray& ba, QObject* parent) { 0063 AccountEntry* entry = new AccountEntry(parent); 0064 QDataStream stream(&ba, QIODevice::ReadOnly); 0065 stream >> entry->text; 0066 stream >> entry->accountType; 0067 stream >> entry->stackComponent; 0068 entry->accountDetails->setProperty("text", entry->text); 0069 while(!stream.atEnd()) { 0070 QByteArray propertyName; 0071 QVariant data; 0072 stream >> propertyName; 0073 stream >> data; 0074 entry->accountDetails->setProperty(propertyName, data); 0075 } 0076 return entry; 0077 } 0078 }; 0079 0080 class CloudAccountsModel::Private { 0081 public: 0082 Private(CloudAccountsModel* qq) 0083 : q(qq) 0084 { 0085 dataFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/calligrageminicloudaccounts"); 0086 loadList(); 0087 } 0088 ~Private() 0089 { 0090 qDeleteAll(entries); 0091 } 0092 CloudAccountsModel* q; 0093 QList<AccountEntry*> entries; 0094 QString dataFile; 0095 0096 void saveList() 0097 { 0098 QByteArray ba; 0099 QDataStream stream(&ba, QIODevice::WriteOnly); 0100 Q_FOREACH(AccountEntry* entry, entries) { 0101 stream << entry->serialize(); 0102 } 0103 QFile data(dataFile); 0104 data.open(QIODevice::WriteOnly); 0105 data.write(ba); 0106 data.close(); 0107 } 0108 0109 void loadList() 0110 { 0111 QByteArray ba; 0112 QFile data(dataFile); 0113 data.open(QIODevice::ReadOnly); 0114 ba = data.readAll(); 0115 data.close(); 0116 0117 q->beginResetModel(); 0118 qDeleteAll(entries); 0119 entries.clear(); 0120 0121 QDataStream stream(&ba, QIODevice::ReadOnly); 0122 QByteArray entryBA; 0123 while(!stream.atEnd()) { 0124 stream >> entryBA; 0125 entries.append(AccountEntry::fromByteArray(entryBA, q)); 0126 } 0127 0128 q->endResetModel(); 0129 } 0130 }; 0131 0132 CloudAccountsModel::CloudAccountsModel(QObject* parent) 0133 : QAbstractListModel(parent) 0134 , d(new Private(this)) 0135 { 0136 QHash<int, QByteArray> roles; 0137 roles[TextRole] = "text"; 0138 roles[SelectedRole] = "selected"; 0139 roles[AccountTypeRole] = "accountType"; 0140 roles[StackComponentRole] = "stackComponent"; 0141 roles[AccountDetailsRole] = "accountDetails"; 0142 setRoleNames(roles); 0143 } 0144 0145 CloudAccountsModel::~CloudAccountsModel() 0146 { 0147 delete d; 0148 } 0149 0150 QVariant CloudAccountsModel::data(const QModelIndex& index, int role) const 0151 { 0152 QVariant result; 0153 if(index.isValid() && index.row() > -1 && index.row() < d->entries.count()) 0154 { 0155 AccountEntry* entry = d->entries.at(index.row()); 0156 switch(role) 0157 { 0158 case TextRole: 0159 result = entry->text; 0160 break; 0161 case SelectedRole: 0162 result = entry->selected; 0163 break; 0164 case AccountTypeRole: 0165 result = entry->accountType; 0166 break; 0167 case StackComponentRole: 0168 result = entry->stackComponent; 0169 break; 0170 case AccountDetailsRole: 0171 result = QVariant::fromValue<QObject*>(entry->accountDetails); 0172 break; 0173 default: 0174 break; 0175 } 0176 } 0177 return result; 0178 } 0179 0180 int CloudAccountsModel::rowCount(const QModelIndex& parent) const 0181 { 0182 if(parent.isValid()) 0183 return 0; 0184 return d->entries.count(); 0185 } 0186 0187 void CloudAccountsModel::selectIndex(int newSelection) 0188 { 0189 Q_FOREACH(AccountEntry* entry, d->entries) { 0190 entry->selected = false; 0191 } 0192 if(newSelection >= 0 && newSelection < d->entries.count()) { 0193 d->entries.at(newSelection)->selected = true; 0194 } 0195 dataChanged(index(0), index(d->entries.count() - 1)); 0196 } 0197 0198 void CloudAccountsModel::addAccount(QString text, QString accountType, QString stackComponent, QObject* accountDetails, bool removeExisting) 0199 { 0200 if(removeExisting) { 0201 removeAccountByName(text); 0202 } 0203 AccountEntry* entry = new AccountEntry(this); 0204 entry->text = text; 0205 entry->accountType = accountType; 0206 entry->stackComponent = stackComponent; 0207 if(accountDetails) { 0208 Q_FOREACH(const QByteArray &name, accountDetails->dynamicPropertyNames()) { 0209 entry->accountDetails->setProperty(name, accountDetails->property(name)); 0210 } 0211 for(int i = accountDetails->metaObject()->propertyOffset(); i < accountDetails->metaObject()->propertyCount(); ++i) { 0212 entry->accountDetails->setProperty(accountDetails->metaObject()->property(i).name(), accountDetails->metaObject()->property(i).read(accountDetails)); 0213 } 0214 } 0215 int count = d->entries.count(); 0216 beginInsertRows(QModelIndex(), count, count); 0217 d->entries.append(entry); 0218 endInsertRows(); 0219 d->saveList(); 0220 } 0221 0222 void CloudAccountsModel::renameAccount(int index, QString newText) 0223 { 0224 if(index > -1 && index < d->entries.count() - 1) 0225 { 0226 d->entries.at(index)->text = newText; 0227 dataChanged(this->index(index), this->index(index)); 0228 d->saveList(); 0229 } 0230 } 0231 0232 void CloudAccountsModel::removeAccountByName(QString text) 0233 { 0234 beginResetModel(); 0235 for(int i = d->entries.count() - 1; i > -1; --i) { 0236 if(d->entries.at(i)->text == text) { 0237 d->entries.removeAt(i); 0238 } 0239 } 0240 endResetModel(); 0241 } 0242 0243 void CloudAccountsModel::removeAccount(int index) 0244 { 0245 if(index > -1 && index < d->entries.count()) 0246 { 0247 beginRemoveRows(QModelIndex(), index, index); 0248 delete(d->entries.takeAt(index)); 0249 endRemoveRows(); 0250 d->saveList(); 0251 } 0252 } 0253 0254 QObject* CloudAccountsModel::accountDetails(int index) 0255 { 0256 if(index > -1 && index < d->entries.count() - 1) 0257 { 0258 return d->entries.at(index)->accountDetails; 0259 } 0260 return 0; 0261 } 0262 0263 void CloudAccountsModel::setAccountDetails(int index, QObject* newDetails) 0264 { 0265 if(index > -1 && index < d->entries.count() - 1) 0266 { 0267 AccountEntry* entry = d->entries.at(index); 0268 if(newDetails) { 0269 Q_FOREACH(const QByteArray &name, newDetails->dynamicPropertyNames()) { 0270 entry->accountDetails->setProperty(name, newDetails->property(name)); 0271 } 0272 for(int i = newDetails->metaObject()->propertyOffset(); i < newDetails->metaObject()->propertyCount(); ++i) { 0273 entry->accountDetails->setProperty(newDetails->metaObject()->property(i).name(), newDetails->metaObject()->property(i).read(newDetails)); 0274 } 0275 } 0276 d->saveList(); 0277 } 0278 }