Skip to content

Commit

Permalink
Merge branch 'jb47389' into 'master'
Browse files Browse the repository at this point in the history
Apply folder sync options before sync

See merge request mer-core/nemo-qml-plugin-email!65
  • Loading branch information
llewelld committed Feb 20, 2020
2 parents c6282d1 + d76bd7c commit 5a4d990
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 8 deletions.
1 change: 1 addition & 0 deletions rpm/nemo-qml-plugin-email-qt5.spec
Expand Up @@ -17,6 +17,7 @@ BuildRequires: pkgconfig(Qt5Concurrent)
BuildRequires: pkgconfig(Qt5Test)
BuildRequires: pkgconfig(QmfMessageServer)
BuildRequires: pkgconfig(QmfClient)
BuildRequires: pkgconfig(accounts-qt5)
Conflicts: nemo-qml-plugin-email-qt5-offline

%description
Expand Down
86 changes: 84 additions & 2 deletions src/emailagent.cpp
@@ -1,7 +1,7 @@
/*
* Copyright 2011 Intel Corporation.
* Copyright (C) 2012-2019 Jolla Ltd.
* Copyright (c) 2019 Open Mobile Platform LLC.
* Copyright (c) 2012 - 2020 Jolla Ltd.
* Copyright (c) 2019 - 2020 Open Mobile Platform LLC.
*
* This program is licensed under the terms and conditions of the
* Apache License, version 2.0. The full text of the Apache License is at
Expand Down Expand Up @@ -30,6 +30,10 @@
#include "folderaccessor.h"
#include "logging_p.h"

// accounts-qt5
#include <Accounts/Manager>
#include <Accounts/Account>

namespace {

QMailAccountId accountForMessageId(const QMailMessageId &msgId)
Expand Down Expand Up @@ -592,6 +596,20 @@ void EmailAgent::accountsSync(bool syncOnlyInbox, uint minimum)
}
}

// Sync all accounts (both ways), just the inboxes
// See also accountsSyncAllFolders(uint minimum)
void EmailAgent::accountsSyncInbox(uint minimum)
{
accountsSync(true, minimum);
}

// Sync all accounts (both ways), all folders
// See also accountsSyncInbox(uint minimum)
void EmailAgent::accountsSyncAllFolders(uint minimum)
{
accountsSync(false, minimum);
}

void EmailAgent::createFolder(const QString &name, int mailAccountId, int parentFolderId)
{
if (name.isEmpty()) {
Expand Down Expand Up @@ -922,6 +940,8 @@ void EmailAgent::retrieveMessageList(int accountId, int folderId, uint minimum)
QMailAccountId acctId(accountId);
QMailFolderId foldId(folderId);

applyFolderSyncPolicy(accountId);

if (acctId.isValid()) {
enqueue(new RetrieveMessageList(m_retrievalAction.data(), acctId, foldId, minimum));
}
Expand Down Expand Up @@ -949,6 +969,8 @@ void EmailAgent::synchronize(int accountId, uint minimum)
return;
}

applyFolderSyncPolicy(accountId);

bool messagesToSend = hasMessagesInOutbox(acctId);
if (messagesToSend) {
m_enqueing = true;
Expand All @@ -969,6 +991,8 @@ void EmailAgent::synchronizeInbox(int accountId, uint minimum)
return;
}

applyFolderSyncPolicy(accountId);

QMailAccount account(acctId);
QMailFolderId foldId = account.standardFolder(QMailFolder::InboxFolder);
if (foldId.isValid()) {
Expand All @@ -987,6 +1011,7 @@ void EmailAgent::synchronizeInbox(int accountId, uint minimum)
}

} else { //Account was never synced, retrieve list of folders and come back here.

connect(this, &EmailAgent::standardFoldersCreated,
this, [=](const QMailAccountId &acctId) {
QMailAccount account(acctId);
Expand All @@ -1005,6 +1030,63 @@ void EmailAgent::synchronizeInbox(int accountId, uint minimum)
}
}

static bool isAncestorFolder(const QMailFolder &folder, const QMailFolderId &ancestor)
{
if (folder.status() & QMailFolder::NonMail) {
return false;
}
QMailFolderId parentId = folder.parentFolderId();
if (!parentId.isValid()) {
return false;
} else {
return parentId == ancestor
|| isAncestorFolder(QMailFolder(parentId), ancestor);
}
}

void EmailAgent::applyFolderSyncPolicy(int accountId)
{
Accounts::Manager accountManager;
Accounts::Account *accountConfig = accountManager.account(accountId);
QString folderSyncPolicy;
if (accountConfig) {
accountConfig->selectService(accountManager.service(QString()));
folderSyncPolicy = accountConfig->valueAsString(QStringLiteral("folderSyncPolicy"));
}

QMailAccountId mailId(accountId);
if (mailId.isValid()) {
bool all = (folderSyncPolicy == QLatin1String("all-folders"));
bool subfolders = (folderSyncPolicy == QLatin1String("inbox-and-subfolders"));
bool inbox = (folderSyncPolicy == QLatin1Literal("inbox"));
// If no flag is set, leave the SynchronizationEnabled status as it is
// to allow a custom combination to be chosen by the user
if (all || subfolders || inbox) {
// Ensure that synchronization flag is set
// for inbox and subfolders or for all.
QMailAccount account(mailId);
QMailFolderId syncFolderId = account.standardFolder(QMailFolder::InboxFolder);
if (all || syncFolderId.isValid()) {
QMailFolderKey key = QMailFolderKey::parentAccountId(mailId);
QList<QMailFolderId> folders = QMailStore::instance()->queryFolders(key);
for (QList<QMailFolderId>::ConstIterator it = folders.constBegin();
it != folders.constEnd(); ++it) {
if (it->isValid()) {
QMailFolder folder(*it);
bool status = all
|| *it == syncFolderId
|| (subfolders && isAncestorFolder(folder, syncFolderId));
folder.setStatus(QMailFolder::SynchronizationEnabled, status);
QMailStore::instance()->updateFolder(&folder);
}
}
} else {
qCWarning(lcEmail) << "Email account has no inbox.";
}
}
}
}

void EmailAgent::respondToCalendarInvitation(int messageId, CalendarInvitationResponse response,
const QString &responseSubject)
{
Expand Down
9 changes: 6 additions & 3 deletions src/emailagent.h
@@ -1,7 +1,7 @@
/*
* Copyright 2011 Intel Corporation.
* Copyright (C) 2012-2019 Jolla Ltd.
* Copyright (c) 2019 Open Mobile Platform LLC.
* Copyright (c) 2012 - 2019 Jolla Ltd.
* Copyright (c) 2019 - 2020 Open Mobile Platform LLC.
*
* This program is licensed under the terms and conditions of the
* Apache License, version 2.0. The full text of the Apache License is at
Expand Down Expand Up @@ -113,7 +113,8 @@ class Q_DECL_EXPORT EmailAgent : public QObject
void setupAccountFlags();
int standardFolderId(int accountId, QMailFolder::StandardFolder folder) const;

Q_INVOKABLE void accountsSync(bool syncOnlyInbox = false, uint minimum = 20);
Q_INVOKABLE void accountsSyncInbox(uint minimum = 20);
Q_INVOKABLE void accountsSyncAllFolders(uint minimum = 20);
Q_INVOKABLE void createFolder(const QString &name, int mailAccountId, int parentFolderId);
Q_INVOKABLE void deleteFolder(int folderId);
Q_INVOKABLE void deleteMessage(int messageId);
Expand Down Expand Up @@ -218,6 +219,7 @@ private slots:
// Holds a list of the attachments currently downloading or queued for download
QHash<QString, AttachmentInfo> m_attachmentDownloadQueue;

void accountsSync(bool syncOnlyInbox = false, uint minimum = 20);
bool actionInQueue(QSharedPointer<EmailAction> action) const;
quint64 actionInQueueId(QSharedPointer<EmailAction> action) const;
void dequeue();
Expand All @@ -234,6 +236,7 @@ private slots:
void emitSearchStatusChanges(QSharedPointer<EmailAction> action, EmailAgent::SearchStatus status);
bool easCalendarInvitationResponse(const QMailMessage &message, CalendarInvitationResponse response,
const QString &responseSubject);
void applyFolderSyncPolicy(int accountId);
};

#endif
136 changes: 136 additions & 0 deletions src/folderlistfiltertypemodel.cpp
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2020 Jolla Ltd.
* Copyright (c) 2020 Open Mobile Platform LLC.
*
* This program is licensed under the terms and conditions of the
* Apache License, version 2.0. The full text of the Apache License is at
* http://www.apache.org/licenses/LICENSE-2.0
*/

