I have made the following changes intended for :
  CE:MW:Shared / nemo-qml-plugins

Please review and accept or decline.
BOSS has already run some checks on this request.
See the "Messages from BOSS" section below.

https://build.pub.meego.com//request/show/7582

Thank You,
John Brooks

[This message was auto-generated]

---

Request # 7582:

Messages from BOSS:

State: review at 2012-12-28T01:41:22 by bossbot

Reviews:
       accepted by bossbot : Prechecks succeeded.
       new for CE-maintainers : Please replace this text with a review and 
approve/reject the review (not the SR). BOSS will take care of the rest

Changes:
  submit: home:special:branches:CE:MW:Shared / nemo-qml-plugins -> CE:MW:Shared 
/ nemo-qml-plugins
  
changes files:
--------------
--- nemo-qml-plugins.changes
+++ nemo-qml-plugins.changes
@@ -0,0 +1,3 @@
+* Thu Dec 27 2012 John Brooks <[email protected]> - 0.1.10
+- Fix account configuration value saving, add ServiceAccountModel (by Chris 
Adams)
+

old:
----
  nemo-qml-plugins-0.1.9.tar.bz2

new:
----
  nemo-qml-plugins-0.1.10.tar.bz2

spec files:
-----------
--- nemo-qml-plugins.spec
+++ nemo-qml-plugins.spec
@@ -9,7 +9,7 @@
 # << macros
 
 Summary:    Nemo QML plugins source package.
-Version:    0.1.9
+Version:    0.1.10
 Release:    1
 Group:      System/Libraries
 License:    BSD

other changes:
--------------

++++++ nemo-qml-plugins-0.1.9.tar.bz2 -> nemo-qml-plugins-0.1.10.tar.bz2
--- accounts/src/accountinterface.cpp
+++ accounts/src/accountinterface.cpp
@@ -68,6 +68,26 @@
 {
 }
 
