File indexing completed on 2025-01-26 04:53:06

0001 /*
0002    SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "sendlaterconfigurewidget.h"
0008 #include "sendlaterutil.h"
0009 
0010 #include <MessageComposer/SendLaterDialog>
0011 #include <MessageComposer/SendLaterInfo>
0012 
0013 #include <KLocalizedString>
0014 #include <KMessageBox>
0015 #include <QIcon>
0016 #include <QMenu>
0017 #include <QPointer>
0018 
0019 namespace
0020 {
0021 inline QString sendLaterItemPattern()
0022 {
0023     return QStringLiteral("SendLaterItem \\d+");
0024 }
0025 }
0026 
0027 // #define DEBUG_MESSAGE_ID
0028 
0029 SendLaterItem::SendLaterItem(QTreeWidget *parent)
0030     : QTreeWidgetItem(parent)
0031 {
0032 }
0033 
0034 SendLaterItem::~SendLaterItem()
0035 {
0036     delete mInfo;
0037 }
0038 
0039 void SendLaterItem::setInfo(MessageComposer::SendLaterInfo *info)
0040 {
0041     mInfo = info;
0042 }
0043 
0044 MessageComposer::SendLaterInfo *SendLaterItem::info() const
0045 {
0046     return mInfo;
0047 }
0048 
0049 SendLaterWidget::SendLaterWidget(QWidget *parent)
0050     : QWidget(parent)
0051 {
0052     mWidget = new Ui::SendLaterConfigureWidget;
0053     mWidget->setupUi(this);
0054     QStringList headers;
0055     headers << i18n("To") << i18n("Subject") << i18n("Send around") << i18n("Recurrent")
0056 #ifdef DEBUG_MESSAGE_ID
0057             << i18n("Message Id");
0058 #else
0059         ;
0060 #endif
0061 
0062     mWidget->treeWidget->setObjectName(QLatin1StringView("treewidget"));
0063     mWidget->treeWidget->setHeaderLabels(headers);
0064     mWidget->treeWidget->setSortingEnabled(true);
0065     mWidget->treeWidget->setRootIsDecorated(false);
0066     mWidget->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
0067     mWidget->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0068     mWidget->treeWidget->setDefaultText(i18n("No messages waiting..."));
0069 
0070     connect(mWidget->treeWidget, &QTreeWidget::customContextMenuRequested, this, &SendLaterWidget::slotCustomContextMenuRequested);
0071 
0072     connect(mWidget->deleteItem, &QPushButton::clicked, this, &SendLaterWidget::slotDeleteItem);
0073     connect(mWidget->modifyItem, &QPushButton::clicked, this, &SendLaterWidget::slotModifyItem);
0074     connect(mWidget->treeWidget, &QTreeWidget::itemSelectionChanged, this, &SendLaterWidget::updateButtons);
0075     connect(mWidget->treeWidget, &QTreeWidget::itemDoubleClicked, this, &SendLaterWidget::slotModifyItem);
0076     load();
0077     updateButtons();
0078 }
0079 
0080 SendLaterWidget::~SendLaterWidget()
0081 {
0082     delete mWidget;
0083 }
0084 
0085 void SendLaterWidget::slotCustomContextMenuRequested(QPoint)
0086 {
0087     const QList<QTreeWidgetItem *> listItems = mWidget->treeWidget->selectedItems();
0088     if (!listItems.isEmpty()) {
0089         QMenu menu(this);
0090         if (listItems.count() == 1) {
0091             menu.addAction(mWidget->modifyItem->text(), this, &SendLaterWidget::slotModifyItem);
0092             menu.addSeparator();
0093             menu.addAction(i18n("Send now"), this, &SendLaterWidget::slotSendNow);
0094         }
0095         menu.addSeparator();
0096         menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete"), this, &SendLaterWidget::slotDeleteItem);
0097         menu.exec(QCursor::pos());
0098     }
0099 }
0100 
0101 void SendLaterWidget::slotSendNow()
0102 {
0103     const QList<QTreeWidgetItem *> listItems = mWidget->treeWidget->selectedItems();
0104     if (listItems.count() == 1) {
0105         auto mailItem = static_cast<SendLaterItem *>(listItems.first());
0106         Q_EMIT sendNow(mailItem->info()->itemId());
0107     }
0108 }
0109 
0110 void SendLaterWidget::restoreTreeWidgetHeader(const QByteArray &data)
0111 {
0112     mWidget->treeWidget->header()->restoreState(data);
0113 }
0114 
0115 void SendLaterWidget::saveTreeWidgetHeader(KConfigGroup &group)
0116 {
0117     group.writeEntry("HeaderState", mWidget->treeWidget->header()->saveState());
0118 }
0119 
0120 void SendLaterWidget::updateButtons()
0121 {
0122     const QList<QTreeWidgetItem *> listItems = mWidget->treeWidget->selectedItems();
0123     if (listItems.isEmpty()) {
0124         mWidget->deleteItem->setEnabled(false);
0125         mWidget->modifyItem->setEnabled(false);
0126     } else if (listItems.count() == 1) {
0127         mWidget->deleteItem->setEnabled(true);
0128         mWidget->modifyItem->setEnabled(true);
0129     } else {
0130         mWidget->deleteItem->setEnabled(true);
0131         mWidget->modifyItem->setEnabled(false);
0132     }
0133 }
0134 
0135 void SendLaterWidget::load()
0136 {
0137     KSharedConfig::Ptr config = SendLaterUtil::defaultConfig();
0138     const QStringList filterGroups = config->groupList().filter(QRegularExpression(sendLaterItemPattern()));
0139     const int numberOfItem = filterGroups.count();
0140     for (int i = 0; i < numberOfItem; ++i) {
0141         KConfigGroup group = config->group(filterGroups.at(i));
0142         auto info = SendLaterUtil::readSendLaterInfo(group);
0143         if (info->isValid()) {
0144             createOrUpdateItem(info);
0145         } else {
0146             delete info;
0147         }
0148     }
0149     mWidget->treeWidget->setShowDefaultText(numberOfItem == 0);
0150 }
0151 
0152 void SendLaterWidget::createOrUpdateItem(MessageComposer::SendLaterInfo *info, SendLaterItem *item)
0153 {
0154     if (!item) {
0155         item = new SendLaterItem(mWidget->treeWidget);
0156     }
0157     item->setText(Recursive, info->isRecurrence() ? i18n("Yes") : i18n("No"));
0158 #ifdef DEBUG_MESSAGE_ID
0159     item->setText(MessageId, QString::number(info->itemId()));
0160 #endif
0161     const QString date{info->dateTime().toString()};
0162     item->setText(SendAround, date);
0163     item->setToolTip(SendAround, date);
0164     const QString subject{info->subject()};
0165     item->setText(Subject, subject);
0166     item->setToolTip(Subject, subject);
0167     item->setText(To, info->to());
0168     item->setToolTip(To, info->to());
0169     item->setInfo(info);
0170     mWidget->treeWidget->setShowDefaultText(false);
0171 }
0172 
0173 void SendLaterWidget::save()
0174 {
0175     if (!mChanged) {
0176         return;
0177     }
0178     KSharedConfig::Ptr config = SendLaterUtil::defaultConfig();
0179 
0180     // first, delete all filter groups:
0181     const QStringList filterGroups = config->groupList().filter(QRegularExpression(sendLaterItemPattern()));
0182 
0183     for (const QString &group : filterGroups) {
0184         config->deleteGroup(group);
0185     }
0186 
0187     const int numberOfItem(mWidget->treeWidget->topLevelItemCount());
0188     for (int i = 0; i < numberOfItem; ++i) {
0189         auto mailItem = static_cast<SendLaterItem *>(mWidget->treeWidget->topLevelItem(i));
0190         if (mailItem->info()) {
0191             SendLaterUtil::writeSendLaterInfo(config, mailItem->info());
0192         }
0193     }
0194     config->sync();
0195     config->reparseConfiguration();
0196 }
0197 
0198 void SendLaterWidget::slotDeleteItem()
0199 {
0200     const QList<QTreeWidgetItem *> listItems = mWidget->treeWidget->selectedItems();
0201 
0202     if (listItems.isEmpty()) {
0203         return;
0204     }
0205     const int numberOfItems(listItems.count());
0206     int answer = KMessageBox::warningTwoActions(this,
0207                                                 i18np("Do you want to delete the selected item?", "Do you want to delete the selected items?", numberOfItems),
0208                                                 i18nc("@title:window", "Delete Items"),
0209                                                 KStandardGuiItem::del(),
0210                                                 KStandardGuiItem::cancel());
0211     if (answer == KMessageBox::ButtonCode::SecondaryAction) {
0212         return;
0213     }
0214 
0215     answer = KMessageBox::warningTwoActions(this,
0216                                             i18np("Do you want to delete the message as well?", "Do you want to delete the messages as well?", numberOfItems),
0217                                             i18nc("@title:window", "Delete Messages"),
0218                                             KStandardGuiItem::del(),
0219                                             KGuiItem(i18nc("@action:button", "Do Not Delete"), QStringLiteral("dialog-cancel")));
0220     const bool deleteMessage = (answer == KMessageBox::ButtonCode::PrimaryAction);
0221 
0222     for (QTreeWidgetItem *item : listItems) {
0223         if (deleteMessage) {
0224             auto mailItem = static_cast<SendLaterItem *>(item);
0225             if (mailItem->info()) {
0226                 Akonadi::Item::Id id = mailItem->info()->itemId();
0227                 if (id != -1) {
0228                     mListMessagesToRemove << id;
0229                 }
0230             }
0231         }
0232         delete item;
0233     }
0234     mChanged = true;
0235     mWidget->treeWidget->setShowDefaultText(mWidget->treeWidget->topLevelItemCount() == 0);
0236     updateButtons();
0237 }
0238 
0239 void SendLaterWidget::slotModifyItem()
0240 {
0241     const QList<QTreeWidgetItem *> listItems = mWidget->treeWidget->selectedItems();
0242     if (listItems.count() == 1) {
0243         QTreeWidgetItem *item = listItems.at(0);
0244         if (!item) {
0245             return;
0246         }
0247         auto mailItem = static_cast<SendLaterItem *>(item);
0248 
0249         QPointer<MessageComposer::SendLaterDialog> dialog = new MessageComposer::SendLaterDialog(mailItem->info(), this);
0250         if (dialog->exec()) {
0251             auto info = dialog->info();
0252             createOrUpdateItem(info, mailItem);
0253             mChanged = true;
0254         }
0255         delete dialog;
0256     }
0257 }
0258 
0259 void SendLaterWidget::needToReload()
0260 {
0261     mWidget->treeWidget->clear();
0262     KSharedConfig::Ptr config = SendLaterUtil::defaultConfig();
0263     config->reparseConfiguration();
0264     load();
0265 }
0266 
0267 QList<Akonadi::Item::Id> SendLaterWidget::messagesToRemove() const
0268 {
0269     return mListMessagesToRemove;
0270 }
0271 
0272 #include "moc_sendlaterconfigurewidget.cpp"