Mailcommon

collectionexpirywidget.cpp
1/*
2 SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "collectionexpirywidget.h"
8#include "attributes/expirecollectionattribute.h"
9#include "collectionexpiryjob.h"
10#include "folder/foldersettings.h"
11#include "folderrequester.h"
12#include "kernel/mailkernel.h"
13#include "util/mailutil.h"
14
15#include <Akonadi/CollectionModifyJob>
16
17#include <KMessageBox>
18#include <KPluralHandlingSpinBox>
19#include <QCheckBox>
20#include <QFormLayout>
21#include <QGroupBox>
22#include <QHBoxLayout>
23#include <QPushButton>
24#include <QRadioButton>
25
26using namespace MailCommon;
27
28class DaysSpinBox : public KPluralHandlingSpinBox
29{
30public:
31 DaysSpinBox(QWidget *parent)
33 {
34 setMaximum(999999);
35 setSuffix(ki18ncp("Expire messages after %1", " day", " days"));
36 setSpecialValueText(i18n("Never"));
37 }
38
39 [[nodiscard]] QString textFromValue(int value) const override
40 {
41 if (value == 0) {
42 return i18n("Never");
43 }
45 }
46
47 [[nodiscard]] int valueFromText(const QString &text) const override
48 {
50 }
51
52 QValidator::State validate(QString &text, int &pos) const override
53 {
54 if (text == i18n("Never")) {
56 }
58 }
59};
60
61CollectionExpiryWidget::CollectionExpiryWidget(QWidget *parent)
62 : QWidget(parent)
63 , mExpireReadMailSB(new DaysSpinBox(this))
64 , mExpireUnreadMailSB(new DaysSpinBox(this))
65 , mFolderSelector(new FolderRequester(this))
66 , mExpireNowPB(new QPushButton(i18n("Save Settings and Expire Now"), this))
67 , mExpireMailWithInvalidDateCB(new QCheckBox(i18n("Expire messages with invalid date"), this))
68{
69 auto formLayout = new QFormLayout(this);
70 formLayout->setContentsMargins({});
71
72 connect(mExpireReadMailSB, &KPluralHandlingSpinBox::valueChanged, this, &CollectionExpiryWidget::slotChanged);
73 formLayout->addRow(i18n("Expire read messages after:"), mExpireReadMailSB);
74
75 connect(mExpireUnreadMailSB, &KPluralHandlingSpinBox::valueChanged, this, &CollectionExpiryWidget::slotChanged);
76 formLayout->addRow(i18n("Expire unread messages after:"), mExpireUnreadMailSB);
77
78 connect(mExpireMailWithInvalidDateCB, &QCheckBox::toggled, this, &CollectionExpiryWidget::slotChanged);
79 formLayout->addRow(QString(), mExpireMailWithInvalidDateCB);
80
81 auto actionsGroup = new QGroupBox(this);
82 actionsGroup->setFlat(true); // for mutual exclusion of the radio buttons
83 formLayout->addRow(actionsGroup);
84
85 auto moveToHBox = new QHBoxLayout();
86 moveToHBox->setContentsMargins({});
87 moveToHBox->setSpacing(6);
88
89 mMoveToRB = new QRadioButton(actionsGroup);
90 mMoveToRB->setText(i18n("Move expired messages to:"));
91 connect(mMoveToRB, &QRadioButton::toggled, this, &CollectionExpiryWidget::slotChanged);
92 moveToHBox->addWidget(mMoveToRB);
93
94 mFolderSelector->setMustBeReadWrite(true);
95 mFolderSelector->setShowOutbox(false);
96 moveToHBox->addWidget(mFolderSelector);
97 formLayout->addRow(QString(), moveToHBox);
98 connect(mFolderSelector, &FolderRequester::folderChanged, this, &CollectionExpiryWidget::slotChanged);
99
100 mDeletePermanentlyRB = new QRadioButton(actionsGroup);
101 mDeletePermanentlyRB->setText(i18n("Delete expired messages permanently"));
102 connect(mDeletePermanentlyRB, &QRadioButton::toggled, this, &CollectionExpiryWidget::slotChanged);
103
104 formLayout->addRow(QString(), mDeletePermanentlyRB);
105
106 connect(mExpireNowPB, &QPushButton::clicked, this, &CollectionExpiryWidget::saveAndExpireRequested);
107 formLayout->addRow(QString(), mExpireNowPB);
108
109 mDeletePermanentlyRB->setChecked(true);
110 slotChanged();
111}
112
113CollectionExpiryWidget::~CollectionExpiryWidget() = default;
114
115void CollectionExpiryWidget::hideExpireNowButton()
116{
117 mExpireNowPB->setVisible(false);
118}
119
120void CollectionExpiryWidget::slotChanged()
121{
122 const bool showExpiryActions = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
123 mMoveToRB->setEnabled(showExpiryActions);
124 mFolderSelector->setEnabled(showExpiryActions && mMoveToRB->isChecked());
125 mDeletePermanentlyRB->setEnabled(showExpiryActions);
126 mExpireNowPB->setEnabled(showExpiryActions);
127
128 Q_EMIT configChanged();
129}
130
131void CollectionExpiryWidget::load(const MailCommon::CollectionExpirySettings &settings)
132{
133 if (settings.isValid()) {
134 bool expiryGloballyOn = settings.expiryGloballyOn;
135 if (expiryGloballyOn && settings.mReadExpireUnits != ExpireCollectionAttribute::ExpireNever && settings.daysToExpireRead >= 0) {
136 mExpireReadMailSB->setValue(settings.daysToExpireRead);
137 } else {
138 mExpireReadMailSB->setValue(0);
139 }
140 if (expiryGloballyOn && settings.mUnreadExpireUnits != ExpireCollectionAttribute::ExpireNever && settings.daysToExpireUnread >= 0) {
141 mExpireUnreadMailSB->setValue(settings.daysToExpireUnread);
142 } else {
143 mExpireUnreadMailSB->setValue(0);
144 }
145
146 if (settings.mExpireAction == ExpireCollectionAttribute::ExpireDelete) {
147 mDeletePermanentlyRB->setChecked(true);
148 } else {
149 mMoveToRB->setChecked(true);
150 }
151
152 mExpireMailWithInvalidDateCB->setChecked(settings.expiryMessagesWithInvalidDate);
153 Akonadi::Collection::Id destFolderID = settings.mExpireToFolderId;
154 if (destFolderID > 0) {
155 Akonadi::Collection destFolder = Kernel::self()->collectionFromId(destFolderID);
156 if (destFolder.isValid()) {
157 mFolderSelector->setCollection(destFolder);
158 }
159 }
160 } else {
161 mDeletePermanentlyRB->setChecked(true);
162 }
163 slotChanged();
164}
165
166bool CollectionExpiryWidget::validateExpireFolder(bool expireNow)
167{
168 const bool enableGlobally = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
169 const Akonadi::Collection expireToFolder = mFolderSelector->collection();
170 if (enableGlobally && mMoveToRB->isChecked() && !expireToFolder.isValid()) {
172 i18n("Please select a folder to expire messages into.\nIf this is not done, expired messages will be permanently deleted."),
173 i18n("No Folder Selected"));
174 mDeletePermanentlyRB->setChecked(true);
175 expireNow = false; // settings are not valid
176 }
177 return expireNow;
178}
179
180MailCommon::ExpireCollectionAttribute *CollectionExpiryWidget::assignFolderAttribute(Akonadi::Collection &collection, bool &expireNow)
181{
182 const Akonadi::Collection expireToFolder = mFolderSelector->collection();
183 MailCommon::ExpireCollectionAttribute *attribute = nullptr;
184 if (expireToFolder.isValid() && mMoveToRB->isChecked()) {
185 if (expireToFolder.id() == collection.id()) {
187 i18n("Please select a different folder than the current folder to expire messages into.\nIf this is not done, expired messages "
188 "will be permanently deleted."),
189 i18n("Wrong Folder Selected"));
190 mDeletePermanentlyRB->setChecked(true);
191 expireNow = false; // settings are not valid
192 } else {
193 attribute = collection.attribute<MailCommon::ExpireCollectionAttribute>(Akonadi::Collection::AddIfMissing);
194 attribute->setExpireToFolderId(expireToFolder.id());
195 }
196 }
197 if (!attribute) {
198 attribute = collection.attribute<MailCommon::ExpireCollectionAttribute>(Akonadi::Collection::AddIfMissing);
199 }
200 return attribute;
201}
202
203CollectionExpirySettings CollectionExpiryWidget::settings() const
204{
205 CollectionExpirySettings settings;
206 settings.expiryGloballyOn = mExpireReadMailSB->value() != 0 || mExpireUnreadMailSB->value() != 0;
207 settings.expiryMessagesWithInvalidDate = mExpireMailWithInvalidDateCB->isChecked();
208 // we always write out days now
209 settings.daysToExpireRead = mExpireReadMailSB->value();
210 settings.daysToExpireUnread = mExpireUnreadMailSB->value();
211 settings.mReadExpireUnits =
212 mExpireReadMailSB->value() != 0 ? MailCommon::ExpireCollectionAttribute::ExpireDays : MailCommon::ExpireCollectionAttribute::ExpireNever;
213 settings.mUnreadExpireUnits =
214 mExpireUnreadMailSB->value() != 0 ? MailCommon::ExpireCollectionAttribute::ExpireDays : MailCommon::ExpireCollectionAttribute::ExpireNever;
215
216 if (mDeletePermanentlyRB->isChecked()) {
217 settings.mExpireAction = ExpireCollectionAttribute::ExpireDelete;
218 } else {
219 settings.mExpireAction = ExpireCollectionAttribute::ExpireMove;
220 }
221 return settings;
222}
223
224void CollectionExpiryWidget::save(const CollectionExpirySettings &collectionExpirySettings, Akonadi::Collection &collection, bool saveSettings, bool expireNow)
225{
226 expireNow = validateExpireFolder(expireNow);
227 MailCommon::ExpireCollectionAttribute *attribute = assignFolderAttribute(collection, expireNow);
228 attribute->setAutoExpire(collectionExpirySettings.expiryGloballyOn);
229 // we always write out days now
230 attribute->setReadExpireAge(collectionExpirySettings.daysToExpireRead);
231 attribute->setUnreadExpireAge(collectionExpirySettings.daysToExpireUnread);
232 attribute->setReadExpireUnits(collectionExpirySettings.mReadExpireUnits);
233 attribute->setUnreadExpireUnits(collectionExpirySettings.mUnreadExpireUnits);
234 attribute->setExpireAction(collectionExpirySettings.mExpireAction);
235
236 if (saveSettings) {
237 auto job = new CollectionExpiryJob;
238 job->setExpireNow(expireNow);
239 job->setCollection(collection);
240 job->start();
241 } else {
242 if (expireNow) {
243 MailCommon::Util::expireOldMessages(collection, true /*immediate*/);
244 }
245 }
246 Q_EMIT configChanged(false);
247}
248
249void CollectionExpiryWidget::save(Akonadi::Collection &collection, bool saveSettings, bool expireNow)
250{
251 const CollectionExpirySettings collectionExpirySettings = settings();
252 save(collectionExpirySettings, collection, saveSettings, expireNow);
253}
254
255bool CollectionExpiryWidget::canHandle(const Akonadi::Collection &col)
256{
257 QSharedPointer<FolderSettings> fd = FolderSettings::forCollection(col, false);
258 return fd->canDeleteMessages() && !fd->isStructural() && !MailCommon::Util::isVirtualCollection(col);
259}
260
261bool CollectionExpirySettings::isValid() const
262{
263 const bool valid = daysToExpireRead != -1 || daysToExpireUnread != -1 || mUnreadExpireUnits != ExpireCollectionAttribute::ExpireNever
264 || mReadExpireUnits != ExpireCollectionAttribute::ExpireNever || mExpireAction != ExpireCollectionAttribute::ExpireDelete || mExpireToFolderId != -1;
265 return valid;
266}
267
268QDebug operator<<(QDebug d, const CollectionExpirySettings &t)
269{
270 d << " expiryGloballyOn " << t.expiryGloballyOn;
271 d << " expiryMessagesWithInvalidDate " << t.expiryMessagesWithInvalidDate;
272 d << " daysToExpireRead " << t.daysToExpireRead;
273 d << " daysToExpireUnread " << t.daysToExpireUnread;
274 d << " mUnreadExpireUnits " << t.mUnreadExpireUnits;
275 d << " mReadExpireUnits " << t.mReadExpireUnits;
276 d << " mExpireAction " << t.mExpireAction;
277 d << " mExpireToFolderId " << t.mExpireToFolderId;
278 return d;
279}
280
281#include "moc_collectionexpirywidget.cpp"
bool isValid() const
const T * attribute() const
void setSuffix(const KLocalizedString &suffix)
KLocalizedString KI18N_EXPORT ki18ncp(const char *context, const char *singular, const char *plural)
QString i18n(const char *text, const TYPE &arg...)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
The filter dialog.
QDebug operator<<(QDebug dbg, const PerceptualColor::LchaDouble &value)
bool isChecked() const const
void clicked(bool checked)
void toggled(bool checked)
void setSpecialValueText(const QString &txt)
virtual QValidator::State validate(QString &input, int &pos) const const
Q_EMITQ_EMIT
QObject * parent() const const
void setMaximum(int max)
virtual QString textFromValue(int value) const const
void valueChanged(int i)
virtual int valueFromText(const QString &text) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setEnabled(bool)
virtual void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.