File indexing completed on 2024-12-22 05:01:01
0001 /* 0002 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-only 0005 */ 0006 0007 #include "configureaccountpage.h" 0008 #include "configagentdelegate.h" 0009 #include "kmkernel.h" 0010 #include "newmailnotifierinterface.h" 0011 #include "settings/kmailsettings.h" 0012 #include "undosend/undosendcombobox.h" 0013 #include <MailCommon/AccountConfigOrderDialog> 0014 #include <MessageComposer/MessageComposerSettings> 0015 #include <PimCommon/ConfigureImmutableWidgetUtils> 0016 using namespace PimCommon::ConfigureImmutableWidgetUtils; 0017 #include <MailTransport/TransportManagementWidget> 0018 using MailTransport::TransportManagementWidget; 0019 #include <MailCommon/MailUtil> 0020 0021 #include "identity/identitypage.h" 0022 #include "kmail_debug.h" 0023 #include <Akonadi/AgentConfigurationDialog> 0024 #include <Akonadi/AgentManager> 0025 #include <Akonadi/AgentType> 0026 #include <Akonadi/AgentTypeDialog> 0027 #include <KConfigGroup> 0028 #include <KLDAPWidgets/LdapConfigureWidget> 0029 #include <KLocalizedString> 0030 #include <KMessageBox> 0031 #include <QComboBox> 0032 0033 #include <QAbstractItemView> 0034 #include <QFormLayout> 0035 #include <QLabel> 0036 #include <QMenu> 0037 #include <QProcess> 0038 0039 #include <memory> 0040 0041 QString AccountsPage::helpAnchor() const 0042 { 0043 return QStringLiteral("configure-accounts"); 0044 } 0045 0046 AccountsPage::AccountsPage(QObject *parent, const KPluginMetaData &data) 0047 : ConfigModuleWithTabs(parent, data) 0048 { 0049 // Identity Tab: 0050 auto identityTab = new KMail::IdentityPage(); 0051 addTab(identityTab, i18nc("@title:tab Tab page where the user configures identities", "Identities")); 0052 0053 // 0054 // "Receiving" tab: 0055 // 0056 auto receivingTab = new AccountsPageReceivingTab(); 0057 addTab(receivingTab, i18nc("@title:tab Tab page where the user configures accounts to receive mail", "Receiving")); 0058 connect(receivingTab, &AccountsPageReceivingTab::accountListChanged, this, &AccountsPage::accountListChanged); 0059 0060 // 0061 // "Sending" tab: 0062 // 0063 auto sendingTab = new AccountsPageSendingTab(); 0064 addTab(sendingTab, i18nc("@title:tab Tab page where the user configures accounts to send mail", "Sending")); 0065 0066 // 0067 // "Sending" tab: 0068 // 0069 auto ldapCompletionTab = new LdapCompetionTab(); 0070 addTab(ldapCompletionTab, i18nc("@title:tab Tab page where the user configures ldap server", "LDAP server")); 0071 } 0072 0073 AccountsPageSendingTab::~AccountsPageSendingTab() = default; 0074 0075 QString AccountsPageSendingTab::helpAnchor() const 0076 { 0077 return QStringLiteral("configure-accounts-sending"); 0078 } 0079 0080 AccountsPageSendingTab::AccountsPageSendingTab(QWidget *parent) 0081 : ConfigModuleTab(parent) 0082 { 0083 auto formLayout = new QFormLayout(this); 0084 // label: zero stretch ### FIXME more 0085 formLayout->addRow(new QLabel(i18n("Outgoing accounts (add at least one):"), this)); 0086 0087 auto tmw = new TransportManagementWidget(this); 0088 tmw->layout()->setContentsMargins({}); 0089 formLayout->addRow(tmw); 0090 0091 // "confirm before send" check box: 0092 mConfirmSendCheck = new QCheckBox(i18n("&Confirm action"), this); 0093 formLayout->addRow(i18n("Before sending:"), mConfirmSendCheck); 0094 connect(mConfirmSendCheck, &QCheckBox::stateChanged, this, &AccountsPageSendingTab::slotEmitChanged); 0095 0096 mCheckSpellingBeforeSending = new QCheckBox(i18n("Check spelling"), this); 0097 formLayout->addRow(QString(), mCheckSpellingBeforeSending); 0098 connect(mCheckSpellingBeforeSending, &QCheckBox::stateChanged, this, &AccountsPageSendingTab::slotEmitChanged); 0099 0100 // "send on check" combo: 0101 mSendOnCheckCombo = new QComboBox(this); 0102 mSendOnCheckCombo->setEditable(false); 0103 mSendOnCheckCombo->addItems(QStringList() << i18n("Never Automatically") << i18n("On Manual Mail Checks") << i18n("On All Mail Checks")); 0104 mSendOnCheckCombo->setWhatsThis(i18n(KMailSettings::self()->sendOnCheckItem()->whatsThis().toUtf8().constData())); 0105 formLayout->addRow(i18n("Send &messages in outbox folder:"), mSendOnCheckCombo); 0106 connect(mSendOnCheckCombo, &QComboBox::activated, this, &AccountsPageSendingTab::slotEmitChanged); 0107 0108 // "default send method" combo: 0109 mSendMethodCombo = new QComboBox(this); 0110 mSendMethodCombo->setEditable(false); 0111 mSendMethodCombo->addItems(QStringList() << i18n("Send Now") << i18n("Send Later")); 0112 formLayout->addRow(i18n("Defa&ult send method:"), mSendMethodCombo); 0113 connect(mSendMethodCombo, &QComboBox::activated, this, &AccountsPageSendingTab::slotEmitChanged); 0114 0115 auto hLayout = new QHBoxLayout; 0116 mUndoSend = new QCheckBox(i18n("Enable Undo Send"), this); 0117 hLayout->addWidget(mUndoSend); 0118 connect(mUndoSend, &QCheckBox::toggled, this, [this](bool state) { 0119 mUndoSendComboBox->setEnabled(state); 0120 slotEmitChanged(); 0121 }); 0122 0123 mUndoSendComboBox = new UndoSendCombobox(this); 0124 mUndoSendComboBox->setEnabled(false); 0125 hLayout->addWidget(mUndoSendComboBox); 0126 formLayout->addRow(QString(), hLayout); 0127 connect(mUndoSendComboBox, &QComboBox::activated, this, &AccountsPageSendingTab::slotEmitChanged); 0128 } 0129 0130 void AccountsPageSendingTab::doLoadFromGlobalSettings() 0131 { 0132 mSendOnCheckCombo->setCurrentIndex(KMailSettings::self()->sendOnCheck()); 0133 loadWidget(mConfirmSendCheck, KMailSettings::self()->confirmBeforeSendItem()); 0134 loadWidget(mCheckSpellingBeforeSending, KMailSettings::self()->checkSpellingBeforeSendItem()); 0135 loadWidget(mUndoSend, KMailSettings::self()->enabledUndoSendItem()); 0136 mUndoSendComboBox->setDelay(KMailSettings::self()->undoSendDelay()); 0137 } 0138 0139 void AccountsPageSendingTab::doLoadOther() 0140 { 0141 mSendMethodCombo->setCurrentIndex(MessageComposer::MessageComposerSettings::self()->sendImmediate() ? 0 : 1); 0142 loadWidget(mConfirmSendCheck, KMailSettings::self()->confirmBeforeSendItem()); 0143 loadWidget(mCheckSpellingBeforeSending, KMailSettings::self()->checkSpellingBeforeSendItem()); 0144 loadWidget(mUndoSend, KMailSettings::self()->enabledUndoSendItem()); 0145 mUndoSendComboBox->setDelay(KMailSettings::self()->undoSendDelay()); 0146 } 0147 0148 void AccountsPageSendingTab::save() 0149 { 0150 KMailSettings::self()->setSendOnCheck(mSendOnCheckCombo->currentIndex()); 0151 saveCheckBox(mConfirmSendCheck, KMailSettings::self()->confirmBeforeSendItem()); 0152 saveCheckBox(mCheckSpellingBeforeSending, KMailSettings::self()->checkSpellingBeforeSendItem()); 0153 saveCheckBox(mUndoSend, KMailSettings::self()->enabledUndoSendItem()); 0154 MessageComposer::MessageComposerSettings::self()->setSendImmediate(mSendMethodCombo->currentIndex() == 0); 0155 KMailSettings::self()->setUndoSendDelay(mUndoSendComboBox->delay()); 0156 } 0157 0158 QString AccountsPageReceivingTab::helpAnchor() const 0159 { 0160 return QStringLiteral("configure-accounts-receiving"); 0161 } 0162 0163 AccountsPageReceivingTab::AccountsPageReceivingTab(QWidget *parent) 0164 : ConfigModuleTab(parent) 0165 { 0166 const auto service = Akonadi::ServerManager::self()->agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("akonadi_newmailnotifier_agent")); 0167 mNewMailNotifierInterface = 0168 new OrgFreedesktopAkonadiNewMailNotifierInterface(service, QStringLiteral("/NewMailNotifierAgent"), QDBusConnection::sessionBus(), this); 0169 if (!mNewMailNotifierInterface->isValid()) { 0170 qCDebug(KMAIL_LOG) << " org.freedesktop.Akonadi.NewMailNotifierAgent not found. Please verify your installation"; 0171 delete mNewMailNotifierInterface; 0172 mNewMailNotifierInterface = nullptr; 0173 } 0174 mAccountsReceiving.setupUi(this); 0175 0176 mAccountsReceiving.mAccountsReceiving->setMimeTypeFilter(QStringList() << KMime::Message::mimeType()); 0177 mAccountsReceiving.mAccountsReceiving->setCapabilityFilter(QStringList() << QStringLiteral("Resource")); 0178 mAccountsReceiving.mAccountsReceiving->setExcludeCapabilities(QStringList() 0179 << QStringLiteral("MailTransport") << QStringLiteral("Notes") << QStringLiteral("Autostart")); 0180 0181 KConfig specialMailCollection(QStringLiteral("specialmailcollectionsrc")); 0182 if (specialMailCollection.hasGroup(QStringLiteral("SpecialCollections"))) { 0183 KConfigGroup grp = specialMailCollection.group(QStringLiteral("SpecialCollections")); 0184 mAccountsReceiving.mAccountsReceiving->setSpecialCollectionIdentifier(grp.readEntry(QStringLiteral("DefaultResourceId"))); 0185 } 0186 auto configDelegate = new ConfigAgentDelegate(mAccountsReceiving.mAccountsReceiving->view()); 0187 mAccountsReceiving.mAccountsReceiving->setItemDelegate(configDelegate); 0188 connect(configDelegate, &ConfigAgentDelegate::optionsClicked, this, &AccountsPageReceivingTab::slotShowMailCheckMenu); 0189 0190 connect(mAccountsReceiving.mVerboseNotificationCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); 0191 0192 connect(mAccountsReceiving.mOtherNewMailActionsButton, &QAbstractButton::clicked, this, &AccountsPageReceivingTab::slotEditNotifications); 0193 connect(mAccountsReceiving.customizeAccountOrder, &QAbstractButton::clicked, this, &AccountsPageReceivingTab::slotCustomizeAccountOrder); 0194 mAccountsReceiving.mAccountsReceiving->disconnectAddAccountButton(); 0195 auto accountMenu = new QMenu(this); 0196 accountMenu->addAction(i18n("Add Mail Account..."), this, &AccountsPageReceivingTab::slotAddMailAccount); 0197 accountMenu->addAction(i18n("Custom Account..."), this, &AccountsPageReceivingTab::slotAddCustomAccount); 0198 mAccountsReceiving.mAccountsReceiving->addAccountButton()->setMenu(accountMenu); 0199 } 0200 0201 AccountsPageReceivingTab::~AccountsPageReceivingTab() 0202 { 0203 delete mNewMailNotifierInterface; 0204 mRetrievalHash.clear(); 0205 } 0206 0207 void AccountsPageReceivingTab::slotAddCustomAccount() 0208 { 0209 mAccountsReceiving.mAccountsReceiving->slotAddAccount(); 0210 } 0211 0212 void AccountsPageReceivingTab::slotAddMailAccount() 0213 { 0214 const QString path = QStandardPaths::findExecutable(QStringLiteral("accountwizard")); 0215 if (path.isEmpty() || !QProcess::startDetached(path, {})) { 0216 KMessageBox::error(this, 0217 i18n("Could not start the account wizard. " 0218 "Please make sure you have AccountWizard properly installed."), 0219 i18nc("@title:window", "Unable to start account wizard")); 0220 } 0221 } 0222 0223 void AccountsPageReceivingTab::slotCustomizeAccountOrder() 0224 { 0225 if (KMKernel::self()) { 0226 MailCommon::AccountConfigOrderDialog dlg(KMKernel::self()->mailCommonSettings(), this); 0227 dlg.exec(); 0228 } 0229 } 0230 0231 void AccountsPageReceivingTab::slotShowMailCheckMenu(const QString &ident, const QPoint &pos) 0232 { 0233 QMenu menu(this); 0234 0235 bool IncludeInManualChecks; 0236 bool OfflineOnShutdown; 0237 bool CheckOnStartup; 0238 if (!mRetrievalHash.contains(ident)) { 0239 const QString resourceGroupPattern(QStringLiteral("Resource %1")); 0240 0241 KConfigGroup group; 0242 KConfig *conf = nullptr; 0243 if (KMKernel::self()) { 0244 group = KConfigGroup(KMKernel::self()->config(), resourceGroupPattern.arg(ident)); 0245 } else { 0246 conf = new KConfig(QStringLiteral("kmail2rc")); 0247 group = KConfigGroup(conf, resourceGroupPattern.arg(ident)); 0248 } 0249 0250 IncludeInManualChecks = group.readEntry("IncludeInManualChecks", true); 0251 0252 // Keep sync with kmkernel, don't forget to change there. 0253 OfflineOnShutdown = group.readEntry("OfflineOnShutdown", ident.startsWith(QLatin1StringView("akonadi_pop3_resource")) ? true : false); 0254 0255 CheckOnStartup = group.readEntry("CheckOnStartup", false); 0256 QSharedPointer<RetrievalOptions> opts(new RetrievalOptions(IncludeInManualChecks, OfflineOnShutdown, CheckOnStartup)); 0257 mRetrievalHash.insert(ident, opts); 0258 delete conf; 0259 } else { 0260 QSharedPointer<RetrievalOptions> opts = mRetrievalHash.value(ident); 0261 IncludeInManualChecks = opts->IncludeInManualChecks; 0262 OfflineOnShutdown = opts->OfflineOnShutdown; 0263 CheckOnStartup = opts->CheckOnStartup; 0264 } 0265 0266 if (!MailCommon::Util::isVirtualCollection(ident)) { 0267 auto manualMailCheck = new QAction(i18nc("Label to a checkbox, so is either checked/unchecked", "Include in Manual Mail Check"), &menu); 0268 manualMailCheck->setCheckable(true); 0269 manualMailCheck->setChecked(IncludeInManualChecks); 0270 manualMailCheck->setData(ident); 0271 menu.addAction(manualMailCheck); 0272 connect(manualMailCheck, &QAction::toggled, this, &AccountsPageReceivingTab::slotIncludeInCheckChanged); 0273 } 0274 0275 auto switchOffline = new QAction(i18nc("Label to a checkbox, so is either checked/unchecked", "Switch offline on KMail Shutdown"), &menu); 0276 switchOffline->setCheckable(true); 0277 switchOffline->setChecked(OfflineOnShutdown); 0278 switchOffline->setData(ident); 0279 menu.addAction(switchOffline); 0280 connect(switchOffline, &QAction::toggled, this, &AccountsPageReceivingTab::slotOfflineOnShutdownChanged); 0281 0282 auto checkOnStartup = new QAction(i18n("Check mail on startup"), &menu); 0283 checkOnStartup->setCheckable(true); 0284 checkOnStartup->setChecked(CheckOnStartup); 0285 checkOnStartup->setData(ident); 0286 menu.addAction(checkOnStartup); 0287 0288 connect(checkOnStartup, &QAction::toggled, this, &AccountsPageReceivingTab::slotCheckOnStatupChanged); 0289 0290 menu.exec(mAccountsReceiving.mAccountsReceiving->view()->mapToGlobal(pos)); 0291 } 0292 0293 void AccountsPageReceivingTab::slotCheckOnStatupChanged(bool checked) 0294 { 0295 auto action = qobject_cast<QAction *>(sender()); 0296 const QString ident = action->data().toString(); 0297 0298 QSharedPointer<RetrievalOptions> opts = mRetrievalHash.value(ident); 0299 opts->CheckOnStartup = checked; 0300 slotEmitChanged(); 0301 } 0302 0303 void AccountsPageReceivingTab::slotIncludeInCheckChanged(bool checked) 0304 { 0305 auto action = qobject_cast<QAction *>(sender()); 0306 const QString ident = action->data().toString(); 0307 0308 QSharedPointer<RetrievalOptions> opts = mRetrievalHash.value(ident); 0309 opts->IncludeInManualChecks = checked; 0310 slotEmitChanged(); 0311 } 0312 0313 void AccountsPageReceivingTab::slotOfflineOnShutdownChanged(bool checked) 0314 { 0315 auto action = qobject_cast<QAction *>(sender()); 0316 const QString ident = action->data().toString(); 0317 0318 QSharedPointer<RetrievalOptions> opts = mRetrievalHash.value(ident); 0319 opts->OfflineOnShutdown = checked; 0320 slotEmitChanged(); 0321 } 0322 0323 void AccountsPageReceivingTab::slotEditNotifications() 0324 { 0325 const auto instance = Akonadi::AgentManager::self()->instance(QStringLiteral("akonadi_newmailnotifier_agent")); 0326 if (instance.isValid()) { 0327 std::make_unique<Akonadi::AgentConfigurationDialog>(instance, this)->exec(); 0328 } else { 0329 KMessageBox::error(this, i18n("New Mail Notifier Agent not registered. Please contact your administrator.")); 0330 } 0331 } 0332 0333 void AccountsPageReceivingTab::doLoadFromGlobalSettings() 0334 { 0335 if (mNewMailNotifierInterface) { 0336 mAccountsReceiving.mVerboseNotificationCheck->setChecked(mNewMailNotifierInterface->verboseMailNotification()); 0337 } 0338 } 0339 0340 void AccountsPageReceivingTab::save() 0341 { 0342 // Save Mail notification settings 0343 if (mNewMailNotifierInterface) { 0344 mNewMailNotifierInterface->setVerboseMailNotification(mAccountsReceiving.mVerboseNotificationCheck->isChecked()); 0345 } 0346 0347 const QString resourceGroupPattern(QStringLiteral("Resource %1")); 0348 QHash<QString, QSharedPointer<RetrievalOptions>>::const_iterator it = mRetrievalHash.cbegin(); 0349 const QHash<QString, QSharedPointer<RetrievalOptions>>::const_iterator itEnd = mRetrievalHash.cend(); 0350 for (; it != itEnd; ++it) { 0351 KConfigGroup group; 0352 KConfig *conf = nullptr; 0353 if (KMKernel::self()) { 0354 group = KConfigGroup(KMKernel::self()->config(), resourceGroupPattern.arg(it.key())); 0355 } else { 0356 conf = new KConfig(QStringLiteral("kmail2rc")); 0357 group = KConfigGroup(conf, resourceGroupPattern.arg(it.key())); 0358 } 0359 QSharedPointer<RetrievalOptions> opts = it.value(); 0360 group.writeEntry("IncludeInManualChecks", opts->IncludeInManualChecks); 0361 group.writeEntry("OfflineOnShutdown", opts->OfflineOnShutdown); 0362 group.writeEntry("CheckOnStartup", opts->CheckOnStartup); 0363 delete conf; 0364 } 0365 } 0366 0367 LdapCompetionTab::LdapCompetionTab(QWidget *parent) 0368 : ConfigModuleTab(parent) 0369 , mLdapConfigureWidget(new KLDAPWidgets::LdapConfigureWidget(this)) 0370 { 0371 auto layout = new QVBoxLayout(this); 0372 layout->setContentsMargins({}); 0373 0374 layout->addWidget(mLdapConfigureWidget); 0375 0376 connect(mLdapConfigureWidget, &KLDAPWidgets::LdapConfigureWidget::changed, this, qOverload<bool>(&LdapCompetionTab::changed)); 0377 } 0378 0379 LdapCompetionTab::~LdapCompetionTab() = default; 0380 0381 QString LdapCompetionTab::helpAnchor() const 0382 { 0383 return {}; 0384 } 0385 0386 void LdapCompetionTab::save() 0387 { 0388 mLdapConfigureWidget->save(); 0389 } 0390 0391 void LdapCompetionTab::doLoadOther() 0392 { 0393 mLdapConfigureWidget->load(); 0394 } 0395 0396 #include "moc_configureaccountpage.cpp"