I have made the following changes intended for : nemo:devel:mw / 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.merproject.org//request/show/166 Thank You, John Brooks [This message was auto-generated] --- Request # 166: Messages from BOSS: State: review at 2013-04-04T00:02:23 by cibot Reviews: accepted by cibot : Prechecks succeeded. new for nemo:devel:mw : 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:jbrooks:branches:nemo:devel:mw / nemo-qml-plugins -> nemo:devel:mw / nemo-qml-plugins changes files: -------------- --- nemo-qml-plugins.changes +++ nemo-qml-plugins.changes @@ -0,0 +1,12 @@ +* Wed Apr 03 2013 John Brooks <[email protected]> - 0.3.6 +- social: Improve error message handling and Facebook heuristics (from Chris Adams) +- contacts: Remove superfluous SeasidePerson.presenceAccountUris property (from Matt Vogt) +- contacts: Export service icon path of each IM account (from Matt Vogt) +- calendar: Add CalendarEventCache (from Robin Burchell) +- folderlistmodel: Add Qt5 compatibility for DirModel (from Arto Jalkanen) +- email: Make messageListModel sorting persistent (from Valerio Valerio) +- email: Add sort by read status to MessageListModel (from Valerio Valerio) +- email: Add sort by attachments and sort by priority to MessageListModel (from Valerio Valerio) +- email: Add sort by size and size section role to MessageListModel (from Valerio Valerio) +- email: Add getters for SenderDisplayName, SenderEmailAddress, size, accountId, priority to messageListModel (from Valerio Valerio) + old: ---- nemo-qml-plugins-0.3.5.tar.bz2 new: ---- nemo-qml-plugins-0.3.6.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.5 +Version: 0.3.6 Release: 1 Group: System/Libraries License: BSD other changes: -------------- ++++++ nemo-qml-plugins-0.3.5.tar.bz2 -> nemo-qml-plugins-0.3.6.tar.bz2 --- calendar/src/calendaragendamodel.cpp +++ calendar/src/calendaragendamodel.cpp @@ -36,6 +36,7 @@ // mkcal #include <event.h> +#include "calendareventcache.h" #include "calendaragendamodel.h" #include "calendarevent.h" #include "calendardb.h" @@ -48,6 +49,9 @@ roles[SectionBucketRole] = "sectionBucket"; roles[NotebookColorRole] = "notebookColor"; setRoleNames(roles); + + connect(this, SIGNAL(startDateChanged()), this, SLOT(load())); + connect(NemoCalendarEventCache::instance(), SIGNAL(modelReset()), this, SLOT(load())); } NemoCalendarAgendaModel::~NemoCalendarAgendaModel() @@ -67,14 +71,13 @@ mStartDate = startDate; emit startDateChanged(); +} - // load from database - // TODO: this init code should only run once, probably - NemoCalendarDb::storage()->loadNotebookIncidences(NemoCalendarDb::storage()->defaultNotebook()->uid()); - +void NemoCalendarAgendaModel::load() +{ // TODO: we really need a centralised event cache - KCalCore::Event::List eventList = NemoCalendarDb::calendar()->rawEventsForDate(startDate, KDateTime::Spec(KDateTime::LocalZone), KCalCore::EventSortStartDate, KCalCore::SortDirectionAscending); - qDebug() << Q_FUNC_INFO << "Loaded " << eventList.count() << " events for " << startDate; + KCalCore::Event::List eventList = NemoCalendarDb::calendar()->rawEventsForDate(mStartDate, KDateTime::Spec(KDateTime::LocalZone), KCalCore::EventSortStartDate, KCalCore::SortDirectionAscending); + qDebug() << Q_FUNC_INFO << "Loaded " << eventList.count() << " events for " << mStartDate; beginResetModel(); qDeleteAll(mEvents); @@ -108,7 +111,7 @@ case SectionBucketRole: return mEvents.at(index.row())->startTime().date(); case NotebookColorRole: - return "blue"; // TODO: hardcoded, as we only support local events for now + return "#00aeef"; // TODO: hardcoded, as we only support local events for now default: return QVariant(); } --- calendar/src/calendaragendamodel.h +++ calendar/src/calendaragendamodel.h @@ -62,6 +62,9 @@ signals: void startDateChanged(); +private slots: + void load(); + private: QDate mStartDate; QList<NemoCalendarEvent *> mEvents; --- calendar/src/calendareventcache.cpp +++ calendar/src/calendareventcache.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 Jolla Ltd. + * Contact: Robin Burchell <[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." + */ + +// Qt +#include <QDebug> + +// mkcal +#include <event.h> + +#include "calendardb.h" +#include "calendareventcache.h" + +NemoCalendarEventCache::NemoCalendarEventCache() + : QObject(0) + , mKCal::ExtendedStorageObserver() +{ + NemoCalendarDb::storage()->registerObserver(this); + + // initialize storage + NemoCalendarDb::storage()->loadNotebookIncidences(NemoCalendarDb::storage()->defaultNotebook()->uid()); +} + +NemoCalendarEventCache *NemoCalendarEventCache::instance() +{ + static NemoCalendarEventCache *cacheInstance; + if (!cacheInstance) + cacheInstance = new NemoCalendarEventCache; + + return cacheInstance; +} + +void NemoCalendarEventCache::storageModified(mKCal::ExtendedStorage *storage, const QString &info) +{ + // 'info' is either a path to the database (in which case we're screwed, we + // have no idea what changed, so tell all interested models to reload) or a + // space-seperated list of event UIDs. + // + // unfortunately we don't know *what* about these events changed with the + // current mkcal API, so we'll have to try our best to guess when the time + // comes. + // + // for now, let's just ask models to reload whenever a change happens. + NemoCalendarDb::storage()->loadNotebookIncidences(NemoCalendarDb::storage()->defaultNotebook()->uid()); + qDebug() << Q_FUNC_INFO << "Emitting reset"; + emit modelReset(); +} + +void NemoCalendarEventCache::storageProgress(mKCal::ExtendedStorage *storage, const QString &info) +{ + +} + +void NemoCalendarEventCache::storageFinished(mKCal::ExtendedStorage *storage, bool error, const QString &info) +{ + +} + --- calendar/src/calendareventcache.h +++ calendar/src/calendareventcache.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 Jolla Ltd. + * Contact: Robin Burchell <[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 CALENDAREVENTCACHE_H +#define CALENDAREVENTCACHE_H + +// Qt +#include <QDebug> +#include <QObject> + +// mkcal +#include <event.h> +#include <extendedstorage.h> + +class NemoCalendarEventCache : public QObject, public mKCal::ExtendedStorageObserver +{ + Q_OBJECT +private: + NemoCalendarEventCache(); + +public: + static NemoCalendarEventCache *instance(); + + /* mKCal::ExtendedStorageObserver */ + void storageModified(mKCal::ExtendedStorage *storage, const QString &info); + void storageProgress(mKCal::ExtendedStorage *storage, const QString &info); + void storageFinished(mKCal::ExtendedStorage *storage, bool error, const QString &info); + +signals: + void modelReset(); +}; + +#endif // CALENDAREVENTCACHE_H --- calendar/src/src.pro +++ calendar/src/src.pro @@ -9,13 +9,15 @@ calendarabstractmodel.cpp \ calendarevent.cpp \ calendaragendamodel.cpp \ - calendardb.cpp + calendardb.cpp \ + calendareventcache.cpp HEADERS += \ calendarevent.h \ calendarabstractmodel.h \ calendaragendamodel.h \ - calendardb.h + calendardb.h \ + calendareventcache.h MOC_DIR = $$PWD/../.moc OBJECTS_DIR = $$PWD/../.obj --- contacts/src/seasideperson.cpp +++ contacts/src/seasideperson.cpp @@ -743,63 +743,68 @@ namespace { // Helper functions -template<class ListType, class MapType> -typename MapType::mapped_type selectMatching(ListType list, MapType map) +int someElementPresentAtIndex(const QStringList &needleList, const QStringList &haystack) { - // Return the mapped value for the first supplied key that we find in the map - foreach (const typename ListType::value_type &item, list) { - const typename MapType::const_iterator it = map.constFind(item); - if (it != map.constEnd()) { - return *it; + QStringList::const_iterator it = haystack.constBegin(), end = haystack.constEnd(); + for ( ; it != end; ++it) { + if (needleList.contains(*it)) { + return (it - haystack.constBegin()); } } - return typename MapType::mapped_type(); -} - + return -1; } -QStringList SeasidePerson::presenceAccountUris() const +template<class ListType, class AccountListType> +ListType inAccountOrder(ListType list, AccountListType accountList) { - QStringList rv; + ListType rv; - QMap<QString, QString> accountUris; - foreach (const QContactOnlineAccount &account, mContact.details<QContactOnlineAccount>()) { - if (account.hasValue("AccountPath")) - accountUris.insert(account.detailUri(), account.value("AccountPath")); + // Find the detailUri for each reportable account in the order they're yielded + QStringList uriList; + foreach (const typename AccountListType::value_type &account, accountList) { + if (account.hasValue("AccountPath")) { + uriList.append(account.detailUri()); + } } - // Return the account URIs as reported by the presence details - foreach (const QContactPresence &presence, mContact.details<QContactPresence>()) { - rv.append(selectMatching(presence.linkedDetailUris(), accountUris)); + rv.reserve(uriList.count()); + + // For each value, insert in the order that the linked account is present + foreach (const typename ListType::value_type &item, list) { + int index = someElementPresentAtIndex(item.linkedDetailUris(), uriList); + if (index != -1) { + if (rv.count() > index) { + rv[index] = item; + } else { + while (rv.count() < index) { + rv.append(typename ListType::value_type()); + } + rv.append(item); + } + } } return rv; } +} + QStringList SeasidePerson::presenceAccountProviders() const { - QStringList rv; - - QMap<QString, QString> accountProviders; - foreach (const QContactOnlineAccount &account, mContact.details<QContactOnlineAccount>()) { - accountProviders.insert(account.detailUri(), account.serviceProvider()); - } - - // Return the account provider names as reported by the presence details - foreach (const QContactPresence &presence, mContact.details<QContactPresence>()) { - rv.append(selectMatching(presence.linkedDetailUris(), accountProviders)); - } - - return rv; + return accountProviders(); } QList<int> SeasidePerson::presenceStates() const { QList<int> rv; - foreach (const QContactPresence &presence, mContact.details<QContactPresence>()) { - rv.append(static_cast<int>(presence.presenceState())); + foreach (const QContactPresence &presence, inAccountOrder(mContact.details<QContactPresence>(), mContact.details<QContactOnlineAccount>())) { + if (!presence.isEmpty()) { + rv.append(static_cast<int>(presence.presenceState())); + } else { + rv.append(QContactPresence::PresenceUnknown); + } } return rv; @@ -809,8 +814,12 @@ { QStringList rv; - foreach (const QContactPresence &presence, mContact.details<QContactPresence>()) { - rv.append(presence.customMessage()); + foreach (const QContactPresence &presence, inAccountOrder(mContact.details<QContactPresence>(), mContact.details<QContactOnlineAccount>())) { + if (!presence.isEmpty()) { + rv.append(presence.customMessage()); + } else { + rv.append(QString()); + } } return rv; @@ -836,6 +845,34 @@ LIST_PROPERTY_FROM_FIELD_NAME(QContactOnlineAccount, "AccountPath") // QContactOnlineAccount__FieldAccountPath } +QStringList SeasidePerson::accountProviders() const +{ + QStringList rv; + + foreach (const QContactOnlineAccount &account, mContact.details<QContactOnlineAccount>()) { + // Include the provider value for each account returned by accountPaths + if (account.hasValue("AccountPath")) { + rv.append(account.serviceProvider()); + } + } + + return rv; +} + +QStringList SeasidePerson::accountIconPaths() const +{ + QStringList rv; + + foreach (const QContactOnlineAccount &account, mContact.details<QContactOnlineAccount>()) { + // Include the icon path value for each account returned by accountPaths + if (account.hasValue("AccountPath")) { + rv.append(account.value("ServiceIconPath")); + } + } + + return rv; +} + QContact SeasidePerson::contact() const { return mContact; @@ -916,7 +953,6 @@ emit presenceMessagesChanged(); } if (urisChanged) { - emit presenceAccountUrisChanged(); emit presenceAccountProvidersChanged(); } } @@ -926,6 +962,8 @@ emit emailAddressesChanged(); emit accountUrisChanged(); emit accountPathsChanged(); + emit accountProvidersChanged(); + emit accountIconPathsChanged(); recalculateDisplayLabel(); } --- contacts/src/seasideperson.h +++ contacts/src/seasideperson.h @@ -111,8 +111,9 @@ AnniversaryType, // Presence information GlobalPresenceStateType, - PresenceAccountUrisType, - PresenceAccountProvidersType, + AccountProvidersType, + PresenceAccountProvidersType = AccountProvidersType, // To be removed + AccountIconPathsType, PresenceStatesType, PresenceMessagesType, }; @@ -220,9 +221,7 @@ Q_PROPERTY(PresenceState globalPresenceState READ globalPresenceState NOTIFY globalPresenceStateChanged) PresenceState globalPresenceState() const; - Q_PROPERTY(QStringList presenceAccountUris READ presenceAccountUris NOTIFY presenceAccountUrisChanged) - QStringList presenceAccountUris() const; - + // To be removed: Q_PROPERTY(QStringList presenceAccountProviders READ presenceAccountProviders NOTIFY presenceAccountProvidersChanged) QStringList presenceAccountProviders() const; @@ -238,6 +237,12 @@ Q_PROPERTY(QStringList accountPaths READ accountPaths NOTIFY accountPathsChanged) QStringList accountPaths() const; + Q_PROPERTY(QStringList accountProviders READ accountProviders NOTIFY accountProvidersChanged) + QStringList accountProviders() const; + + Q_PROPERTY(QStringList accountIconPaths READ accountIconPaths NOTIFY accountIconPathsChanged) + QStringList accountIconPaths() const; + QContact contact() const; void setContact(const QContact &contact); @@ -276,12 +281,13 @@ void birthdayChanged(); void anniversaryChanged(); void globalPresenceStateChanged(); - void presenceAccountUrisChanged(); void presenceAccountProvidersChanged(); void presenceStatesChanged(); void presenceMessagesChanged(); void accountUrisChanged(); void accountPathsChanged(); + void accountProvidersChanged(); + void accountIconPathsChanged(); public slots: void recalculateDisplayLabel(SeasideProxyModel::DisplayLabelOrder order = SeasideProxyModel::FirstNameFirst); --- email/src/emailaccountlistmodel.h +++ email/src/emailaccountlistmodel.h @@ -20,7 +20,7 @@ Q_OBJECT public: - explicit EmailAccountListModel (QObject *parent = 0); + explicit EmailAccountListModel(QObject *parent = 0); ~EmailAccountListModel(); enum Role { --- email/src/emailagent.h +++ email/src/emailagent.h @@ -30,11 +30,11 @@ public: static EmailAgent *instance(); - explicit EmailAgent (QDeclarativeItem *parent = 0); + explicit EmailAgent(QDeclarativeItem *parent = 0); ~EmailAgent(); void initMailServer(); - void sendMessages (const QMailAccountId &id); + void sendMessages(const QMailAccountId &id); bool isSynchronizing() const; void exportUpdates(const QMailAccountId id); @@ -76,7 +76,7 @@ void error(const QMailAccountId &id, const QString &msg, int code); void attachmentDownloadStarted(); void attachmentDownloadCompleted(); - void progressUpdate (int percent); + void progressUpdate(int percent); void folderRetrievalCompleted(const QMailAccountId &id); private slots: --- email/src/emailmessage.h +++ email/src/emailmessage.h @@ -20,19 +20,19 @@ Q_ENUMS(Priority) public: - explicit EmailMessage (QDeclarativeItem *parent = 0); + explicit EmailMessage(QDeclarativeItem *parent = 0); ~EmailMessage (); enum Priority { LowPriority, NormalPriority, HighPriority }; - Q_INVOKABLE void setFrom (const QString &sender); - Q_INVOKABLE void setTo (const QStringList &toList); - Q_INVOKABLE void setCc (const QStringList &ccList); + Q_INVOKABLE void setFrom(const QString &sender); + Q_INVOKABLE void setTo(const QStringList &toList); + Q_INVOKABLE void setCc(const QStringList &ccList); Q_INVOKABLE void setBcc(const QStringList &bccList); - Q_INVOKABLE void setSubject (const QString &subject); - Q_INVOKABLE void setBody (const QString &body, bool textOnly); - Q_INVOKABLE void setAttachments (const QStringList &uris); - Q_INVOKABLE void setPriority (Priority priority); + Q_INVOKABLE void setSubject(const QString &subject); + Q_INVOKABLE void setBody(const QString &body, bool textOnly); + Q_INVOKABLE void setAttachments(const QStringList &uris); + Q_INVOKABLE void setPriority(Priority priority); Q_INVOKABLE void send(); Q_INVOKABLE void saveDraft(); --- email/src/emailmessagelistmodel.cpp +++ email/src/emailmessagelistmodel.cpp @@ -87,6 +87,8 @@ roles[MessageTimeSectionRole] = "timeSection"; roles[MessagePriorityRole] = "priority"; roles[MessageAccountIdRole] = "accountId"; + roles[MessageHasAttachmentsRole] = "hasAttachments"; + roles[MessageSizeSectionRole] = "sizeSection"; setRoleNames(roles); EmailAgent::instance()->initMailServer(); @@ -97,8 +99,8 @@ QMailMessageKey accountKey = QMailMessageKey::parentAccountId(m_mailAccountIds); QMailMessageListModel::setKey(accountKey); m_key = key(); - QMailMessageSortKey sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); - QMailMessageListModel::setSortKey(sortKey); + m_sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + QMailMessageListModel::setSortKey(m_sortKey); m_selectedMsgIds.clear(); } @@ -243,6 +245,27 @@ else if (role == MessageAccountIdRole) { return messageMetaData.parentAccountId(); } + else if (role == MessageHasAttachmentsRole) { + if (messageMetaData.status() & QMailMessageMetaData::HasAttachments) + return 1; + else + return 0; + } + else if (role == MessageSizeSectionRole) { + const uint size(messageMetaData.size()); + // <100 KB + if (size < 100 * 1024) { + return 0; + } + // <500 KB + else if (size < 500 * 1024) { + return 1; + } + // >500 KB + else { + return 2; + } + } return QMailMessageListModel::data(index, role); } @@ -262,7 +285,7 @@ m_search = search; } -void EmailMessageListModel::setFolderKey (QVariant id) +void EmailMessageListModel::setFolderKey(QVariant id) { m_currentFolderId = id.value<QMailFolderId>(); if (!m_currentFolderId.isValid()) @@ -270,14 +293,13 @@ QMailMessageKey folderKey = QMailMessageKey::parentFolderId(m_currentFolderId); QMailMessageListModel::setKey(folderKey); m_key=key(); - QMailMessageSortKey sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); - QMailMessageListModel::setSortKey(sortKey); + QMailMessageListModel::setSortKey(m_sortKey); if (combinedInbox()) setCombinedInbox(false); } -void EmailMessageListModel::setAccountKey (QVariant id) +void EmailMessageListModel::setAccountKey(QVariant id) { QMailAccountId accountId = id.value<QMailAccountId>(); if (!accountId.isValid()) { @@ -304,9 +326,7 @@ SLOT(foldersAdded( const QMailFolderIdList &))); } } - - QMailMessageSortKey sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); - QMailMessageListModel::setSortKey(sortKey); + QMailMessageListModel::setSortKey(m_sortKey); m_key= key(); @@ -335,44 +355,69 @@ } } -void EmailMessageListModel::sortBySender(int key) +void EmailMessageListModel::sortBySender(int order) { - impl()->reset(); - QMailMessageSortKey sortKey; - if (key == 0) // descending - sortKey = QMailMessageSortKey::sender(Qt::DescendingOrder); - else - sortKey = QMailMessageSortKey::sender(Qt::AscendingOrder); + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::sender(sortOrder); + QMailMessageListModel::setSortKey(m_sortKey); +} - QMailMessageListModel::setSortKey(sortKey); +void EmailMessageListModel::sortBySubject(int order) +{ + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::subject(sortOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + QMailMessageListModel::setSortKey(m_sortKey); } -void EmailMessageListModel::sortBySubject(int key) +void EmailMessageListModel::sortByDate(int order) { - QMailMessageSortKey sortKey; - if (key == 0) // descending - sortKey = QMailMessageSortKey::subject(Qt::DescendingOrder); - else - sortKey = QMailMessageSortKey::subject(Qt::AscendingOrder); + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::timeStamp(sortOrder); + QMailMessageListModel::setSortKey(m_sortKey); +} - QMailMessageListModel::setSortKey(sortKey); +void EmailMessageListModel::sortByAttachment(int order) +{ + // 0 - messages with attachments before messages without + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::status(QMailMessage::HasAttachments, sortOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + QMailMessageListModel::setSortKey(m_sortKey); } -void EmailMessageListModel::sortByDate(int key) +void EmailMessageListModel::sortByReadStatus(int order) { - QMailMessageSortKey sortKey; - if (key == 0) // descending - sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); - else - sortKey = QMailMessageSortKey::timeStamp(Qt::AscendingOrder); + // 0 - read before non-read + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::status(QMailMessage::Read, sortOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + QMailMessageListModel::setSortKey(m_sortKey); +} + +void EmailMessageListModel::sortByPriority(int order) +{ + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); - QMailMessageListModel::setSortKey(sortKey); + if (sortOrder == Qt::AscendingOrder) { + m_sortKey = QMailMessageSortKey::status(QMailMessage::HighPriority, sortOrder) & + QMailMessageSortKey::status(QMailMessage::LowPriority, Qt::DescendingOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + } + else { + m_sortKey = QMailMessageSortKey::status(QMailMessage::HighPriority, sortOrder) & + QMailMessageSortKey::status(QMailMessage::LowPriority, Qt::AscendingOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + } + QMailMessageListModel::setSortKey(m_sortKey); } -void EmailMessageListModel::sortByAttachment(int key) +void EmailMessageListModel::sortBySize(int order) { - // TDB - Q_UNUSED(key); + Qt::SortOrder sortOrder = static_cast<Qt::SortOrder>(order); + m_sortKey = QMailMessageSortKey::size(sortOrder) & + QMailMessageSortKey::timeStamp(Qt::DescendingOrder); + QMailMessageListModel::setSortKey(m_sortKey); } QVariant EmailMessageListModel::accountIdForMessage(QVariant messageId) @@ -389,7 +434,7 @@ return metaData.parentFolderId(); } -QVariant EmailMessageListModel::indexFromMessageId (QString uuid) +QVariant EmailMessageListModel::indexFromMessageId(QString uuid) { quint64 id = uuid.toULongLong(); QMailMessageId msgId (id); @@ -402,78 +447,103 @@ return -1; } -QVariant EmailMessageListModel::messageId (int idx) +QVariant EmailMessageListModel::messageId(int idx) { QMailMessageId id = idFromIndex (index(idx)); return id; } -QVariant EmailMessageListModel::subject (int idx) +QVariant EmailMessageListModel::subject(int idx) { return data(index(idx), QMailMessageModelBase::MessageSubjectTextRole); } -QVariant EmailMessageListModel::mailSender (int idx) +QVariant EmailMessageListModel::mailSender(int idx) { return data(index(idx), QMailMessageModelBase::MessageAddressTextRole); } -QVariant EmailMessageListModel::timeStamp (int idx) +QVariant EmailMessageListModel::senderDisplayName(int idx) +{ + return data(index(idx), MessageSenderDisplayNameRole); +} + +QVariant EmailMessageListModel::senderEmailAddress(int idx) +{ + return data(index(idx), MessageSenderEmailAddressRole); +} + +QVariant EmailMessageListModel::timeStamp(int idx) { return data(index(idx), QMailMessageModelBase::MessageTimeStampTextRole); } -QVariant EmailMessageListModel::body (int idx) +QVariant EmailMessageListModel::body(int idx) { return data(index(idx), QMailMessageModelBase::MessageBodyTextRole); } -QVariant EmailMessageListModel::quotedBody (int idx) +QVariant EmailMessageListModel::quotedBody(int idx) { return data(index(idx), MessageQuotedBodyRole); } -QVariant EmailMessageListModel::htmlBody (int idx) +QVariant EmailMessageListModel::htmlBody(int idx) { return data(index(idx), MessageHtmlBodyRole); } -QVariant EmailMessageListModel::attachments (int idx) +QVariant EmailMessageListModel::attachments(int idx) { return data(index(idx), MessageAttachmentsRole); } -QVariant EmailMessageListModel::numberOfAttachments (int idx) +QVariant EmailMessageListModel::numberOfAttachments(int idx) { return data(index(idx), MessageAttachmentCountRole); } -QVariant EmailMessageListModel::toList (int idx) +QVariant EmailMessageListModel::toList(int idx) { return data(index(idx), MessageToRole); } -QVariant EmailMessageListModel::recipients (int idx) +QVariant EmailMessageListModel::recipients(int idx) { return data(index(idx), MessageRecipientsRole); } -QVariant EmailMessageListModel::ccList (int idx) +QVariant EmailMessageListModel::ccList(int idx) { return data(index(idx), MessageCcRole); } -QVariant EmailMessageListModel::bccList (int idx) +QVariant EmailMessageListModel::bccList(int idx) { return data(index(idx), MessageBccRole); } -QVariant EmailMessageListModel::messageRead (int idx) +QVariant EmailMessageListModel::messageRead(int idx) { return data(index(idx), MessageReadStatusRole); } -int EmailMessageListModel::messagesCount () +QVariant EmailMessageListModel::size(int idx) +{ + return data(index(idx), QMailMessageModelBase::MessageSizeTextRole); +} + +QVariant EmailMessageListModel::accountId(int idx) +{ + return data(index(idx), MessageAccountIdRole); +} + +QVariant EmailMessageListModel::priority(int idx) +{ + return data(index(idx), MessagePriorityRole); +} + +int EmailMessageListModel::messagesCount() { return rowCount(); } @@ -495,7 +565,7 @@ } } -void EmailMessageListModel::selectMessage( int idx ) +void EmailMessageListModel::selectMessage(int idx) { QMailMessageId msgId = idFromIndex(index(idx)); @@ -505,7 +575,7 @@ } } -void EmailMessageListModel::deSelectMessage (int idx ) +void EmailMessageListModel::deSelectMessage(int idx) { QMailMessageId msgId = idFromIndex(index(idx)); @@ -526,7 +596,7 @@ m_selectedMsgIds.clear(); EmailAgent::instance()->exportUpdates(msg.parentAccountId()); } - +//TODO: support to delete messages from mutiple accounts void EmailMessageListModel::deleteSelectedMessageIds() { if (m_selectedMsgIds.empty()) @@ -636,8 +706,7 @@ } QMailMessageListModel::setKey(accountKey); m_key = key(); - QMailMessageSortKey sortKey = QMailMessageSortKey::timeStamp(Qt::DescendingOrder); - QMailMessageListModel::setSortKey(sortKey); + QMailMessageListModel::setSortKey(m_sortKey); m_combinedInbox = false; } emit combinedInboxChanged(); --- email/src/emailmessagelistmodel.h +++ email/src/emailmessagelistmodel.h @@ -23,6 +23,7 @@ { Q_OBJECT Q_ENUMS(Priority) + Q_ENUMS(Sort) public: enum Roles @@ -45,18 +46,22 @@ MessagePreviewRole, // returns message preview if available MessageTimeSectionRole, // returns time section relative to the current time MessagePriorityRole, // returns message priority - MessageAccountIdRole // returns parent account id for the message + MessageAccountIdRole, // returns parent account id for the message + MessageHasAttachmentsRole, // returns 1 if message has attachments, 0 otherwise + MessageSizeSectionRole // returns size section (0-2) }; - EmailMessageListModel (QObject *parent = 0); + EmailMessageListModel(QObject *parent = 0); ~EmailMessageListModel(); - int rowCount (const QModelIndex & parent = QModelIndex()) const; - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex & parent = QModelIndex()) const; + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; QString bodyHtmlText(const QMailMessage &) const; QString bodyPlainText(const QMailMessage &) const; enum Priority { LowPriority, NormalPriority, HighPriority }; + enum Sort { Time, Sender, Size, ReadStatus, Priority, Attachments, Subject}; + Q_PROPERTY(bool combinedInbox READ combinedInbox WRITE setCombinedInbox NOTIFY combinedInboxChanged) Q_PROPERTY(bool filterUnread READ filterUnread WRITE setFilterUnread NOTIFY filterUnreadChanged) @@ -74,35 +79,43 @@ void messageDownloadCompleted(); public slots: - Q_INVOKABLE void setFolderKey (QVariant id); - Q_INVOKABLE void setAccountKey (QVariant id); - Q_INVOKABLE void sortBySender (int key); - Q_INVOKABLE void sortBySubject (int key); - Q_INVOKABLE void sortByDate (int key); - Q_INVOKABLE void sortByAttachment (int key); + Q_INVOKABLE void setFolderKey(QVariant id); + Q_INVOKABLE void setAccountKey(QVariant id); + Q_INVOKABLE void sortBySender(int order = 0); + Q_INVOKABLE void sortBySubject(int order = 0); + Q_INVOKABLE void sortByDate(int order = 1); + Q_INVOKABLE void sortByAttachment(int order = 1); + Q_INVOKABLE void sortByReadStatus(int order = 0); + Q_INVOKABLE void sortByPriority(int order = 1); + Q_INVOKABLE void sortBySize(int order = 1); Q_INVOKABLE void setSearch(const QString search); Q_INVOKABLE QVariant accountIdForMessage(QVariant messageId); Q_INVOKABLE QVariant indexFromMessageId(QString msgId); Q_INVOKABLE QVariant folderIdForMessage(QVariant messageId); - Q_INVOKABLE QVariant messageId (int index); - Q_INVOKABLE QVariant subject (int index); - Q_INVOKABLE QVariant mailSender (int index); - Q_INVOKABLE QVariant timeStamp (int index); - Q_INVOKABLE QVariant body (int index); - Q_INVOKABLE QVariant htmlBody (int index); - Q_INVOKABLE QVariant quotedBody (int index); - Q_INVOKABLE QVariant attachments (int index); - Q_INVOKABLE QVariant numberOfAttachments (int index); - Q_INVOKABLE QVariant recipients (int index); - Q_INVOKABLE QVariant ccList (int index); - Q_INVOKABLE QVariant bccList (int index); - Q_INVOKABLE QVariant toList (int index); - Q_INVOKABLE QVariant messageRead (int index); - Q_INVOKABLE int messagesCount (); + Q_INVOKABLE QVariant messageId(int index); + Q_INVOKABLE QVariant subject(int index); + Q_INVOKABLE QVariant mailSender(int index); + Q_INVOKABLE QVariant senderDisplayName(int index); + Q_INVOKABLE QVariant senderEmailAddress(int index); + Q_INVOKABLE QVariant timeStamp(int index); + Q_INVOKABLE QVariant body(int index); + Q_INVOKABLE QVariant htmlBody(int index); + Q_INVOKABLE QVariant quotedBody(int index); + Q_INVOKABLE QVariant attachments(int index); + Q_INVOKABLE QVariant numberOfAttachments(int index); + Q_INVOKABLE QVariant recipients(int index); + Q_INVOKABLE QVariant ccList(int index); + Q_INVOKABLE QVariant bccList(int index); + Q_INVOKABLE QVariant toList(int index); + Q_INVOKABLE QVariant messageRead(int index); + Q_INVOKABLE QVariant size(int index); + Q_INVOKABLE QVariant accountId(int index); + Q_INVOKABLE QVariant priority(int index); + Q_INVOKABLE int messagesCount(); Q_INVOKABLE void deSelectAllMessages(); - Q_INVOKABLE void selectMessage( int index ); - Q_INVOKABLE void deSelectMessage (int index ); + Q_INVOKABLE void selectMessage(int index); + Q_INVOKABLE void deSelectMessage(int index); Q_INVOKABLE void moveSelectedMessageIds(QVariant vFolderId); Q_INVOKABLE void deleteSelectedMessageIds(); Q_INVOKABLE void markAllMessagesAsRead(); @@ -123,6 +136,7 @@ QMailRetrievalAction *m_retrievalAction; QString m_search; QMailMessageKey m_key; // key set externally other than search + QMailMessageSortKey m_sortKey; QList<QMailMessageId> m_selectedMsgIds; }; --- email/src/folderlistmodel.h +++ email/src/folderlistmodel.h @@ -19,7 +19,7 @@ Q_OBJECT public: - explicit FolderListModel (QObject *parent = 0); + explicit FolderListModel(QObject *parent = 0); ~FolderListModel(); enum Role { @@ -33,12 +33,12 @@ int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; - Q_INVOKABLE void setAccountKey (QVariant id); + Q_INVOKABLE void setAccountKey(QVariant id); Q_INVOKABLE QStringList folderNames(); Q_INVOKABLE QVariant folderId(int index); Q_INVOKABLE int indexFromFolderId(QVariant vFolderId); Q_INVOKABLE QVariant folderServerCount(QVariant vFolderId); - Q_INVOKABLE QVariant inboxFolderId (); + Q_INVOKABLE QVariant inboxFolderId(); Q_INVOKABLE QVariant inboxFolderName(); Q_INVOKABLE int totalNumberOfFolders(); Q_INVOKABLE QVariant folderUnreadCount(QVariant folderId); --- folderlistmodel/dirmodel.cpp +++ folderlistmodel/dirmodel.cpp @@ -43,6 +43,10 @@ Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread); +namespace { + QHash<QByteArray, int> roleMapping; +} + class DirListWorker : public IORequest { Q_OBJECT @@ -95,7 +99,29 @@ { mNameFilters = QStringList() << "*"; - QHash<int, QByteArray> roles = roleNames(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + // There's no setRoleNames in Qt5. + setRoleNames(buildRoleNames()); +#endif +} + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +// roleNames has changed between Qt4 and Qt5. In Qt5 it is a virtual +// function and setRoleNames should not be used. +QHash<int, QByteArray> DirModel::roleNames() const +{ + static QHash<int, QByteArray> roles; + if (roles.isEmpty()) { + roles = buildRoleNames(); + } + + return roles; +} +#endif + +QHash<int, QByteArray> DirModel::buildRoleNames() const +{ + QHash<int, QByteArray> roles; roles.insert(FileNameRole, QByteArray("fileName")); roles.insert(CreationDateRole, QByteArray("creationDate")); roles.insert(ModifiedDateRole, QByteArray("modifiedDate")); @@ -107,22 +133,25 @@ roles.insert(IsReadableRole, QByteArray("isReadable")); roles.insert(IsWritableRole, QByteArray("isWritable")); roles.insert(IsExecutableRole, QByteArray("isExecutable")); - setRoleNames(roles); // populate reverse mapping - QHash<int, QByteArray>::ConstIterator it = roles.constBegin(); - for (;it != roles.constEnd(); ++it) - mRoleMapping.insert(it.value(), it.key()); + if (roleMapping.isEmpty()) { + QHash<int, QByteArray>::ConstIterator it = roles.constBegin(); + for (;it != roles.constEnd(); ++it) + roleMapping.insert(it.value(), it.key()); + + // make sure we cover all roles + // Q_ASSERT(roles.count() == IsFileRole - FileNameRole); + } - // make sure we cover all roles -// Q_ASSERT(roles.count() == IsFileRole - FileNameRole); + return roles; } QVariant DirModel::data(int row, const QByteArray &stringRole) const { - QHash<QByteArray, int>::ConstIterator it = mRoleMapping.constFind(stringRole); + QHash<QByteArray, int>::ConstIterator it = roleMapping.constFind(stringRole); - if (it == mRoleMapping.constEnd()) + if (it == roleMapping.constEnd()) return QVariant(); return data(index(row, 0), *it); --- folderlistmodel/dirmodel.h +++ folderlistmodel/dirmodel.h @@ -112,12 +112,18 @@ void error(const QString &errorTitle, const QString &errorMessage); private: + QHash<int, QByteArray> buildRoleNames() const; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + // In Qt5, the roleNames() is virtual and will work just fine. On qt4 setRoleNames must be used with buildRoleNames. + QHash<int, QByteArray> roleNames() const; +#endif + QStringList mNameFilters; bool mShowDirectories; bool mAwaitingResults; QString mCurrentDir; QVector<QFileInfo> mDirectoryContents; - QHash<QByteArray, int> mRoleMapping; }; --- social/src/facebook/facebookinterface.cpp +++ social/src/facebook/facebookinterface.cpp @@ -123,7 +123,7 @@ return FacebookInterface::Comment; else if (data.value(FACEBOOK_ONTOLOGY_ALBUM_PRIVACY).isValid() && data.value(FACEBOOK_ONTOLOGY_ALBUM_CANUPLOAD).isValid()) return FacebookInterface::Album; - else if (data.value(FACEBOOK_ONTOLOGY_PHOTO_TAGS).isValid() && data.value(FACEBOOK_ONTOLOGY_PHOTO_SOURCE).isValid()) + else if (data.value(FACEBOOK_ONTOLOGY_PHOTO_WIDTH).isValid() && data.value(FACEBOOK_ONTOLOGY_PHOTO_SOURCE).isValid()) return FacebookInterface::Photo; else if (data.value(FACEBOOK_ONTOLOGY_USER_FIRSTNAME).isValid() || data.value(FACEBOOK_ONTOLOGY_USER_GENDER).isValid()) return FacebookInterface::User; @@ -150,7 +150,10 @@ QUrl retn; retn.setScheme("https"); retn.setHost("graph.facebook.com"); - retn.setPath(objectId + QLatin1String("/") + extraPath); + if (extraPath.isEmpty()) + retn.setPath(objectId); + else + retn.setPath(objectId + QLatin1String("/") + extraPath); retn.setQueryItems(queryItems); return retn; } @@ -254,6 +257,27 @@ error = SocialNetworkInterface::RequestError; errorMessage = QLatin1String("Error populating node: response is invalid. Perhaps the requested object id was incorrect? Response: ") + QString::fromLatin1(replyData.constData()); status = SocialNetworkInterface::Error; + emit q->statusChanged(); + emit q->errorChanged(); + emit q->errorMessageChanged(); + return; + } + + if (responseData.contains(QLatin1String("error"))) { + QString errorResponse = QLatin1String("\n error:"); + QVariantMap errMap = responseData.value(QLatin1String("error")).toMap(); + QStringList keys = errMap.keys(); + foreach (const QString &key, keys) { + errorResponse += QLatin1String("\n ") + key + QLatin1String("=") + errMap.value(key).toString(); + } + qWarning() << Q_FUNC_INFO << "error response:" << errorResponse << "while getting:" << requestUrl.toString(); + + error = SocialNetworkInterface::RequestError; + errorMessage = QLatin1String("Error populating node: response is error. Response: ") + QString::fromLatin1(replyData.constData()); + status = SocialNetworkInterface::Error; + emit q->statusChanged(); + emit q->errorChanged(); + emit q->errorMessageChanged(); return; } @@ -281,7 +305,10 @@ void FacebookInterfacePrivate::errorHandler(QNetworkReply::NetworkError err) { Q_Q(FacebookInterface); - qWarning() << Q_FUNC_INFO << "Error: network error occurred:" << err; + if (err == QNetworkReply::UnknownContentError) { + // ignore this. It's not actually an error, Facebook just formats some responses strangely. + return; + } switch (err) { case QNetworkReply::NoError: errorMessage = QLatin1String("QNetworkReply::NoError"); break; @@ -311,6 +338,8 @@ default: errorMessage = QLatin1String("Unknown QNetworkReply::NetworkError"); break; } + qWarning() << Q_FUNC_INFO << "Error: network error occurred:" << err << ":" << errorMessage; + error = SocialNetworkInterface::RequestError; status = SocialNetworkInterface::Error; @@ -521,7 +550,8 @@ QVariantMap modifiedExtraData = extraData; if (!extraData.contains(QLatin1String("metadata"))) modifiedExtraData.insert(QLatin1String("metadata"), QLatin1String("1")); // request "type" field. - return d->qnam->get(QNetworkRequest(d->requestUrl(objectIdentifier, extraPath, whichFields, extraData))); + QUrl geturl = d->requestUrl(objectIdentifier, extraPath, whichFields, modifiedExtraData); + return d->qnam->get(QNetworkRequest(geturl)); } /*! \reimp */ ++++++ 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.5 +Version: 0.3.6 Release: 1 Sources: - "%{name}-%{version}.tar.bz2"
