File indexing completed on 2025-01-19 04:52:00
0001 /* 0002 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com> 0003 0004 This library is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to the 0016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301, USA. 0018 */ 0019 #include "recepientautocompletionmodel.h" 0020 0021 #include <QStandardItemModel> 0022 #include <QSettings> 0023 #include <QStandardPaths> 0024 #include <QSet> 0025 #include <QDebug> 0026 #include <QTimer> 0027 #include <KMime/Message> 0028 #include <sink/store.h> 0029 #include <sink/applicationdomaintype.h> 0030 0031 using namespace Sink::ApplicationDomain; 0032 0033 RecipientAutocompletionModel::RecipientAutocompletionModel(QObject *parent) 0034 : QSortFilterProxyModel(parent), 0035 mSourceModel(new QStandardItemModel), 0036 mTimer(new QTimer) 0037 { 0038 setSourceModel(mSourceModel.data()); 0039 setDynamicSortFilter(true); 0040 setFilterCaseSensitivity(Qt::CaseInsensitive); 0041 mTimer->setSingleShot(true); 0042 QObject::connect(mTimer.data(), &QTimer::timeout, this, &RecipientAutocompletionModel::save); 0043 0044 load(); 0045 } 0046 0047 RecipientAutocompletionModel::~RecipientAutocompletionModel() 0048 { 0049 save(); 0050 } 0051 0052 static QString getPath() 0053 { 0054 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kube/recepientautocompletion.ini"; 0055 } 0056 0057 void RecipientAutocompletionModel::save() 0058 { 0059 QSet<QString> list; 0060 for (int row = 0; row < mSourceModel->rowCount(); row++) { 0061 list << mSourceModel->item(row)->data(Text).toString(); 0062 } 0063 0064 QSettings settings(getPath(), QSettings::IniFormat); 0065 settings.setValue("list", QStringList{list.values()}); 0066 } 0067 0068 void RecipientAutocompletionModel::load() 0069 { 0070 QSettings settings(getPath(), QSettings::IniFormat); 0071 auto list = settings.value("list").toStringList(); 0072 auto add = [] (const QString &n) { 0073 auto item = new QStandardItem{n}; 0074 item->setData(n, Text); 0075 return item; 0076 }; 0077 for (const auto &entry : list) { 0078 //Validate entries because we used to write unquoted nonsense like "Doe, John doe@example.com" 0079 KMime::Types::Mailbox mb; 0080 mb.fromUnicodeString(entry); 0081 if (mb.address().isEmpty()) { 0082 continue; 0083 } 0084 mSourceModel->appendRow(add(entry)); 0085 } 0086 Sink::Query query; 0087 query.request<Contact::Fn>(); 0088 query.request<Contact::Emails>(); 0089 Sink::Store::fetchAll<Contact>(query) 0090 .then([this] (const QList<Contact::Ptr> &list) { 0091 for (const auto &c : list) { 0092 for (const auto &email : c->getEmails()) { 0093 addToModel(email.email, c->getFn()); 0094 } 0095 } 0096 }).exec(); 0097 } 0098 0099 QHash< int, QByteArray > RecipientAutocompletionModel::roleNames() const 0100 { 0101 QHash<int, QByteArray> roles; 0102 roles[Text] = "text"; 0103 roles[Color] = "color"; 0104 return roles; 0105 } 0106 0107 0108 bool RecipientAutocompletionModel::addToModel(const QString &address, const QString &name) 0109 { 0110 auto add = [] (const QString &n) { 0111 auto item = new QStandardItem{n}; 0112 item->setData(n, Text); 0113 return item; 0114 }; 0115 auto formattedName = [&] () { 0116 if (name.isEmpty()) { 0117 return address; 0118 } 0119 KMime::Types::Mailbox mb; 0120 mb.setName(name); 0121 mb.setAddress(address.toUtf8()); 0122 return mb.prettyAddress(KMime::Types::Mailbox::QuoteWhenNecessary); 0123 }(); 0124 auto matches = mSourceModel->findItems(formattedName); 0125 if (matches.isEmpty()) { 0126 mSourceModel->appendRow(add(formattedName)); 0127 return true; 0128 } 0129 return false; 0130 } 0131 0132 void RecipientAutocompletionModel::addEntry(const QByteArray &address, const QByteArray &name) 0133 { 0134 if (addToModel(address, name)) { 0135 mTimer->start(100); 0136 } 0137 } 0138 0139 void RecipientAutocompletionModel::setFilter(const QString &filter) 0140 { 0141 setFilterWildcard("*" + filter +"*"); 0142 }