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/8210

Thank You,
John Brooks

[This message was auto-generated]

---

Request # 8210:

Messages from BOSS:

State: review at 2013-03-01T07:40:55 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,12 @@
+* Fri Mar 01 2013 John Brooks <[email protected]> - 0.3.2
+- email: Fix bug in folderUnreadCount binding (from Valerio Valerio)
+- accounts: Allow changing the identifier of an identity after initialization 
(from Chris Adams)
+- accounts: Make Account and ServiceAccount more robust (from Chris Adams)
+- accounts: Force reload of service/provider files on account model creation 
(from Chris Adams)
+- accounts: Sign out of active authentication sessions on Identity removal 
(from Chris Adams)
+- alarms: Set the bootFlag for alarms (from Petri M. Gerdt)
+- contacts: Split search strings more intelligently (from Andrew den Exter)
+- contacts: Add vCard() method to Person (from Martin Jones)
+- social: Only take ownership of filters/sorters if they have no parent (from 
Chris Adams)
+- social: Fix cached node handling (from Chris Adams)
+

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

new:
----
  nemo-qml-plugins-0.3.2.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.3.1
+Version:    0.3.2
 Release:    1
 Group:      System/Libraries
 License:    BSD

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

++++++ nemo-qml-plugins-0.3.1.tar.bz2 -> nemo-qml-plugins-0.3.2.tar.bz2
--- README
+++ README
@@ -7,10 +7,8 @@
 the current maintainer is: Robin Burchell ([email protected])
 
 current plugins:
- - thumbnailer: offers an image provider for fast thumbnailing/sharing of
-   thumbnail cache between multiple applications
-
-   to use, access image://nemoThumbnail/path/to/file.jpg in an Image element.
+- thumbnailer: offers an image provider for fast thumbnailing/sharing of
+  thumbnail cache between multiple applications
 
 - contacts: offers an API similar to QtMobility.contacts, except without the
   fail
@@ -24,4 +22,7 @@
 - email: offers a QML-friendly email API using Qt Messaging Framework as a 
backend.
 
 - time: provides WallClock element useful for clock displays, including keeping