#include <QTimerEvent>

#include "folderlistfiltertypemodel.h"
#include "folderlistmodel.h"

FolderListFilterTypeModel::FolderListFilterTypeModel(QObject *parent) :
QSortFilterProxyModel(parent),
m_count(0),
m_syncFolderList(),
updateSyncFolderListTimer(-1)
{
// Default to email folders
m_typeFilter << EmailFolder::NormalFolder << EmailFolder::InboxFolder;

m_folderModel = new FolderListModel(this);
setSourceModel(m_folderModel);
connect(m_folderModel, &FolderListModel::accountKeyChanged, this, &FolderListFilterTypeModel::accountKeyChanged);
connect(m_folderModel, &FolderListModel::rowsInserted, this, &FolderListFilterTypeModel::updateData);
connect(m_folderModel, &FolderListModel::rowsRemoved, this, &FolderListFilterTypeModel::updateData);
connect(m_folderModel, &FolderListModel::dataChanged, this, &FolderListFilterTypeModel::updateData);
connect(m_folderModel, &FolderListModel::rowsMoved, this, &FolderListFilterTypeModel::updateData);
connect(m_folderModel, &FolderListModel::modelReset, this, &FolderListFilterTypeModel::updateData);
}

bool FolderListFilterTypeModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
Q_UNUSED(source_parent)

