File indexing completed on 2024-05-12 05:13:14
0001 /* 0002 SPDX-FileCopyrightText: 2000, 2001 Cornelius Schumacher <schumacher@kde.org> 0003 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0006 */ 0007 0008 // ArchiveDialog -- archive/delete past events. 0009 0010 #include "archivedialog.h" 0011 #include "eventarchiver.h" 0012 #include "kcalprefs.h" 0013 0014 #include <Akonadi/IncidenceChanger> 0015 0016 #include <KDateComboBox> 0017 #include <KLineEdit> 0018 #include <KLocalizedString> 0019 #include <KMessageBox> 0020 #include <KUrlRequester> 0021 #include <QComboBox> 0022 #include <QHBoxLayout> 0023 #include <QUrl> 0024 0025 #include <QButtonGroup> 0026 #include <QCheckBox> 0027 #include <QDialogButtonBox> 0028 #include <QFrame> 0029 #include <QGroupBox> 0030 #include <QLabel> 0031 #include <QPushButton> 0032 #include <QRadioButton> 0033 #include <QSpinBox> 0034 #include <QVBoxLayout> 0035 #include <QWhatsThis> 0036 0037 using namespace CalendarSupport; 0038 0039 ArchiveDialog::ArchiveDialog(const Akonadi::ETMCalendar::Ptr &cal, Akonadi::IncidenceChanger *changer, QWidget *parent) 0040 : QDialog(parent) 0041 , mUser1Button(new QPushButton(this)) 0042 { 0043 setWindowTitle(i18nc("@title:window", "Archive/Delete Past Events and To-dos")); 0044 auto mainLayout = new QVBoxLayout(this); 0045 auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, this); 0046 buttonBox->addButton(mUser1Button, QDialogButtonBox::ActionRole); 0047 connect(buttonBox, &QDialogButtonBox::rejected, this, &ArchiveDialog::reject); 0048 mUser1Button->setDefault(true); 0049 setModal(false); 0050 mUser1Button->setText(i18nc("@action:button", "&Archive")); 0051 mCalendar = cal; 0052 mChanger = changer; 0053 0054 auto topFrame = new QFrame(this); 0055 mainLayout->addWidget(topFrame); 0056 mainLayout->addWidget(buttonBox); 0057 0058 auto topLayout = new QVBoxLayout(topFrame); 0059 topLayout->setContentsMargins(0, 0, 0, 0); 0060 auto descLabel = new QLabel(topFrame); 0061 descLabel->setText(xi18nc("@info:whatsthis", 0062 "Archiving saves old items into the given file and " 0063 "then deletes them in the current calendar. If the archive file " 0064 "already exists they will be added. " 0065 "(<link url=\"#\">How to restore</link>)")); 0066 descLabel->setWhatsThis(i18nc("@info:whatsthis", 0067 "In order to add an archive to your calendar, use the Merge Calendar " 0068 "function. You can view an archive by opening it like you would any " 0069 "other calendar. It is not saved in a special format, but as " 0070 "vCalendar.")); 0071 descLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard | Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard); 0072 descLabel->setWordWrap(true); 0073 descLabel->setContextMenuPolicy(Qt::NoContextMenu); 0074 topLayout->addWidget(descLabel); 0075 connect(descLabel, &QLabel::linkActivated, this, &ArchiveDialog::showWhatsThis); 0076 0077 auto radioBG = new QButtonGroup(this); 0078 connect(radioBG, &QButtonGroup::buttonClicked, this, &ArchiveDialog::slotActionChanged); 0079 0080 auto dateLayout = new QHBoxLayout(); 0081 dateLayout->setContentsMargins(0, 0, 0, 0); 0082 mArchiveOnceRB = new QRadioButton(i18nc("@option:radio", "Archive now items older than:"), topFrame); 0083 mArchiveOnceRB->setToolTip(i18nc("@info:tooltip", "Enable one time archiving or purging of older items")); 0084 mArchiveOnceRB->setWhatsThis(i18nc("@info:whatsthis", 0085 "If you check this box, events and to-dos older than the specified age " 0086 "will be archived or purged. The items will be archived unless the " 0087 "\"Delete only\" option is enabled; else the items will be purged " 0088 "and not saved.")); 0089 0090 dateLayout->addWidget(mArchiveOnceRB); 0091 radioBG->addButton(mArchiveOnceRB); 0092 mDateEdit = new KDateComboBox(topFrame); 0093 mDateEdit->setToolTip(i18nc("@info:tooltip", "Set the one time archiving cut-off date")); 0094 mDateEdit->setWhatsThis(i18nc("@info:whatsthis", 0095 "The date before which items should be archived. All older events " 0096 "and to-dos will be saved and deleted, the newer (and events " 0097 "exactly on that date) will be kept.")); 0098 dateLayout->addWidget(mDateEdit); 0099 topLayout->addLayout(dateLayout); 0100 0101 // Checkbox, numinput and combo for auto-archiving (similar to kmail's 0102 // mExpireFolderCheckBox/mReadExpiryTimeNumInput in kmfolderdia.cpp) 0103 auto autoArchiveHBox = new QWidget(topFrame); 0104 auto autoArchiveHBoxHBoxLayout = new QHBoxLayout(autoArchiveHBox); 0105 autoArchiveHBoxHBoxLayout->setContentsMargins(0, 0, 0, 0); 0106 topLayout->addWidget(autoArchiveHBox); 0107 mAutoArchiveRB = new QRadioButton(i18nc("@option:radio", "Automaticall&y archive items older than:"), autoArchiveHBox); 0108 mAutoArchiveRB->setToolTip(i18nc("@info:tooltip", "Enable automatic archiving or purging of older items")); 0109 mAutoArchiveRB->setWhatsThis(i18nc("@info:whatsthis", 0110 "If this feature is enabled, the application will regularly check if " 0111 "events and to-dos have to be archived; this means you will not " 0112 "need to use this dialog box again, except to change the settings.")); 0113 radioBG->addButton(mAutoArchiveRB); 0114 autoArchiveHBoxHBoxLayout->addWidget(mAutoArchiveRB); 0115 0116 mExpiryTimeNumInput = new QSpinBox(autoArchiveHBox); 0117 autoArchiveHBoxHBoxLayout->addWidget(mExpiryTimeNumInput); 0118 mExpiryTimeNumInput->setRange(1, 500); 0119 mExpiryTimeNumInput->setSingleStep(1); 0120 0121 mExpiryTimeNumInput->setEnabled(false); 0122 mExpiryTimeNumInput->setValue(7); 0123 mExpiryTimeNumInput->setToolTip(i18nc("@info:tooltip", "Set the archival age in days, weeks or months")); 0124 mExpiryTimeNumInput->setWhatsThis(i18nc("@info:whatsthis", 0125 "The age of the events and to-dos to archive. All older items " 0126 "will be saved and deleted, the newer will be kept.")); 0127 0128 mExpiryUnitsComboBox = new QComboBox(autoArchiveHBox); 0129 autoArchiveHBoxHBoxLayout->addWidget(mExpiryUnitsComboBox); 0130 mExpiryUnitsComboBox->setToolTip(i18nc("@info:tooltip", "Set the units for the automatic archive age")); 0131 mExpiryUnitsComboBox->setWhatsThis(i18nc("@info:whatsthis", "Select the time units (days, weeks or months) for automatic archiving.")); 0132 // Those items must match the "Expiry Unit" enum in the kcfg file! 0133 mExpiryUnitsComboBox->addItem(i18nc("@item:inlistbox expires in daily units", "Day(s)")); 0134 mExpiryUnitsComboBox->addItem(i18nc("@item:inlistbox expiration in weekly units", "Week(s)")); 0135 mExpiryUnitsComboBox->addItem(i18nc("@item:inlistbox expiration in monthly units", "Month(s)")); 0136 mExpiryUnitsComboBox->setEnabled(false); 0137 0138 auto fileLayout = new QHBoxLayout(); 0139 fileLayout->setContentsMargins(0, 0, 0, 0); 0140 auto l = new QLabel(i18nc("@label", "Archive &file:"), topFrame); 0141 fileLayout->addWidget(l); 0142 mArchiveFile = new KUrlRequester(QUrl::fromLocalFile(KCalPrefs::instance()->mArchiveFile), topFrame); 0143 mArchiveFile->setMode(KFile::File); 0144 mArchiveFile->setNameFilter(i18nc("@label filter for KUrlRequester", "iCalendar Files (*.ics)")); 0145 mArchiveFile->setToolTip(i18nc("@info:tooltip", "Set the location of the archive")); 0146 mArchiveFile->setWhatsThis(i18nc("@info:whatsthis", 0147 "The path of the archive file. The events and to-dos will be appended " 0148 "to the specified file, so any events that are already in the file " 0149 "will not be modified or deleted. You can later load or merge the " 0150 "file like any other calendar. It is not saved in a special " 0151 "format, it uses the iCalendar format.")); 0152 l->setBuddy(mArchiveFile->lineEdit()); 0153 fileLayout->addWidget(mArchiveFile); 0154 topLayout->addLayout(fileLayout); 0155 0156 auto typeBox = new QGroupBox(i18nc("@title:group", "Type of Items to Archive")); 0157 typeBox->setWhatsThis(i18nc("@info:whatsthis", 0158 "Here you can select which items " 0159 "should be archived. Events are archived if they " 0160 "ended before the date given above; to-dos are archived if " 0161 "they were finished before the date.")); 0162 0163 topLayout->addWidget(typeBox); 0164 QBoxLayout *typeLayout = new QVBoxLayout(typeBox); 0165 0166 mEvents = new QCheckBox(i18nc("@option:check", "Archive &Events")); 0167 mEvents->setToolTip(i18nc("@option:check", "Archive or purge events")); 0168 mEvents->setWhatsThis(i18nc("@info:whatsthis", "Select this option to archive events if they ended before the date given above.")); 0169 typeLayout->addWidget(mEvents); 0170 0171 mTodos = new QCheckBox(i18nc("@option:check", "Archive Completed &To-dos")); 0172 mTodos->setToolTip(i18nc("@option:check", "Archive or purge completed to-dos")); 0173 mTodos->setWhatsThis(i18nc("@info:whatsthis", 0174 "Select this option to archive to-dos if they were completed " 0175 "before the date given above.")); 0176 typeLayout->addWidget(mTodos); 0177 0178 mDeleteCb = new QCheckBox(i18nc("@option:check", "&Delete only, do not save"), topFrame); 0179 mDeleteCb->setToolTip(i18nc("@info:tooltip", "Purge the old items without saving them")); 0180 mDeleteCb->setWhatsThis(i18nc("@info:whatsthis", 0181 "Select this option to delete old events and to-dos without saving " 0182 "them. It is not possible to recover the events later.")); 0183 topLayout->addWidget(mDeleteCb); 0184 connect(mDeleteCb, &QCheckBox::toggled, mArchiveFile, &KUrlRequester::setDisabled); 0185 connect(mDeleteCb, &QCheckBox::toggled, this, &ArchiveDialog::slotEnableUser1); 0186 connect(mArchiveFile->lineEdit(), &QLineEdit::textChanged, this, &ArchiveDialog::slotEnableUser1); 0187 0188 // Load settings from KCalPrefs 0189 mExpiryTimeNumInput->setValue(KCalPrefs::instance()->mExpiryTime); 0190 mExpiryUnitsComboBox->setCurrentIndex(KCalPrefs::instance()->mExpiryUnit); 0191 mDeleteCb->setChecked(KCalPrefs::instance()->mArchiveAction == KCalPrefs::actionDelete); 0192 mEvents->setChecked(KCalPrefs::instance()->mArchiveEvents); 0193 mTodos->setChecked(KCalPrefs::instance()->mArchiveTodos); 0194 0195 slotEnableUser1(); 0196 0197 // The focus should go to a useful field by default, not to the top richtext-label 0198 if (KCalPrefs::instance()->mAutoArchive) { 0199 mAutoArchiveRB->setChecked(true); 0200 mAutoArchiveRB->setFocus(); 0201 } else { 0202 mArchiveOnceRB->setChecked(true); 0203 mArchiveOnceRB->setFocus(); 0204 } 0205 slotActionChanged(); 0206 connect(mUser1Button, &QPushButton::clicked, this, &ArchiveDialog::slotUser1); 0207 } 0208 0209 ArchiveDialog::~ArchiveDialog() = default; 0210 0211 void ArchiveDialog::slotEnableUser1() 0212 { 0213 const bool state = (mDeleteCb->isChecked() || !mArchiveFile->lineEdit()->text().trimmed().isEmpty()); 0214 mUser1Button->setEnabled(state); 0215 } 0216 0217 void ArchiveDialog::slotActionChanged() 0218 { 0219 mDateEdit->setEnabled(mArchiveOnceRB->isChecked()); 0220 mExpiryTimeNumInput->setEnabled(mAutoArchiveRB->isChecked()); 0221 mExpiryUnitsComboBox->setEnabled(mAutoArchiveRB->isChecked()); 0222 } 0223 0224 // Archive old events 0225 void ArchiveDialog::slotUser1() 0226 { 0227 EventArchiver archiver; 0228 connect(&archiver, &EventArchiver::eventsDeleted, this, &ArchiveDialog::slotEventsDeleted); 0229 0230 KCalPrefs::instance()->mAutoArchive = mAutoArchiveRB->isChecked(); 0231 KCalPrefs::instance()->mExpiryTime = mExpiryTimeNumInput->value(); 0232 KCalPrefs::instance()->mExpiryUnit = mExpiryUnitsComboBox->currentIndex(); 0233 0234 if (mDeleteCb->isChecked()) { 0235 KCalPrefs::instance()->mArchiveAction = KCalPrefs::actionDelete; 0236 } else { 0237 KCalPrefs::instance()->mArchiveAction = KCalPrefs::actionArchive; 0238 0239 // Get destination URL 0240 QUrl destUrl(mArchiveFile->url()); 0241 if (!destUrl.isValid()) { 0242 KMessageBox::error(this, i18nc("@info", "The archive file name is not valid.")); 0243 return; 0244 } 0245 // Force filename to be ending with vCalendar extension 0246 QString filename = destUrl.fileName(); 0247 if (!filename.endsWith(QLatin1StringView(".vcs")) && !filename.endsWith(QLatin1StringView(".ics"))) { 0248 filename.append(QLatin1StringView(".ics")); 0249 destUrl = destUrl.adjusted(QUrl::RemoveFilename); 0250 destUrl.setPath(destUrl.path() + filename); 0251 } 0252 0253 KCalPrefs::instance()->mArchiveFile = destUrl.url(); 0254 } 0255 if (KCalPrefs::instance()->mAutoArchive) { 0256 archiver.runAuto(mCalendar, mChanger, this, true /*with gui*/); 0257 Q_EMIT autoArchivingSettingsModified(); 0258 accept(); 0259 } else { 0260 archiver.runOnce(mCalendar, mChanger, mDateEdit->date(), this); 0261 accept(); 0262 } 0263 } 0264 0265 void ArchiveDialog::slotEventsDeleted() 0266 { 0267 Q_EMIT eventsDeleted(); 0268 if (!KCalPrefs::instance()->mAutoArchive) { 0269 accept(); 0270 } 0271 } 0272 0273 void ArchiveDialog::showWhatsThis() 0274 { 0275 QWidget *widget = qobject_cast<QWidget *>(sender()); 0276 if (widget && !widget->whatsThis().isEmpty()) { 0277 QWhatsThis::showText(QCursor::pos(), widget->whatsThis()); 0278 } 0279 } 0280 0281 #include "moc_archivedialog.cpp"