-  time in sync with system time changes.
+time in sync with system time changes.
+
+- alarms: provides QML APIs for creating, editing, and fetching information
+  about alarms
--- accounts/src/account-model.cpp
+++ accounts/src/account-model.cpp
@@ -71,6 +71,7 @@
 {
     Q_D(AccountModel);
     d->manager = new Accounts::Manager();
+    Accounts::ServiceList allServices = d->manager->serviceList(); // force 
reload of service files.
     d->headerData.insert(AccountIdRole, "accountId");
     d->headerData.insert(AccountDisplayNameRole, "accountDisplayName");
     d->headerData.insert(AccountIconRole, "accountIcon" );
--- accounts/src/account-provider-model.cpp
+++ accounts/src/account-provider-model.cpp
@@ -77,6 +77,7 @@
 
     setRoleNames(d->headerData);
     Accounts::Manager m;
+    Accounts::ServiceList allServices = m.serviceList(); // force reload of 
service files.
     Accounts::ProviderList providers = m.providerList();
 
     for (int i = 0; i < providers.size(); i++)
--- accounts/src/accountinterface.cpp
+++ accounts/src/accountinterface.cpp
@@ -289,6 +289,11 @@
 void AccountInterfacePrivate::handleSynced()
 {
     if (status == AccountInterface::SyncInProgress) {
+        if (!account) {
+            qWarning() << Q_FUNC_INFO << "Account not valid";
+            return;
+        }
+
         // check to see if the id was updated
         int newIdentifier = account->id();
         if (identifier != newIdentifier) {
--- accounts/src/service-account-model.cpp
+++ accounts/src/service-account-model.cpp
@@ -75,6 +75,7 @@
 {
     Q_D(ServiceAccountModel);
     d->manager = new Accounts::Manager();
+    Accounts::ServiceList allServices = d->manager->serviceList(); // force 
reload of service files.
     d->headerData.insert(AccountIdRole, "accountId");
     d->headerData.insert(AccountDisplayNameRole, "accountDisplayName");
     d->headerData.insert(AccountIconRole, "accountIcon" );
--- accounts/src/serviceaccountinterface.cpp
+++ accounts/src/serviceaccountinterface.cpp
@@ -113,17 +113,21 @@
 
 bool ServiceAccountInterface::enabled() const
 {
-    return d->serviceAccount->enabled();
+    if (d->serviceAccount)
+        return d->serviceAccount->enabled();
+    return false;
 }
 
 /*!
     \qmlproperty int ServiceAccount::identifier
-    Returns the identifier of the account
+    Returns the identifier of the account, or zero if not initialized
 */
 
 int ServiceAccountInterface::identifier() const
 {
-    return d->serviceAccount->account()->id();
+    if (d->serviceAccount && d->serviceAccount->account())
+        return d->serviceAccount->account()->id();
+    return 0;
 }
 
 /*!
@@ -171,8 +175,12 @@
         return;
     }
 
-    d->serviceAccount->setValue(key, value);
-    d->serviceAccount->account()->sync();
+    if (d->serviceAccount) {
+        d->serviceAccount->setValue(key, value);
+        if (d->serviceAccount->account()) {
+            d->serviceAccount->account()->sync();
+        }
+    }
 }
 
 /*!
@@ -184,8 +192,12 @@
 */
 void ServiceAccountInterface::removeConfigurationValue(const QString &key)
 {
-    d->serviceAccount->remove(key);
-    d->serviceAccount->account()->sync();
+    if (d->serviceAccount) {
+        d->serviceAccount->remove(key);
+        if (d->serviceAccount->account()) {
+            d->serviceAccount->account()->sync();
+        }
+    }
 }
 
 /*!
@@ -217,6 +229,8 @@
     // doesn't emit a changed() signal the way Accounts::AccountService does.
     // Since we can't notify on changes, let's not pretend it's a property.
     Accounts::Account *acct = d->serviceAccount->account();
+    if (!acct)
+        return QVariantMap();
     Accounts::Service srv = acct->selectedService();
     acct->selectService(Accounts::Service());
     QStringList allKeys = acct->allKeys();
--- alarms/src/alarmobject.cpp
+++ alarms/src/alarmobject.cpp
@@ -137,6 +137,7 @@
         ev.setAlarmFlag();
         // Trigger the voland alarm/reminder dialog
         ev.setReminderFlag();
+        ev.setBootFlag();
 
         ev.setAttribute(QLatin1String("APPLICATION"), 
QLatin1String("nemoalarms"));
         ev.setAttribute(QLatin1String("createdDate"), 
m_createdDate.toString());
--- contacts/src/seasidefilteredmodel.cpp
+++ contacts/src/seasidefilteredmodel.cpp
@@ -40,6 +40,7 @@
 #include <QContactOnlineAccount>
 #include <QContactOrganization>
 #include <QContactPhoneNumber>
+#include <QTextBoundaryFinder>
 
 #include <QtDebug>
 
@@ -52,6 +53,29 @@
         destination->insert(to + i, source.at(i));
 }
 
+// Splits a string at word boundaries identified by QTextBoundaryFinder and 
returns a list of
+// of the fragments that occur between StartWord and EndWord boundaries.
+static QStringList splitWords(const QString &string)
+{
+    QStringList words;
+    QTextBoundaryFinder finder(QTextBoundaryFinder::Word, string);
+
+    for (int start = 0; finder.position() != -1 && finder.position() < 
string.length();) {
+        if (!(finder.boundaryReasons() & QTextBoundaryFinder::StartWord)) {
+            finder.toNextBoundary();
+            start = finder.position();
+        }
+
+        finder.toNextBoundary();
+
+        if (finder.position() > start && finder.boundaryReasons() & 
QTextBoundaryFinder::EndWord) {
+            words.append(string.mid(start, finder.position() - start));
+            start = finder.position();
+        }
+    }
+    return words;
+}
+
 SeasideFilteredModel::SeasideFilteredModel(QObject *parent)
     : QAbstractListModel(parent)
     , m_filterIndex(0)
@@ -149,7 +173,7 @@
         const bool subFilter = !wasEmpty && 
pattern.startsWith(m_filterPattern, Qt::CaseInsensitive);
 
         m_filterPattern = pattern;
-        m_filterParts = m_filterPattern.split(QLatin1Char(' '));
+        m_filterParts = splitWords(m_filterPattern);
         m_referenceIndex = 0;
         m_filterIndex = 0;
 
@@ -206,17 +230,17 @@
     // other locales, see MBreakIterator
 
     if (item->filterKey.isEmpty()) {
-        item->filterKey = 
item->contact.detail<QContactName>().customLabel().split(QLatin1Char(' '));
+        item->filterKey = 
splitWords(item->contact.detail<QContactName>().customLabel());
 
         foreach (const QContactPhoneNumber &detail, 
item->contact.details<QContactPhoneNumber>())
-            item->filterKey.append(detail.number());
+            item->filterKey.append(splitWords(detail.number()));
         foreach (const QContactEmailAddress &detail, 
item->contact.details<QContactEmailAddress>())
-            item->filterKey.append(detail.emailAddress());
+            item->filterKey.append(splitWords(detail.emailAddress()));
         foreach (const QContactOrganization &detail, 
item->contact.details<QContactOrganization>())
-            item->filterKey.append(detail.name().split(QLatin1Char(' ')));
+            item->filterKey.append(splitWords(detail.name()));
         foreach (const QContactOnlineAccount &detail, 
item->contact.details<QContactOnlineAccount>()) {
-            item->filterKey.append(detail.accountUri());
-            item->filterKey.append(detail.serviceProvider());
+            item->filterKey.append(splitWords(detail.accountUri()));
+            item->filterKey.append(splitWords(detail.serviceProvider()));
         }
     }
 
@@ -317,7 +341,6 @@
         if (filterId(m_referenceContactIds->at(i)))
             m_filteredContactIds.append(m_referenceContactIds->at(i));
     }
-
     if (!m_filteredContactIds.isEmpty())
         beginInsertRows(QModelIndex(), 0, m_filteredContactIds.count() - 1);
 
--- contacts/src/seasideperson.cpp
+++ contacts/src/seasideperson.cpp
@@ -44,6 +44,9 @@
 #include <QContactOrganization>
 #include <QContactUrl>
 
+#include <QVersitWriter>
+#include <QVersitContactExporter>
+
 #include "seasideperson.h"
 
 SeasidePerson::SeasidePerson(QObject *parent)
@@ -772,3 +775,21 @@
     recalculateDisplayLabel();
 }
 
+QString SeasidePerson::vCard() const
+{
+    QVersitContactExporter exporter;
+    if (!exporter.exportContacts(QList<QContact>() << mContact, 
QVersitDocument::VCard21Type)) {
+        qWarning() << Q_FUNC_INFO << "Failed to create vCard: " << 
exporter.errorMap();
+        return QString();
+    }
+
+    QByteArray vcard;
+    QVersitWriter writer(&vcard);
+    if (!writer.startWriting(exporter.documents())) {
+        qWarning() << Q_FUNC_INFO << "Can't start writing vcard " << 
writer.error();
+        return QString();
+    }
+    writer.waitForFinished();
+
+    return QString::fromUtf8(vcard);
+}
--- contacts/src/seasideperson.h
+++ contacts/src/seasideperson.h
@@ -210,6 +210,8 @@
     Q_INVOKABLE QVariant contactData() const { return 
QVariant::fromValue(contact()); }
     Q_INVOKABLE void setContactData(const QVariant &data) { 
setContact(data.value<QContact>()); }
 
+    Q_INVOKABLE QString vCard() const;
+
     static QString generateDisplayLabel(
                 const QContact &mContact,
                 SeasideProxyModel::DisplayLabelOrder order = 
SeasideProxyModel::FirstNameFirst);
--- contacts/tests/tst_seasidefilteredmodel/seasidecache.cpp
+++ contacts/tests/tst_seasidefilteredmodel/seasidecache.cpp
@@ -34,6 +34,7 @@
 
 #include <QContactName>
 #include <QContactAvatar>
+#include <QContactEmailAddress>
 
 #include <QtDebug>
 
@@ -42,19 +43,21 @@
     const char *firstName;
     const char *lastName;
     const char *fullName;
-    const char *avatar;
     const bool isFavorite;
+    const char *email;
+    const char *avatar;
+
 };
 
 static const Contact contactsData[] =
 {
-    { "Aaron", "Aaronson", "Aaron Aaronson", 0, false },            // 0
-    { "Aaron", "Arthur", "Aaron Arthur", 0, false },                // 1
-    { "Aaron", "Johns", "Aaron Johns", 0, true },                   // 2
-    { "Arthur", "Johns", "Arthur Johns", 0, false },                // 3
-    { "Jason", "Aaronson", "Jason Aaronson", 0, false },            // 4
-    { "Joe", "Johns", "Joe Johns", "file:///cache/joe.jpg", true }, // 5
-    { "Robin", "Burchell", "Robin Burchell", 0, true }              // 6
+/*0*/   { "Aaron",  "Aaronson", "Aaron Aaronson", false, 
"[email protected]", 0 },
+/*1*/   { "Aaron",  "Arthur",   "Aaron Arthur",   false, 
"[email protected]", 0 },
+/*2*/   { "Aaron",  "Johns",    "Aaron Johns",    true,  "[email protected]", 
0 },
+/*3*/   { "Arthur", "Johns",    "Arthur Johns",   false, 
"[email protected]", 0 },
+/*4*/   { "Jason",  "Aaronson", "Jason Aaronson", false, "[email protected]", 
0 },
+/*5*/   { "Joe",    "Johns",    "Joe Johns",      true,  "[email protected]", 
"file:///cache/joe.jpg" },
+/*6*/   { "Robin",  "Burchell", "Robin Burchell", true,  0, 0 }
 };
 
 SeasideCache *SeasideCache::instance = 0;
@@ -96,6 +99,13 @@
             avatar.setImageUrl(QUrl(QLatin1String(contactsData[i].avatar)));
             contact.saveDetail(&avatar);
         }
+
+        if (contactsData[i].email) {
+            QContactEmailAddress email;
+            email.setEmailAddress(QLatin1String(contactsData[i].email));
+            contact.saveDetail(&email);
+        }
+
         m_cache.append(SeasideCacheItem(contact));
     }
 }
--- contacts/tests/tst_seasidefilteredmodel/tst_seasidefilteredmodel.cpp
+++ contacts/tests/tst_seasidefilteredmodel/tst_seasidefilteredmodel.cpp
@@ -48,6 +48,7 @@
     void populated();
     void filterType();
     void filterPattern();
+    void filterEmail();
     void rowsInserted();
     void rowsRemoved();
     void dataChanged();
@@ -212,7 +213,7 @@
     patternSpy.clear();
     removedSpy.clear();
 
-    //
+    // empty
     model.setFilterType(SeasideFilteredModel::FilterFavorites);
     QCOMPARE(model.filterPattern(), QString("aaronso"));
     QCOMPARE(model.rowCount(), 0);
@@ -296,6 +297,7 @@
     insertedSpy.clear();
     removedSpy.clear();
 
+    // empty
     model.setFilterPattern(QString());
     QCOMPARE(model.filterPattern(), QString());
     QCOMPARE(model.rowCount(), 0);
@@ -303,6 +305,81 @@
     QCOMPARE(insertedSpy.count(), 0);
     QCOMPARE(removedSpy.count(), 1);
     QCOMPARE(removedSpy.at(0).at(1).value<int>(), 0); 
QCOMPARE(removedSpy.at(0).at(2).value<int>(), 3);
+
+    patternSpy.clear();
+    removedSpy.clear();
+}
+
+void tst_SeasideFilteredModel::filterEmail()
+{
+    cache.insert(SeasideFilteredModel::FilterAll, 0, QVector<QContactLocalId>()
+            << 0 << 1 << 2 << 3 << 4 << 5);
+    cache.insert(SeasideFilteredModel::FilterFavorites, 0, 
QVector<QContactLocalId>()
+            << 2 << 5);
+
+    SeasideFilteredModel model;
+    QSignalSpy insertedSpy(&model, SIGNAL(rowsInserted(QModelIndex,int,int)));
+    QSignalSpy removedSpy(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+
+    QCOMPARE(model.filterType(), SeasideFilteredModel::FilterAll);
+    QCOMPARE(model.filterPattern(), QString());
+    QCOMPARE(model.rowCount(), 6);
+
+    // 0 1 2 3 4 5
+    model.setFilterPattern("example");
+    QCOMPARE(model.rowCount(), 6);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 0);
+
+    // 0 1 2 3 4 5
+    model.setFilterPattern("example.");
+    QCOMPARE(model.rowCount(), 6);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 0);
+
+    // 0 1 2
+    model.setFilterPattern("example.com");
+    QCOMPARE(model.rowCount(), 3);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 1);
+    QCOMPARE(removedSpy.at(0).at(1).value<int>(), 3); 
QCOMPARE(removedSpy.at(0).at(2).value<int>(), 5);
+
+    removedSpy.clear();
+
+    // 3 4 5
+    model.setFilterPattern("example.org");
+    QCOMPARE(model.rowCount(), 3);
+    QCOMPARE(insertedSpy.count(), 1);
+    QCOMPARE(insertedSpy.at(0).at(1).value<int>(), 0); 
QCOMPARE(insertedSpy.at(0).at(2).value<int>(), 2);
+    QCOMPARE(removedSpy.count(), 1);
+    QCOMPARE(removedSpy.at(0).at(1).value<int>(), 0); 
QCOMPARE(removedSpy.at(0).at(2).value<int>(), 2);
+
+    insertedSpy.clear();
+    removedSpy.clear();
+
+    // 4 5
+    model.setFilterPattern("examplez.org");
+    QCOMPARE(model.rowCount(), 2);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 1);
+    QCOMPARE(removedSpy.at(0).at(1).value<int>(), 0); 
QCOMPARE(removedSpy.at(0).at(2).value<int>(), 0);
+
+    removedSpy.clear();
+
+    // 4
+    model.setFilterPattern("[email protected]");
+    QCOMPARE(model.rowCount(), 1);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 1);
+    QCOMPARE(removedSpy.at(0).at(1).value<int>(), 1); 
QCOMPARE(removedSpy.at(0).at(2).value<int>(), 1);
+
+    removedSpy.clear();
+
+    // 4
+    model.setFilterPattern("jay");
+    QCOMPARE(model.rowCount(), 1);
+    QCOMPARE(insertedSpy.count(), 0);
+    QCOMPARE(removedSpy.count(), 0);
 }
 
 void tst_SeasideFilteredModel::rowsInserted()
--- contacts/tests/tst_seasidefilteredmodel/tst_seasidefilteredmodel.pro
+++ contacts/tests/tst_seasidefilteredmodel/tst_seasidefilteredmodel.pro
@@ -5,7 +5,7 @@
 SRCDIR = $$PWD/../../src
 
 CONFIG += mobility
-MOBILITY += contacts
+MOBILITY += contacts versit
 
 QT += declarative
 
--- contacts/tests/tst_seasideperson/tst_seasideperson.cpp
+++ contacts/tests/tst_seasideperson/tst_seasideperson.cpp
@@ -76,6 +76,7 @@
     void presenceState();
     void marshalling();
     void setContact();
+    void vcard();
 };
 
 void tst_SeasidePerson::firstName()
@@ -485,6 +486,20 @@
     }
 }
 
+void tst_SeasidePerson::vcard()
+{
+    QScopedPointer<SeasidePerson> person(new SeasidePerson);
+    person->setFirstName("Star");
+    person->setLastName("Fish");
+    person->setPhoneNumbers(QStringList() << "12345678");
+
+    QString vcard = person->vCard();
+
+    QVERIFY(vcard.indexOf("N:Fish;Star;") > 0);
+    QVERIFY(vcard.indexOf("FN:Star Fish") > 0);
+    QVERIFY(vcard.indexOf("TEL:12345678") > 0);
+}
+
 
 // TODO:
 // - account URIs/paths (or let contactsd do that?)
