File indexing completed on 2024-11-10 04:50:09

0001 /*
0002   SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "accountconfigorderdialog.h"
0008 #include "mailcommon_debug.h"
0009 #include "mailcommonsettings_base.h"
0010 #include "util/mailutil.h"
0011 #include <KLocalizedString>
0012 #include <PimCommon/PimUtil>
0013 #include <QIcon>
0014 #include <QPushButton>
0015 #include <QVBoxLayout>
0016 
0017 #include <Akonadi/AgentInstance>
0018 #include <Akonadi/AgentManager>
0019 
0020 #include <KConfigGroup>
0021 #include <KWindowConfig>
0022 #include <QCheckBox>
0023 #include <QDialogButtonBox>
0024 #include <QHBoxLayout>
0025 #include <QListWidget>
0026 #include <QWindow>
0027 
0028 using namespace MailCommon;
0029 namespace
0030 {
0031 static const char myAccountConfigOrderDialogName[] = "AccountConfigOrderDialog";
0032 }
0033 struct InstanceStruct {
0034     QString name;
0035     QIcon icon;
0036     [[nodiscard]] bool isValid() const
0037     {
0038         return !name.isEmpty();
0039     }
0040 };
0041 
0042 class MailCommon::AccountConfigOrderDialogPrivate
0043 {
0044 public:
0045     QListWidget *mListAccount = nullptr;
0046     QPushButton *mUpButton = nullptr;
0047     QPushButton *mDownButton = nullptr;
0048     QCheckBox *mEnableAccountOrder = nullptr;
0049     MailCommon::MailCommonSettings *mSettings = nullptr;
0050 };
0051 
0052 AccountConfigOrderDialog::AccountConfigOrderDialog(MailCommon::MailCommonSettings *settings, QWidget *parent)
0053     : QDialog(parent)
0054     , d(new MailCommon::AccountConfigOrderDialogPrivate)
0055 {
0056     d->mSettings = settings;
0057     setWindowTitle(i18nc("@title:window", "Edit Accounts Order"));
0058     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0059     auto mainLayout = new QVBoxLayout(this);
0060 
0061     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0062     okButton->setDefault(true);
0063     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0064     connect(buttonBox, &QDialogButtonBox::rejected, this, &AccountConfigOrderDialog::reject);
0065 
0066     auto page = new QWidget(this);
0067     mainLayout->addWidget(page);
0068     mainLayout->addWidget(buttonBox);
0069 
0070     auto vbox = new QVBoxLayout;
0071     vbox->setContentsMargins({});
0072     page->setLayout(vbox);
0073 
0074     d->mEnableAccountOrder = new QCheckBox(i18n("Use custom order"), this);
0075     connect(d->mEnableAccountOrder, &QCheckBox::clicked, this, &AccountConfigOrderDialog::slotEnableAccountOrder);
0076     vbox->addWidget(d->mEnableAccountOrder);
0077 
0078     auto vlay = new QHBoxLayout;
0079     vbox->addLayout(vlay);
0080 
0081     d->mListAccount = new QListWidget(this);
0082     d->mListAccount->setDragDropMode(QAbstractItemView::InternalMove);
0083     vlay->addWidget(d->mListAccount);
0084 
0085     auto upDownBox = new QWidget(page);
0086     auto upDownBoxVBoxLayout = new QVBoxLayout(upDownBox);
0087     upDownBoxVBoxLayout->setContentsMargins({});
0088     d->mUpButton = new QPushButton(upDownBox);
0089     upDownBoxVBoxLayout->addWidget(d->mUpButton);
0090     d->mUpButton->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0091     d->mUpButton->setToolTip(i18nc("Move selected account up.", "Up"));
0092     d->mUpButton->setEnabled(false); // b/c no item is selected yet
0093     d->mUpButton->setFocusPolicy(Qt::StrongFocus);
0094     d->mUpButton->setAutoRepeat(true);
0095 
0096     d->mDownButton = new QPushButton(upDownBox);
0097     upDownBoxVBoxLayout->addWidget(d->mDownButton);
0098     d->mDownButton->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0099     d->mDownButton->setToolTip(i18nc("Move selected account down.", "Down"));
0100     d->mDownButton->setEnabled(false); // b/c no item is selected yet
0101     d->mDownButton->setFocusPolicy(Qt::StrongFocus);
0102     d->mDownButton->setAutoRepeat(true);
0103 
0104     auto spacer = new QWidget(upDownBox);
0105     upDownBoxVBoxLayout->addWidget(spacer);
0106     upDownBoxVBoxLayout->setStretchFactor(spacer, 100);
0107     vlay->addWidget(upDownBox);
0108 
0109     connect(d->mUpButton, &QPushButton::clicked, this, &AccountConfigOrderDialog::slotMoveUp);
0110     connect(d->mDownButton, &QPushButton::clicked, this, &AccountConfigOrderDialog::slotMoveDown);
0111     connect(d->mListAccount, &QListWidget::itemSelectionChanged, this, &AccountConfigOrderDialog::slotEnableControls);
0112     connect(d->mListAccount->model(), &QAbstractItemModel::rowsMoved, this, &AccountConfigOrderDialog::slotEnableControls);
0113 
0114     connect(okButton, &QPushButton::clicked, this, &AccountConfigOrderDialog::slotOk);
0115     readConfig();
0116     init();
0117 }
0118 
0119 AccountConfigOrderDialog::~AccountConfigOrderDialog()
0120 {
0121     writeConfig();
0122 }
0123 
0124 void AccountConfigOrderDialog::slotEnableAccountOrder(bool state)
0125 {
0126     d->mListAccount->setEnabled(state);
0127     d->mUpButton->setEnabled(state);
0128     d->mDownButton->setEnabled(state);
0129     if (state) {
0130         slotEnableControls();
0131     }
0132 }
0133 
0134 void AccountConfigOrderDialog::slotMoveUp()
0135 {
0136     if (!d->mListAccount->currentItem()) {
0137         return;
0138     }
0139     const int pos = d->mListAccount->row(d->mListAccount->currentItem());
0140     d->mListAccount->blockSignals(true);
0141     QListWidgetItem *item = d->mListAccount->takeItem(pos);
0142     // now selected item is at idx(idx-1), so
0143     // insert the other item at idx, ie. above(below).
0144     d->mListAccount->insertItem(pos - 1, item);
0145     d->mListAccount->blockSignals(false);
0146     d->mListAccount->setCurrentRow(pos - 1);
0147 }
0148 
0149 void AccountConfigOrderDialog::slotMoveDown()
0150 {
0151     if (!d->mListAccount->currentItem()) {
0152         return;
0153     }
0154     const int pos = d->mListAccount->row(d->mListAccount->currentItem());
0155     d->mListAccount->blockSignals(true);
0156     QListWidgetItem *item = d->mListAccount->takeItem(pos);
0157     // now selected item is at idx(idx-1), so
0158     // insert the other item at idx, ie. above(below).
0159     d->mListAccount->insertItem(pos + 1, item);
0160     d->mListAccount->blockSignals(false);
0161     d->mListAccount->setCurrentRow(pos + 1);
0162 }
0163 
0164 void AccountConfigOrderDialog::slotEnableControls()
0165 {
0166     QListWidgetItem *item = d->mListAccount->currentItem();
0167 
0168     d->mUpButton->setEnabled(item && d->mListAccount->currentRow() != 0);
0169     d->mDownButton->setEnabled(item && d->mListAccount->currentRow() != d->mListAccount->count() - 1);
0170 }
0171 
0172 void AccountConfigOrderDialog::init()
0173 {
0174     const QStringList listOrderAccount = d->mSettings->order();
0175     QStringList instanceList;
0176 
0177     QMap<QString, InstanceStruct> mapInstance;
0178     const Akonadi::AgentInstance::List lstInstances = Akonadi::AgentManager::self()->instances();
0179     for (const Akonadi::AgentInstance &instance : lstInstances) {
0180         const QString identifier = instance.identifier();
0181         if (!MailCommon::Util::isMailAgent(instance) || identifier.contains(POP3_RESOURCE_IDENTIFIER)) {
0182             continue;
0183         }
0184         instanceList << instance.identifier();
0185         InstanceStruct instanceStruct;
0186         instanceStruct.name = instance.name();
0187         if (PimCommon::Util::isImapResource(identifier)) {
0188             instanceStruct.name += QLatin1StringView(" (IMAP)");
0189         } else if (identifier.startsWith(QLatin1StringView("akonadi_maildir_resource"))) {
0190             instanceStruct.name += QLatin1StringView(" (Maildir)");
0191         } else if (identifier.startsWith(QLatin1StringView("akonadi_mailbox_resource"))) {
0192             instanceStruct.name += QLatin1StringView(" (Mailbox)");
0193         } else if (identifier.startsWith(QLatin1StringView("akonadi_mixedmaildir_resource"))) {
0194             instanceStruct.name += QLatin1StringView(" (Mixedmaildir)");
0195         } else {
0196             qCDebug(MAILCOMMON_LOG) << " Unknown resource type " << identifier;
0197         }
0198         instanceStruct.icon = instance.type().icon();
0199         mapInstance.insert(instance.identifier(), instanceStruct);
0200     }
0201     instanceList.sort(Qt::CaseInsensitive);
0202     const int numberOfList(listOrderAccount.count());
0203     for (int i = 0; i < numberOfList; ++i) {
0204         instanceList.removeOne(listOrderAccount.at(i));
0205     }
0206 
0207     QStringList finalList(listOrderAccount);
0208     finalList += instanceList;
0209 
0210     const int numberOfElement(finalList.count());
0211     for (int i = 0; i < numberOfElement; ++i) {
0212         const QString identifier(finalList.at(i));
0213         const InstanceStruct tmp = mapInstance.value(identifier);
0214         if (tmp.isValid()) {
0215             auto item = new QListWidgetItem(tmp.icon, tmp.name, d->mListAccount);
0216             item->setData(AccountConfigOrderDialog::IdentifierAccount, identifier);
0217             d->mListAccount->addItem(item);
0218         }
0219     }
0220     const bool enabled = d->mSettings->enableAccountOrder();
0221     d->mEnableAccountOrder->setChecked(enabled);
0222     slotEnableAccountOrder(enabled);
0223 }
0224 
0225 void AccountConfigOrderDialog::slotOk()
0226 {
0227     QStringList order;
0228     const int numberOfItems(d->mListAccount->count());
0229     order.reserve(numberOfItems);
0230     for (int i = 0; i < numberOfItems; ++i) {
0231         order << d->mListAccount->item(i)->data(AccountConfigOrderDialog::IdentifierAccount).toString();
0232     }
0233 
0234     d->mSettings->setOrder(order);
0235     d->mSettings->setEnableAccountOrder(d->mEnableAccountOrder->isChecked());
0236     d->mSettings->save();
0237     QDialog::accept();
0238 }
0239 
0240 void AccountConfigOrderDialog::readConfig()
0241 {
0242     create(); // ensure a window is created
0243     windowHandle()->resize(QSize(500, 150));
0244     KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myAccountConfigOrderDialogName));
0245     KWindowConfig::restoreWindowSize(windowHandle(), group);
0246     resize(windowHandle()->size()); // workaround for QTBUG-40584
0247 }
0248 
0249 void AccountConfigOrderDialog::writeConfig()
0250 {
0251     KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myAccountConfigOrderDialogName));
0252     KWindowConfig::saveWindowSize(windowHandle(), group);
0253     group.sync();
0254 }
0255 
0256 #include "moc_accountconfigorderdialog.cpp"