You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

282 lines
11 KiB

/*
SPDX-FileCopyrightText: 2020-2021 Laurent Montel <montel@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "collectionexpirywidget.h"
#include "attributes/expirecollectionattribute.h"
#include "collectionexpiryjob.h"
#include "folder/foldersettings.h"
#include "folderrequester.h"
#include "kernel/mailkernel.h"
#include "mailcommon_debug.h"
#include "util/mailutil.h"
#include <Akonadi/CollectionModifyJob>
#include <KMessageBox>
#include <KPluralHandlingSpinBox>
#include <QCheckBox>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QPushButton>
#include <QRadioButton>
using namespace MailCommon;
class DaysSpinBox : public KPluralHandlingSpinBox
{
public:
DaysSpinBox(QWidget *parent)
: KPluralHandlingSpinBox(parent)
{
setMaximum(999999);
setSuffix(ki18ncp("Expire messages after %1", " day", " days"));
setSpecialValueText(i18n("Never"));
}
QString textFromValue(int value) const override
{
if (value == 0) {
return i18n("Never");
}
return KPluralHandlingSpinBox::textFromValue(value);
}
int valueFromText(const QString &text) const override
{
return KPluralHandlingSpinBox::valueFromText(text);
}
QValidator::State validate(QString &text, int &pos) const override
{
if (text == i18n("Never")) {
return QValidator::Acceptable;
}
return KPluralHandlingSpinBox::validate(text, pos);
}
};
CollectionExpiryWidget::CollectionExpiryWidget(QWidget *parent)
: QWidget(parent)
, mExpireReadMailSB(new DaysSpinBox(this))
, mExpireUnreadMailSB(new DaysSpinBox(this))
, mFolderSelector(new FolderRequester(this))
, mExpireNowPB(new QPushButton(i18n("Save Settings and Expire Now"), this))
, mExpireMailWithInvalidDateCB(new QCheckBox(i18n("Expire messages with invalid date"), this))
{
auto formLayout = new QFormLayout(this);
formLayout->setContentsMargins({});
connect(mExpireReadMailSB, &KPluralHandlingSpinBox::valueChanged, this, &CollectionExpiryWidget::slotChanged);
formLayout->addRow(i18n("Expire read messages after:"), mExpireReadMailSB);
connect(mExpireUnreadMailSB, &KPluralHandlingSpinBox::valueChanged, this, &CollectionExpiryWidget::slotChanged);
formLayout->addRow(i18n("Expire unread messages after:"), mExpireUnreadMailSB);
connect(mExpireMailWithInvalidDateCB, &QCheckBox::toggled, this, &CollectionExpiryWidget::slotChanged);
formLayout->addRow(QString(), mExpireMailWithInvalidDateCB);
auto actionsGroup = new QGroupBox(this);
actionsGroup->setFlat(true); // for mutual exclusion of the radio buttons
formLayout->addRow(actionsGroup);
auto moveToHBox = new QHBoxLayout();
moveToHBox->setContentsMargins({});
moveToHBox->setSpacing(6);
mMoveToRB = new QRadioButton(actionsGroup);
mMoveToRB->setText(i18n("Move expired messages to:"));
connect(mMoveToRB, &QRadioButton::toggled, this, &CollectionExpiryWidget::slotChanged);
moveToHBox->addWidget(mMoveToRB);
mFolderSelector->setMustBeReadWrite(true);
mFolderSelector->setShowOutbox(false);
moveToHBox->addWidget(mFolderSelector);
formLayout->addRow(QString(), moveToHBox);
connect(mFolderSelector, &FolderRequester::folderChanged, this, &CollectionExpiryWidget::slotChanged);
mDeletePermanentlyRB = new QRadioButton(actionsGroup);
mDeletePermanentlyRB->setText(i18n("Delete expired messages permanently"));
connect(mDeletePermanentlyRB, &QRadioButton::toggled, this, &CollectionExpiryWidget::slotChanged);
formLayout->addRow(QString(), mDeletePermanentlyRB);
connect(mExpireNowPB, &QPushButton::clicked, this, &CollectionExpiryWidget::saveAndExpireRequested);
formLayout->addRow(QString(), mExpireNowPB);
mDeletePermanentlyRB->setChecked(true);
slotChanged();
}
CollectionExpiryWidget::~CollectionExpiryWidget()
{
}
void CollectionExpiryWidget::hideExpireNowButton()
{
mExpireNowPB->setVisible(false);
}
void CollectionExpiryWidget::slotChanged()
{
const bool showExpiryActions = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
mMoveToRB->setEnabled(showExpiryActions);
mFolderSelector->setEnabled(showExpiryActions && mMoveToRB->isChecked());
mDeletePermanentlyRB->setEnabled(showExpiryActions);
mExpireNowPB->setEnabled(showExpiryActions);
Q_EMIT configChanged();
}
void CollectionExpiryWidget::load(const MailCommon::CollectionExpirySettings &settings)
{
if (settings.isValid()) {
bool expiryGloballyOn = settings.expiryGloballyOn;
if (expiryGloballyOn && settings.mReadExpireUnits != ExpireCollectionAttribute::ExpireNever && settings.daysToExpireRead >= 0) {
mExpireReadMailSB->setValue(settings.daysToExpireRead);
} else {
mExpireReadMailSB->setValue(0);
}
if (expiryGloballyOn && settings.mUnreadExpireUnits != ExpireCollectionAttribute::ExpireNever && settings.daysToExpireUnread >= 0) {
mExpireUnreadMailSB->setValue(settings.daysToExpireUnread);
} else {
mExpireUnreadMailSB->setValue(0);
}
if (settings.mExpireAction == ExpireCollectionAttribute::ExpireDelete) {
mDeletePermanentlyRB->setChecked(true);
} else {
mMoveToRB->setChecked(true);
}
mExpireMailWithInvalidDateCB->setChecked(settings.expiryMessagesWithInvalidDate);
Akonadi::Collection::Id destFolderID = settings.mExpireToFolderId;
if (destFolderID > 0) {
Akonadi::Collection destFolder = Kernel::self()->collectionFromId(destFolderID);
if (destFolder.isValid()) {
mFolderSelector->setCollection(destFolder);
}
}
} else {
mDeletePermanentlyRB->setChecked(true);
}
slotChanged();
}
bool CollectionExpiryWidget::validateExpireFolder(bool expireNow)
{
const bool enableGlobally = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
const Akonadi::Collection expireToFolder = mFolderSelector->collection();
if (enableGlobally && mMoveToRB->isChecked() && !expireToFolder.isValid()) {
KMessageBox::error(this,
i18n("Please select a folder to expire messages into.\nIf this is not done, expired messages will be permanently deleted."),
i18n("No Folder Selected"));
mDeletePermanentlyRB->setChecked(true);
expireNow = false; // settings are not valid
}
return expireNow;
}
MailCommon::ExpireCollectionAttribute *CollectionExpiryWidget::assignFolderAttribute(Akonadi::Collection &collection, bool &expireNow)
{
const Akonadi::Collection expireToFolder = mFolderSelector->collection();
MailCommon::ExpireCollectionAttribute *attribute = nullptr;
if (expireToFolder.isValid() && mMoveToRB->isChecked()) {
if (expireToFolder.id() == collection.id()) {
KMessageBox::error(this,
i18n("Please select a different folder than the current folder to expire messages into.\nIf this is not done, expired messages "
"will be permanently deleted."),
i18n("Wrong Folder Selected"));
mDeletePermanentlyRB->setChecked(true);
expireNow = false; // settings are not valid
} else {
attribute = collection.attribute<MailCommon::ExpireCollectionAttribute>(Akonadi::Collection::AddIfMissing);
attribute->setExpireToFolderId(expireToFolder.id());
}
}
if (!attribute) {
attribute = collection.attribute<MailCommon::ExpireCollectionAttribute>(Akonadi::Collection::AddIfMissing);
}
return attribute;
}
CollectionExpirySettings CollectionExpiryWidget::settings() const
{
CollectionExpirySettings settings;
settings.expiryGloballyOn = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
settings.expiryMessagesWithInvalidDate = mExpireMailWithInvalidDateCB->isChecked();
// we always write out days now
settings.daysToExpireRead = mExpireReadMailSB->value();
settings.daysToExpireUnread = mExpireUnreadMailSB->value();
settings.mReadExpireUnits =
mExpireReadMailSB->value() != 0 ? MailCommon::ExpireCollectionAttribute::ExpireDays : MailCommon::ExpireCollectionAttribute::ExpireNever;
settings.mUnreadExpireUnits =
mExpireUnreadMailSB->value() != 0 ? MailCommon::ExpireCollectionAttribute::ExpireDays : MailCommon::ExpireCollectionAttribute::ExpireNever;
if (mDeletePermanentlyRB->isChecked()) {
settings.mExpireAction = ExpireCollectionAttribute::ExpireDelete;
} else {
settings.mExpireAction = ExpireCollectionAttribute::ExpireMove;
}
return settings;
}
void CollectionExpiryWidget::save(const CollectionExpirySettings &collectionExpirySettings, Akonadi::Collection &collection, bool saveSettings, bool expireNow)
{
expireNow = validateExpireFolder(expireNow);
MailCommon::ExpireCollectionAttribute *attribute = assignFolderAttribute(collection, expireNow);
attribute->setAutoExpire(collectionExpirySettings.expiryGloballyOn);
// we always write out days now
attribute->setReadExpireAge(collectionExpirySettings.daysToExpireRead);
attribute->setUnreadExpireAge(collectionExpirySettings.daysToExpireUnread);
attribute->setReadExpireUnits(collectionExpirySettings.mReadExpireUnits);
attribute->setUnreadExpireUnits(collectionExpirySettings.mUnreadExpireUnits);
attribute->setExpireAction(collectionExpirySettings.mExpireAction);
if (saveSettings) {
auto job = new CollectionExpiryJob;
job->setExpireNow(expireNow);
job->setCollection(collection);
job->start();
} else {
if (expireNow) {
MailCommon::Util::expireOldMessages(collection, true /*immediate*/);
}
}
Q_EMIT configChanged(false);
}
void CollectionExpiryWidget::save(Akonadi::Collection &collection, bool saveSettings, bool expireNow)
{
const CollectionExpirySettings collectionExpirySettings = settings();
save(collectionExpirySettings, collection, saveSettings, expireNow);
}
bool CollectionExpiryWidget::canHandle(const Akonadi::Collection &col)
{
QSharedPointer<FolderSettings> fd = FolderSettings::forCollection(col, false);
return fd->canDeleteMessages() && !fd->isStructural() && !MailCommon::Util::isVirtualCollection(col);
}
bool CollectionExpirySettings::isValid() const
{
const bool valid = daysToExpireRead != -1 || daysToExpireUnread != -1 || mUnreadExpireUnits != ExpireCollectionAttribute::ExpireNever
|| mReadExpireUnits != ExpireCollectionAttribute::ExpireNever || mExpireAction != ExpireCollectionAttribute::ExpireDelete || mExpireToFolderId != -1;
return valid;
}
QDebug operator<<(QDebug d, const CollectionExpirySettings &t)
{
d << " expiryGloballyOn " << t.expiryGloballyOn;
d << " expiryMessagesWithInvalidDate " << t.expiryMessagesWithInvalidDate;
d << " daysToExpireRead " << t.daysToExpireRead;
d << " daysToExpireUnread " << t.daysToExpireUnread;
d << " mUnreadExpireUnits " << t.mUnreadExpireUnits;
d << " mReadExpireUnits " << t.mReadExpireUnits;
d << " mExpireAction " << t.mExpireAction;
d << " mExpireToFolderId " << t.mExpireToFolderId;
return d;
}