--- email/src/folderlistmodel.cpp
+++ email/src/folderlistmodel.cpp
@@ -161,5 +161,9 @@
 QVariant FolderListModel::folderUnreadCount(QVariant folderId)
 {
     int folderIndex = indexFromFolderId(folderId);
+
+    if (folderIndex < 0)
+        return 0;
+
     return data(index(folderIndex), FolderUnreadCount);
 }
--- signon/src/identityinterface.cpp
+++ signon/src/identityinterface.cpp
@@ -77,6 +77,18 @@
 
     identity = ident;
     identifier = identity->id();
+    if (status != IdentityInterface::Initializing) {
+        status = IdentityInterface::Initializing;
+        bool needsEmit = false;
+        if (!statusMessage.isEmpty()) {
+            statusMessage = QString();
+            needsEmit = true;
+        }
+        emit q->statusChanged();
+        if (needsEmit) {
+            emit q->statusMessageChanged();
+        }
+    }
 
     connect(identity, SIGNAL(info(SignOn::IdentityInfo)), this, 
SLOT(handleInfo(SignOn::IdentityInfo)));
     connect(identity, SIGNAL(removed()), this, SLOT(handleRemoved()));
@@ -439,6 +451,7 @@
 
 IdentityInterface::~IdentityInterface()
 {
+    signOut(); // sign out of the currently active authsession
 }
 
 // QDeclarativeParserStatus