+static QVariant configurationValueVariant(Accounts::Account *acc, const 
QString &key)
+{
+    QString strVal = acc->valueAsString(key);
+    if (!strVal.isNull())
+        return QVariant(strVal);
+
+    quint64 uintMax = 0xffffffffffffffffU;
+    quint64 uintVal = acc->valueAsUInt64(key, uintMax);
+    if (uintVal != uintMax)
+        return QVariant(uintVal);
+
+    int intMax = 0xffffffff;
+    int intVal = acc->valueAsInt(key, intMax);
+    if (intVal != intMax)
+        return QVariant(intVal);
+
+    bool boolVal = acc->valueAsBool(key);
+    return QVariant(boolVal);
+}
+
 void AccountInterfacePrivate::setAccount(Accounts::Account *acc)
 {
     if (!acc) {
@@ -172,11 +192,8 @@
         // enumerate the configuration values
         QVariantMap allValues;
         QStringList allKeys = account->allKeys();
-        foreach (const QString &key, allKeys) {
-            QVariant currValue;
-            account->value(key, currValue); // pass by ref.
-            allValues.insert(key, currValue);
-        }
+        foreach (const QString &key, allKeys)
+            allValues.insert(key, configurationValueVariant(account, key));
         if (configurationValues != allValues) {
             configurationValues = allValues;
             emit q->configurationValuesChanged();
@@ -298,11 +315,8 @@
         // check to see if the configuration values were updated
         QVariantMap allValues;
         QStringList allKeys = account->allKeys();
-        foreach (const QString &key, allKeys) {
-            QVariant currValue;
-            account->value(key, currValue); // pass by ref.
-            allValues.insert(key, currValue);
-        }
+        foreach (const QString &key, allKeys)
+            allValues.insert(key, configurationValueVariant(account, key));
         if (configurationValues != allValues) {
             configurationValues = allValues;
             emit q->configurationValuesChanged();
@@ -506,9 +520,6 @@
         d->enabledServiceNamesPendingInit = false;
     }
 
-    d->account->setEnabled(d->enabled);
-    d->account->setDisplayName(d->displayName);
-
     // set the credentials / identity identifiers for each service.
     foreach (const QString &srvn, d->supportedServiceNames) {
         int currIdentId = d->identityIdentifiers.value(srvn).value<int>();
@@ -548,14 +559,32 @@
     // set the configuration values.
     QStringList allKeys = d->account->allKeys();
     QStringList setKeys = d->configurationValues.keys();
+    QStringList doneKeys;
     foreach (const QString &key, allKeys) {
+        // overwrite existing keys
         if (setKeys.contains(key)) {
+            doneKeys.append(key);
             const QVariant &currValue = d->configurationValues.value(key);
-            d->account->setValue(key, currValue);
+            if (currValue.isValid()) {
+                d->account->setValue(key, currValue);
+            } else {
+                d->account->remove(key);
+            }
         } else {
+            // remove removed keys
             d->account->remove(key);
         }
     }
+    foreach (const QString &key, setKeys) {
+        // add new keys
+        if (!doneKeys.contains(key)) {
+            const QVariant &currValue = d->configurationValues.value(key);
+            d->account->setValue(key, currValue);
+        }
+    }
+
+    d->account->setEnabled(d->enabled);
+    d->account->setDisplayName(d->displayName);
 
     d->setStatus(AccountInterface::SyncInProgress);
     d->account->sync();
@@ -579,13 +608,22 @@
 /*!
     \qmlmethod void Account::setConfigurationValue(const QString &key, const 
QVariant &value)
     Sets the account's configuration settings value for the key \a key
-    to the value \a value.
+    to the value \a value.  The only supported value types are int, quint64, 
bool and QString.
 */
 void AccountInterface::setConfigurationValue(const QString &key, const 
QVariant &value)
 {
     if (d->status == AccountInterface::Invalid || d->status == 
AccountInterface::SyncInProgress)
         return;
 
+    if (value.type() != QVariant::Int
+            && value.type() != QVariant::LongLong
+            && value.type() != QVariant::ULongLong
+            && value.type() != QVariant::Bool
+            && value.type() != QVariant::String) {
+        qWarning() << Q_FUNC_INFO << "Unsupported configuration value type!  
Must be int, quint64, bool or string.";
+        return; // unsupported value type.
+    }
+
     d->configurationValues.insert(key, value);
     if (d->status == AccountInterface::Initializing)
         d->configurationValuesPendingInit = true;
@@ -916,6 +954,8 @@
     Some default settings are usually specified in the \c{.service}
     file installed by the account provider plugin.  Other settings
     may be specified directly for an account.
+
+    The only supported value types are int, quint64, bool and QString.
 */
 
 QVariantMap AccountInterface::configurationValues() const
@@ -929,7 +969,24 @@
 {
     if (d->status == AccountInterface::Invalid || d->status == 
AccountInterface::SyncInProgress)
         return;
-    d->configurationValues = values;
+
+    QVariantMap validValues;
+    QStringList vkeys = values.keys();
+    foreach (const QString &key, vkeys) {
+        QVariant currValue = values.value(key);
+        if (currValue.type() == QVariant::Bool
+                || currValue.type() == QVariant::Int
+                || currValue.type() == QVariant::LongLong
+                || currValue.type() == QVariant::ULongLong
+                || currValue.type() == QVariant::String) {
+            validValues.insert(key, currValue);
+        }
+    }
+
+    if (d->configurationValues == validValues)
+        return;
+
+    d->configurationValues = validValues;
     if (d->status == AccountInterface::Initializing)
         d->configurationValuesPendingInit = true;
     else
--- accounts/src/plugin.cpp
+++ accounts/src/plugin.cpp
@@ -36,6 +36,7 @@
 
 #include "account-model.h"
 #include "account-provider-model.h"
+#include "service-account-model.h"
 
 #include "accountinterface.h"
 #include "accountmanagerinterface.h"
@@ -65,6 +66,7 @@
 
         // Types which should be exposed to "normal" applications:
         qmlRegisterType<AccountModel>(uri, 1, 0, "AccountModel");
+        qmlRegisterType<ServiceAccountModel>(uri, 1, 0, "ServiceAccountModel");
         qmlRegisterType<AccountProviderModel>(uri, 1, 0, 
"AccountProviderModel");
         qmlRegisterType<ProviderInterface>(uri, 1, 0, "Provider");
         qmlRegisterUncreatableType<ServiceAccountInterface>(uri, 1, 0, 
"ServiceAccount", m2);
--- accounts/src/providerinterface.cpp
+++ accounts/src/providerinterface.cpp
@@ -31,10 +31,14 @@
 
 #include "providerinterface.h"
 
+//libaccounts-qt
+#include <Accounts/Manager>
+
 class ProviderInterfacePrivate
 {
 public:
     Accounts::Provider provider;
+    QStringList serviceNames;
 };
 
 /*!
@@ -58,6 +62,15 @@
     : QObject(parent), d(new ProviderInterfacePrivate)
 {
     d->provider = provider;
+
+    // first time fetch of service names.
+    Accounts::Manager m;
+    Accounts::ServiceList services = m.serviceList();
+    foreach (const Accounts::Service &srv, services) {
+        if (srv.provider() == d->provider.name()) {
+            d->serviceNames.append(srv.name());
+        }
+    }
 }
 
 ProviderInterface::~ProviderInterface()
@@ -96,3 +109,13 @@
     return d->provider.iconName();
 }
 
+/*!
+    \qmlproperty QStringList Provider::serviceNames
+    The names of services provided by this provider.
+*/
+
+QStringList ProviderInterface::serviceNames() const
+{
+    return d->serviceNames;
+}
+
--- accounts/src/providerinterface.h
+++ accounts/src/providerinterface.h
@@ -53,6 +53,7 @@
     Q_PROPERTY(QString name READ name CONSTANT)
     Q_PROPERTY(QString displayName READ displayName CONSTANT)
     Q_PROPERTY(QString iconName READ iconName CONSTANT)
+    Q_PROPERTY(QStringList serviceNames READ serviceNames CONSTANT)
     // XXX TODO: expose the QDomDocument?  What about the translation 
catalogue for the display name?
 
 public:
@@ -64,6 +65,8 @@
     QString displayName() const;
     QString iconName() const;
 
+    QStringList serviceNames() const;
+
 private:
     ProviderInterfacePrivate *d;
 };
--- accounts/src/service-account-model.cpp
+++ accounts/src/service-account-model.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2012 Jolla Ltd.  <[email protected]>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Nemo Mobile nor the names of its contributors
+ *     may be used to endorse or promote products derived from this
+ *     software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+//project
+#include "service-account-model.h"
+#include "serviceaccountinterface.h"
+#include "providerinterface.h"
+
+//Qt
+#include <QtDebug>
+
+//libaccounts-qt
+#include <Accounts/Manager>
+#include <Accounts/Account>
+#include <Accounts/Provider>
+
+struct DisplayData {
+    DisplayData(Accounts::AccountService *acct) : account(acct), 
enabledWithService(false) {}
+    ~DisplayData() { delete account; }
+    Accounts::AccountService *account;
+    QString providerName;
+    QString providerDisplayName;
+    QString accountIcon;
+    QString serviceName;
+    QString serviceDisplayName;
+    QString serviceIcon;
+    bool enabledWithService;
+    Q_DISABLE_COPY(DisplayData);
+};
+
+class ServiceAccountModel::ServiceAccountModelPrivate
+{
+public:
+    ~ServiceAccountModelPrivate()
+    {
+        qDeleteAll(accountsList);
+    }
+
+    QHash<int, QByteArray> headerData;
+    Accounts::Manager *manager;
+    QList<DisplayData *> accountsList;
+};
+
+ServiceAccountModel::ServiceAccountModel(QObject* parent)
+    : QAbstractListModel(parent)
+    , d_ptr(new ServiceAccountModelPrivate())
+{
+    Q_D(ServiceAccountModel);
+    d->manager = new Accounts::Manager();
+    d->headerData.insert(AccountIdRole, "accountId");
+    d->headerData.insert(AccountDisplayNameRole, "accountDisplayName");
+    d->headerData.insert(AccountIconRole, "accountIcon" );
+    d->headerData.insert(ServiceNameRole, "serviceName");
+    d->headerData.insert(ServiceDisplayNameRole, "serviceDisplayName");
+    d->headerData.insert(ServiceIconRole, "serviceIcon" );
+    d->headerData.insert(ProviderNameRole, "providerName");
+    d->headerData.insert(ProviderDisplayNameRole, "providerDisplayName");
+    d->headerData.insert(EnabledWithServiceRole, "enabledWithService");
+    d->headerData.insert(ColumnCountRole, "columncount");
+    QObject::connect(d->manager, SIGNAL(accountCreated(Accounts::AccountId)),
+                     this, SLOT(accountCreated(Accounts::AccountId)));
+    setRoleNames(d->headerData);
+    Accounts::AccountIdList idList = d->manager->accountList();
+    foreach (Accounts::AccountId id, idList)
+    {
+        Accounts::Account *account = d->manager->account(id);
+        Accounts::ServiceList accountServices = account->services();
+        foreach (const Accounts::Service &srv, accountServices) {
+            Accounts::AccountService *srvAcc = new 
Accounts::AccountService(account, srv);
+            d->accountsList.append(new DisplayData(srvAcc));
+        }
+    }
+}
+
+ServiceAccountModel::~ServiceAccountModel()
+{
+}
+
+int ServiceAccountModel::rowCount(const QModelIndex &parent) const
+{
+    Q_D(const ServiceAccountModel);
+    if (parent.isValid())
+        return 0;
+    return d->accountsList.length();
+}
+
+int ServiceAccountModel::columnCount(const QModelIndex &parent) const
+{
+    if (parent.isValid())
+        return 0;
+    return ColumnCount;
+}
+
+QVariant ServiceAccountModel::data(const QModelIndex &index, int role) const
+{
+    Q_D(const ServiceAccountModel);
+    if (!index.isValid() || index.row() >= d->accountsList.length())
+        return QVariant();
+
+    DisplayData *data = d->accountsList[index.row()];
+    Accounts::AccountService *account = data->account;
+
+    if (role == AccountIdRole ||
+            (role == Qt::DisplayRole && index.column() == AccountIdColumn))
+        return QVariant::fromValue(account->account()->id());
+
+    if (role == AccountDisplayNameRole ||
+            (role == Qt::DisplayRole && index.column() == 
AccountDisplayNameColumn))
+        return QVariant::fromValue(account->account()->displayName());
+
+    if (role == AccountIconRole ||
+            (role == Qt::DisplayRole && index.column() == AccountIconColumn)) {
+        if (data->accountIcon.isNull()) {
+            Accounts::Provider provider = 
d->manager->provider(account->account()->providerName());
+            data->accountIcon = provider.iconName();
+        }
+        return QVariant::fromValue(data->accountIcon);
+    }
+
+    if (role == ServiceNameRole ||
+            (role == Qt::DisplayRole && index.column() == ServiceNameColumn)) {
+        data->serviceName = account->service().name();
+        return QVariant::fromValue(data->serviceName);
+    }
+
+    if (role == ServiceDisplayNameRole ||
+            (role == Qt::DisplayRole && index.column() == 
ServiceDisplayNameColumn)) {
+        data->serviceDisplayName = account->service().displayName();
+        return QVariant::fromValue(data->serviceDisplayName);
+    }
+
+    if (role == ServiceIconRole ||
+            (role == Qt::DisplayRole && index.column() == ServiceIconColumn)) {
+        if (data->serviceIcon.isNull())
+            data->serviceIcon = account->service().iconName();
+        return QVariant::fromValue(data->serviceIcon);
+    }
+
+    if (role == ProviderNameRole ||
+            (role == Qt::DisplayRole && index.column() == ProviderNameColumn)) 
{
+        Accounts::Provider provider = 
d->manager->provider(account->account()->providerName());
+        data->providerName = provider.name();
+        return QVariant::fromValue(data->providerName);
+    }
+
+    if (role == ProviderDisplayNameRole ||
+            (role == Qt::DisplayRole && index.column() == 
ProviderDisplayNameColumn)) {
+        Accounts::Provider provider = 
d->manager->provider(account->account()->providerName());
+        data->providerDisplayName = provider.displayName();
+        return QVariant::fromValue(data->providerDisplayName);
+    }
+
+    if (role == EnabledWithServiceRole ||
+            (role == Qt::DisplayRole && index.column() == 
EnabledWithServiceColumn)) {
+        data->enabledWithService = account->enabled();
+        return QVariant::fromValue(data->enabledWithService);
+    }
+
+    return QVariant();
+}
+
+QVariant ServiceAccountModel::headerData(int section, Qt::Orientation 
orientation, int role) const
+{
+    Q_D(const ServiceAccountModel);
+    if (orientation != Qt::Horizontal) {
+        return QVariant();
+    }
+    Columns column = static_cast<Columns>(section);
+
+    if (role == Qt::DisplayRole) {
+        if (section < d->headerData.size()) {
+            return d->headerData.value(column);
+        }
+    }
+    return QVariant();
+}
+
+void ServiceAccountModel::accountCreated(Accounts::AccountId id)
+{
+    Q_D(ServiceAccountModel);
+    QModelIndex index;
+    Accounts::Account *account = d->manager->account(id);
+
+    QObject::connect(account, SIGNAL(removed()),
+                     this, SLOT(accountRemoved()));
+    QObject::connect(account, SIGNAL(enabledChanged(const QString, bool)),
+                     this, SLOT(accountUpdated()));
+
+    if (account != 0) {
+        Accounts::ServiceList srvList = account->services();
+        int count = srvList.size();
+        beginInsertRows(index, 0, count - 1);
+        for (int i = 0; i < count; ++i) {
+            Accounts::AccountService *accSrv = new 
Accounts::AccountService(account, srvList.at(i));
+            d->accountsList.insert(0, new DisplayData(accSrv));
+        }
+        endInsertRows();
+    }
+}
+
+void ServiceAccountModel::accountRemoved()
+{
+    Q_D(ServiceAccountModel);
+    Accounts::Account *account = qobject_cast<Accounts::Account *>(sender());
+
+    QList<int> indexes = getAccountIndexes(account);
+    if (!indexes.size()) {
+        qWarning() << Q_FUNC_INFO << "Account not present in the list:" << 
account->id();
+        return;
+    }
+
+    QModelIndex parent;
+    QList<DisplayData *> cleanupList;
+
+    // remove them in contiguous chunks if possible.
+    qSort(indexes);
+    int maxIdx = indexes.last();
+    int firstIdx = indexes.first();
+    int lastIdx = firstIdx;
+    int which = 0;
+    while (lastIdx < maxIdx) {
+        int currIdx = indexes.at(++which);
+        if (currIdx == (lastIdx + 1)) {
+            // contiguous
+            lastIdx += 1;
+        } else {
+            // noncontiguous.  Remove the chunk.
+            beginRemoveRows(parent, firstIdx, lastIdx);
+            for (int i = firstIdx; i < lastIdx; ++i) {
+                DisplayData *data = d->accountsList[i];
+                d->accountsList.removeAt(i);
+                cleanupList.append(data);
+            }
+            endRemoveRows();
+            qDeleteAll(cleanupList);
+            cleanupList.clear();
+
+            // prepare for next chunk.
+            firstIdx = currIdx;
+            lastIdx = currIdx;
+        }
+    }
+
+    // remove the last (or possibly only) chunk
+    beginRemoveRows(parent, firstIdx, lastIdx);
+    for (int i = firstIdx; i < lastIdx; ++i) {
+        DisplayData *data = d->accountsList[i];
+        d->accountsList.removeAt(i);
+        cleanupList.append(data);
+    }
+    endRemoveRows();
+    qDeleteAll(cleanupList);
+}
+
+void ServiceAccountModel::accountUpdated()
+{
+    Accounts::Account *account = qobject_cast<Accounts::Account *>(sender());
+    QList<int> indexes = getAccountIndexes(account);
+    if (!indexes.size()) {
+        qWarning() << Q_FUNC_INFO << "Account not present in the list:" << 
account->id();
+        return;
+    }
+
+    // emit change signals for contiguous chunks
+    qSort(indexes);
+    int maxIdx = indexes.last();
+    int firstIdx = indexes.first();
+    int lastIdx = firstIdx;
+    int which = 0;
+    while (lastIdx < maxIdx) {
+        int currIdx = indexes.at(++which);
+        if (currIdx == (lastIdx + 1)) {
+            // contiguous
+            lastIdx += 1;
+        } else {
+            // noncontiguous.  Emit change signal for the chunk.
+            emit dataChanged(index(firstIdx, 0), index(lastIdx, 0));
+
+            // prepare for next chunk.
+            firstIdx = currIdx;
+            lastIdx = currIdx;
+        }
+    }
+
+    // emit change signal for the last (or possibly only) chunk
+    emit dataChanged(index(firstIdx, 0), index(lastIdx, 0));
+}
+
+// Each Account can be represented multiple times in the list (as it may 
support multiple services)
+QList<int> ServiceAccountModel::getAccountIndexes(Accounts::Account *account) 
const
+{
+    Q_D(const ServiceAccountModel);
+    QList<int> indexes;
+    for (int i = 0; i < d->accountsList.count(); ++i) {
+        const DisplayData *data = d->accountsList[i];
+        if (data->account->account() == account)
+            indexes.append(i);
+    }
+    return indexes;
+}
+
+/*!
+    \qmltype ServiceAccountModel
+    \instantiates ServiceAccountModel
+    \inqmlmodule org.nemomobile.accounts 1
+    \brief Provides a model of existing per-service accounts
+
+    The ServiceAccountModel can be used to provide service account data to a 
view.
+    For each account in the database, it exposes:
+    \list
+    \li accountId
+    \li accountDisplayName
+    \li accountIcon
+    \li serviceName
+    \li serviceDisplayName
+    \li serviceIcon
+    \li providerName
+    \li providerDisplayName
+    \li enabledWithService
+    \endlist
+
+    It also provides invokable methods to retrieve a Provider
+    associated with an account.
+*/
+
+/*!
+    \qmlmethod Provider* ServiceAccountModel::provider(const QString 
&providerName, QObject *parent)
+    Returns the Provider with the given \a providerName, or zero if no such
+    provider exists.  The returned Provider will be owned by the specified
+    \a parent.
+ */
+ProviderInterface *ServiceAccountModel::provider(const QString &providerName, 
QObject *parent)
+{
+    Q_D(ServiceAccountModel);
+
+    if (providerName.isEmpty())
+        return 0;
+
+    Accounts::Provider retnProv;
+    Accounts::ProviderList providers = d->manager->providerList();
+    foreach (const Accounts::Provider &p, providers) {
+        if (p.name() == providerName) {
+            retnProv = p;
+            break;
+        }
+    }
+
+    if (!retnProv.isValid())
+        return 0;
+
+    return new ProviderInterface(retnProv, parent);
+}
+
+/*!
+    \qmlmethod Provider* ServiceAccountModel::provider(const QString 
&providerName, QObject *parent)
+    Returns the Provider which provides the account identified by the given
+    \a accountId, or zero if no such account exists.  The returned Provider
+    will be owned by the specified \a parent.
+ */
+ProviderInterface *ServiceAccountModel::provider(int accountId, QObject 
*parent)
+{
+    Q_D(ServiceAccountModel);
+
+    if (accountId == 0)
+        return 0;
+
+    for (int i = 0; i < d->accountsList.size(); ++i) {
+        DisplayData *data = d->accountsList.at(i);
+        if (data->account->account()->id() == accountId) {
+            return provider(data->account->account()->providerName(), parent);
+        }
+    }
+
+    return 0;
+}
+
--- accounts/src/service-account-model.h
+++ accounts/src/service-account-model.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 Jolla Ltd.  <[email protected]>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Nemo Mobile nor the names of its contributors
+ *     may be used to endorse or promote products derived from this
+ *     software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef SERVICEACCOUNTMODEL_H
+#define SERVICEACCOUNTMODEL_H
+
+//accounts-qt
+#include <Accounts/Manager>
+
+//Qt
+#include <QAbstractTableModel>
+#include <QMap>
+#include <QVariant>
+
+class ServiceAccountInterface;
+class ProviderInterface;
+
+/*!
+ * The Service Account Model is the model for per-service accounts
+ */
+
+class ServiceAccountModel : public QAbstractListModel
+{
+    Q_OBJECT
+    class ServiceAccountModelPrivate;
+
+public:
+
+    enum Columns {
+        AccountIdColumn,
+        AccountDisplayNameColumn,
+        AccountIconColumn,
+        ServiceNameColumn,
+        ServiceDisplayNameColumn,
+        ServiceIconColumn,
+        ProviderNameColumn,
+        ProviderDisplayNameColumn,
+        EnabledWithServiceColumn,
+        ColumnCount
+    };
+
+    enum Roles{
+        AccountIdRole = Qt::UserRole + 1,
+        AccountDisplayNameRole,
+        AccountIconRole,
+        ServiceNameRole,
+        ServiceDisplayNameRole,
+        ServiceIconRole,
+        ProviderNameRole,
+        ProviderDisplayNameRole,
+        EnabledWithServiceRole,
+        ColumnCountRole
+    };
+
+
+    ServiceAccountModel(QObject *parent = 0);
+    virtual ~ServiceAccountModel();
+
+    int rowCount(const QModelIndex &index = QModelIndex()) const;
+    int columnCount(const QModelIndex &index) const;
+    QVariant data(const QModelIndex &index, int role) const;
+    QVariant headerData(int section, Qt::Orientation orientation,
+                        int role) const;
+
+    Q_INVOKABLE ProviderInterface *provider(const QString &providerName, 
QObject *parent = 0);
+    Q_INVOKABLE ProviderInterface *provider(int accountId, QObject *parent = 
0);
+
+private slots:
+    void accountCreated(Accounts::AccountId id);
+    void accountRemoved();
+    void accountUpdated();
+
+private:
+    QList<int> getAccountIndexes(Accounts::Account *account) const;
+
+private:
+    ServiceAccountModelPrivate* d_ptr;
+    Q_DISABLE_COPY(ServiceAccountModel)
+    Q_DECLARE_PRIVATE(ServiceAccountModel);
+};
+Q_DECLARE_METATYPE(Accounts::AccountService *)
+
+#endif // SERVICEACCOUNTMODEL_H
--- accounts/src/src.pro
+++ accounts/src/src.pro
@@ -16,7 +16,8 @@
            $$PWD/providerinterface.cpp \
            $$PWD/serviceaccountinterface.cpp \
            $$PWD/serviceinterface.cpp \
-           $$PWD/servicetypeinterface.cpp
+           $$PWD/servicetypeinterface.cpp \
+           $$PWD/service-account-model.cpp
 
 HEADERS += \
            $$PWD/accountinterface.h \
@@ -30,7 +31,8 @@
            $$PWD/accountinterface_p.h \
            $$PWD/accountmanagerinterface_p.h \
            $$PWD/serviceaccountinterface_p.h \
-           $$PWD/servicetypeinterface.h
+           $$PWD/servicetypeinterface.h \
+           $$PWD/service-account-model.h
 
 OTHER_FILES += accounts.qdoc accounts.qdocconf
 
--- accounts/tests/tst_accountinterface/tst_accountinterface.cpp
+++ accounts/tests/tst_accountinterface/tst_accountinterface.cpp
@@ -172,12 +172,21 @@
 void tst_AccountInterface::displayName()
 {
     QScopedPointer<AccountInterface> account(new AccountInterface);
+    account->classBegin();
     account->setProviderName("test-provider");
     QCOMPARE(account->displayName(), QString(QLatin1String("")));
     QSignalSpy spy(account.data(), SIGNAL(displayNameChanged()));
     account->setDisplayName(QString(QLatin1String("test-display-name")));
     QCOMPARE(spy.count(), 1);
     QCOMPARE(account->displayName(), 
QString(QLatin1String("test-display-name")));
+    account->sync(); // pending sync.
+    account->componentComplete(); // will construct new account.
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    account->setDisplayName(QString(QLatin1String("test-display-name-two")));
+    account->sync();
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    QCOMPARE(account->displayName(), 
QString(QLatin1String("test-display-name-two")));
+    account->remove();
 }
 
 void tst_AccountInterface::supportedServiceNames()
@@ -219,25 +228,88 @@
 {
     QVariantMap testData;
     QString testKey(QLatin1String("test-key"));
-    QVariant testValue(QString(QLatin1String("test-value")));
-    testData.insert(testKey, testValue);
+    QVariant testStrValue(QString(QLatin1String("test-value")));
+    QVariant testBoolValue(true);
+    QVariant testIntValue(-5);
+    QVariant testQuintValue(0xaaaaaaaaaaaa);
+    testData.insert(testKey, testStrValue);
 
     QVariantMap noValueTestData;
     noValueTestData.insert(testKey, QVariant());
 
     QScopedPointer<AccountInterface> account(new AccountInterface);
+    account->classBegin();
     account->setProviderName("test-provider");
     QCOMPARE(account->configurationValues(), QVariantMap());
     QSignalSpy spy(account.data(), SIGNAL(configurationValuesChanged()));
     account->setConfigurationValues(testData);
     QCOMPARE(spy.count(), 1);
     QCOMPARE(account->configurationValues(), testData);
-    account->setConfigurationValue(testKey, QVariant());
-    QCOMPARE(spy.count(), 2);
-    QCOMPARE(account->configurationValues(), noValueTestData);
     account->removeConfigurationValue(testKey);
-    QCOMPARE(spy.count(), 3);
+    QCOMPARE(spy.count(), 2);
     QCOMPARE(account->configurationValues(), QVariantMap());
+
+    // invalid values
+    account->setConfigurationValue(testKey, QVariant(QColor(Qt::black)));
+    QCOMPARE(spy.count(), 2); // no change signal
+    QCOMPARE(account->configurationValues(), QVariantMap()); // not set.
+    account->setConfigurationValue(testKey, QVariant());
+    QCOMPARE(spy.count(), 2); // no change signal
+    QCOMPARE(account->configurationValues(), QVariantMap()); // not set.
+
+    // bool, int, quint64 and string should all work.
+    account->setConfigurationValue(testKey, testBoolValue);
+    QCOMPARE(spy.count(), 3);
+    QCOMPARE(account->configurationValues().value(testKey), testBoolValue);
+    account->setConfigurationValue(testKey, testIntValue);
+    QCOMPARE(spy.count(), 4);
+    QCOMPARE(account->configurationValues().value(testKey), testIntValue);
+    account->setConfigurationValue(testKey, testQuintValue);
+    QCOMPARE(spy.count(), 5);
+    QCOMPARE(account->configurationValues().value(testKey), testQuintValue);
+    account->setConfigurationValue(testKey, testStrValue);
+    QCOMPARE(spy.count(), 6);
+    QCOMPARE(account->configurationValues().value(testKey), testStrValue);
+
+    // ensure that configuration values can be saved.
+    account->sync(); // pending sync.
+    account->componentComplete(); // will create new account.
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    QCOMPARE(account->configurationValues().value(testKey), testStrValue);
+    account->setConfigurationValue(testKey, testQuintValue);
+    account->sync();
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    QCOMPARE(account->configurationValues().value(testKey), testQuintValue);
+    account->setConfigurationValue(testKey, testIntValue);
+    account->sync();
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    QCOMPARE(account->configurationValues().value(testKey), testIntValue);
+    account->setConfigurationValue(testKey, testBoolValue);
+    account->sync();
+    QTRY_COMPARE(account->status(), AccountInterface::Synced);
+    QCOMPARE(account->configurationValues().value(testKey), testBoolValue);
+
+    // ensure that configuration values from subgroups are reported correctly.
+    QString testGroup = QLatin1String("test-group");
+    Accounts::Manager m;
+    Accounts::Account *a = m.account(account->identifier());
+    QVERIFY(a != 0);
+    a->beginGroup(testGroup);
+    a->setValue(testKey, testStrValue);
+    a->endGroup();
+    a->sync();
+
+    // account doesn't emit signals on configuration values changed...
+    // we really need a "refresh" function, similar to the one in Identity.
+    QScopedPointer<AccountInterface> existingAccount(new AccountInterface);
+    existingAccount->classBegin();
+    existingAccount->setIdentifier(account->identifier());
+    existingAccount->componentComplete(); // will load existing account
+    QTRY_COMPARE(existingAccount->status(), AccountInterface::Initialized);
+    
QCOMPARE(existingAccount->configurationValues().value(QString("%1/%2").arg(testGroup).arg(testKey)),
 testStrValue);
+
+    // cleanup.
+    account->remove();
 }
 
 void tst_AccountInterface::status()
--- signon/src/authsessioninterface.cpp
+++ signon/src/authsessioninterface.cpp
@@ -36,6 +36,7 @@
 
 //libsignon-qt
 #include <SignOn/AuthSession>
+#include <SignOn/SessionData>
 
 
 AuthSessionInterfacePrivate::AuthSessionInterfacePrivate(SignOn::AuthSession 
*authSession, AuthSessionInterface *parent)
@@ -130,18 +131,34 @@
 */
 void AuthSessionInterface::process(SessionDataInterface *sessionData, const 
QString &mechanism)
 {
+    if (!sessionData)
+        return;
     d->session->process(sessionData->sessionData(), mechanism);
 }
 
+/*!
+    \qmlmethod void AuthSession::process(const QVariantMap &sessionData, const 
QString &mechanism)
+    Process an authentication request contained in the \a sessionData using 
the given \a mechanism.
+    The \a sessionData should include credentials including userName, secret, 
etc.
+*/
+void AuthSessionInterface::process(const QVariantMap &sessionData, const 
QString &mechanism)
+{
+    d->session->process(SignOn::SessionData(sessionData), mechanism);
+}
+
 // TODO: remove request() as it is mostly unused
 void AuthSessionInterface::request(SessionDataInterface *sessionData, const 
QString &mechanism)
 {
+    if (!sessionData)
+        return;
     d->session->request(sessionData->sessionData(), mechanism);
 }
 
 // TODO: remove challenge() as it is mostly unused
 void AuthSessionInterface::challenge(SessionDataInterface *sessionData, const 
QString &mechanism)
 {
+    if (!sessionData)
+        return;
     d->session->challenge(sessionData->sessionData(), mechanism);
 }
 
--- signon/src/authsessioninterface.h
+++ signon/src/authsessioninterface.h
@@ -113,6 +113,7 @@
     ~AuthSessionInterface();
 
     // invokable api
+    Q_INVOKABLE void process(const QVariantMap &sessionData, const QString 
&mechanism);
     Q_INVOKABLE void process(SessionDataInterface *sessionData, const QString 
&mechanism);
     Q_INVOKABLE void request(SessionDataInterface *sessionData, const QString 
&mechanism);
     Q_INVOKABLE void challenge(SessionDataInterface *sessionData, const 
QString &mechanism);

++++++ nemo-qml-plugins.yaml
--- nemo-qml-plugins.yaml
+++ nemo-qml-plugins.yaml
@@ -2,7 +2,7 @@
 Summary: Nemo QML plugins source package.
 Group: System/Libraries
 Description: Do not install this, install the subpackaged plugins.
-Version: 0.1.9
+Version: 0.1.10
 Release: 1
 Sources:
     - "%{name}-%{version}.tar.bz2"



Reply via email to