Mailcommon

collectionexpirywidget.cpp
1 /*
2  SPDX-FileCopyrightText: 2020-2023 Laurent Montel <[email protected]>
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 
26 using namespace MailCommon;
27 
28 class DaysSpinBox : public KPluralHandlingSpinBox
29 {
30 public:
31  DaysSpinBox(QWidget *parent)
32  : KPluralHandlingSpinBox(parent)
33  {
34  setMaximum(999999);
35  setSuffix(ki18ncp("Expire messages after %1", " day", " days"));
36  setSpecialValueText(i18n("Never"));
37  }
38 
39  Q_REQUIRED_RESULT QString textFromValue(int value) const override
40  {
41  if (value == 0) {
42  return i18n("Never");
43  }
45  }
46 
47  Q_REQUIRED_RESULT 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  }
57  return KPluralHandlingSpinBox::validate(text, pos);
58  }
59 };
60 
61 CollectionExpiryWidget::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 
113 CollectionExpiryWidget::~CollectionExpiryWidget() = default;
114 
115 void CollectionExpiryWidget::hideExpireNowButton()
116 {
117  mExpireNowPB->setVisible(false);
118 }
119 
120 void 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 
131 void 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 
166 bool 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()) {
171  KMessageBox::error(this,
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 
180 MailCommon::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()) {
186  KMessageBox::error(this,
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 
203 CollectionExpirySettings 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 
224 void 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 
249 void CollectionExpiryWidget::save(Akonadi::Collection &collection, bool saveSettings, bool expireNow)
250 {
251  const CollectionExpirySettings collectionExpirySettings = settings();
252  save(collectionExpirySettings, collection, saveSettings, expireNow);
253 }
254 
255 bool 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 
261 bool 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 
268 QDebug 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"
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
void clicked(bool checked)
virtual QString textFromValue(int value) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void toggled(bool checked)
QString i18n(const char *text, const TYPE &arg...)
KLocalizedString KI18N_EXPORT ki18ncp(const char *context, const char *singular, const char *plural)
const T * attribute() const
virtual int valueFromText(const QString &text) const const
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
bool isValid() const
virtual QValidator::State validate(QString &text, int &pos) const const override
void valueChanged(int i)
The filter dialog.
QAction * save(const QObject *recvr, const char *slot, QObject *parent)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 21 2023 04:03:06 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.