Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit beb910b8 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

MessageViewer: use custom Akonadi::Session

Have MessageViewer use a custom Akonadi::Session instead of the
shared default one. This way the MessageViewer will still be able
to show message, even if the default session is currently busy.
This addresses the issue when a long-running operations (like large
moves) block the default session, so that user has to stare at the
"Retrieving folder contents" screen until the operation finishes.

This is not as good as a generic "session pool" solution, but that
introduced various issues in behaviour and consumed more resources.
parent 9356e2fe
......@@ -25,14 +25,16 @@
#include <QTemporaryFile>
#include <QUrl>
#include <AkonadiCore/ItemModifyJob>
#include <AkonadiCore/Session>
#include <KMime/Content>
using namespace MessageViewer;
AttachmentEditJob::AttachmentEditJob(QObject *parent)
AttachmentEditJob::AttachmentEditJob(Akonadi::Session *session, QObject *parent)
: QObject(parent)
, mShowWarning(true)
, mMainWindow(nullptr)
, mSession(session)
{
}
......@@ -97,7 +99,7 @@ void AttachmentEditJob::slotAttachmentEditDone(MessageViewer::EditorWatcher *edi
file.close();
mMessageItem.setPayloadFromData(mMessage->encodedContent());
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem, mSession);
connect(job, &KJob::result, this, &AttachmentEditJob::slotItemModifiedResult);
removeEditorWatcher(editorWatcher, name);
}
......
......@@ -27,13 +27,16 @@
namespace KMime {
class Content;
}
namespace Akonadi {
class Session;
}
namespace MessageViewer {
class EditorWatcher;
class AttachmentEditJob : public QObject
{
Q_OBJECT
public:
explicit AttachmentEditJob(QObject *parent = nullptr);
explicit AttachmentEditJob(Akonadi::Session *session, QObject *parent = nullptr);
~AttachmentEditJob();
void setMainWindow(QWidget *mainWindow);
......@@ -57,6 +60,7 @@ private:
KMime::Message::Ptr mMessage;
bool mShowWarning;
QWidget *mMainWindow;
Akonadi::Session *mSession;
};
}
......
......@@ -21,12 +21,14 @@
#include "messageviewer_debug.h"
#include <AkonadiCore/ItemModifyJob>
#include <AkonadiCore/Session>
#include "viewer/messagedisplayformatattribute.h"
using namespace MessageViewer;
ModifyMessageDisplayFormatJob::ModifyMessageDisplayFormatJob(QObject *parent)
ModifyMessageDisplayFormatJob::ModifyMessageDisplayFormatJob(Akonadi::Session *session, QObject *parent)
: QObject(parent)
, mSession(session)
, mMessageFormat(Viewer::UseGlobalSetting)
, mRemoteContent(false)
, mResetFormat(false)
......@@ -74,7 +76,7 @@ void ModifyMessageDisplayFormatJob::setMessageItem(const Akonadi::Item &messageI
void ModifyMessageDisplayFormatJob::resetDisplayFormat()
{
mMessageItem.removeAttribute<MessageViewer::MessageDisplayFormatAttribute>();
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem, mSession);
modify->setIgnorePayload(true);
modify->disableRevisionCheck();
connect(modify, &KJob::result, this, &ModifyMessageDisplayFormatJob::slotModifyItemDone);
......@@ -87,7 +89,7 @@ void ModifyMessageDisplayFormatJob::modifyDisplayFormat()
Akonadi::Item::AddIfMissing);
attr->setRemoteContent(mRemoteContent);
attr->setMessageFormat(mMessageFormat);
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem, mSession);
modify->setIgnorePayload(true);
modify->disableRevisionCheck();
connect(modify, &KJob::result, this, &ModifyMessageDisplayFormatJob::slotModifyItemDone);
......
......@@ -22,12 +22,15 @@
#include <QObject>
#include "viewer/viewer_p.h"
namespace Akonadi {
class Session;
}
namespace MessageViewer {
class ModifyMessageDisplayFormatJob : public QObject
{
Q_OBJECT
public:
explicit ModifyMessageDisplayFormatJob(QObject *parent = nullptr);
explicit ModifyMessageDisplayFormatJob(Akonadi::Session *session, QObject *parent = nullptr);
~ModifyMessageDisplayFormatJob();
void setRemoteContent(bool remote);
......@@ -41,6 +44,7 @@ private:
void slotModifyItemDone(KJob *job);
void resetDisplayFormat();
void modifyDisplayFormat();
Akonadi::Session *mSession;
Akonadi::Item mMessageItem;
Viewer::DisplayFormatMessage mMessageFormat;
bool mRemoteContent;
......
......@@ -24,6 +24,7 @@
#include "settings/messageviewersettings.h"
#include <AkonadiCore/itemmodifyjob.h>
#include <AkonadiCore/Session>
#include <Akonadi/KMime/MessageFlags>
#include <QTimer>
......@@ -52,7 +53,7 @@ void MarkMessageReadHandler::Private::handleMessages()
// mark as read
item.setFlag(Akonadi::MessageFlags::Seen);
Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob(item, q);
Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob(item, q->session());
modifyJob->disableRevisionCheck();
modifyJob->setIgnorePayload(true);
sListItem->removeAll(item);
......
......@@ -58,6 +58,7 @@ public:
private:
//@cond PRIVATE
class Private;
friend class Private;
Private *const d;
Q_PRIVATE_SLOT(d, void handleMessages())
......
......@@ -48,6 +48,35 @@
#include <QAction>
namespace MessageViewer {
class AbstractMessageLoadedHandler::Private
{
public:
Akonadi::Session *mSession = nullptr;
};
AbstractMessageLoadedHandler::AbstractMessageLoadedHandler()
: d(new Private)
{
}
AbstractMessageLoadedHandler::~AbstractMessageLoadedHandler()
{
delete d;
}
void AbstractMessageLoadedHandler::setSession(Akonadi::Session *session)
{
d->mSession = session;
}
Akonadi::Session *AbstractMessageLoadedHandler::session() const
{
return d->mSession;
}
Viewer::Viewer(QWidget *aParent, QWidget *mainWindow, KActionCollection *actionCollection)
: QWidget(aParent)
, d_ptr(new ViewerPrivate(this, mainWindow, actionCollection))
......@@ -507,7 +536,8 @@ QAbstractItemModel *Viewer::messageTreeModel() const
Akonadi::ItemFetchJob *Viewer::createFetchJob(const Akonadi::Item &item)
{
Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(item);
Q_D(Viewer);
Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(item, d->mSession);
job->fetchScope().fetchAllAttributes();
job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
job->fetchScope().fetchFullPayload(true);
......@@ -524,6 +554,7 @@ void Viewer::addMessageLoadedHandler(AbstractMessageLoadedHandler *handler)
return;
}
handler->setSession(d->mSession);
d->mMessageLoadedHandlers.insert(handler);
}
......
......@@ -65,13 +65,12 @@ class ViewerPrivate;
* An interface to plug in a handler that is called when
* an message item has been loaded into the view.
*/
class Viewer;
class AbstractMessageLoadedHandler
{
public:
virtual ~AbstractMessageLoadedHandler()
{
}
AbstractMessageLoadedHandler();
virtual ~AbstractMessageLoadedHandler();
/**
* This method is called whenever a message item has been loaded
......@@ -80,6 +79,16 @@ public:
* @param item The message item that has been loaded.
*/
virtual void setItem(const Akonadi::Item &item) = 0;
protected:
Akonadi::Session *session() const;
private:
void setSession(Akonadi::Session *session);
friend class Viewer;
class Private;
Private * const d;
};
//TODO(Andras) once only those methods are public that really need to be public, probably export the whole class instead of just some methods
......@@ -301,7 +310,7 @@ public:
* It will set the correct fetch scope.
* You still need to connect to the job's result signal.
*/
static Akonadi::ItemFetchJob *createFetchJob(const Akonadi::Item &item);
Akonadi::ItemFetchJob *createFetchJob(const Akonadi::Item &item);
/**
* Adds a @p handler for actions that will be executed when the message
......
......@@ -219,6 +219,7 @@ ViewerPrivate::ViewerPrivate(Viewer *aParent, QWidget *mainWindow,
, mCurrentContent(nullptr)
, mMessagePartNode(nullptr)
, q(aParent)
, mSession(new Akonadi::Session("MessageViewer-" + QByteArray::number(reinterpret_cast<quintptr>(this)), this))
, mPreviouslyViewedItem(-1)
, mScamDetectionWarning(nullptr)
, mOpenAttachmentFolderWidget(nullptr)
......@@ -280,6 +281,7 @@ ViewerPrivate::ViewerPrivate(Viewer *aParent, QWidget *mainWindow,
// FIXME: Don't use the full payload here when attachment loading on demand is used, just
// like in KMMainWidget::slotMessageActivated().
mMonitor.setSession(mSession);
Akonadi::ItemFetchScope fs;
fs.fetchFullPayload();
fs.fetchAttribute<MailTransport::ErrorAttribute>();
......@@ -464,7 +466,7 @@ bool ViewerPrivate::deleteAttachment(KMime::Content *node, bool showWarning)
mMimePartTree->mimePartModel()->setRoot(modifiedMessage);
#endif
mMessageItem.setPayloadFromData(modifiedMessage->encodedContent());
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem, mSession);
job->disableRevisionCheck();
connect(job, &KJob::result, this, &ViewerPrivate::itemModifiedResult);
return true;
......@@ -481,7 +483,7 @@ void ViewerPrivate::itemModifiedResult(KJob *job)
void ViewerPrivate::editAttachment(KMime::Content *node, bool showWarning)
{
MessageViewer::AttachmentEditJob *job = new MessageViewer::AttachmentEditJob(this);
MessageViewer::AttachmentEditJob *job = new MessageViewer::AttachmentEditJob(mSession, this);
connect(job, &AttachmentEditJob::refreshMessage, this, &ViewerPrivate::slotRefreshMessage);
job->setMainWindow(mMainWindow);
job->setMessageItem(mMessageItem);
......@@ -1006,7 +1008,7 @@ void ViewerPrivate::collectionFetchedForStoringDecryptedMessage(KJob *job)
KMime::Message::Ptr unencryptedMessage = mNodeHelper->unencryptedMessage(mMessage);
if (unencryptedMessage) {
mMessageItem.setPayload<KMime::Message::Ptr>(unencryptedMessage);
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob(mMessageItem, mSession);
connect(job, &KJob::result, this, &ViewerPrivate::itemModifiedResult);
}
}
......@@ -1044,7 +1046,8 @@ void ViewerPrivate::postProcessMessage(MimeTreeParser::ObjectTreeParser *otp,
// on the wrong item!
Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(
Akonadi::Collection::root(),
Akonadi::CollectionFetchJob::Recursive);
Akonadi::CollectionFetchJob::Recursive,
mSession);
connect(job, &KJob::result,
this, &ViewerPrivate::collectionFetchedForStoringDecryptedMessage);
}
......@@ -2788,7 +2791,7 @@ void ViewerPrivate::slotAttachmentEdit()
return;
}
MessageViewer::AttachmentEditJob *job = new MessageViewer::AttachmentEditJob(this);
MessageViewer::AttachmentEditJob *job = new MessageViewer::AttachmentEditJob(mSession, this);
connect(job, &AttachmentEditJob::refreshMessage, this, &ViewerPrivate::slotRefreshMessage);
job->setMainWindow(mMainWindow);
job->setMessageItem(mMessageItem);
......@@ -3198,7 +3201,7 @@ void ViewerPrivate::slotSaveMessageDisplayFormat()
{
if (mMessageItem.isValid()) {
MessageViewer::ModifyMessageDisplayFormatJob *job
= new MessageViewer::ModifyMessageDisplayFormatJob(this);
= new MessageViewer::ModifyMessageDisplayFormatJob(mSession, this);
job->setMessageFormat(displayFormatMessageOverwrite());
job->setMessageItem(mMessageItem);
job->setRemoteContent(htmlLoadExtOverride());
......@@ -3211,7 +3214,7 @@ void ViewerPrivate::slotResetMessageDisplayFormat()
if (mMessageItem.isValid()) {
if (mMessageItem.hasAttribute<MessageViewer::MessageDisplayFormatAttribute>()) {
MessageViewer::ModifyMessageDisplayFormatJob *job
= new MessageViewer::ModifyMessageDisplayFormatJob(this);
= new MessageViewer::ModifyMessageDisplayFormatJob(mSession, this);
job->setMessageItem(mMessageItem);
job->setResetFormat(true);
job->start();
......@@ -3250,7 +3253,7 @@ void ViewerPrivate::slotMessageIsNotAScam()
MessageViewer::ScamAttribute *attr = mMessageItem.attribute<MessageViewer::ScamAttribute>(
Akonadi::Item::AddIfMissing);
attr->setIsAScam(false);
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem);
Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob(mMessageItem, mSession);
modify->setIgnorePayload(true);
modify->disableRevisionCheck();
connect(modify, &KJob::result, this, &ViewerPrivate::slotModifyItemDone);
......
......@@ -30,6 +30,7 @@
#include <AkonadiCore/item.h>
#include <AkonadiCore/monitor.h>
#include <AkonadiCore/session.h>
#include <kio/job.h>
#include <KMime/Message>
#include <kservice.h>
......@@ -682,6 +683,7 @@ public:
QColor mBackgroundError;
Viewer *const q;
Akonadi::Session *mSession;
Akonadi::Monitor mMonitor;
QSet<AbstractMessageLoadedHandler *> mMessageLoadedHandlers;
Akonadi::Item::Id mPreviouslyViewedItem;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment