File indexing completed on 2025-01-05 04:58:19
0001 /* 0002 This file is part of libkdepim. 0003 0004 SPDX-FileCopyrightText: 2006 Christian Schaarschmidt <schaarsc@gmx.de> 0005 SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "kmailcompletion.h" 0011 #include <QRegularExpression> 0012 #include <QSet> 0013 0014 using namespace PimCommon; 0015 0016 KMailCompletion::KMailCompletion() 0017 { 0018 setIgnoreCase(true); 0019 } 0020 0021 void KMailCompletion::clear() 0022 { 0023 m_keyMap.clear(); 0024 KCompletion::clear(); 0025 } 0026 0027 QString KMailCompletion::makeCompletion(const QString &string) 0028 { 0029 QString match = KCompletion::makeCompletion(string); 0030 0031 static const QRegularExpression emailRegularExpression{QRegularExpression(QStringLiteral("(@)|(<.*>)"))}; 0032 // this should be in postProcessMatch, but postProcessMatch is const and will not allow nextMatch 0033 if (!match.isEmpty()) { 0034 const QString firstMatch(match); 0035 while (match.indexOf(emailRegularExpression) == -1) { 0036 /* local email do not require @domain part, if match is an address we'll 0037 * find last+first <match> in m_keyMap and we'll know that match is 0038 * already a valid email. 0039 * 0040 * Distribution list do not have last+first <match> entry, they will be 0041 * in mailAddr 0042 */ 0043 const QStringList &mailAddr = m_keyMap[match]; // get all mailAddr for this keyword 0044 bool isEmail = false; 0045 for (QStringList::ConstIterator sit(mailAddr.begin()), sEnd(mailAddr.end()); sit != sEnd; ++sit) { 0046 if ((*sit).indexOf(QLatin1Char('<') + match + QLatin1Char('>')) != -1 || (*sit) == match) { 0047 isEmail = true; 0048 break; 0049 } 0050 } 0051 0052 if (!isEmail) { 0053 // match is a keyword, skip it and try to find match <email@domain> 0054 match = nextMatch(); 0055 if (firstMatch == match) { 0056 match.clear(); 0057 break; 0058 } 0059 } else { 0060 break; 0061 } 0062 } 0063 } 0064 return match; 0065 } 0066 0067 void KMailCompletion::addItemWithKeys(const QString &email, int weight, const QStringList *keyWords) 0068 { 0069 Q_ASSERT(keyWords != nullptr); 0070 QStringList::ConstIterator end = keyWords->constEnd(); 0071 for (QStringList::ConstIterator it(keyWords->constBegin()); it != end; ++it) { 0072 QStringList &emailList = m_keyMap[(*it)]; // lookup email-list for given keyword 0073 if (!emailList.contains(email)) { // add email if not there 0074 emailList.append(email); 0075 } 0076 addItem((*it), weight); // inform KCompletion about keyword 0077 } 0078 } 0079 0080 void KMailCompletion::postProcessMatches(QStringList *pMatches) const 0081 { 0082 Q_ASSERT(pMatches != nullptr); 0083 if (pMatches->isEmpty()) { 0084 return; 0085 } 0086 0087 // KCompletion has found the keywords for us, we can now map them to mail-addr 0088 QSet<QString> mailAddrDistinct; 0089 for (QStringList::ConstIterator sit2(pMatches->begin()), sEnd2(pMatches->end()); sit2 != sEnd2; ++sit2) { 0090 const QStringList &mailAddr = m_keyMap[(*sit2)]; // get all mailAddr for this keyword 0091 if (mailAddr.isEmpty()) { 0092 mailAddrDistinct.insert(*sit2); 0093 } else { 0094 for (QStringList::ConstIterator sit(mailAddr.begin()), sEnd(mailAddr.end()); sit != sEnd; ++sit) { 0095 mailAddrDistinct.insert(*sit); // store mailAddr, QSet will make them unique 0096 } 0097 } 0098 } 0099 pMatches->clear(); // delete keywords 0100 (*pMatches) += mailAddrDistinct.values(); // add emailAddr 0101 } 0102 0103 #include "moc_kmailcompletion.cpp"