File indexing completed on 2025-02-02 05:08:40

0001 /*
0002    SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "followupreminderinfowidget.h"
0007 #include "followupreminderagent_debug.h"
0008 #include "followupreminderinfo.h"
0009 #include "followupreminderutil.h"
0010 #include "jobs/followupremindershowmessagejob.h"
0011 
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <KSharedConfig>
0015 #include <QHBoxLayout>
0016 #include <QHeaderView>
0017 #include <QIcon>
0018 #include <QKeyEvent>
0019 #include <QLocale>
0020 #include <QMenu>
0021 #include <QTreeWidget>
0022 
0023 // #define DEBUG_MESSAGE_ID
0024 namespace
0025 {
0026 inline QString followUpItemPattern()
0027 {
0028     return QStringLiteral("FollowupReminderItem \\d+");
0029 }
0030 }
0031 
0032 FollowUpReminderInfoItem::FollowUpReminderInfoItem(QTreeWidget *parent)
0033     : QTreeWidgetItem(parent)
0034 {
0035 }
0036 
0037 FollowUpReminderInfoItem::~FollowUpReminderInfoItem()
0038 {
0039     delete mInfo;
0040 }
0041 
0042 void FollowUpReminderInfoItem::setInfo(FollowUpReminder::FollowUpReminderInfo *info)
0043 {
0044     mInfo = info;
0045 }
0046 
0047 FollowUpReminder::FollowUpReminderInfo *FollowUpReminderInfoItem::info() const
0048 {
0049     return mInfo;
0050 }
0051 
0052 FollowUpReminderInfoWidget::FollowUpReminderInfoWidget(QWidget *parent)
0053     : QWidget(parent)
0054     , mTreeWidget(new QTreeWidget(this))
0055 {
0056     setObjectName(QLatin1StringView("FollowUpReminderInfoWidget"));
0057     auto hbox = new QHBoxLayout(this);
0058     hbox->setContentsMargins({});
0059     mTreeWidget->setObjectName(QLatin1StringView("treewidget"));
0060     QStringList headers;
0061     headers << i18n("To") << i18n("Subject") << i18n("Deadline") << i18n("Answer")
0062 #ifdef DEBUG_MESSAGE_ID
0063             << QStringLiteral("Message Id") << QStringLiteral("Answer Message Id")
0064 #endif
0065         ;
0066 
0067     mTreeWidget->setHeaderLabels(headers);
0068     mTreeWidget->setSortingEnabled(true);
0069     mTreeWidget->setRootIsDecorated(false);
0070     mTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
0071     mTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0072     mTreeWidget->installEventFilter(this);
0073 
0074     connect(mTreeWidget, &QTreeWidget::customContextMenuRequested, this, &FollowUpReminderInfoWidget::slotCustomContextMenuRequested);
0075     connect(mTreeWidget, &QTreeWidget::itemDoubleClicked, this, &FollowUpReminderInfoWidget::slotItemDoubleClicked);
0076 
0077     hbox->addWidget(mTreeWidget);
0078 }
0079 
0080 FollowUpReminderInfoWidget::~FollowUpReminderInfoWidget() = default;
0081 
0082 bool FollowUpReminderInfoWidget::eventFilter(QObject *object, QEvent *event)
0083 {
0084     if (object == mTreeWidget) {
0085         if (event->type() == QEvent::KeyPress) {
0086             auto keyEvent = static_cast<QKeyEvent *>(event);
0087             if (keyEvent->key() == Qt::Key_Delete) {
0088                 const auto listItems = mTreeWidget->selectedItems();
0089                 deleteItems(listItems);
0090             }
0091         }
0092     }
0093 
0094     return false;
0095 }
0096 
0097 void FollowUpReminderInfoWidget::setInfo(const QList<FollowUpReminder::FollowUpReminderInfo *> &infoList)
0098 {
0099     mTreeWidget->clear();
0100     for (FollowUpReminder::FollowUpReminderInfo *info : infoList) {
0101         if (info->isValid()) {
0102             createOrUpdateItem(info);
0103         } else {
0104             delete info;
0105         }
0106     }
0107 }
0108 
0109 void FollowUpReminderInfoWidget::load()
0110 {
0111     auto config = FollowUpReminder::FollowUpReminderUtil::defaultConfig();
0112     const QStringList filterGroups = config->groupList().filter(QRegularExpression(followUpItemPattern()));
0113     const int numberOfItem = filterGroups.count();
0114     for (int i = 0; i < numberOfItem; ++i) {
0115         KConfigGroup group = config->group(filterGroups.at(i));
0116 
0117         auto info = new FollowUpReminder::FollowUpReminderInfo(group);
0118         if (info->isValid()) {
0119             createOrUpdateItem(info);
0120         } else {
0121             delete info;
0122         }
0123     }
0124 }
0125 
0126 QList<qint32> FollowUpReminderInfoWidget::listRemoveId() const
0127 {
0128     return mListRemoveId;
0129 }
0130 
0131 void FollowUpReminderInfoWidget::createOrUpdateItem(FollowUpReminder::FollowUpReminderInfo *info, FollowUpReminderInfoItem *item)
0132 {
0133     if (!item) {
0134         item = new FollowUpReminderInfoItem(mTreeWidget);
0135     }
0136     item->setInfo(info);
0137     item->setText(To, info->to());
0138     item->setToolTip(To, info->to());
0139     item->setText(Subject, info->subject());
0140     item->setToolTip(Subject, info->subject());
0141     const QString date = QLocale().toString(info->followUpReminderDate());
0142     item->setText(DeadLine, date);
0143     item->setToolTip(DeadLine, date);
0144     const bool answerWasReceived = info->answerWasReceived();
0145     item->setText(AnswerWasReceived, answerWasReceived ? i18n("Received") : i18n("On hold"));
0146     item->setData(0, AnswerItemFound, answerWasReceived);
0147     if (answerWasReceived) {
0148         item->setBackground(DeadLine, Qt::green);
0149     } else {
0150         if (info->followUpReminderDate() < QDate::currentDate()) {
0151             item->setBackground(DeadLine, Qt::red);
0152         }
0153     }
0154 #ifdef DEBUG_MESSAGE_ID
0155     item->setText(MessageId, QString::number(info->originalMessageItemId()));
0156     item->setText(AnswerMessageId, QString::number(info->answerMessageItemId()));
0157 #endif
0158 }
0159 
0160 bool FollowUpReminderInfoWidget::save() const
0161 {
0162     if (!mChanged) {
0163         return false;
0164     }
0165     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0166 
0167     // first, delete all filter groups:
0168     const QStringList filterGroups = config->groupList().filter(QRegularExpression(followUpItemPattern()));
0169 
0170     for (const QString &group : filterGroups) {
0171         config->deleteGroup(group);
0172     }
0173 
0174     const int numberOfItem(mTreeWidget->topLevelItemCount());
0175     int i = 0;
0176     for (; i < numberOfItem; ++i) {
0177         auto mailItem = static_cast<FollowUpReminderInfoItem *>(mTreeWidget->topLevelItem(i));
0178         if (mailItem->info()) {
0179             KConfigGroup group = config->group(FollowUpReminder::FollowUpReminderUtil::followUpReminderPattern().arg(i));
0180             mailItem->info()->writeConfig(group, i);
0181         }
0182     }
0183     ++i;
0184     KConfigGroup general = config->group(QStringLiteral("General"));
0185     general.writeEntry("Number", i);
0186     config->sync();
0187     return true;
0188 }
0189 
0190 void FollowUpReminderInfoWidget::slotItemDoubleClicked(QTreeWidgetItem *item)
0191 {
0192     if (!item)
0193         return;
0194 
0195     const auto mailItem = static_cast<FollowUpReminderInfoItem *>(item);
0196     const auto answerMessageItemId = mailItem->info()->answerMessageItemId();
0197     if (answerMessageItemId >= 0) {
0198         openShowMessage(answerMessageItemId);
0199     } else {
0200         openShowMessage(mailItem->info()->originalMessageItemId());
0201     }
0202 }
0203 
0204 void FollowUpReminderInfoWidget::slotCustomContextMenuRequested(QPoint pos)
0205 {
0206     Q_UNUSED(pos)
0207     const QList<QTreeWidgetItem *> listItems = mTreeWidget->selectedItems();
0208     const int nbElementSelected = listItems.count();
0209     if (nbElementSelected > 0) {
0210         QMenu menu(this);
0211         QAction *showMessage = nullptr;
0212         QAction *showOriginalMessage = nullptr;
0213         FollowUpReminderInfoItem *mailItem = nullptr;
0214         if ((nbElementSelected == 1)) {
0215             mailItem = static_cast<FollowUpReminderInfoItem *>(listItems.at(0));
0216             if (mailItem->data(0, AnswerItemFound).toBool()) {
0217                 showMessage = menu.addAction(i18n("Show Message"));
0218                 menu.addSeparator();
0219             }
0220             showOriginalMessage = menu.addAction(QIcon::fromTheme(QStringLiteral("mail-message")), i18n("Show Original Message"));
0221             menu.addSeparator();
0222         }
0223         QAction *deleteItem = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete"));
0224         QAction *result = menu.exec(QCursor::pos());
0225         if (result) {
0226             if (result == showMessage) {
0227                 openShowMessage(mailItem->info()->answerMessageItemId());
0228             } else if (result == deleteItem) {
0229                 deleteItems(listItems);
0230             } else if (result == showOriginalMessage) {
0231                 openShowMessage(mailItem->info()->originalMessageItemId());
0232             }
0233         }
0234     }
0235 }
0236 
0237 void FollowUpReminderInfoWidget::openShowMessage(Akonadi::Item::Id id)
0238 {
0239     auto job = new FollowUpReminderShowMessageJob(id);
0240     job->start();
0241 }
0242 
0243 void FollowUpReminderInfoWidget::deleteItems(const QList<QTreeWidgetItem *> &mailItemLst)
0244 {
0245     if (mailItemLst.isEmpty()) {
0246         qCDebug(FOLLOWUPREMINDERAGENT_LOG) << "Not item selected";
0247     } else {
0248         const auto answer = KMessageBox::warningContinueCancel(
0249             this,
0250             i18np("Do you want to delete this selected item?", "Do you want to delete these %1 selected items?", mailItemLst.count()),
0251             i18nc("@title:window", "Delete Items"),
0252             KStandardGuiItem::del());
0253         if (answer == KMessageBox::Continue) {
0254             for (QTreeWidgetItem *item : mailItemLst) {
0255                 auto mailItem = static_cast<FollowUpReminderInfoItem *>(item);
0256                 mListRemoveId << mailItem->info()->uniqueIdentifier();
0257                 delete mailItem;
0258             }
0259             mChanged = true;
0260         }
0261     }
0262 }
0263 
0264 void FollowUpReminderInfoWidget::restoreTreeWidgetHeader(const QByteArray &data)
0265 {
0266     mTreeWidget->header()->restoreState(data);
0267 }
0268 
0269 void FollowUpReminderInfoWidget::saveTreeWidgetHeader(KConfigGroup &group)
0270 {
0271     group.writeEntry("HeaderState", mTreeWidget->header()->saveState());
0272 }
0273 
0274 #include "moc_followupreminderinfowidget.cpp"