File indexing completed on 2024-12-22 05:01:00
0001 /* 0002 This file is part of KMail, the KDE mail client. 0003 SPDX-FileCopyrightText: 2005 Till Adam <adam@kde.org> 0004 SPDX-FileCopyrightText: 2011-2024 Laurent Montel <montel@kde.org> 0005 SPDX-FileCopyrightText: 2012 Jonathan Marten <jjm@keelhaul.me.uk> 0006 0007 SPDX-License-Identifier: GPL-2.0-only 0008 */ 0009 0010 #include "collectionmailinglistpage.h" 0011 #include "util.h" 0012 #include <MailCommon/MailKernel> 0013 #include <MailCommon/MailUtil> 0014 0015 #include <Akonadi/ItemFetchJob> 0016 #include <Akonadi/ItemFetchScope> 0017 #include <Akonadi/MessageParts> 0018 0019 #include <QCheckBox> 0020 #include <QFormLayout> 0021 #include <QHBoxLayout> 0022 #include <QLabel> 0023 #include <QLineEdit> 0024 #include <QPushButton> 0025 0026 #include "kmail_debug.h" 0027 #include <KEditListWidget> 0028 #include <KLocalizedString> 0029 #include <KMessageBox> 0030 #include <KSqueezedTextLabel> 0031 #include <QComboBox> 0032 0033 using namespace MailCommon; 0034 0035 CollectionMailingListPage::CollectionMailingListPage(QWidget *parent) 0036 : CollectionPropertiesPage(parent) 0037 { 0038 setObjectName(QLatin1StringView("KMail::CollectionMailingListPage")); 0039 setPageTitle(i18nc("@title:tab Mailing list settings for a folder.", "Mailing List")); 0040 } 0041 0042 CollectionMailingListPage::~CollectionMailingListPage() = default; 0043 0044 void CollectionMailingListPage::slotConfigChanged() 0045 { 0046 changed = true; 0047 } 0048 0049 bool CollectionMailingListPage::canHandle(const Akonadi::Collection &col) const 0050 { 0051 QSharedPointer<FolderSettings> fd = FolderSettings::forCollection(col, false); 0052 return !CommonKernel->isSystemFolderCollection(col) && !fd->isStructural() && !MailCommon::Util::isVirtualCollection(col); 0053 } 0054 0055 void CollectionMailingListPage::init(const Akonadi::Collection &col) 0056 { 0057 mCurrentCollection = col; 0058 mFolder = FolderSettings::forCollection(col, false); 0059 0060 auto topLayout = new QFormLayout(this); 0061 0062 mHoldsMailingList = new QCheckBox(i18n("Folder holds a mailing list"), this); 0063 connect(mHoldsMailingList, &QCheckBox::toggled, this, &CollectionMailingListPage::slotHoldsML); 0064 connect(mHoldsMailingList, &QCheckBox::toggled, this, &CollectionMailingListPage::slotConfigChanged); 0065 topLayout->addRow(QString(), mHoldsMailingList); 0066 0067 mDetectButton = new QPushButton(i18n("Detect Automatically"), this); 0068 connect(mDetectButton, &QPushButton::pressed, this, &CollectionMailingListPage::slotDetectMailingList); 0069 topLayout->addRow(QString(), mDetectButton); 0070 0071 mMLId = new KSqueezedTextLabel(QString(), this); 0072 mMLId->setTextElideMode(Qt::ElideRight); 0073 topLayout->addRow(i18n("Mailing list description:"), mMLId); 0074 0075 // FIXME: add QWhatsThis 0076 mMLHandlerCombo = new QComboBox(this); 0077 mMLHandlerCombo->addItem(i18n("KMail"), MailingList::KMail); 0078 mMLHandlerCombo->addItem(i18n("Browser"), MailingList::Browser); 0079 connect(mMLHandlerCombo, &QComboBox::activated, this, &CollectionMailingListPage::slotMLHandling); 0080 0081 topLayout->addRow(i18n("Preferred handler:"), mMLHandlerCombo); 0082 0083 auto addressWidget = new QWidget(this); 0084 addressWidget->setContentsMargins({}); 0085 auto addressTypeLayout = new QHBoxLayout(addressWidget); 0086 addressTypeLayout->setContentsMargins({}); 0087 mAddressCombo = new QComboBox(this); 0088 addressTypeLayout->addWidget(mAddressCombo); 0089 0090 // FIXME: if the mailing list actions have either QAction's or toolbar buttons 0091 // associated with them - remove this button since it's really silly 0092 // here 0093 mHandleButton = new QPushButton(i18n("Invoke Handler"), this); 0094 if (mFolder) { 0095 connect(mHandleButton, &QPushButton::clicked, this, &CollectionMailingListPage::slotInvokeHandler); 0096 } else { 0097 mHandleButton->setEnabled(false); 0098 } 0099 addressTypeLayout->addWidget(mHandleButton); 0100 topLayout->addRow(i18n("Address type:"), addressWidget); 0101 0102 topLayout->addRow(new QLabel(i18n("URL for mailing list posting:"), this)); 0103 0104 mEditList = new KEditListWidget(this); 0105 mEditList->lineEdit()->setClearButtonEnabled(true); 0106 connect(mEditList, &KEditListWidget::changed, this, &CollectionMailingListPage::slotConfigChanged); 0107 topLayout->addRow(mEditList); 0108 0109 // Order is important because the activate handler and fillMLFromWidgets 0110 // depend on it 0111 const QStringList el{i18n("Post to List"), i18n("Subscribe to List"), i18n("Unsubscribe From List"), i18n("List Archives"), i18n("List Help")}; 0112 mAddressCombo->addItems(el); 0113 connect(mAddressCombo, &QComboBox::activated, this, &CollectionMailingListPage::slotAddressChanged); 0114 0115 mMLId->setEnabled(false); 0116 mMLHandlerCombo->setEnabled(false); 0117 mAddressCombo->setEnabled(false); 0118 mHandleButton->setEnabled(false); 0119 mEditList->setEnabled(false); 0120 } 0121 0122 void CollectionMailingListPage::load(const Akonadi::Collection &col) 0123 { 0124 init(col); 0125 0126 if (mFolder) { 0127 mMailingList = mFolder->mailingList(); 0128 } 0129 0130 mMLId->setText((mMailingList.id().isEmpty() ? i18n("Not available") : mMailingList.id())); 0131 mMLHandlerCombo->setCurrentIndex(mMailingList.handler()); 0132 mEditList->insertStringList(QUrl::toStringList(mMailingList.postUrls())); 0133 0134 mAddressCombo->setCurrentIndex(mLastItem); 0135 mHoldsMailingList->setChecked(mFolder && mFolder->isMailingListEnabled()); 0136 slotHoldsML(mHoldsMailingList->isChecked()); 0137 changed = false; 0138 } 0139 0140 void CollectionMailingListPage::save(Akonadi::Collection &col) 0141 { 0142 Q_UNUSED(col) 0143 if (changed) { 0144 if (mFolder) { 0145 // settings for mailingList 0146 mFolder->setMailingListEnabled(mHoldsMailingList && mHoldsMailingList->isChecked()); 0147 fillMLFromWidgets(); 0148 mFolder->setMailingList(mMailingList); 0149 } 0150 } 0151 } 0152 0153 //---------------------------------------------------------------------------- 0154 void CollectionMailingListPage::slotHoldsML(bool holdsML) 0155 { 0156 mMLId->setEnabled(holdsML); 0157 mMLHandlerCombo->setEnabled(holdsML); 0158 mAddressCombo->setEnabled(holdsML); 0159 if (mFolder) { 0160 mHandleButton->setEnabled(holdsML); 0161 } 0162 mEditList->setEnabled(holdsML); 0163 mDetectButton->setEnabled(mFolder && mFolder->count() != 0); 0164 } 0165 0166 //---------------------------------------------------------------------------- 0167 void CollectionMailingListPage::slotDetectMailingList() 0168 { 0169 if (!mFolder) { 0170 return; // in case the folder was just created 0171 } 0172 0173 qCDebug(KMAIL_LOG) << "Detecting mailing list"; 0174 0175 // next try the 5 most recently added messages 0176 if (!(mMailingList.features() & MailingList::Post)) { 0177 // FIXME not load all folder 0178 auto job = new Akonadi::ItemFetchJob(mCurrentCollection, this); 0179 job->fetchScope().fetchPayloadPart(Akonadi::MessagePart::Header); 0180 connect(job, &Akonadi::ItemFetchJob::result, this, &CollectionMailingListPage::slotFetchDone); 0181 // Don't allow to reactive it 0182 mDetectButton->setEnabled(false); 0183 } else { 0184 mMLId->setText((mMailingList.id().isEmpty() ? i18n("Not available.") : mMailingList.id())); 0185 fillEditBox(); 0186 } 0187 } 0188 0189 void CollectionMailingListPage::slotFetchDone(KJob *job) 0190 { 0191 mDetectButton->setEnabled(true); 0192 if (MailCommon::Util::showJobErrorMessage(job)) { 0193 return; 0194 } 0195 auto fjob = qobject_cast<Akonadi::ItemFetchJob *>(job); 0196 Q_ASSERT(fjob); 0197 Akonadi::Item::List items = fjob->items(); 0198 const int maxchecks = 5; 0199 int num = items.size(); 0200 for (int i = --num; (i > num - maxchecks) && (i >= 0); --i) { 0201 Akonadi::Item item = items[i]; 0202 if (item.hasPayload<KMime::Message::Ptr>()) { 0203 auto message = item.payload<KMime::Message::Ptr>(); 0204 mMailingList = MessageCore::MailingList::detect(message); 0205 if (mMailingList.features() & MailingList::Post) { 0206 break; 0207 } 0208 } 0209 } 0210 if (!(mMailingList.features() & MailingList::Post)) { 0211 if (mMailingList.features() == MailingList::None) { 0212 KMessageBox::error(this, i18n("KMail was unable to detect any mailing list in this folder.")); 0213 } else { 0214 KMessageBox::error(this, 0215 i18n("KMail was unable to fully detect a mailing list in this folder. " 0216 "Please fill in the addresses by hand.")); 0217 } 0218 } else { 0219 mMLId->setText((mMailingList.id().isEmpty() ? i18n("Not available.") : mMailingList.id())); 0220 fillEditBox(); 0221 } 0222 } 0223 0224 //---------------------------------------------------------------------------- 0225 void CollectionMailingListPage::slotMLHandling(int element) 0226 { 0227 mMailingList.setHandler(static_cast<MailingList::Handler>(element)); 0228 slotConfigChanged(); 0229 } 0230 0231 //---------------------------------------------------------------------------- 0232 void CollectionMailingListPage::slotAddressChanged(int i) 0233 { 0234 fillMLFromWidgets(); 0235 fillEditBox(); 0236 mLastItem = i; 0237 slotConfigChanged(); 0238 } 0239 0240 //---------------------------------------------------------------------------- 0241 void CollectionMailingListPage::fillMLFromWidgets() 0242 { 0243 if (!mHoldsMailingList->isChecked()) { 0244 return; 0245 } 0246 0247 // make sure that email addresses are prepended by "mailto:" 0248 bool listChanged = false; 0249 const QStringList oldList = mEditList->items(); 0250 QStringList newList; // the correct string list 0251 QStringList::ConstIterator end = oldList.constEnd(); 0252 for (QStringList::ConstIterator it = oldList.constBegin(); it != end; ++it) { 0253 if (!(*it).startsWith(QLatin1StringView("http:")) && !(*it).startsWith(QLatin1StringView("https:")) && !(*it).startsWith(QLatin1StringView("mailto:")) 0254 && ((*it).contains(QLatin1Char('@')))) { 0255 listChanged = true; 0256 newList << QStringLiteral("mailto:") + *it; 0257 } else { 0258 newList << *it; 0259 } 0260 } 0261 if (listChanged) { 0262 mEditList->clear(); 0263 mEditList->insertStringList(newList); 0264 } 0265 0266 // mMailingList.setHandler( static_cast<MailingList::Handler>( mMLHandlerCombo->currentIndex() ) ); 0267 switch (mLastItem) { 0268 case 0: 0269 mMailingList.setPostUrls(QUrl::fromStringList(mEditList->items())); 0270 break; 0271 case 1: 0272 mMailingList.setSubscribeUrls(QUrl::fromStringList(mEditList->items())); 0273 break; 0274 case 2: 0275 mMailingList.setUnsubscribeUrls(QUrl::fromStringList(mEditList->items())); 0276 break; 0277 case 3: 0278 mMailingList.setArchiveUrls(QUrl::fromStringList(mEditList->items())); 0279 break; 0280 case 4: 0281 mMailingList.setHelpUrls(QUrl::fromStringList(mEditList->items())); 0282 break; 0283 default: 0284 qCWarning(KMAIL_LOG) << "Wrong entry in the mailing list entry combo!"; 0285 } 0286 } 0287 0288 void CollectionMailingListPage::fillEditBox() 0289 { 0290 mEditList->clear(); 0291 switch (mAddressCombo->currentIndex()) { 0292 case 0: 0293 mEditList->insertStringList(QUrl::toStringList(mMailingList.postUrls())); 0294 break; 0295 case 1: 0296 mEditList->insertStringList(QUrl::toStringList(mMailingList.subscribeUrls())); 0297 break; 0298 case 2: 0299 mEditList->insertStringList(QUrl::toStringList(mMailingList.unsubscribeUrls())); 0300 break; 0301 case 3: 0302 mEditList->insertStringList(QUrl::toStringList(mMailingList.archiveUrls())); 0303 break; 0304 case 4: 0305 mEditList->insertStringList(QUrl::toStringList(mMailingList.helpUrls())); 0306 break; 0307 default: 0308 qCWarning(KMAIL_LOG) << "Wrong entry in the mailing list entry combo!"; 0309 } 0310 } 0311 0312 void CollectionMailingListPage::slotInvokeHandler() 0313 { 0314 save(mCurrentCollection); 0315 switch (mAddressCombo->currentIndex()) { 0316 case 0: 0317 if (!KMail::Util::mailingListPost(mFolder, mCurrentCollection)) { 0318 qCWarning(KMAIL_LOG) << "invalid folder"; 0319 } 0320 break; 0321 case 1: 0322 if (!KMail::Util::mailingListSubscribe(mFolder, mCurrentCollection)) { 0323 qCWarning(KMAIL_LOG) << "invalid folder"; 0324 } 0325 break; 0326 case 2: 0327 if (!KMail::Util::mailingListUnsubscribe(mFolder, mCurrentCollection)) { 0328 qCWarning(KMAIL_LOG) << "invalid folder"; 0329 } 0330 break; 0331 case 3: 0332 if (!KMail::Util::mailingListArchives(mFolder, mCurrentCollection)) { 0333 qCWarning(KMAIL_LOG) << "invalid folder"; 0334 } 0335 break; 0336 case 4: 0337 if (!KMail::Util::mailingListHelp(mFolder, mCurrentCollection)) { 0338 qCWarning(KMAIL_LOG) << "invalid folder"; 0339 } 0340 break; 0341 default: 0342 qCWarning(KMAIL_LOG) << "Wrong entry in the mailing list entry combo!"; 0343 } 0344 } 0345 0346 #include "moc_collectionmailinglistpage.cpp"