File indexing completed on 2024-11-10 04:50:03
0001 /* 0002 * SPDX-FileCopyrightText: 1996-1998 Stefan Taferner <taferner@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 * 0006 */ 0007 0008 #include "filteractionaddtoaddressbook.h" 0009 0010 #include <Akonadi/AddContactJob> 0011 0012 #include <Akonadi/TagSelectionDialog> 0013 #include <Akonadi/TagWidget> 0014 0015 #include <Akonadi/CollectionComboBox> 0016 #include <KComboBox> 0017 #include <KContacts/Addressee> 0018 #include <KEmailAddress> 0019 #include <KLocalizedString> 0020 0021 #include <QGridLayout> 0022 #include <QLabel> 0023 0024 using namespace MailCommon; 0025 0026 FilterAction *FilterActionAddToAddressBook::newAction() 0027 { 0028 return new FilterActionAddToAddressBook; 0029 } 0030 0031 FilterActionAddToAddressBook::FilterActionAddToAddressBook(QObject *parent) 0032 : FilterActionWithStringList(QStringLiteral("add to address book"), i18n("Add to Address Book"), parent) 0033 , mFromStr(i18nc("Email sender", "From")) 0034 , mToStr(i18nc("Email recipient", "To")) 0035 , mCCStr(i18n("CC")) 0036 , mBCCStr(i18n("BCC")) 0037 , mHeaderType(UnknownHeader) 0038 , mCollectionId(-1) 0039 , mCategory(i18n("KMail Filter")) 0040 { 0041 } 0042 0043 bool FilterActionAddToAddressBook::isEmpty() const 0044 { 0045 return (mCollectionId == -1) || (mHeaderType == UnknownHeader); 0046 } 0047 0048 FilterAction::ReturnCode FilterActionAddToAddressBook::process(ItemContext &context, bool) const 0049 { 0050 if (isEmpty()) { 0051 return ErrorButGoOn; 0052 } 0053 0054 const auto msg = context.item().payload<KMime::Message::Ptr>(); 0055 0056 QString headerLine; 0057 switch (mHeaderType) { 0058 case FromHeader: 0059 headerLine = msg->from()->asUnicodeString(); 0060 break; 0061 case ToHeader: 0062 headerLine = msg->to()->asUnicodeString(); 0063 break; 0064 case CcHeader: 0065 headerLine = msg->cc()->asUnicodeString(); 0066 break; 0067 case BccHeader: 0068 headerLine = msg->bcc()->asUnicodeString(); 0069 break; 0070 case UnknownHeader: 0071 break; 0072 } 0073 if (headerLine.isEmpty()) { 0074 return ErrorButGoOn; 0075 } 0076 0077 const QStringList emails = KEmailAddress::splitAddressList(headerLine); 0078 0079 for (const QString &singleEmail : emails) { 0080 QString name; 0081 QString emailString; 0082 KContacts::Addressee::parseEmailAddress(singleEmail, name, emailString); 0083 0084 KContacts::Addressee contact; 0085 contact.setNameFromString(name); 0086 KContacts::Email email(emailString); 0087 email.setPreferred(true); 0088 contact.addEmail(email); 0089 if (!mCategory.isEmpty()) { 0090 contact.setCategories(mCategory.split(QLatin1Char(';'))); 0091 } 0092 0093 auto job = new Akonadi::AddContactJob(contact, Akonadi::Collection(mCollectionId)); 0094 job->showMessageBox(false); 0095 job->start(); 0096 } 0097 0098 return GoOn; 0099 } 0100 0101 SearchRule::RequiredPart FilterActionAddToAddressBook::requiredPart() const 0102 { 0103 return SearchRule::Envelope; 0104 } 0105 0106 QWidget *FilterActionAddToAddressBook::createParamWidget(QWidget *parent) const 0107 { 0108 auto widget = new QWidget(parent); 0109 auto layout = new QGridLayout(widget); 0110 0111 const auto headerCombo = new KComboBox(widget); 0112 headerCombo->setMinimumWidth(50); 0113 headerCombo->setObjectName(QLatin1StringView("HeaderComboBox")); 0114 layout->addWidget(headerCombo, 0, 0, 2, 1, Qt::AlignVCenter); 0115 0116 auto label = new QLabel(i18n("with category"), widget); 0117 label->setObjectName(QLatin1StringView("label_with_category")); 0118 layout->addWidget(label, 0, 1); 0119 0120 auto categoryEdit = new Akonadi::TagWidget(widget); 0121 categoryEdit->setObjectName(QLatin1StringView("CategoryEdit")); 0122 layout->addWidget(categoryEdit, 0, 2); 0123 0124 label = new QLabel(i18n("in address book"), widget); 0125 label->setObjectName(QLatin1StringView("label_in_addressbook")); 0126 layout->addWidget(label, 1, 1); 0127 0128 auto collectionComboBox = new Akonadi::CollectionComboBox(widget); 0129 collectionComboBox->setMimeTypeFilter(QStringList() << KContacts::Addressee::mimeType()); 0130 collectionComboBox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem); 0131 0132 collectionComboBox->setObjectName(QLatin1StringView("AddressBookComboBox")); 0133 collectionComboBox->setToolTip( 0134 i18n("This defines the preferred address book.\n" 0135 "If it is not accessible, the filter will fallback to the default address book.")); 0136 layout->addWidget(collectionComboBox, 1, 2); 0137 connect(headerCombo, &KComboBox::currentIndexChanged, this, &FilterActionAddToAddressBook::filterActionModified); 0138 connect(collectionComboBox, &Akonadi::CollectionComboBox::activated, this, &FilterActionAddToAddressBook::filterActionModified); 0139 connect(categoryEdit, &Akonadi::TagWidget::selectionChanged, this, &FilterActionAddToAddressBook::filterActionModified); 0140 0141 setParamWidgetValue(widget); 0142 0143 return widget; 0144 } 0145 0146 namespace 0147 { 0148 Akonadi::Tag::List namesToTags(const QStringList &names) 0149 { 0150 Akonadi::Tag::List tags; 0151 tags.reserve(names.size()); 0152 std::transform(names.cbegin(), names.cend(), std::back_inserter(tags), [](const QString &name) { 0153 return Akonadi::Tag{name}; 0154 }); 0155 return tags; 0156 } 0157 0158 QStringList tagsToNames(const Akonadi::Tag::List &tags) 0159 { 0160 QStringList names; 0161 names.reserve(tags.size()); 0162 std::transform(tags.cbegin(), tags.cend(), std::back_inserter(names), std::bind(&Akonadi::Tag::name, std::placeholders::_1)); 0163 return names; 0164 } 0165 } 0166 0167 void FilterActionAddToAddressBook::setParamWidgetValue(QWidget *paramWidget) const 0168 { 0169 const auto headerCombo = paramWidget->findChild<KComboBox *>(QStringLiteral("HeaderComboBox")); 0170 Q_ASSERT(headerCombo); 0171 headerCombo->clear(); 0172 headerCombo->addItem(mFromStr, FromHeader); 0173 headerCombo->addItem(mToStr, ToHeader); 0174 headerCombo->addItem(mCCStr, CcHeader); 0175 headerCombo->addItem(mBCCStr, BccHeader); 0176 0177 headerCombo->setCurrentIndex(headerCombo->findData(mHeaderType)); 0178 0179 auto categoryEdit = paramWidget->findChild<Akonadi::TagWidget *>(QStringLiteral("CategoryEdit")); 0180 Q_ASSERT(categoryEdit); 0181 categoryEdit->setSelection(namesToTags(mCategory.split(QLatin1Char(';')))); 0182 0183 auto collectionComboBox = paramWidget->findChild<Akonadi::CollectionComboBox *>(QStringLiteral("AddressBookComboBox")); 0184 Q_ASSERT(collectionComboBox); 0185 collectionComboBox->setDefaultCollection(Akonadi::Collection(mCollectionId)); 0186 collectionComboBox->setProperty("collectionId", mCollectionId); 0187 } 0188 0189 void FilterActionAddToAddressBook::applyParamWidgetValue(QWidget *paramWidget) 0190 { 0191 const auto headerCombo = paramWidget->findChild<QComboBox *>(QStringLiteral("HeaderComboBox")); 0192 Q_ASSERT(headerCombo); 0193 mHeaderType = static_cast<HeaderType>(headerCombo->itemData(headerCombo->currentIndex()).toInt()); 0194 0195 const auto categoryEdit = paramWidget->findChild<Akonadi::TagWidget *>(QStringLiteral("CategoryEdit")); 0196 Q_ASSERT(categoryEdit); 0197 mCategory = tagsToNames(categoryEdit->selection()).join(QLatin1Char(';')); 0198 0199 const Akonadi::CollectionComboBox *collectionComboBox = paramWidget->findChild<Akonadi::CollectionComboBox *>(QStringLiteral("AddressBookComboBox")); 0200 Q_ASSERT(collectionComboBox); 0201 const Akonadi::Collection collection = collectionComboBox->currentCollection(); 0202 0203 // it might be that the model of collectionComboBox has not finished loading yet, so 0204 // we use the previously 'stored' value from the 'collectionId' property 0205 if (collection.isValid()) { 0206 mCollectionId = collection.id(); 0207 connect(collectionComboBox, &Akonadi::CollectionComboBox::currentIndexChanged, this, &FilterActionAddToAddressBook::filterActionModified); 0208 } else { 0209 const QVariant value = collectionComboBox->property("collectionId"); 0210 if (value.isValid()) { 0211 mCollectionId = value.toLongLong(); 0212 } 0213 } 0214 } 0215 0216 void FilterActionAddToAddressBook::clearParamWidget(QWidget *paramWidget) const 0217 { 0218 const auto headerCombo = paramWidget->findChild<QComboBox *>(QStringLiteral("HeaderComboBox")); 0219 Q_ASSERT(headerCombo); 0220 headerCombo->setCurrentIndex(0); 0221 0222 auto categoryEdit = paramWidget->findChild<Akonadi::TagWidget *>(QStringLiteral("CategoryEdit")); 0223 Q_ASSERT(categoryEdit); 0224 categoryEdit->setSelection(namesToTags(mCategory.split(QLatin1Char(';')))); 0225 } 0226 0227 QString FilterActionAddToAddressBook::argsAsString() const 0228 { 0229 QString result; 0230 0231 switch (mHeaderType) { 0232 case FromHeader: 0233 result = QStringLiteral("From"); 0234 break; 0235 case ToHeader: 0236 result = QStringLiteral("To"); 0237 break; 0238 case CcHeader: 0239 result = QStringLiteral("CC"); 0240 break; 0241 case BccHeader: 0242 result = QStringLiteral("BCC"); 0243 break; 0244 case UnknownHeader: 0245 break; 0246 } 0247 0248 result += QLatin1Char('\t'); 0249 result += QString::number(mCollectionId); 0250 result += QLatin1Char('\t'); 0251 result += mCategory; 0252 0253 return result; 0254 } 0255 0256 void FilterActionAddToAddressBook::argsFromString(const QString &argsStr) 0257 { 0258 const QStringList parts = argsStr.split(QLatin1Char('\t'), Qt::KeepEmptyParts); 0259 const QString firstElement = parts[0]; 0260 if (firstElement == QLatin1StringView("From")) { 0261 mHeaderType = FromHeader; 0262 } else if (firstElement == QLatin1StringView("To")) { 0263 mHeaderType = ToHeader; 0264 } else if (firstElement == QLatin1StringView("CC")) { 0265 mHeaderType = CcHeader; 0266 } else if (firstElement == QLatin1StringView("BCC")) { 0267 mHeaderType = BccHeader; 0268 } else { 0269 mHeaderType = UnknownHeader; 0270 } 0271 if (parts.count() >= 2) { 0272 mCollectionId = parts[1].toLongLong(); 0273 } 0274 0275 if (parts.count() < 3) { 0276 mCategory.clear(); 0277 } else { 0278 mCategory = parts[2]; 0279 } 0280 } 0281 0282 QString FilterActionAddToAddressBook::informationAboutNotValidAction() const 0283 { 0284 QString result; 0285 if (mHeaderType == UnknownHeader) { 0286 result = i18n("Header type selected is unknown."); 0287 } 0288 if (mCollectionId == -1) { 0289 if (!result.isEmpty()) { 0290 result += QLatin1Char('\n'); 0291 } 0292 result += i18n("No addressbook selected."); 0293 } 0294 return result; 0295 } 0296 0297 #include "moc_filteractionaddtoaddressbook.cpp"