Warning, file /office/calligra/gemini/CloudAccountsModel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2014 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  *
0006  */
0007 
0008 #include "CloudAccountsModel.h"
0009 #include "PropertyContainer.h"
0010 
0011 #include <QDebug>
0012 #include <QByteArray>
0013 #include <QDataStream>
0014 #include <QVariant>
0015 #include <QMetaObject>
0016 #include <QMetaProperty>
0017 #include <QFile>
0018 #include <QStandardPaths>
0019 
0020 struct AccountEntry {
0021 public:
0022     AccountEntry(QObject* parent)
0023         : selected(false)
0024         , accountDetails(new PropertyContainer("", parent))
0025     {}
0026     QString text;
0027     bool selected;
0028     QString accountType;
0029     QString stackComponent;
0030     QObject* accountDetails;
0031 
0032     QByteArray serialize() {
0033         // selected is not serialised, because that would be silly
0034         QByteArray ba;
0035         QDataStream stream(&ba, QIODevice::WriteOnly);
0036         stream << text;
0037         stream << accountType;
0038         stream << stackComponent;
0039         Q_FOREACH(const QByteArray &name, accountDetails->dynamicPropertyNames()) {
0040             stream << name << accountDetails->property(name);
0041         }
0042         for(int i = accountDetails->metaObject()->propertyOffset(); i < accountDetails->metaObject()->propertyCount(); ++i) {
0043             stream << accountDetails->metaObject()->property(i).name() << accountDetails->metaObject()->property(i).read(accountDetails);
0044         }
0045         return ba;
0046     }
0047 
0048     static AccountEntry* fromByteArray(QByteArray& ba, QObject* parent) {
0049         AccountEntry* entry = new AccountEntry(parent);
0050         QDataStream stream(&ba, QIODevice::ReadOnly);
0051         stream >> entry->text;
0052         stream >> entry->accountType;
0053         stream >> entry->stackComponent;
0054         entry->accountDetails->setProperty("text", entry->text);
0055         while(!stream.atEnd()) {
0056             QByteArray propertyName;
0057             QVariant data;
0058             stream >> propertyName;
0059             stream >> data;
0060             entry->accountDetails->setProperty(propertyName, data);
0061         }
0062         return entry;
0063     }
0064 };
0065 
0066 class CloudAccountsModel::Private {
0067 public:
0068     Private(CloudAccountsModel* qq)
0069         : q(qq)
0070     {
0071         dataFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/calligrageminicloudaccounts");
0072         loadList();
0073     }
0074     ~Private()
0075     {
0076         qDeleteAll(entries);
0077     }
0078     CloudAccountsModel* q;
0079     QList<AccountEntry*> entries;
0080     QString dataFile;
0081 
0082     void saveList()
0083     {
0084         QByteArray ba;
0085         QDataStream stream(&ba, QIODevice::WriteOnly);
0086         Q_FOREACH(AccountEntry* entry, entries) {
0087             stream << entry->serialize();
0088         }
0089         QFile data(dataFile);
0090         data.open(QIODevice::WriteOnly);
0091         data.write(ba);
0092         data.close();
0093     }
0094 
0095     void loadList()
0096     {
0097         QByteArray ba;
0098         QFile data(dataFile);
0099         data.open(QIODevice::ReadOnly);
0100         ba = data.readAll();
0101         data.close();
0102 
0103         q->beginResetModel();
0104         qDeleteAll(entries);
0105         entries.clear();
0106 
0107         QDataStream stream(&ba, QIODevice::ReadOnly);
0108         QByteArray entryBA;
0109         while(!stream.atEnd()) {
0110             stream >> entryBA;
0111             entries.append(AccountEntry::fromByteArray(entryBA, q));
0112         }
0113 
0114         q->endResetModel();
0115     }
0116 };
0117 
0118 CloudAccountsModel::CloudAccountsModel(QObject* parent)
0119     : QAbstractListModel(parent)
0120     , d(new Private(this))
0121 {
0122 }
0123 
0124 CloudAccountsModel::~CloudAccountsModel()
0125 {
0126     delete d;
0127 }
0128 
0129 QHash<int, QByteArray> CloudAccountsModel::roleNames() const
0130 {
0131     QHash<int, QByteArray> roles;
0132     roles[TextRole] = "text";
0133     roles[SelectedRole] = "selected";
0134     roles[AccountTypeRole] = "accountType";
0135     roles[StackComponentRole] = "stackComponent";
0136     roles[AccountDetailsRole] = "accountDetails";
0137     return roles;
0138 }
0139 
0140 QVariant CloudAccountsModel::data(const QModelIndex& index, int role) const
0141 {
0142     QVariant result;
0143     if(index.isValid() && index.row() > -1 && index.row() < d->entries.count())
0144     {
0145         AccountEntry* entry = d->entries.at(index.row());
0146         switch(role)
0147         {
0148             case TextRole:
0149                 result = entry->text;
0150                 break;
0151             case SelectedRole:
0152                 result = entry->selected;
0153                 break;
0154             case AccountTypeRole:
0155                 result = entry->accountType;
0156                 break;
0157             case StackComponentRole:
0158                 result = entry->stackComponent;
0159                 break;
0160             case AccountDetailsRole:
0161                 result = QVariant::fromValue<QObject*>(entry->accountDetails);
0162                 break;
0163             default:
0164                 break;
0165         }
0166     }
0167     return result;
0168 }
0169 
0170 int CloudAccountsModel::rowCount(const QModelIndex& parent) const
0171 {
0172     if(parent.isValid())
0173         return 0;
0174     return d->entries.count();
0175 }
0176 
0177 void CloudAccountsModel::selectIndex(int newSelection)
0178 {
0179     Q_FOREACH(AccountEntry* entry, d->entries) {
0180         entry->selected = false;
0181     }
0182     if(newSelection >= 0 && newSelection < d->entries.count()) {
0183         d->entries.at(newSelection)->selected = true;
0184     }
0185     dataChanged(index(0), index(d->entries.count() - 1));
0186 }
0187 
0188 void CloudAccountsModel::addAccount(QString text, QString accountType, QString stackComponent, QObject* accountDetails, bool removeExisting)
0189 {
0190     if(removeExisting) {
0191         removeAccountByName(text);
0192     }
0193     AccountEntry* entry = new AccountEntry(this);
0194     entry->text = text;
0195     entry->accountType = accountType;
0196     entry->stackComponent = stackComponent;
0197     if(accountDetails) {
0198         Q_FOREACH(const QByteArray &name, accountDetails->dynamicPropertyNames()) {
0199             entry->accountDetails->setProperty(name, accountDetails->property(name));
0200         }
0201         for(int i = accountDetails->metaObject()->propertyOffset(); i < accountDetails->metaObject()->propertyCount(); ++i) {
0202             entry->accountDetails->setProperty(accountDetails->metaObject()->property(i).name(), accountDetails->metaObject()->property(i).read(accountDetails));
0203         }
0204     }
0205     int count = d->entries.count();
0206     beginInsertRows(QModelIndex(), count, count);
0207     d->entries.append(entry);
0208     endInsertRows();
0209     d->saveList();
0210 }
0211 
0212 void CloudAccountsModel::renameAccount(int index, QString newText)
0213 {
0214     if(index > -1 && index < d->entries.count() - 1)
0215     {
0216         d->entries.at(index)->text = newText;
0217         dataChanged(this->index(index), this->index(index));
0218         d->saveList();
0219     }
0220 }
0221 
0222 void CloudAccountsModel::removeAccountByName(QString text)
0223 {
0224     beginResetModel();
0225     for(int i = d->entries.count() - 1; i > -1; --i) {
0226         if(d->entries.at(i)->text == text) {
0227             d->entries.removeAt(i);
0228         }
0229     }
0230     endResetModel();
0231 }
0232 
0233 void CloudAccountsModel::removeAccount(int index)
0234 {
0235     if(index > -1 && index < d->entries.count())
0236     {
0237         beginRemoveRows(QModelIndex(), index, index);
0238         delete(d->entries.takeAt(index));
0239         endRemoveRows();
0240         d->saveList();
0241     }
0242 }
0243 
0244 QObject* CloudAccountsModel::accountDetails(int index)
0245 {
0246     if(index > -1 && index < d->entries.count() - 1)
0247     {
0248         return d->entries.at(index)->accountDetails;
0249     }
0250     return 0;
0251 }
0252 
0253 void CloudAccountsModel::setAccountDetails(int index, QObject* newDetails)
0254 {
0255     if(index > -1 && index < d->entries.count() - 1)
0256     {
0257         AccountEntry* entry = d->entries.at(index);
0258         if(newDetails) {
0259             Q_FOREACH(const QByteArray &name, newDetails->dynamicPropertyNames()) {
0260                 entry->accountDetails->setProperty(name, newDetails->property(name));
0261             }
0262             for(int i = newDetails->metaObject()->propertyOffset(); i < newDetails->metaObject()->propertyCount(); ++i) {
0263                 entry->accountDetails->setProperty(newDetails->metaObject()->property(i).name(), newDetails->metaObject()->property(i).read(newDetails));
0264             }
0265         }
0266         d->saveList();
0267     }
0268 }