@@ -474,9 +487,6 @@
 
     If the \c identifier is set, the identity in the database
     with the specified identifier will be loaded.
-
-    You cannot change identifier of the Identity after initialization,
-    unless you initialize the identifierPending property to true.
 */
 
 int IdentityInterface::identifier() const
@@ -496,15 +506,29 @@
                 emit identifierChanged();
             componentComplete(); // now initialize.
         }
+    } else if (id != 0 && id != d->identifier) {
+        // changing identifier after initialisation.
+        if (d->identity && d->identity->parent() == this) {
+            disconnect(d->identity);
+            d->identity->deleteLater();
+        }
+
+        d->identity = 0;
+        d->identifier = id;
+        componentComplete();
     }
 }
 
 /*!
     \qmlproperty int Identity::identifierPending
+
     This property should be set to true if the Identity is an existing
     identity, but the identifier is not available at initialization time.
     When this property is set, the Identity will remain in the Initializing
     state until the identifier is set.
+
+    If this property is not set, and no identifier is set for the Identity,
+    a new signon identity will be instantiated for the Identity.
 */
 bool IdentityInterface::identifierPending() const
 {
@@ -904,6 +928,13 @@
     if (!d->identity)
         return;
 
+    // since we are removing the SignOn::Identity itself, we not only sign
+    // out of the active auth session via IdentityInterface::signOut() but
+    // we actually sign out of all active auth sessions via
+    // SignOn::Identity::signOut().
+    d->identity->signOut();
+
+    // remove the identity
     d->setStatus(IdentityInterface::SyncInProgress);
     d->identity->remove();
     d->identity = 0; // seems like libsignon-qt doesn't propagate the signal 
correctly.  assume it worked...
--- signon/src/identityinterface_p.h
+++ signon/src/identityinterface_p.h
@@ -40,6 +40,8 @@
 #include <SignOn/Identity>
 #include <SignOn/identityinfo.h>
 
+using namespace SignOn;
+
 class IdentityInterfacePrivate : public QObject
 {
     Q_OBJECT
@@ -98,7 +100,7 @@
 
     // auth session related
     void handleResponse(const SignOn::SessionData &sd);
-    void handleStateChanged(SignOn::AuthSession::AuthSessionState newState, 
const QString &message);
+    void handleStateChanged(AuthSession::AuthSessionState newState, const 
QString &message);
 
 public:
     void setUpSessionSignals();
--- signon/src/serviceaccountidentityinterface.cpp
+++ signon/src/serviceaccountidentityinterface.cpp
@@ -267,6 +267,7 @@
 
 ServiceAccountIdentityInterface::~ServiceAccountIdentityInterface()
 {
+    signOut();
 }
 
 /*!
@@ -477,20 +478,25 @@
     The ServiceAccountIdentity will have a status of Invalid
     until its identifier is set to the identifier of a valid
     Identity in the database.
-
-    Once set, you may not change the identifier.
 */
 
 void ServiceAccountIdentityInterface::setIdentifier(int identityId)
 {
     // XXX TODO: make this more robust using QDeclarativeParserStatus / 
Initializing.
-    if (identityId == 0)
+    if (identityId == 0 || identityId == identifier())
         return;
 
     if (!d->startedInitialization) {
         d->startedInitialization = true;
         SignOn::Identity *ident = 
SignOn::Identity::existingIdentity(identityId, d);
         d->setIdentity(ident, true, true);
+        emit identifierChanged();
+    } else {
+        d->deleteLater();
+        d = new ServiceAccountIdentityInterfacePrivate(0, this);
+        d->startedInitialization = true;
+        SignOn::Identity *ident = 
SignOn::Identity::existingIdentity(identityId, d);
+        d->setIdentity(ident, true, true);
         emit identifierChanged();
     }
 }
--- signon/tests/tst_identityinterface/tst_identityinterface.cpp
+++ signon/tests/tst_identityinterface/tst_identityinterface.cpp
@@ -108,8 +108,35 @@
     QTRY_COMPARE(spy.count(), 1);
     QVERIFY(identity->identifier() > 0);
 
+    QScopedPointer<IdentityInterface> identityTwo(new IdentityInterface);
+    identityTwo->classBegin();
+    identityTwo->componentComplete();
+    QTRY_COMPARE(identityTwo->status(), IdentityInterface::Initialized);
+    QCOMPARE(identityTwo->identifier(), 0);
+    QSignalSpy spyTwo(identityTwo.data(), SIGNAL(identifierChanged()));
+    identityTwo->setUserName(QString(QLatin1String("test-username-two")));
+    identityTwo->setSecret(QString(QLatin1String("test-secret")));
+    identityTwo->setCaption(QString(QLatin1String("test-caption")));
+    identityTwo->setMethodMechanisms(QString(QLatin1String("password")), 
QStringList() << QString(QLatin1String("ClientLogin")));
+    identityTwo->sync();
+    QTRY_COMPARE(spyTwo.count(), 1);
+    QVERIFY(identityTwo->identifier() > 0);
+
+    // this one doesn't create a new identity, but references an existing 
identity
+    QScopedPointer<IdentityInterface> identityThree(new IdentityInterface);
+    identityThree->classBegin();
+    identityThree->setIdentifier(identity->identifier());
+    identityThree->componentComplete();
+    QTRY_COMPARE(identityThree->status(), IdentityInterface::Initialized);
+    QCOMPARE(identityThree->userName(), QLatin1String("test-username"));
+    identityThree->setIdentifier(identityTwo->identifier()); // test that you 
can set it after initialization.
+    QCOMPARE(identityThree->status(), IdentityInterface::Initializing);
+    QTRY_COMPARE(identityThree->status(), IdentityInterface::Synced);
+    QCOMPARE(identityThree->userName(), QLatin1String("test-username-two"));
+
     // cleanup
     identity->remove();
+    identityTwo->remove();
 }
 
 void tst_IdentityInterface::identifierPending()
@@ -307,22 +334,54 @@
 
 void tst_IdentityInterface::signInOut()
 {
-    // first, create a new Identity so that we can use it for authentication.
+    // test that signIn / signOut work, and that remove() signs out if 
necessary
+    {
+        // first, create a new Identity so that we can use it for 
authentication.
+        QScopedPointer<IdentityInterface> identity(new IdentityInterface);
+        identity->classBegin();
+        identity->componentComplete();
+        QTRY_COMPARE(identity->status(), IdentityInterface::Initialized);
+        identity->setUserName(QString(QLatin1String("test-username")));
+        identity->setMethodMechanisms(QString(QLatin1String("password")), 
QStringList() << QString(QLatin1String("ClientLogin")));
+        identity->sync(); // begin sync.
+        QTRY_COMPARE(identity->status(), IdentityInterface::Synced);
+        QVERIFY(identity->signIn("password", "ClientLogin", QVariantMap())); 
// start new auth session
+        // not expecting a response, as the client login signon plugin may not 
exist.
+        QVERIFY(!identity->signIn("password", "ClientLogin", QVariantMap())); 
// already in progress
+        identity->process(QVariantMap()); // shouldn't crash
+        identity->signOut(); // shouldn't crash
+        QVERIFY(identity->signIn("password", "ClientLogin", QVariantMap())); 
// start new auth session
+        QSignalSpy spy(identity.data(), SIGNAL(statusChanged()));
+        identity->remove(); // remove should also signOut.
+        QCOMPARE(spy.count(), 3); // (some signIn() state) -> NotStarted -> 
SyncInProgress -> Invalid
+    }
+
+    // test that dtor signs out if necessary
+    int identityToRemove = 0;
+    {
+        // first, create a new Identity so that we can use it for 
authentication.
+        IdentityInterface *identity = new IdentityInterface;
+        identity->classBegin();
+        identity->componentComplete();
+        QTRY_COMPARE(identity->status(), IdentityInterface::Initialized);
+        identity->setUserName(QString(QLatin1String("test-username")));
+        identity->setMethodMechanisms(QString(QLatin1String("password")), 
QStringList() << QString(QLatin1String("ClientLogin")));
+        identity->sync(); // begin sync.
+        QTRY_COMPARE(identity->status(), IdentityInterface::Synced);
+        identityToRemove = identity->identifier();
+        QVERIFY(identity->signIn("password", "ClientLogin", QVariantMap())); 
// start new auth session
+        // not expecting a response, as the client login signon plugin may not 
exist.
+        QSignalSpy spy(identity, SIGNAL(statusChanged()));
+        delete identity; // delete should also sign out
+        QCOMPARE(spy.count(), 1); // (some signIn() state) -> NotStarted
+    }
+
+    // clean up
     QScopedPointer<IdentityInterface> identity(new IdentityInterface);
     identity->classBegin();
+    identity->setIdentifier(identityToRemove);
     identity->componentComplete();
-    QTRY_COMPARE(identity->status(), IdentityInterface::Initialized);
-    identity->setUserName(QString(QLatin1String("test-username")));
-    identity->setMethodMechanisms(QString(QLatin1String("password")), 
QStringList() << QString(QLatin1String("ClientLogin")));
-    identity->sync(); // begin sync.
-    QTRY_COMPARE(identity->status(), IdentityInterface::Synced);
-    QVERIFY(identity->signIn("password", "ClientLogin", QVariantMap())); // 
start new auth session
-    // not expecting a response, as the client login signon plugin may not 
exist.
-    QVERIFY(!identity->signIn("password", "ClientLogin", QVariantMap())); // 
already in progress
-    identity->process(QVariantMap()); // shouldn't crash
-    identity->signOut(); // shouldn't crash
-
-    // cleanup
+    QTRY_VERIFY(identity->status() == IdentityInterface::Initialized || 
identity->status() == IdentityInterface::Synced);
     identity->remove();
 }
 
--- 
signon/tests/tst_serviceaccountidentityinterface/tst_serviceaccountidentityinterface.cpp
+++ 
signon/tests/tst_serviceaccountidentityinterface/tst_serviceaccountidentityinterface.cpp
@@ -101,19 +101,33 @@
     int identityIdentifier = identity->identifier();
     QVERIFY(identityIdentifier > 0); // ensure save succeeded.
 
+    // second, create another new Identity so that we can try 
post-initialization identifier change
+    QScopedPointer<IdentityInterface> identityTwo(new IdentityInterface);
+    identityTwo->classBegin();
+    identityTwo->componentComplete();
+    QTRY_COMPARE(identityTwo->status(), IdentityInterface::Initialized);
+    identityTwo->setUserName(QString(QLatin1String("test-username-two")));
+    identityTwo->sync(); // begin sync.
+    QTRY_COMPARE(identityTwo->status(), IdentityInterface::Synced);
+    int identityIdentifierTwo = identityTwo->identifier();
+    QVERIFY(identityIdentifierTwo > 0); // ensure save succeeded.
+
     QScopedPointer<ServiceAccountIdentityInterface> saidentity(new 
ServiceAccountIdentityInterface);
     QCOMPARE(saidentity->identifier(), 0);
     QSignalSpy spy(saidentity.data(), SIGNAL(identifierChanged()));
     saidentity->setIdentifier(identityIdentifier);
     QTRY_COMPARE(spy.count(), 1);
     QCOMPARE(saidentity->identifier(), identityIdentifier);
-    saidentity->setIdentifier(identityIdentifier + 1);
-    QTest::qWait(500);
-    QCOMPARE(saidentity->identifier(), identityIdentifier); // once set, 
cannot be set to anything else.
-    QCOMPARE(spy.count(), 1);
+    saidentity->setIdentifier(identityIdentifier + 999999); // some invalid 
identifier
+    QCOMPARE(saidentity->status(), 
ServiceAccountIdentityInterface::Initializing);
+    QTRY_COMPARE(saidentity->status(), 
ServiceAccountIdentityInterface::Error); // invalid identifier
+    saidentity->setIdentifier(identityIdentifierTwo);
+    QCOMPARE(saidentity->status(), 
ServiceAccountIdentityInterface::Initializing);
+    QTRY_COMPARE(saidentity->status(), 
ServiceAccountIdentityInterface::Initialized);
 
     // cleanup
     identity->remove();
+    identityTwo->remove();
 }
 
 void tst_ServiceAccountIdentityInterface::status()
