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"