diff --git a/CMakeLists.txt b/CMakeLists.txt index f181c9a..ee0cf35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,81 +1,86 @@ cmake_minimum_required(VERSION 3.0) set(PIM_VERSION "5.10.2") project(libkdepim VERSION ${PIM_VERSION}) set(KF5_VERSION "5.51.0") find_package(ECM ${KF5_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) set(LIBRARY_NAMELINK) include(GenerateExportHeader) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) include(ECMAddTests) set(LIBKDEPIM_LIB_VERSION ${PIM_VERSION}) set(AKONADICONTACT_LIB_VERSION "5.10.2") set(QT_REQUIRED_VERSION "5.9.0") set(KLDAP_LIB_VERSION "5.10.2") set(KCONTACTS_LIB_VERSION "5.10.2") set(AKONADISEARCH_LIB_VERSION "5.10.2") set(AKONADI_VERSION "5.10.2") find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets Test DBus Network) find_package(KF5Codecs ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Completion ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5CoreAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ItemViews ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5JobWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KCMUtils ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Wallet ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADICONTACT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Contacts ${KCONTACTS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Ldap ${KLDAP_LIB_VERSION} CONFIG REQUIRED) +option(FORCE_DISABLE_AKONADI_SEARCH "Disable features and API that require akonadi-search, e.g. because xapian isn't available" OFF) +if (NOT FORCE_DISABLE_AKONADI_SEARCH) find_package(KF5AkonadiSearch ${AKONADISEARCH_LIB_VERSION} CONFIG REQUIRED) set_package_properties(KF5AkonadiSearch PROPERTIES DESCRIPTION "The Akonadi Search libraries" URL "http://www.kde.org" TYPE REQUIRED PURPOSE "Provides search capabilities in KMail and Akonadi") +endif() +set(DISABLE_AKONADI_SEARCH FORCE_DISABLE_AKONADI_SEARCH) +configure_file(config-akonadi-search.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/config-akonadi-search.h) find_package(KF5DesignerPlugin ${KF5_VERSION} CONFIG) set_package_properties(KF5DesignerPlugin PROPERTIES DESCRIPTION "KF5 designer plugin" TYPE OPTIONAL) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Libkdepim") configure_package_config_file(MailTransportDBusServiceConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/MailTransportDBusServiceConfig.cmake PATH_VARS KDE_INSTALL_DBUSINTERFACEDIR INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/MailTransportDBusService") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MailTransportDBusServiceConfig.cmake DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/MailTransportDBusService") add_subdirectory(src) install( FILES libkdepim.categories libkdepim.renamecategories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/config-akonadi-search.h.in b/config-akonadi-search.h.in new file mode 100644 index 0000000..d44dd92 --- /dev/null +++ b/config-akonadi-search.h.in @@ -0,0 +1 @@ +#cmakedefine01 DISABLE_AKONADI_SEARCH diff --git a/src/libkdepimakonadi/CMakeLists.txt b/src/libkdepimakonadi/CMakeLists.txt index f0e8335..b760fd5 100644 --- a/src/libkdepimakonadi/CMakeLists.txt +++ b/src/libkdepimakonadi/CMakeLists.txt @@ -1,232 +1,243 @@ ecm_setup_version(PROJECT VARIABLE_PREFIX LIBKDEPIM VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/libkdepimakonadi_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5LibkdepimAkonadiConfigVersion.cmake" SOVERSION 5 ) if(BUILD_TESTING) add_subdirectory(tests) - add_subdirectory(addressline/blacklistbaloocompletion/autotests) + if (NOT FORCE_DISABLE_AKONADI_SEARCH) + add_subdirectory(addressline/blacklistbaloocompletion/autotests) + endif() add_subdirectory(addressline/autotests/) endif() add_subdirectory(designer) set(kdepim_addressline_LIB_SRCS addressline/completionorder/completionordereditor.cpp addressline/completionorder/completionorderwidget.cpp addressline/addresslineedit/addresseelineedit.cpp addressline/addresslineedit/addresseelineedit_p.cpp addressline/addresslineedit/addresseelineeditmanager.cpp addressline/addresslineedit/addresseelineeditldap.cpp addressline/addresslineedit/addresseelineeditakonadi.cpp addressline/addresslineedit/addresseelineeditbaloo.cpp addressline/addresslineedit/kmailcompletion.cpp addressline/addresslineedit/baloocompletionemail.cpp addressline/completionconfiguredialog/completionconfiguredialog.cpp ) +if (NOT FORCE_DISABLE_AKONADI_SEARCH) set(kdepim_addressline_blacklist_baloo_LIB_SRCS addressline/blacklistbaloocompletion/blacklistbalooemaillist.cpp - addressline/blacklistbaloocompletion/blacklistbalooemailsearchjob.cpp addressline/blacklistbaloocompletion/blacklistbalooemailutil.cpp addressline/blacklistbaloocompletion/blacklistbalooemailcompletionwidget.cpp addressline/blacklistbaloocompletion/blacklistbalooemailwarning.cpp + addressline/blacklistbaloocompletion/blacklistbalooemailsearchjob.cpp ) +endif() set(kdepim_addressline_plugin_LIB_SRCS addressline/plugins/addressesslineeditabstractplugin.cpp addressline/plugins/addressesslineeditpluginmanager.cpp ) ############ next target ############### set(kdepimakonadi_progresswidget_LIB_SRCS progresswidget/progressmanagerakonadi.cpp progresswidget/agentprogressmonitor.cpp ) set(kdepim_job_LIB_SRCS job/addemailaddressjob.cpp job/addcontactjob.cpp job/openemailaddressjob.cpp job/addemaildisplayjob.cpp - job/collectionsearchjob.cpp - job/personsearchjob.cpp ) +if (NOT FORCE_DISABLE_AKONADI_SEARCH) + list(APPEND kdepim_job_LIB_SRCS + job/collectionsearchjob.cpp + job/personsearchjob.cpp + ) +endif() set(kdepimakonadi_widgets_LIB_SRCS widgets/tagwidgets.cpp widgets/tagselectioncombo.cpp ) set(kdepimakonadi_LIB_SRCS ${kdepim_job_LIB_SRCS} ${kdepimakonadi_widgets_LIB_SRCS} ${kdepim_addressline_LIB_SRCS} ${kdepim_addressline_blacklist_baloo_LIB_SRCS} ${kdepimakonadi_progresswidget_LIB_SRCS} ${kdepim_addressline_plugin_LIB_SRCS} ) ecm_qt_declare_logging_category(kdepimakonadi_LIB_SRCS HEADER libkdepimakonadi_debug.h IDENTIFIER LIBKDEPIMAKONADI_LOG CATEGORY_NAME org.kde.pim.libkdepimakonadi) add_library(KF5LibkdepimAkonadi ${kdepimakonadi_LIB_SRCS}) generate_export_header(KF5LibkdepimAkonadi BASE_NAME kdepimakonadi) add_library(KF5::LibkdepimAkonadi ALIAS KF5LibkdepimAkonadi) target_include_directories(KF5LibkdepimAkonadi INTERFACE "$") target_include_directories(KF5LibkdepimAkonadi PUBLIC "$") target_link_libraries(KF5LibkdepimAkonadi PUBLIC KF5::AkonadiCore KF5::AkonadiContact KF5::Libkdepim KF5::Completion PRIVATE KF5::AkonadiWidgets KF5::Ldap KF5::Contacts KF5::Codecs KF5::I18n KF5::ItemViews - KF5::AkonadiSearchPIM KF5::KIOCore KF5::KIOWidgets Qt5::DBus Qt5::Network KF5::ConfigWidgets ) if(MINGW) - target_link_libraries(KF5LibkdepimAkonadi oleaut32) + target_link_libraries(KF5LibkdepimAkonadi PRIVATE oleaut32) +endif() + +if (NOT FORCE_DISABLE_AKONADI_SEARCH) + target_link_libraries(KF5LibkdepimAkonadi PRIVATE KF5::AkonadiSearchPIM) endif() set_target_properties(KF5LibkdepimAkonadi PROPERTIES VERSION ${LIBKDEPIM_VERSION_STRING} SOVERSION ${LIBKDEPIM_SOVERSION} EXPORT_NAME LibkdepimAkonadi ) install(TARGETS KF5LibkdepimAkonadi EXPORT KF5LibkdepimAkonadiTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) ecm_generate_headers(libkdepimakonadi_Camelcasewidgets_HEADERS HEADER_NAMES TagSelectionCombo TagWidgets REQUIRED_HEADERS libkdepimakonadi_widgets_HEADERS PREFIX LibkdepimAkonadi RELATIVE widgets ) ecm_generate_headers(libkdepimakonadi_Camelcaseprogresswidget_HEADERS HEADER_NAMES ProgressManagerAkonadi REQUIRED_HEADERS libkdepimakonadi_progresswidget_HEADERS PREFIX LibkdepimAkonadi RELATIVE progresswidget ) ecm_generate_headers(libkdepim_Camelcasejob_HEADERS HEADER_NAMES AddContactJob AddEmailAddressJob AddEmailDisplayJob CollectionSearchJob OpenEmailAddressJob PersonSearchJob Person REQUIRED_HEADERS libkdepim_job_HEADERS PREFIX LibkdepimAkonadi RELATIVE job ) ecm_generate_headers(libkdepim_Camelcaseaddressline_HEADERS HEADER_NAMES AddresseeLineEdit REQUIRED_HEADERS libkdepim_addressline_HEADERS PREFIX LibkdepimAkonadi RELATIVE addressline/addresslineedit/ ) ecm_generate_headers(libkdepim_Camelcasecompletionorder_HEADERS HEADER_NAMES CompletionOrderEditor REQUIRED_HEADERS libkdepim_completionorder_HEADERS PREFIX LibkdepimAkonadi RELATIVE addressline/completionorder ) ecm_generate_headers(libkdepim_Camelcasecompletionconfiguredialog_HEADERS HEADER_NAMES CompletionConfigureDialog REQUIRED_HEADERS libkdepim_completionconfiguredialog_HEADERS PREFIX LibkdepimAkonadi RELATIVE addressline/completionconfiguredialog/ ) ecm_generate_pri_file(BASE_NAME LibkdepimAkonadi LIB_NAME KF5LibkdepimAkonadi DEPS "AkonadiCore AkonadiContact Libkdepim" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/LibkdepimAkonadi ) install(FILES ${libkdepim_Camelcasecompletionconfiguredialog_HEADERS} ${libkdepim_Camelcasecompletionorder_HEADERS} ${libkdepimakonadi_Camelcaseprogresswidget_HEADERS} ${libkdepimakonadi_Camelcasewidgets_HEADERS} ${libkdepim_Camelcasejob_HEADERS} ${libkdepim_Camelcaseaddressline_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/LibkdepimAkonadi COMPONENT Devel ) install(FILES ${libkdepim_completionconfiguredialog_HEADERS} ${libkdepim_completionorder_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/kdepimakonadi_export.h ${libkdepimakonadi_progresswidget_HEADERS} ${libkdepimakonadi_widgets_HEADERS} ${libkdepim_job_HEADERS} ${libkdepim_addressline_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/libkdepimakonadi COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5LibkdepimAkonadi") install(EXPORT KF5LibkdepimAkonadiTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5LibkdepimAkonadiTargets.cmake NAMESPACE KF5::) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5LibkdepimAkonadiConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5LibkdepimAkonadiConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5LibkdepimAkonadiConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5LibkdepimAkonadiConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libkdepimakonadi_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) diff --git a/src/libkdepimakonadi/addressline/addresslineedit/addresseelineedit_p.cpp b/src/libkdepimakonadi/addressline/addresslineedit/addresseelineedit_p.cpp index d5a2e4a..019512a 100644 --- a/src/libkdepimakonadi/addressline/addresslineedit/addresseelineedit_p.cpp +++ b/src/libkdepimakonadi/addressline/addresslineedit/addresseelineedit_p.cpp @@ -1,988 +1,993 @@ /* Copyright (c) 2015-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "addresseelineedit_p.h" #include "addressline/completionorder/completionordereditor.h" #include "addresseelineeditmanager.h" #include "addresseelineedit.h" #include "kmailcompletion.h" #include "libkdepimakonadi_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#if !DISABLE_AKONADI_SEARCH #include +#endif #include #include #include using namespace KPIM; AddresseeLineEditPrivate::AddresseeLineEditPrivate(KPIM::AddresseeLineEdit *qq, bool enableCompletion) : QObject(qq) , q(qq) , mRecentAddressConfig(nullptr) , mUseCompletion(enableCompletion) , mCompletionInitialized(false) , mSmartPaste(false) , mLastSearchMode(false) , mSearchExtended(false) , mUseSemicolonAsSeparator(false) , mEnableBalooSearch(true) , mEnableAkonadiSearch(true) , mExpandIntern(true) , mShowRecentAddresses(true) , mCanDeleteLineEdit(true) { mDelayedQueryTimer = new QTimer(this); mDelayedQueryTimer->setSingleShot(true); connect(mDelayedQueryTimer, &QTimer::timeout, this, &AddresseeLineEditPrivate::slotTriggerDelayedQueries); } AddresseeLineEditPrivate::~AddresseeLineEditPrivate() { if (AddresseeLineEditManager::self()->addressLineEdit() == q) { AddresseeLineEditManager::self()->stopLDAPLookup(); } } void AddresseeLineEditPrivate::restartTime(const QString &searchString) { if (useCompletion()) { AddresseeLineEditManager::self()->restartLdap(searchString, q); } } static const QString s_completionItemIndentString = QStringLiteral(" "); class SourceWithWeight { public: int weight; // the weight of the source int index; // index into AddresseeLineEditStatic::self()->completionSources QString sourceName; // the name of the source, e.g. "LDAP Server" bool operator<(const SourceWithWeight &other) const { if (weight > other.weight) { return true; } if (weight < other.weight) { return false; } return sourceName < other.sourceName; } }; void AddresseeLineEditPrivate::init() { if (mToolButton) { return; } mToolButton = new QToolButton(q); mToolButton->setVisible(false); mToolButton->setCursor(Qt::ArrowCursor); const int size = q->sizeHint().height() - 5; mToolButton->setFixedSize(size, size); int padding = (q->sizeHint().height() - size) / 2; mToolButton->move(2, padding); mToolButton->setStyleSheet(QStringLiteral("QToolButton { border: none; }")); connect(mToolButton, &QToolButton::clicked, q, &AddresseeLineEdit::iconClicked); if (!AddresseeLineEditManager::self()) { AddresseeLineEditManager::self()->completion()->setOrder(KCompletion::Weighted); AddresseeLineEditManager::self()->completion()->setIgnoreCase(true); } if (mUseCompletion) { AddresseeLineEditManager::self()->initializeLdap(); AddresseeLineEditManager::self()->setBalooCompletionSource(q->addCompletionSource(i18nc("@title:group", "Contacts found in your data"), -1)); AddresseeLineEditManager::self()->updateLDAPWeights(); if (!mCompletionInitialized) { q->setCompletionObject(AddresseeLineEditManager::self()->completion(), false); connect(q, &KLineEdit::completion, this, &AddresseeLineEditPrivate::slotCompletion); connect(q, &AddresseeLineEdit::returnPressed, this, &AddresseeLineEditPrivate::slotReturnPressed); KCompletionBox *box = q->completionBox(); connect(box, QOverload::of(&KCompletionBox::activated), this, &AddresseeLineEditPrivate::slotPopupCompletion); connect(box, &KCompletionBox::userCancelled, this, &AddresseeLineEditPrivate::slotUserCancelled); connect(AddresseeLineEditManager::self()->ldapTimer(), &QTimer::timeout, this, &AddresseeLineEditPrivate::slotStartLDAPLookup); connect(AddresseeLineEditManager::self()->ldapSearch(), QOverload::of(&KLDAP::LdapClientSearch::searchData), this, &AddresseeLineEditPrivate::slotLDAPSearchData); mCompletionInitialized = true; } } connect(q, &AddresseeLineEdit::textCompleted, q, &AddresseeLineEdit::slotEditingFinished); connect(q, &AddresseeLineEdit::editingFinished, q, &AddresseeLineEdit::slotEditingFinished); } void AddresseeLineEditPrivate::setIcon(const QIcon &icon, const QString &tooltip) { if (icon.isNull()) { mToolButton->setVisible(false); q->setStyleSheet(QString()); } else { mToolButton->setIcon(icon); mToolButton->setToolTip(tooltip); const int padding = mToolButton->width() - q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); q->setStyleSheet(QStringLiteral("QLineEdit { padding-left: %1px }").arg(padding)); mToolButton->setVisible(true); } } void AddresseeLineEditPrivate::searchInBaloo() { +#if !DISABLE_AKONADI_SEARCH const QString trimmedString = mSearchString.trimmed(); Akonadi::Search::PIM::ContactCompleter com(trimmedString, 20); const QStringList listEmail = AddresseeLineEditManager::self()->cleanupEmailList(com.complete()); for (const QString &email : listEmail) { addCompletionItem(email, 1, AddresseeLineEditManager::self()->balooCompletionSource()); } doCompletion(mLastSearchMode); +#endif } void AddresseeLineEditPrivate::setCompletedItems(const QStringList &items, bool autoSuggest) { KCompletionBox *completionBox = q->completionBox(); if (!items.isEmpty() && !(items.count() == 1 && mSearchString == items.first())) { completionBox->clear(); const int numberOfItems(items.count()); for (int i = 0; i < numberOfItems; ++i) { QListWidgetItem *item = new QListWidgetItem(items.at(i), completionBox); if (!items.at(i).startsWith(s_completionItemIndentString)) { item->setFlags(item->flags() & ~Qt::ItemIsSelectable); item->setBackgroundColor(AddresseeLineEditManager::self()->alternateColor()); } completionBox->addItem(item); } if (!completionBox->isVisible()) { if (!mSearchString.isEmpty()) { completionBox->setCancelledText(mSearchString); } completionBox->popup(); // we have to install the event filter after popup(), since that // calls show(), and that's where KCompletionBox installs its filter. // We want to be first, though, so do it now. if (AddresseeLineEditManager::self()->completion()->order() == KCompletion::Weighted) { qApp->installEventFilter(q); } } QListWidgetItem *item = completionBox->item(1); if (item) { completionBox->blockSignals(true); completionBox->setCurrentItem(item); item->setSelected(true); completionBox->blockSignals(false); } if (autoSuggest) { const int index = items.first().indexOf(mSearchString); const QString newText = items.first().mid(index); q->callSetUserSelection(false); q->callSetCompletedText(newText, true); } } else { if (completionBox && completionBox->isVisible()) { completionBox->hide(); completionBox->setItems(QStringList()); } } } void AddresseeLineEditPrivate::addCompletionItem(const QString &string, int weight, int completionItemSource, const QStringList *keyWords) { // Check if there is an exact match for item already, and use the // maximum weight if so. Since there's no way to get the information // from KCompletion, we have to keep our own QMap. // We also update the source since the item should always be shown from the source with the highest weight AddresseeLineEditManager::CompletionItemsMap::iterator it = AddresseeLineEditManager::self()->completionItemMap.find(string); if (it != AddresseeLineEditManager::self()->completionItemMap.end()) { weight = qMax((*it).first, weight); (*it).first = weight; (*it).second = completionItemSource; } else { AddresseeLineEditManager::self()->completionItemMap.insert(string, qMakePair(weight, completionItemSource)); } AddresseeLineEditManager::self()->completion()->addItem(string, weight); if (keyWords && !keyWords->isEmpty()) { AddresseeLineEditManager::self()->completion()->addItemWithKeys(string, weight, keyWords); // see kmailcompletion.cpp } } const QStringList KPIM::AddresseeLineEditPrivate::adjustedCompletionItems(bool fullSearch) { QStringList items = fullSearch ? AddresseeLineEditManager::self()->completion()->allMatches(mSearchString) : AddresseeLineEditManager::self()->completion()->substringCompletion(mSearchString); //force items to be sorted by email items.sort(); // For weighted mode, the algorithm is the following: // In the first loop, we add each item to its section (there is one section per completion source) // We also add spaces in front of the items. // The sections are appended to the items list. // In the second loop, we then walk through the sections and add all the items in there to the // sorted item list, which is the final result. // // The algo for non-weighted mode is different. int lastSourceIndex = -1; unsigned int i = 0; // Maps indices of the items list, which are section headers/source items, // to a QStringList which are the items of that section/source. QMap sections; QStringList sortedItems; for (QStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i) { AddresseeLineEditManager::CompletionItemsMap::const_iterator cit = AddresseeLineEditManager::self()->completionItemMap.constFind(*it); if (cit == AddresseeLineEditManager::self()->completionItemMap.constEnd()) { continue; } const int index = (*cit).second; if (AddresseeLineEditManager::self()->completion()->order() == KCompletion::Weighted) { if (lastSourceIndex == -1 || lastSourceIndex != index) { const QString sourceLabel(AddresseeLineEditManager::self()->completionSources.at(index)); if (sections.find(index) == sections.end()) { it = items.insert(it, sourceLabel); ++it; //skip new item } lastSourceIndex = index; } (*it) = (*it).prepend(s_completionItemIndentString); // remove preferred email sort added in addContact() (*it).replace(QLatin1String(" <"), QStringLiteral(" <")); } sections[ index ].append(*it); if (AddresseeLineEditManager::self()->completion()->order() == KCompletion::Sorted) { sortedItems.append(*it); } } if (AddresseeLineEditManager::self()->completion()->order() == KCompletion::Weighted) { // Sort the sections QVector sourcesAndWeights; const int numberOfCompletionSources(AddresseeLineEditManager::self()->completionSources.count()); sourcesAndWeights.reserve(numberOfCompletionSources); for (int i = 0; i < numberOfCompletionSources; ++i) { SourceWithWeight sww; sww.sourceName = AddresseeLineEditManager::self()->completionSources.at(i); sww.weight = AddresseeLineEditManager::self()->completionSourceWeights[sww.sourceName]; sww.index = i; sourcesAndWeights.append(sww); } std::sort(sourcesAndWeights.begin(), sourcesAndWeights.end()); // Add the sections and their items to the final sortedItems result list const int numberOfSources(sourcesAndWeights.size()); for (int i = 0; i < numberOfSources; ++i) { const SourceWithWeight source = sourcesAndWeights.at(i); const QStringList sectionItems = sections[source.index]; if (!sectionItems.isEmpty()) { sortedItems.append(source.sourceName); for (const QString &itemInSection : sectionItems) { sortedItems.append(itemInSection); } } } } else { sortedItems.sort(); } return sortedItems; } void AddresseeLineEditPrivate::updateSearchString() { mSearchString = q->text(); int n = -1; bool inQuote = false; const int searchStringLength = mSearchString.length(); for (int i = 0; i < searchStringLength; ++i) { const QChar searchChar = mSearchString.at(i); if (searchChar == QLatin1Char('"')) { inQuote = !inQuote; } if (searchChar == QLatin1Char('\\') && (i + 1) < searchStringLength && mSearchString.at(i + 1) == QLatin1Char('"')) { ++i; } if (inQuote) { continue; } if (i < searchStringLength && (searchChar == QLatin1Char(',') || (mUseSemicolonAsSeparator && searchChar == QLatin1Char(';')))) { n = i; } } if (n >= 0) { ++n; // Go past the "," const int len = mSearchString.length(); // Increment past any whitespace... while (n < len && mSearchString.at(n).isSpace()) { ++n; } mPreviousAddresses = mSearchString.left(n); mSearchString = mSearchString.mid(n).trimmed(); } else { mPreviousAddresses.clear(); } } void AddresseeLineEditPrivate::slotTriggerDelayedQueries() { const QString strSearch = mSearchString.trimmed(); if (strSearch.size() <= 2) { return; } if (mEnableBalooSearch) { searchInBaloo(); } // We send a contactsearch job through akonadi. // This not only searches baloo but also servers if remote search is enabled if (mEnableAkonadiSearch) { akonadiPerformSearch(); } } void AddresseeLineEditPrivate::startSearches() { if (!mDelayedQueryTimer->isActive()) { mDelayedQueryTimer->start(50); } } void AddresseeLineEditPrivate::akonadiPerformSearch() { qCDebug(LIBKDEPIMAKONADI_LOG) << "searching akonadi with:" << mSearchString; // first, kill all job still in flight, they are no longer current for (const QPointer &job : qAsConst(AddresseeLineEditManager::self()->akonadiJobsInFlight)) { if (!job.isNull()) { job.data()->kill(); } } AddresseeLineEditManager::self()->akonadiJobsInFlight.clear(); // now start new jobs Akonadi::ContactSearchJob *contactJob = new Akonadi::ContactSearchJob(AddresseeLineEditManager::self()->akonadiSession()); contactJob->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); contactJob->setQuery(Akonadi::ContactSearchJob::NameOrEmail, mSearchString, Akonadi::ContactSearchJob::ContainsWordBoundaryMatch); connect(contactJob, &Akonadi::ItemSearchJob::itemsReceived, this, &AddresseeLineEditPrivate::slotAkonadiHandleItems); connect(contactJob, &KJob::result, this, &AddresseeLineEditPrivate::slotAkonadiSearchResult); Akonadi::ContactGroupSearchJob *groupJob = new Akonadi::ContactGroupSearchJob(AddresseeLineEditManager::self()->akonadiSession()); groupJob->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); groupJob->setQuery(Akonadi::ContactGroupSearchJob::Name, mSearchString, Akonadi::ContactGroupSearchJob::ContainsMatch); connect(contactJob, &Akonadi::ItemSearchJob::itemsReceived, this, &AddresseeLineEditPrivate::slotAkonadiHandleItems); connect(groupJob, &KJob::result, this, &AddresseeLineEditPrivate::slotAkonadiSearchResult); AddresseeLineEditManager::self()->akonadiJobsInFlight.append(contactJob); AddresseeLineEditManager::self()->akonadiJobsInFlight.append(groupJob); akonadiHandlePending(); } void AddresseeLineEditPrivate::akonadiHandlePending() { qCDebug(LIBKDEPIMAKONADI_LOG) << "Pending items: " << AddresseeLineEditManager::self()->akonadiPendingItems.size(); Akonadi::Item::List::iterator it = AddresseeLineEditManager::self()->akonadiPendingItems.begin(); while (it != AddresseeLineEditManager::self()->akonadiPendingItems.end()) { const Akonadi::Item item = *it; const AddresseeLineEditManager::collectionInfo sourceIndex = AddresseeLineEditManager::self()->akonadiCollectionToCompletionSourceMap.value(item.parentCollection().id(), AddresseeLineEditManager::collectionInfo()); if (sourceIndex.index >= 0) { qCDebug(LIBKDEPIMAKONADI_LOG) << "identified collection: " << AddresseeLineEditManager::self()->completionSources[sourceIndex.index]; if (sourceIndex.enabled) { q->addItem(item, 1, sourceIndex.index); } // remove from the pending it = AddresseeLineEditManager::self()->akonadiPendingItems.erase(it); } else { ++it; } } } void AddresseeLineEditPrivate::doCompletion(bool ctrlT) { mLastSearchMode = ctrlT; const KCompletion::CompletionMode mode = q->completionMode(); if (mode == KCompletion::CompletionNone) { return; } AddresseeLineEditManager::self()->completion()->setOrder(KCompletion::Weighted); // cursor at end of string - or Ctrl+T pressed for substring completion? if (ctrlT) { const QStringList completions = adjustedCompletionItems(false); if (completions.count() == 1) { q->setText(mPreviousAddresses + completions.first().trimmed()); } // Make sure the completion popup is closed if no matching items were found setCompletedItems(completions, true); q->cursorAtEnd(); q->setCompletionMode(mode); //set back to previous mode return; } switch (mode) { case KCompletion::CompletionPopupAuto: if (mSearchString.isEmpty()) { break; } //else: fall-through to the CompletionPopup case Q_FALLTHROUGH(); case KCompletion::CompletionPopup: { const QStringList items = adjustedCompletionItems(false); setCompletedItems(items, false); break; } case KCompletion::CompletionShell: { const QString match = AddresseeLineEditManager::self()->completion()->makeCompletion(mSearchString); if (!match.isNull() && match != mSearchString) { q->setText(mPreviousAddresses + match); q->setModified(true); q->cursorAtEnd(); } break; } case KCompletion::CompletionMan: // Short-Auto in fact case KCompletion::CompletionAuto: //force autoSuggest in KLineEdit::keyPressed or setCompletedText will have no effect q->setCompletionMode(q->completionMode()); if (!mSearchString.isEmpty()) { //if only our \" is left, remove it since user has not typed it either if (mSearchExtended && mSearchString == QLatin1String("\"")) { mSearchExtended = false; mSearchString.clear(); q->setText(mPreviousAddresses); break; } QString match = AddresseeLineEditManager::self()->completion()->makeCompletion(mSearchString); if (!match.isEmpty()) { if (match != mSearchString) { const QString adds = mPreviousAddresses + match; q->callSetCompletedText(adds); } } else { if (!mSearchString.startsWith(QLatin1Char('\"'))) { //try with quoted text, if user has not type one already match = AddresseeLineEditManager::self()->completion()->makeCompletion(QLatin1String("\"") + mSearchString); if (!match.isEmpty() && match != mSearchString) { mSearchString = QLatin1String("\"") + mSearchString; mSearchExtended = true; q->setText(mPreviousAddresses + mSearchString); q->callSetCompletedText(mPreviousAddresses + match); } } else if (mSearchExtended) { //our added \" does not work anymore, remove it mSearchString = mSearchString.mid(1); mSearchExtended = false; q->setText(mPreviousAddresses + mSearchString); //now try again match = AddresseeLineEditManager::self()->completion()->makeCompletion(mSearchString); if (!match.isEmpty() && match != mSearchString) { const QString adds = mPreviousAddresses + match; q->setCompletedText(adds); } } } } break; case KCompletion::CompletionNone: break; } } void AddresseeLineEditPrivate::slotCompletion() { // Called by KLineEdit's keyPressEvent for CompletionModes // Auto,Popup -> new text, update search string. // not called for CompletionShell, this is been taken care of // in AddresseeLineEdit::keyPressEvent updateSearchString(); if (q->completionBox()) { q->completionBox()->setCancelledText(mSearchString); } startSearches(); doCompletion(false); } void AddresseeLineEditPrivate::slotPopupCompletion(const QString &completion) { QString c = completion.trimmed(); if (c.endsWith(QLatin1Char(')'))) { c = completion.mid(0, completion.lastIndexOf(QLatin1String(" ("))).trimmed(); } q->setText(mPreviousAddresses + c); q->cursorAtEnd(); updateSearchString(); q->emitTextCompleted(); } void AddresseeLineEditPrivate::slotReturnPressed(const QString &) { if (!q->completionBox()->selectedItems().isEmpty()) { slotPopupCompletion(q->completionBox()->selectedItems().constFirst()->text()); } } void AddresseeLineEditPrivate::slotStartLDAPLookup() { if (AddresseeLineEditManager::self()->isOnline()) { const KCompletion::CompletionMode mode = q->completionMode(); if (mode == KCompletion::CompletionNone) { return; } if (!AddresseeLineEditManager::self()->ldapSearch()->isAvailable()) { return; } if (AddresseeLineEditManager::self()->addressLineEdit() != q) { return; } AddresseeLineEditManager::self()->startLoadingLDAPEntries(); } } void AddresseeLineEditPrivate::slotLDAPSearchData(const KLDAP::LdapResult::List &results) { if (results.isEmpty() || AddresseeLineEditManager::self()->addressLineEdit() != q) { return; } for (const KLDAP::LdapResult &result : results) { KContacts::Addressee contact; contact.setNameFromString(result.name); contact.setEmails(result.email); QString ou; if (AddresseeLineEditManager::self()->showOU()) { const int depth = result.dn.depth(); for (int i = 0; i < depth; ++i) { const QString rdnStr = result.dn.rdnString(i); if (rdnStr.startsWith(QLatin1String("ou="), Qt::CaseInsensitive)) { ou = rdnStr.mid(3); break; } } } if (!AddresseeLineEditManager::self()->isLdapClientToCompletionSourceMapContains(result.clientNumber)) { AddresseeLineEditManager::self()->updateLDAPWeights(); // we got results from a new source, so update the completion sources } q->addContact(contact, result.completionWeight, AddresseeLineEditManager::self()->ldapClientToCompletionSourceValue(result.clientNumber), ou); } if ((q->hasFocus() || q->completionBox()->hasFocus()) && q->completionMode() != KCompletion::CompletionNone && q->completionMode() != KCompletion::CompletionShell) { q->setText(mPreviousAddresses + mSearchString); // only complete again if the user didn't change the selection while // we were waiting; otherwise the completion box will be closed const QListWidgetItem *current = q->completionBox()->currentItem(); if (!current || mSearchString.trimmed() != current->text().trimmed()) { doCompletion(mLastSearchMode); } } } void AddresseeLineEditPrivate::slotEditCompletionOrder() { if (mUseCompletion) { init(); // for AddresseeLineEditStatic::self()->ldapSearch QPointer dlg = new CompletionOrderEditor(AddresseeLineEditManager::self()->ldapSearch(), nullptr); if (dlg->exec()) { AddresseeLineEditManager::self()->updateCompletionOrder(); } delete dlg; } } KLDAP::LdapClientSearch *AddresseeLineEditPrivate::ldapSearch() { init(); // for AddresseeLineEditStatic::self()->ldapSearch return AddresseeLineEditManager::self()->ldapSearch(); } void AddresseeLineEditPrivate::slotUserCancelled(const QString &cancelText) { if (AddresseeLineEditManager::self()->addressLineEdit() == q) { AddresseeLineEditManager::self()->stopLDAPLookup(); } q->callUserCancelled(mPreviousAddresses + cancelText); // in KLineEdit } void AddresseeLineEditPrivate::slotAkonadiHandleItems(const Akonadi::Item::List &items) { /* We have to fetch the collections of the items, so that the source name can be correctly labeled.*/ for (const Akonadi::Item &item : items) { // check the local cache of collections const Akonadi::Collection::Id colId = item.parentCollection().id(); const AddresseeLineEditManager::collectionInfo sourceIndex = AddresseeLineEditManager::self()->akonadiCollectionToCompletionSourceMap.value(colId, AddresseeLineEditManager::collectionInfo()); if (sourceIndex.index == -1) { qCDebug(LIBKDEPIMAKONADI_LOG) << "Fetching New collection: " << colId; // the collection isn't there, start the fetch job. Akonadi::CollectionFetchJob *collectionJob = new Akonadi::CollectionFetchJob(item.parentCollection(), Akonadi::CollectionFetchJob::Base, AddresseeLineEditManager::self()->akonadiSession()); connect(collectionJob, &Akonadi::CollectionFetchJob::collectionsReceived, this, &AddresseeLineEditPrivate::slotAkonadiCollectionsReceived); /* we don't want to start multiple fetch jobs for the same collection, so insert the collection with an index value of -2 */ AddresseeLineEditManager::collectionInfo info; info.index = -2; AddresseeLineEditManager::self()->akonadiCollectionToCompletionSourceMap.insert(colId, info); AddresseeLineEditManager::self()->akonadiPendingItems.append(item); } else if (sourceIndex.index == -2) { /* fetch job already started, don't need to start another one, so just append the item as pending */ AddresseeLineEditManager::self()->akonadiPendingItems.append(item); } else { if (sourceIndex.enabled) { q->addItem(item, 1, sourceIndex.index); } } } if (!items.isEmpty()) { const QListWidgetItem *current = q->completionBox()->currentItem(); if (!current || mSearchString.trimmed() != current->text().trimmed()) { doCompletion(mLastSearchMode); } } } void AddresseeLineEditPrivate::slotAkonadiSearchResult(KJob *job) { if (job->error()) { qCWarning(LIBKDEPIMAKONADI_LOG) << "Akonadi search job failed: " << job->errorString(); } const int index = AddresseeLineEditManager::self()->akonadiJobsInFlight.indexOf(qobject_cast(job)); if (index != -1) { AddresseeLineEditManager::self()->akonadiJobsInFlight.remove(index); } } void AddresseeLineEditPrivate::slotAkonadiCollectionsReceived( const Akonadi::Collection::List &collections) { KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("kpimcompletionorder")); KConfigGroup groupCompletionWeights(config, "CompletionWeights"); KConfigGroup groupCompletionEnabled(config, "CompletionEnabled"); for (const Akonadi::Collection &collection : collections) { if (collection.isValid()) { const QString sourceString = collection.displayName(); const Akonadi::Collection::Id colId = collection.id(); const int weight = groupCompletionWeights.readEntry(QString::number(colId), 1); const int index = q->addCompletionSource(sourceString, weight); AddresseeLineEditManager::collectionInfo info(index, groupCompletionEnabled.readEntry(QString::number(colId), true)); qCDebug(LIBKDEPIMAKONADI_LOG) << "\treceived: " << sourceString << "index: " << index << " enabled: " << info.enabled; AddresseeLineEditManager::self()->akonadiCollectionToCompletionSourceMap.insert(colId, info); } } // now that we have added the new collections, recheck our list of pending contacts akonadiHandlePending(); // do completion const QListWidgetItem *current = q->completionBox()->currentItem(); if (!current || mSearchString.trimmed() != current->text().trimmed()) { doCompletion(mLastSearchMode); } } void AddresseeLineEditPrivate::slotToggleExpandGroups(bool checked) { AddresseeLineEditManager::self()->setAutoGroupExpand(checked); } void AddresseeLineEditPrivate::slotShowOUChanged(bool checked) { AddresseeLineEditManager::self()->setShowOU(checked); } void AddresseeLineEditPrivate::updateBalooBlackList() { AddresseeLineEditManager::self()->loadBalooBlackList(); q->removeCompletionSource(i18nc("@title:group", "Contacts found in your data")); AddresseeLineEditManager::self()->setBalooCompletionSource(q->addCompletionSource(i18nc("@title:group", "Contacts found in your data"), -1)); } void AddresseeLineEditPrivate::updateCompletionOrder() { AddresseeLineEditManager::self()->updateCompletionOrder(); } bool AddresseeLineEditPrivate::canDeleteLineEdit() const { return mCanDeleteLineEdit; } void AddresseeLineEditPrivate::setCanDeleteLineEdit(bool inprogressToConfigureCompletion) { mCanDeleteLineEdit = inprogressToConfigureCompletion; } KConfig *AddresseeLineEditPrivate::recentAddressConfig() const { return mRecentAddressConfig; } bool AddresseeLineEditPrivate::showRecentAddresses() const { return mShowRecentAddresses; } void AddresseeLineEditPrivate::setRecentAddressConfig(KConfig *config) { mRecentAddressConfig = config; } KContacts::ContactGroup::List AddresseeLineEditPrivate::groups() const { return mGroups; } void AddresseeLineEditPrivate::setGroups(const KContacts::ContactGroup::List &groups) { mGroups = groups; } QList AddresseeLineEditPrivate::mightBeGroupJobs() const { return mMightBeGroupJobs; } void AddresseeLineEditPrivate::setMightBeGroupJobs(const QList &mightBeGroupJobs) { mMightBeGroupJobs = mightBeGroupJobs; } bool AddresseeLineEditPrivate::autoGroupExpand() const { return AddresseeLineEditManager::self()->autoGroupExpand(); } void AddresseeLineEditPrivate::setAutoGroupExpand(bool autoGroupExpand) { AddresseeLineEditManager::self()->setAutoGroupExpand(autoGroupExpand); } void AddresseeLineEditPrivate::setExpandIntern(bool b) { mExpandIntern = b; } bool AddresseeLineEditPrivate::expandIntern() const { return mExpandIntern; } bool AddresseeLineEditPrivate::useSemicolonAsSeparator() const { return mUseSemicolonAsSeparator; } void AddresseeLineEditPrivate::setUseSemicolonAsSeparator(bool useSemicolonAsSeparator) { mUseSemicolonAsSeparator = useSemicolonAsSeparator; } bool AddresseeLineEditPrivate::enableBalooSearch() const { return mEnableBalooSearch; } void AddresseeLineEditPrivate::setEnableBalooSearch(bool enableBalooSearch) { mEnableBalooSearch = enableBalooSearch; } bool AddresseeLineEditPrivate::enableAkonadiSearch() const { return mEnableAkonadiSearch; } void AddresseeLineEditPrivate::setEnableAkonadiSearch(bool enableAkonadiSearch) { mEnableAkonadiSearch = enableAkonadiSearch; } QString AddresseeLineEditPrivate::searchString() const { return mSearchString; } void AddresseeLineEditPrivate::setSearchString(const QString &searchString) { mSearchString = searchString; } bool AddresseeLineEditPrivate::searchExtended() const { return mSearchExtended; } void AddresseeLineEditPrivate::setSearchExtended(bool searchExtended) { mSearchExtended = searchExtended; } bool AddresseeLineEditPrivate::smartPaste() const { return mSmartPaste; } void AddresseeLineEditPrivate::setSmartPaste(bool smartPaste) { mSmartPaste = smartPaste; } bool AddresseeLineEditPrivate::completionInitialized() const { return mCompletionInitialized; } bool AddresseeLineEditPrivate::useCompletion() const { return mUseCompletion; } void AddresseeLineEditPrivate::setUseCompletion(bool useCompletion) { mUseCompletion = useCompletion; } bool AddresseeLineEditPrivate::showOU() const { return AddresseeLineEditManager::self()->showOU(); } void AddresseeLineEditPrivate::removeCompletionSource(const QString &source) { AddresseeLineEditManager::self()->removeCompletionSource(source); } int AddresseeLineEditPrivate::addCompletionSource(const QString &source, int weight) { return AddresseeLineEditManager::self()->addCompletionSource(source, weight); } void AddresseeLineEditPrivate::mightBeGroupJobsClear() { mMightBeGroupJobs.clear(); } bool AddresseeLineEditPrivate::groupsIsEmpty() const { return mGroups.isEmpty(); } void AddresseeLineEditPrivate::setShowRecentAddresses(bool b) { mShowRecentAddresses = b; } void AddresseeLineEditPrivate::groupsClear() { mGroups.clear(); } void AddresseeLineEditPrivate::addGroups(const KContacts::ContactGroup::List &lst) { mGroups << lst; } void AddresseeLineEditPrivate::mightBeGroupJobsRemoveOne(Akonadi::ContactGroupSearchJob *search) { mMightBeGroupJobs.removeOne(search); } void AddresseeLineEditPrivate::mightBeGroupJobsAdd(Akonadi::ContactGroupSearchJob *job) { mMightBeGroupJobs.append(job); } diff --git a/src/libkdepimakonadi/addressline/completionconfiguredialog/completionconfiguredialog.cpp b/src/libkdepimakonadi/addressline/completionconfiguredialog/completionconfiguredialog.cpp index 81c22ff..2c8e05d 100644 --- a/src/libkdepimakonadi/addressline/completionconfiguredialog/completionconfiguredialog.cpp +++ b/src/libkdepimakonadi/addressline/completionconfiguredialog/completionconfiguredialog.cpp @@ -1,137 +1,150 @@ /* Copyright (c) 2015-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "completionconfiguredialog.h" #include #include #include #include #include #include #include #include +#include +#if !DISABLE_AKONADI_SEARCH #include +#endif #include using namespace KPIM; class KPIM::CompletionConfigureDialogPrivate { public: CompletionConfigureDialogPrivate() { } QTabWidget *mTabWidget = nullptr; KPIM::CompletionOrderWidget *mCompletionOrderWidget = nullptr; +#if !DISABLE_AKONADI_SEARCH KPIM::BlackListBalooEmailCompletionWidget *mBlackListBalooWidget = nullptr; +#endif KPIM::RecentAddressWidget *mRecentaddressWidget = nullptr; }; CompletionConfigureDialog::CompletionConfigureDialog(QWidget *parent) : QDialog(parent) , d(new KPIM::CompletionConfigureDialogPrivate) { setWindowTitle(i18n("Configure completion")); QVBoxLayout *mainLayout = new QVBoxLayout(this); d->mTabWidget = new QTabWidget; d->mTabWidget->setObjectName(QStringLiteral("tabwidget")); mainLayout->addWidget(d->mTabWidget); d->mCompletionOrderWidget = new KPIM::CompletionOrderWidget(); d->mCompletionOrderWidget->setObjectName(QStringLiteral("completionorder_widget")); d->mTabWidget->addTab(d->mCompletionOrderWidget, i18n("Completion Order")); d->mRecentaddressWidget = new KPIM::RecentAddressWidget; d->mRecentaddressWidget->setObjectName(QStringLiteral("recentaddress_widget")); d->mTabWidget->addTab(d->mRecentaddressWidget, i18n("Recent Address")); +#if !DISABLE_AKONADI_SEARCH d->mBlackListBalooWidget = new KPIM::BlackListBalooEmailCompletionWidget; d->mBlackListBalooWidget->setObjectName(QStringLiteral("blacklistbaloo_widget")); d->mTabWidget->addTab(d->mBlackListBalooWidget, i18n("Blacklist Email Address")); +#endif QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); buttonBox->setObjectName(QStringLiteral("buttonbox")); connect(buttonBox, &QDialogButtonBox::accepted, this, &CompletionConfigureDialog::slotSave); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); mainLayout->addWidget(buttonBox); readConfig(); } CompletionConfigureDialog::~CompletionConfigureDialog() { writeConfig(); delete d; } void CompletionConfigureDialog::readConfig() { KConfigGroup group(KSharedConfig::openConfig(), "CompletionConfigureDialog"); const QSize size = group.readEntry("Size", QSize(600, 400)); if (size.isValid()) { resize(size); } } void CompletionConfigureDialog::writeConfig() { KConfigGroup group(KSharedConfig::openConfig(), "CompletionConfigureDialog"); group.writeEntry("Size", size()); group.sync(); } void CompletionConfigureDialog::setRecentAddresses(const QStringList &lst) { d->mRecentaddressWidget->setAddresses(lst); } void CompletionConfigureDialog::setLdapClientSearch(KLDAP::LdapClientSearch *ldapSearch) { d->mCompletionOrderWidget->setLdapClientSearch(ldapSearch); } void CompletionConfigureDialog::load() { d->mCompletionOrderWidget->loadCompletionItems(); +#if !DISABLE_AKONADI_SEARCH d->mBlackListBalooWidget->load(); +#endif } bool CompletionConfigureDialog::recentAddressWasChanged() const { return d->mRecentaddressWidget->wasChanged(); } void CompletionConfigureDialog::storeAddresses(KConfig *config) { d->mRecentaddressWidget->storeAddresses(config); } void CompletionConfigureDialog::slotSave() { +#if !DISABLE_AKONADI_SEARCH d->mBlackListBalooWidget->save(); +#endif d->mCompletionOrderWidget->save(); accept(); } void CompletionConfigureDialog::setEmailBlackList(const QStringList &lst) { +#if !DISABLE_AKONADI_SEARCH d->mBlackListBalooWidget->setEmailBlackList(lst); +#endif }