@@ -202,13 +216,16 @@
     QTRY_COMPARE(identity->status(), IdentityInterface::Synced);
     int identityIdentifier = identity->identifier();
 
-    QScopedPointer<ServiceAccountIdentityInterface> saidentity(new 
ServiceAccountIdentityInterface);
+    ServiceAccountIdentityInterface *saidentity = new 
ServiceAccountIdentityInterface;
     saidentity->setIdentifier(identityIdentifier);
     QTRY_COMPARE(saidentity->status(), 
ServiceAccountIdentityInterface::Initialized);
     QCOMPARE(saidentity->methods(), QStringList() << 
QString(QLatin1String("password")));
     QCOMPARE(saidentity->methodMechanisms("password"), QStringList() << 
QString(QLatin1String("ClientLogin")));
     QVERIFY(saidentity->signIn("password", "ClientLogin", QVariantMap()));
     // not expecting a response, as the client login signon plugin may not 
exist.
+    QSignalSpy spy(saidentity, SIGNAL(statusChanged()));
+    delete saidentity; // delete should also sign out
+    QCOMPARE(spy.count(), 1); // (some signIn() state) -> NotStarted
 
     // cleanup
     identity->remove();
--- social/src/facebook/facebookinterface.cpp
+++ social/src/facebook/facebookinterface.cpp
@@ -563,8 +563,20 @@
 {
     qWarning() << Q_FUNC_INFO << "filtering/sorting not implemented.  TODO!";
 
-    // XXX TODO: filter the data
+    // XXX TODO: filter the data in a better manner than linear searches...
     QList<CacheEntry*> filteredData = data;
+    for (int i = 0; i < d->filters.size(); ++i) {
+        QList<CacheEntry*> temp = filteredData;
+        filteredData.clear();
+        FilterInterface *currFilter = d->filters.at(i);
+        for (int j = 0; j < data.size(); ++j) {
+            CacheEntry *currEntry = data.at(j);
+            if ((!currEntry->item && currFilter->matches(currEntry->data))
+                    || (currEntry->item && 
currFilter->matches(currEntry->item))) {
+                filteredData.append(currEntry);
+            }
+        }
+    }
 
     // XXX TODO: sort the filtered data
     QList<CacheEntry*> sortedData = filteredData;
--- social/src/filterinterface.h
+++ social/src/filterinterface.h
@@ -35,6 +35,7 @@
 #include <QtCore/QObject>
 #include <QtCore/QVariantMap>
 
+class SocialNetworkInterfacePrivate;
 class ContentItemInterface;
 
 class FilterInterface : public QObject
@@ -46,6 +47,10 @@
     virtual ~FilterInterface();
     virtual Q_INVOKABLE bool matches(ContentItemInterface *content) const;
     virtual Q_INVOKABLE bool matches(const QVariantMap &contentData) const;
+
+private:
+    bool m_ownedBySni;
+    friend class SocialNetworkInterfacePrivate;
 };
 
 #endif // FILTERINTERFACE_H