if (sourceModel()) {
EmailFolder::FolderType type = static_cast<EmailFolder::FolderType>
(sourceModel()->index(source_row, 0).data(FolderListModel::FolderType).toInt());
return m_typeFilter.contains(type);
}
return false;
}

int FolderListFilterTypeModel::count() const
{
return m_count;
}

void FolderListFilterTypeModel::updateData()
{
if (m_count != rowCount()) {
m_count = rowCount();
emit countChanged();
}

if (updateSyncFolderListTimer != -1) {
killTimer(updateSyncFolderListTimer);
}
// Avoid updating the sync folder list on every signal
updateSyncFolderListTimer = startTimer(100);
}

void FolderListFilterTypeModel::timerEvent(QTimerEvent * event)
{
if (event->timerId() == updateSyncFolderListTimer) {
killTimer(updateSyncFolderListTimer);
updateSyncFolderListTimer = -1;
updateSyncFolderList();
}
}

void FolderListFilterTypeModel::updateSyncFolderList()
{
QStringList syncFolderList;
for (int i = 0; i < sourceModel()->rowCount(); ++i) {
bool sync = sourceModel()->index(i, 0).data(FolderListModel::FolderSyncEnabled).toBool();
if (sync) {
EmailFolder::FolderType type = static_cast<EmailFolder::FolderType>
(sourceModel()->index(i, 0).data(FolderListModel::FolderType).toInt());
if (m_typeFilter.contains(type)) {
QString name = sourceModel()->index(i, 0).data(FolderListModel::FolderName).toString();
syncFolderList += name;
}
}
}

if (m_syncFolderList != syncFolderList) {
m_syncFolderList = syncFolderList;
emit syncFolderListChanged();
}
}

void FolderListFilterTypeModel::setAccountKey(int id)
{
m_folderModel->setAccountKey(id);
}

int FolderListFilterTypeModel::accountKey() const
{
return m_folderModel->accountKey();
}

const QStringList & FolderListFilterTypeModel::syncFolderList() const
{
return m_syncFolderList;
}

QList<int> FolderListFilterTypeModel::typeFilter() const
{
QList<int> types;

for (EmailFolder::FolderType type : m_typeFilter) {
types << type;
}

return types;
}

void FolderListFilterTypeModel::setTypeFilter(QList<int> typeFilter)
{
QSet<EmailFolder::FolderType> types;
for (int type : typeFilter) {
types << static_cast<EmailFolder::FolderType>(type);
}

if (types != m_typeFilter) {
m_typeFilter = types;

emit typeFilterChanged();
invalidateFilter();
updateData();
}
}

66 changes: 66 additions & 0 deletions src/folderlistfiltertypemodel.h
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 Jolla Ltd.
* Copyright (c) 2020 Open Mobile Platform LLC.
*
* This program is licensed under the terms and conditions of the
* Apache License, version 2.0. The full text of the Apache License is at
* http://www.apache.org/licenses/LICENSE-2.0
*/

#ifndef FOLDERLISTFILTERTYPEMODEL_H
#define FOLDERLISTFILTERTYPEMODEL_H

#include <QSet>
#include <QStringList>
#include <QSortFilterProxyModel>

#include <emailfolder.h>

class FolderListModel;

// Filters the folder list by type
// By default shows only the email folders
class Q_DECL_EXPORT FolderListFilterTypeModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QStringList syncFolderList READ syncFolderList NOTIFY syncFolderListChanged)
Q_PROPERTY(int accountKey READ accountKey WRITE setAccountKey NOTIFY accountKeyChanged FINAL)
Q_PROPERTY(QList<int> typeFilter READ typeFilter WRITE setTypeFilter NOTIFY typeFilterChanged FINAL)

public:
explicit FolderListFilterTypeModel(QObject *parent = 0);

virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;

void setAccountKey(int id);
int accountKey() const;
int count() const;
const QStringList &syncFolderList() const;
QList<int> typeFilter() const;
void setTypeFilter(QList<int> typeFilter);

signals:
void accountKeyChanged();
void countChanged();
void syncFolderListChanged();
void typeFilterChanged();

private slots:
void updateData();

protected:
void timerEvent(QTimerEvent * event) override;

private:
void updateSyncFolderList();

private:
int m_count;
QStringList m_syncFolderList;
FolderListModel *m_folderModel;
QSet<EmailFolder::FolderType> m_typeFilter;
int updateSyncFolderListTimer;
};

#endif
1 change: 1 addition & 0 deletions src/folderlistmodel.h
Expand Up @@ -68,6 +68,7 @@ class Q_DECL_EXPORT FolderListModel : public QAbstractListModel
void supportsFolderActionsChanged();
void resyncNeeded();
void accountKeyChanged();
void countChanged();

protected:
virtual QHash<int, QByteArray> roleNames() const;
Expand Down

0 comments on commit 5a4d990

Please sign in to comment.