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/6840 Thank You, Marko Saukko [This message was auto-generated] --- Request # 6840: Messages from BOSS: State: review at 2012-10-01T03:39:32 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: Project:MTF:MW / nemo-qml-plugins -> CE:MW:Shared / nemo-qml-plugins changes files: -------------- --- nemo-qml-plugins.changes +++ nemo-qml-plugins.changes @@ -0,0 +1,6 @@ +* Mon Oct 1 2012 Robin Burchell <[email protected]> - 0.0.7 +- Fixes NEMO#147: Balanced thumbnail directory (from Antti Seppäl) +- Add API for listing details relevant to IM accounts (from Robin) +- Emit all changed signals when a contact is updated (from John Brooks) +- Add API for searching contacts (from Nicola De Filippo) + old: ---- nemo-qml-plugins-0.0.6.tar.bz2 new: ---- nemo-qml-plugins-0.0.7.tar.bz2 spec files: ----------- --- nemo-qml-plugins.spec +++ nemo-qml-plugins.spec @@ -1,6 +1,6 @@ # # Do NOT Edit the Auto-generated Part! -# Generated by: spectacle version 0.24.1 +# Generated by: spectacle version 0.25 # Name: nemo-qml-plugins @@ -9,7 +9,7 @@ # << macros Summary: Nemo QML plugins source package. -Version: 0.0.6 +Version: 0.0.7 Release: 1 Group: System/Libraries License: BSD other changes: -------------- ++++++ nemo-qml-plugins-0.0.6.tar.bz2 -> nemo-qml-plugins-0.0.7.tar.bz2 --- contacts/seasideperson.cpp +++ contacts/seasideperson.cpp @@ -42,265 +42,6 @@ #include "seasideperson.h" -#if 0 - case AvatarRole: - { - QContactAvatar avatar = mContact.detail<QContactAvatar>(); - if(!avatar.imageUrl().isEmpty()) { - return QUrl(avatar.imageUrl()).toString(); - } - return QString(); - } - case ThumbnailRole: - { - QContactThumbnail thumb = mContact.detail<QContactThumbnail>(); - return thumb.thumbnail(); - } - case FavoriteRole: - { - QContactFavorite fav = mContact.detail<QContactFavorite>(); - if(!fav.isEmpty()) - return QVariant(fav.isFavorite()); - return false; - } - case OnlineAccountUriRole: - { - QStringList list; - foreach (const QContactOnlineAccount& account, - mContact.details<QContactOnlineAccount>()){ - if(!account.accountUri().isNull()) - list << account.accountUri(); - } - return list; - } - case OnlineServiceProviderRole: - { - QStringList list; - foreach (const QContactOnlineAccount& account, - mContact.details<QContactOnlineAccount>()){ - if(!account.serviceProvider().isNull()) - list << account.serviceProvider(); - } - return list; - } - case IsSelfRole: - { - if (isSelfContact(mContact.id().localId())) - return true; - return false; - } - case EmailAddressRole: - { - QStringList list; - foreach (const QContactEmailAddress& email, - mContact.details<QContactEmailAddress>()){ - if(!email.emailAddress().isNull()) - list << email.emailAddress(); - } - return list; - } - case EmailContextRole: - { - QStringList list; - foreach (const QContactEmailAddress& email, - mContact.details<QContactEmailAddress>()) { - if (email.contexts().count() > 0) - list << email.contexts().at(0); - } - return list; - } - case PhoneNumberRole: - { - QStringList list; - foreach (const QContactPhoneNumber& phone, - mContact.details<QContactPhoneNumber>()){ - if(!phone.number().isNull()) - list << phone.number(); - } - return list; - } - case PhoneContextRole: - { - QStringList list; - foreach (const QContactPhoneNumber& phone, - mContact.details<QContactPhoneNumber>()) { - if (phone.contexts().count() > 0) - list << phone.contexts().at(0); - else if (phone.subTypes().count() > 0) - list << phone.subTypes().at(0); - } - return list; - } - case AddressRole: - { - QStringList list; - QStringList fieldOrder = priv->localeHelper->getAddressFieldOrder(); - - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) { - QString aStr; - QString temp; - QString addy = address.street(); - QStringList streetList = addy.split("\n"); - - for (int i = 0; i < fieldOrder.size(); ++i) { - temp = ""; - if (fieldOrder.at(i) == "street") { - if (streetList.count() == 2) - temp += streetList.at(0); - else - temp += addy; - } else if (fieldOrder.at(i) == "street2") { - if (streetList.count() == 2) - temp += streetList.at(1); - } - else if (fieldOrder.at(i) == "locale") - temp += address.locality(); - else if (fieldOrder.at(i) == "region") - temp += address.region(); - else if (fieldOrder.at(i) == "zip") - temp += address.postcode(); - else if (fieldOrder.at(i) == "country") - temp += address.country(); - - if (i > 0) - aStr += "\n" + temp.trimmed(); - else - aStr += temp.trimmed(); - } - - if (aStr == "") - aStr = address.street() + "\n" + address.locality() + "\n" + - address.region() + "\n" + address.postcode() + "\n" + - address.country(); - list << aStr; - } - return list; - } - case AddressStreetRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()){ - if(!address.street().isEmpty()) - list << address.street(); - } - return list; - } - case AddressLocaleRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) { - if(!address.locality().isNull()) - list << address.locality(); - } - return list; - } - case AddressRegionRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) { - if(!address.region().isNull()) - list << address.region(); - } - return list; - } - case AddressCountryRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) { - if(!address.country().isNull()) - list << address.country(); - } - return list; - } - case AddressPostcodeRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) - list << address.postcode(); - return list; - } - - case AddressContextRole: - { - QStringList list; - foreach (const QContactAddress& address, - mContact.details<QContactAddress>()) { - if (address.contexts().count() > 0) - list << address.contexts().at(0); - } - return list; - } - case PresenceRole: - { - foreach (const QContactPresence& qp, - mContact.details<QContactPresence>()) { - if(!qp.isEmpty()) - if(qp.presenceState() == QContactPresence::PresenceAvailable) - return qp.presenceState(); - } - foreach (const QContactPresence& qp, - mContact.details<QContactPresence>()) { - if(!qp.isEmpty()) - if(qp.presenceState() == QContactPresence::PresenceBusy) - return qp.presenceState(); - } - return QContactPresence::PresenceUnknown; - } - - case UuidRole: - { - QContactGuid guid = mContact.detail<QContactGuid>(); - if(!guid.guid().isNull()) - return guid.guid(); - return QString(); - } - - case WebUrlRole: - { - QStringList list; - foreach(const QContactUrl &url, mContact.details<QContactUrl>()){ - if(!url.isEmpty()) - list << url.url(); - } - return QStringList(list); - } - - case WebContextRole: - { - QStringList list; - foreach(const QContactUrl &url, mContact.details<QContactUrl>()){ - if(!url.contexts().isEmpty()) - list << url.contexts(); - } - return list; - } - - case NotesRole: - { - QContactNote note = mContact.detail<QContactNote>(); - if(!note.isEmpty()) - return note.note(); - return QString(); - } - case FirstCharacterRole: - { - if (isSelfContact(mContact.id().localId())) - return QString(tr("#")); - - return priv->localeHelper->getBinForString(data(row, - DisplayLabelRole).toString()); - } - case DisplayLabelRole: { - } - -#endif - SeasidePerson::SeasidePerson(QObject *parent) : QObject(parent) { @@ -545,6 +286,25 @@ emit emailAddressesChanged(); } +// TODO: merge with LIST_PROPERTY_FROM_DETAIL_FIELD +#define LIST_PROPERTY_FROM_FIELD_NAME(detailType, fieldName) \ + QStringList list; \ + \ + foreach (const detailType &detail, mContact.details<detailType>()) { \ + if (detail.hasValue(fieldName)) \ + list << detail.value(fieldName); \ + } \ + return list; + +QStringList SeasidePerson::accountUris() const +{ + LIST_PROPERTY_FROM_FIELD_NAME(QContactOnlineAccount, QContactOnlineAccount::FieldAccountUri) +} + +QStringList SeasidePerson::accountPaths() const +{ + LIST_PROPERTY_FROM_FIELD_NAME(QContactOnlineAccount, "AccountPath") // QContactOnlineAccount__FieldAccountPath +} QContact SeasidePerson::contact() const { @@ -553,8 +313,21 @@ void SeasidePerson::setContact(const QContact &contact) { + mContact = contact; + // TODO: this should difference the two contacts, and emit the proper // signals - mContact = contact; + emit firstNameChanged(); + emit lastNameChanged(); + emit companyNameChanged(); + emit favoriteChanged(); + emit avatarPathChanged(); + emit birthdayChanged(); + emit phoneNumbersChanged(); + emit emailAddressesChanged(); + emit accountUrisChanged(); + emit accountPathsChanged(); + + recalculateDisplayLabel(); } --- contacts/seasideperson.h +++ contacts/seasideperson.h @@ -88,6 +88,12 @@ QStringList emailAddresses() const; void setEmailAddresses(const QStringList &emailAddresses); + Q_PROPERTY(QStringList accountUris READ accountUris NOTIFY accountUrisChanged) + QStringList accountUris() const; + + Q_PROPERTY(QStringList accountPaths READ accountPaths NOTIFY accountPathsChanged) + QStringList accountPaths() const; + QContact contact() const; void setContact(const QContact &contact); @@ -104,6 +110,8 @@ void birthdayChanged(); void phoneNumbersChanged(); void emailAddressesChanged(); + void accountUrisChanged(); + void accountPathsChanged(); private: // TODO: private class @@ -112,44 +120,8 @@ QString mDisplayLabel; friend class SeasidePeopleModelPriv; - /* - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - void Changed(); - */ }; Q_DECLARE_METATYPE(SeasidePerson *); -// uuid, presence, self contact - -/* - BirthdayRole, - OnlineAccountUriRole, - OnlineServiceProviderRole, - EmailAddressRole, - EmailContextRole, - PhoneNumberRole, - PhoneContextRole, - AddressRole, - AddressStreetRole, - AddressLocaleRole, - AddressRegionRole, - AddressCountryRole, - AddressPostcodeRole, - AddressContextRole, - WebUrlRole, - WebContextRole, - NotesRole, - FirstCharacterRole, - DisplayLabelRole -*/ - #endif // SEASIDEPERSON_H --- contacts/seasideproxymodel.cpp +++ contacts/seasideproxymodel.cpp @@ -20,6 +20,7 @@ public: SeasideProxyModel::FilterType filterType; LocaleUtils *localeHelper; + QString searchPattern; }; SeasideProxyModel::SeasideProxyModel(QObject *parent) @@ -46,6 +47,13 @@ invalidateFilter(); } +void SeasideProxyModel::search(const QString &pattern) +{ + priv->searchPattern = pattern; + invalidateFilter(); +} + + int SeasideProxyModel::getSourceRow(int row) const { return mapToSource(index(row, 0)).row(); @@ -65,6 +73,41 @@ if (person->id() == model->manager()->selfContactId()) return false; + if (!priv->searchPattern.isEmpty()) { + // split the display label and filter into words. search forwards + // over the display label components for each filter word, making + // sure to find all filter words before considering it a match. + // + // TODO: i18n will require different splitting for thai and possibly + // other locales, see MBreakIterator + // + // TODO: for performance, we may want to consider keeping a cached + // version of the parts comprising a display label - + // QStringList SeasidePerson::displayLabelParts? + QStringList labelList = person->displayLabel().split(" "); + QStringList filterList = priv->searchPattern.split(" "); + int j = 0; + for (int i = 0; i < filterList.size(); i++) { + bool found = false; + for (; j < labelList.size(); j++) { + // TODO: for good i18n, we need to search insensitively taking + // diacritics into account, QString's functions alone aren't good + // enough + if (labelList.at(j).startsWith(filterList.at(i), Qt::CaseInsensitive)) { + found = true; + j++; + break; + } + } + + // if the current filter word wasn't found in the search + // string, then it wasn't a match. we require all words + // to match. + if (!found) + return false; + } + } + if (priv->filterType == FilterAll) { // TODO: this should not be here qDebug("fastscroll: emitting countChanged"); --- contacts/seasideproxymodel.h +++ contacts/seasideproxymodel.h @@ -34,6 +34,9 @@ }; Q_INVOKABLE virtual void setFilter(FilterType filter); + + Q_INVOKABLE virtual void search(const QString &pattern); + Q_INVOKABLE int getSourceRow(int row) const; // for fastscroll support --- thumbnailer/nemothumbnailprovider.cpp +++ thumbnailer/nemothumbnailprovider.cpp @@ -54,19 +54,38 @@ return QDesktopServices::storageLocation(QDesktopServices::CacheLocation) + ".nemothumbs"; } +static inline QString rawCachePath() +{ + return cachePath() + QDir::separator() + "raw"; +} + static void setupCache() { // the syscalls make baby jesus cry; but this protects us against sins like users QDir d(cachePath()); if (!d.exists()) d.mkpath(cachePath()); - if (!d.exists("raw")) - d.mkdir("raw"); + d.mkdir("raw"); // in the future, we might store a nicer UI version which can blend in with our UI better, but // we'll always want the raw version. } +static QString cacheFileName(const QByteArray &hashKey, bool makePath = false) +{ + QString subfolder = QString(hashKey.left(2)); + if (makePath) { + QDir d(rawCachePath()); + d.mkdir(subfolder); + } + + return rawCachePath() + + QDir::separator() + + subfolder + + QDir::separator() + + hashKey; +} + static QByteArray cacheKey(const QString &id, const QSize &requestedSize) { QByteArray baId = id.toLatin1(); // is there a more efficient way than a copy? @@ -82,7 +101,7 @@ static QImage attemptCachedServe(const QString &id, const QByteArray &hashKey) { - QFile fi(cachePath() + QDir::separator() + "raw" + QDir::separator() + hashKey); + QFile fi(cacheFileName(hashKey)); QFileInfo info(fi); if (info.exists() && info.lastModified() >= QFileInfo(id).lastModified()) { if (fi.open(QIODevice::ReadOnly)) { @@ -98,7 +117,7 @@ static void writeCacheFile(const QByteArray &hashKey, const QImage &img) { - QFile fi(cachePath() + QDir::separator() + "raw" + QDir::separator() + hashKey); + QFile fi(cacheFileName(hashKey, true)); if (!fi.open(QIODevice::WriteOnly)) { qWarning() << "Couldn't cache to " << fi.fileName(); return; ++++++ 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.0.6 +Version: 0.0.7 Release: 1 Sources: - "%{name}-%{version}.tar.bz2"