--- social/src/filterinterfaces.cpp
+++ social/src/filterinterfaces.cpp
@@ -38,7 +38,7 @@
 
 // ------------------------------ FilterInterface
 
-FilterInterface::FilterInterface(QObject *parent) : QObject(parent)
+FilterInterface::FilterInterface(QObject *parent) : QObject(parent), 
m_ownedBySni(false)
 {
 }
 
--- social/src/socialnetworkinterface.cpp
+++ social/src/socialnetworkinterface.cpp
@@ -227,8 +227,11 @@
 void 
SocialNetworkInterfacePrivate::filters_append(QDeclarativeListProperty<FilterInterface>
 *list, FilterInterface *filter)
 {
     SocialNetworkInterface *sni = qobject_cast<SocialNetworkInterface 
*>(list->object);
-    if (sni) {
-        filter->setParent(sni);
+    if (sni && filter) {
+        if (!filter->parent()) {
+            filter->setParent(sni);
+            filter->m_ownedBySni = true;
+        }
         sni->d->filters.append(filter);
     }
 }
@@ -247,8 +250,11 @@
 {
     SocialNetworkInterface *sni = qobject_cast<SocialNetworkInterface 
*>(list->object);
     if (sni) {
-        foreach (FilterInterface *cf, sni->d->filters)
-            cf->deleteLater();
+        foreach (FilterInterface *cf, sni->d->filters) {
+            if (cf->m_ownedBySni) {
+                cf->deleteLater();
+            }
+        }
         sni->d->filters.clear();
     }
 }
@@ -266,8 +272,11 @@
 void 
SocialNetworkInterfacePrivate::sorters_append(QDeclarativeListProperty<SorterInterface>
 *list, SorterInterface *sorter)
 {
     SocialNetworkInterface *sni = qobject_cast<SocialNetworkInterface 
*>(list->object);
-    if (sni) {
-        sorter->setParent(sni);
+    if (sni && sorter) {
+        if (!sorter->parent()) {
+            sorter->setParent(sni);
+            sorter->m_ownedBySni = true;
+        }
         sni->d->sorters.append(sorter);
     }
 }
@@ -286,8 +295,11 @@
 {
     SocialNetworkInterface *sni = qobject_cast<SocialNetworkInterface 
*>(list->object);
     if (sni) {
-        foreach (SorterInterface *cs, sni->d->sorters)
-            cs->deleteLater();
+        foreach (SorterInterface *cs, sni->d->sorters) {
+            if (cs->m_ownedBySni) {
+                cs->deleteLater();
+            }
+        }
         sni->d->sorters.clear();
     }
 }
@@ -910,6 +922,7 @@
             // call derived class data update:
             //   perform filtering/sorting based on the defined stuff.
             //   and then emit dataChanged() etc signals.
+            d->pushNode(cachedNode);
             updateInternalData(data);
         } else {
             qWarning() << Q_FUNC_INFO << "Error: cached node has no cached 
content!";
--- social/src/sorterinterface.h
+++ social/src/sorterinterface.h
@@ -34,6 +34,7 @@
 
 #include <QtCore/QObject>
 
+class SocialNetworkInterfacePrivate;
 class ContentItemInterface;
 
 class SorterInterface : public QObject
@@ -44,6 +45,10 @@
     SorterInterface(QObject *parent = 0);
     virtual ~SorterInterface();
     virtual Q_INVOKABLE bool firstLessThanSecond(ContentItemInterface *first, 
ContentItemInterface *second) const;
+
+private:
+    bool m_ownedBySni;
+    friend class SocialNetworkInterfacePrivate;
 };
 
 #endif // SORTERINTERFACE_H
--- social/src/sorterinterfaces.cpp
+++ social/src/sorterinterfaces.cpp
@@ -36,7 +36,7 @@
 // ------------------------------ SorterInterface
 
 SorterInterface::SorterInterface(QObject *parent)
-    : QObject(parent)
+    : QObject(parent), m_ownedBySni(false)
 {
 }
 

++++++ 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.3.1
+Version: 0.3.2
 Release: 1
 Sources:
     - "%{name}-%{version}.tar.bz2"



Reply via email to