diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f9950b1..2ce74d7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,226 +1,226 @@ include(CheckSymbolExists) include(CheckFunctionExists) check_function_exists(mmap HAVE_MMAP) check_symbol_exists(posix_madvise "sys/mman.h" HAVE_MADVISE) configure_file(config-ksycoca.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ksycoca.h ) set(kservice_SRCS kdeinit/ktoolinvocation.cpp services/kautostart.cpp services/kmimetypefactory.cpp services/kmimetypetrader.cpp services/kservice.cpp services/kserviceaction.cpp services/kservicefactory.cpp services/kservicegroup.cpp services/kservicegroupfactory.cpp services/kserviceoffer.cpp services/kservicetype.cpp services/kservicetypefactory.cpp services/kservicetypeprofile.cpp services/kservicetypetrader.cpp services/ktraderparse.cpp services/ktraderparsetree.cpp services/kplugininfo.cpp sycoca/ksycoca.cpp sycoca/ksycocadevices.cpp sycoca/ksycocadict.cpp sycoca/ksycocaentry.cpp sycoca/ksycocafactory.cpp sycoca/kmemfile.cpp sycoca/kbuildmimetypefactory.cpp sycoca/kbuildservicetypefactory.cpp sycoca/kbuildservicefactory.cpp sycoca/kbuildservicegroupfactory.cpp sycoca/kbuildsycoca.cpp sycoca/kctimefactory.cpp sycoca/kmimeassociations.cpp sycoca/vfolder_menu.cpp plugin/kplugintrader.cpp ) if (TARGET Qt5::DBus) list(APPEND kservice_SRCS plugin/kdbusservicestarter.cpp) endif() ecm_qt_declare_logging_category(kservice_SRCS HEADER servicesdebug.h IDENTIFIER SERVICES CATEGORY_NAME kf5.kservice.services) ecm_qt_declare_logging_category(kservice_SRCS HEADER sycocadebug.h IDENTIFIER SYCOCA CATEGORY_NAME kf5.kservice.sycoca) if (WIN32) LIST(APPEND kservice_SRCS kdeinit/ktoolinvocation_win.cpp ) endif() if (UNIX) LIST(APPEND kservice_SRCS kdeinit/ktoolinvocation_x11.cpp ) endif() bison_target(TraderParser services/yacc.y ${CMAKE_CURRENT_BINARY_DIR}/yacc.c COMPILE_FLAGS "-p kiotrader -d" ) flex_target(TraderLexer services/lex.l ${CMAKE_CURRENT_BINARY_DIR}/lex.c COMPILE_FLAGS "-Pkiotrader -B -i" ) add_flex_bison_dependency(TraderLexer TraderParser) list(APPEND kservice_SRCS ${BISON_TraderParser_OUTPUTS} ${FLEX_TraderLexer_OUTPUTS}) set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/yacc.h PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file # kservice cannot depend on kinit (because kinit->kio->kservice), so we need a copy of org.kde.KLauncher.xml here. # And I don't want to have it here as a source file (who wants to edit dbus xml by hand), so it can be # generated from klauncher's implementation header. if (TARGET Qt5::DBus) qt5_add_dbus_interface(kservice_SRCS kdeinit/org.kde.KLauncher.xml klauncher_iface) endif() add_library(KF5Service ${kservice_SRCS}) if(WIN32) #unistd.h does not exist on windows target_compile_definitions(KF5Service PRIVATE YY_NO_UNISTD_H=1) endif() add_library(KF5::Service ALIAS KF5Service) ecm_generate_export_header(KF5Service BASE_NAME KService GROUP_BASE_NAME KF VERSION ${KF5_VERSION} DEPRECATED_BASE_VERSION 0 - DEPRECATION_VERSIONS 5.0 5.15 5.61 5.63 + DEPRECATION_VERSIONS 5.0 5.15 5.61 5.63 5.66 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) set(kservice_includes ${CMAKE_CURRENT_BINARY_DIR}/.. # Since we publicly include kservice_version.h ${CMAKE_CURRENT_SOURCE_DIR}/services ${CMAKE_CURRENT_SOURCE_DIR}/sycoca ${CMAKE_CURRENT_SOURCE_DIR}/plugin ${CMAKE_CURRENT_SOURCE_DIR}/kdeinit ) target_include_directories(KF5Service PUBLIC "$") target_include_directories(KF5Service INTERFACE "$") target_link_libraries(KF5Service PUBLIC KF5::ConfigCore # KConfig and friends KF5::CoreAddons # KShell KPluginLoader PRIVATE KF5::I18n Qt5::Xml # (for vfolder menu) QDomDocument ) if (TARGET KF5::DBusAddons) target_link_libraries(KF5Service PRIVATE KF5::DBusAddons) # KDEInitInterface endif() set_target_properties(KF5Service PROPERTIES VERSION ${KSERVICE_VERSION_STRING} SOVERSION ${KSERVICE_SOVERSION} EXPORT_NAME Service ) ecm_generate_headers(KService_HEADERS HEADER_NAMES KPluginTrader KDBusServiceStarter RELATIVE plugin REQUIRED_HEADERS KService_HEADERS ) ecm_generate_headers(KService_HEADERS HEADER_NAMES KSycoca KSycocaEntry KSycocaType RELATIVE sycoca REQUIRED_HEADERS KService_HEADERS ) ecm_generate_headers(KService_HEADERS HEADER_NAMES KToolInvocation RELATIVE kdeinit REQUIRED_HEADERS KService_HEADERS ) ecm_generate_headers(KService_HEADERS HEADER_NAMES KAutostart KMimeTypeTrader KService KServiceAction KServiceGroup KServiceType KServiceTypeProfile KServiceTypeTrader KPluginInfo RELATIVE services REQUIRED_HEADERS KService_HEADERS ) install(FILES services/kplugininfo.desktop services/application.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR} ) # Local copy for the unittests add_custom_target(copy_servicetypes) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/data/kservicetypes5) add_custom_command(TARGET copy_servicetypes PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/services/kplugininfo.desktop ${CMAKE_CURRENT_SOURCE_DIR}/services/application.desktop ${CMAKE_BINARY_DIR}/bin/data/kservicetypes5) # not using KDE_INSTALL_KSERVICETYPES5DIR because QStandardPaths wants "data" on Windows add_dependencies(KF5Service copy_servicetypes) if (WIN32) install( FILES applications.menu DESTINATION ${KDE_INSTALL_DATAROOTDIR}/xdg/menus RENAME ${APPLICATIONS_MENU_NAME} ) else () install( FILES applications.menu DESTINATION ${KDE_INSTALL_SYSCONFDIR}/xdg/menus RENAME ${APPLICATIONS_MENU_NAME} ) endif () # Local copy for the unittests add_custom_target(copy_menu) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/data/menus) add_custom_command(TARGET copy_menu PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/applications.menu ${CMAKE_BINARY_DIR}/bin/data/menus/${APPLICATIONS_MENU_NAME}) add_dependencies(KF5Service copy_menu) install(TARGETS KF5Service EXPORT KF5ServiceTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kservice_export.h" ${KService_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KService COMPONENT Devel ) if(BUILD_QCH) ecm_add_qch( KF5Service_QCH NAME KService BASE_NAME KF5Service VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${KService_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS KF5Config_QCH KF5CoreAddons_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${kservice_includes} BLANK_MACROS KSERVICE_EXPORT KSERVICE_DEPRECATED KSERVICE_DEPRECATED_EXPORT "KSERVICE_DEPRECATED_VERSION(x, y, t)" TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() add_subdirectory(kbuildsycoca) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KService LIB_NAME KF5Service DEPS "KConfigCore" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KService) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/services/kservicetypeprofile.cpp b/src/services/kservicetypeprofile.cpp index dd51862..d5eee2e 100644 --- a/src/services/kservicetypeprofile.cpp +++ b/src/services/kservicetypeprofile.cpp @@ -1,229 +1,231 @@ /* This file is part of the KDE libraries * Copyright (C) 1999 Torben Weis * Copyright (C) 2006 David Faure * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation; * * 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 "kservicetypeprofile.h" #include "kservicetypeprofile_p.h" #include "kservice.h" #include "kserviceoffer.h" #include "kservicetype.h" #include "ksycoca_p.h" #include #include #include #include #include // servicetype -> profile class KServiceTypeProfiles : public QHash { public: KServiceTypeProfiles() { m_parsed = false; ensureParsed(); } ~KServiceTypeProfiles() { clear(); } void clear() { QMutexLocker lock(&m_mutex); qDeleteAll(*this); QHash::clear(); m_parsed = false; } bool hasProfile(const QString &serviceType) { QMutexLocker lock(&m_mutex); ensureParsed(); return contains(serviceType); } void ensureParsed(); // mutex must be locked when calling this QMutex m_mutex; private: bool m_parsed; }; Q_GLOBAL_STATIC(KServiceTypeProfiles, s_serviceTypeProfiles) void KServiceTypeProfiles::ensureParsed() { if (m_parsed) { return; } m_parsed = true; // Read the service type profiles from servicetype_profilerc // See writeServiceTypeProfile for a description of the file format. // ### Since this new format names groups after servicetypes maybe we can even // avoid doing any init upfront, and just look up the group when asked... KConfig configFile(QStringLiteral("servicetype_profilerc"), KConfig::NoGlobals); const QStringList tmpList = configFile.groupList(); for (QStringList::const_iterator aIt = tmpList.begin(); aIt != tmpList.end(); ++aIt) { const QString type = *aIt; KConfigGroup config(&configFile, type); const int count = config.readEntry("NumberOfEntries", 0); KServiceTypeProfileEntry *p = this->value(type, nullptr); if (!p) { p = new KServiceTypeProfileEntry(); this->insert(type, p); } for (int i = 0; i < count; ++i) { const QString num = QLatin1String("Entry") + QString::number(i); const QString serviceId = config.readEntry(num + QLatin1String("_Service"), QString()); if (!serviceId.isEmpty()) { const int pref = config.readEntry(num + QLatin1String("_Preference"), 0); //qDebug() << "adding service " << serviceId << " to profile for " << type << " with preference " << pref; p->addService(serviceId, pref); } } } } //static void KServiceTypeProfile::clearCache() { if (s_serviceTypeProfiles.exists()) s_serviceTypeProfiles()->clear(); } /** * Returns the offers in the profile for the requested service type. * @param list list of offers (including initialPreference) * @param servicetype the service type * @return the weighted and sorted offer list * @internal used by KServiceTypeTrader */ namespace KServiceTypeProfile { KServiceOfferList sortServiceTypeOffers(const KServiceOfferList &list, const QString &servicetype); } KServiceOfferList KServiceTypeProfile::sortServiceTypeOffers(const KServiceOfferList &list, const QString &serviceType) { QMutexLocker lock(&s_serviceTypeProfiles()->m_mutex); s_serviceTypeProfiles()->ensureParsed(); KServiceTypeProfileEntry *profile = s_serviceTypeProfiles()->value(serviceType, nullptr); KServiceOfferList offers; KServiceOfferList::const_iterator it = list.begin(); const KServiceOfferList::const_iterator end = list.end(); for (; it != end; ++it) { const KService::Ptr servPtr = (*it).service(); //qDebug() << "KServiceTypeProfile::offers considering " << servPtr->storageId(); // Look into the profile (if there's one), to find this service's preference. bool foundInProfile = false; if (profile) { QMap::ConstIterator it2 = profile->m_mapServices.constFind(servPtr->storageId()); if (it2 != profile->m_mapServices.constEnd()) { const int pref = it2.value(); //qDebug() << "found in mapServices pref=" << pref; if (pref > 0) { // 0 disables the service offers.append(KServiceOffer(servPtr, pref, 0, servPtr->allowAsDefault())); } foundInProfile = true; } } if (!foundInProfile) { // This offer isn't in the profile // This can be because we have no profile at all, or because the // services have been installed after the profile was written, // but it's also the case for any service that's neither App nor ReadOnlyPart, e.g. RenameDlg/Plugin //qDebug() << "not found in mapServices. Appending."; // If there's a profile, we use 0 as the preference to ensure new apps don't take over existing apps (which default to 1) offers.append(KServiceOffer(servPtr, profile ? 0 : (*it).preference(), 0, servPtr->allowAsDefault())); } } std::stable_sort(offers.begin(), offers.end()); //qDebug() << "KServiceTypeProfile::offers returning " << offers.count() << " offers"; return offers; } +#if KSERVICE_BUILD_DEPRECATED_SINCE(5, 66) bool KServiceTypeProfile::hasProfile(const QString &serviceType) { return s_serviceTypeProfiles()->hasProfile(serviceType); } void KServiceTypeProfile::writeServiceTypeProfile(const QString &serviceType, const KService::List &services, const KService::List &disabledServices) { /* * [ServiceType] * NumEntries=3 * Entry0_Service=serv.desktop * Entry0_Preference=10 * Entry1_Service=otherserv.desktop * Entry1_Preference=5 * Entry2_Service=broken_service.desktop * Entry2_Preference=0 */ KConfig configFile(QStringLiteral("servicetype_profilerc"), KConfig::SimpleConfig); configFile.deleteGroup(serviceType); KConfigGroup config(&configFile, serviceType); const int count = services.count(); config.writeEntry("NumberOfEntries", count + disabledServices.count()); KService::List::ConstIterator servit = services.begin(); int i = 0; for (; servit != services.end(); ++servit, ++i) { if (*servit) { const QString num = QLatin1String("Entry") + QString::number(i); config.writeEntry(num + QLatin1String("_Service"), (*servit)->storageId()); config.writeEntry(num + QLatin1String("_Preference"), count - i); } } servit = disabledServices.begin(); for (; servit != disabledServices.end(); ++servit, ++i) { if (*servit) { const QString num = QLatin1String("Entry") + QString::number(i); config.writeEntry(num + QLatin1String("_Service"), (*servit)->storageId()); config.writeEntry(num + QLatin1String("_Preference"), 0); } } configFile.sync(); // Drop the whole cache... clearCache(); } void KServiceTypeProfile::deleteServiceTypeProfile(const QString &serviceType) { KConfig config(QStringLiteral("servicetype_profilerc"), KConfig::SimpleConfig); config.deleteGroup(serviceType); config.sync(); // Not threadsafe, but well the whole idea of using this method isn't // threadsafe in the first place. if (s_serviceTypeProfiles.exists()) { delete s_serviceTypeProfiles()->take(serviceType); } } +#endif diff --git a/src/services/kservicetypeprofile.h b/src/services/kservicetypeprofile.h index e04dd96..08d4647 100644 --- a/src/services/kservicetypeprofile.h +++ b/src/services/kservicetypeprofile.h @@ -1,77 +1,83 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright 2007 David Faure 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. */ #ifndef __kservicetypeprofile_h__ #define __kservicetypeprofile_h__ #include #include /** * KServiceTypeProfile represents the user's preferences for services * of a service type. * It consists of a list of services (service offers) for the service type * that is sorted by the user's preference. * KServiceTypeTrader uses KServiceTypeProfile to * get results sorted according to the user's preference. * * @see KService * @see KServiceType * @see KServiceTypeTrader * @short Represents the user's preferences for services of a service type */ +#if KSERVICE_ENABLE_DEPRECATED_SINCE(5, 66) namespace KServiceTypeProfile { /** * Write the complete profile for a given servicetype. * Do not use this for mimetypes. * @param serviceType The name of the servicetype. * @param services Ordered list of services, from the preferred one to the least preferred one. * @param disabledServices List of services which are normally associated with this serviceType, * but which should be disabled, i.e. trader queries will not return them. + * @deprecated since 5.66, unused. */ +KSERVICE_DEPRECATED_VERSION(5, 66, "Unused") KSERVICE_EXPORT void writeServiceTypeProfile(const QString &serviceType, const KService::List &services, const KService::List &disabledServices = KService::List()); /** * Delete the complete profile for a given servicetype, reverting to the default * preference order (the one specified by InitialPreference in the .desktop files). * * Do not use this for mimetypes. * @param serviceType The name of the servicetype. */ +KSERVICE_DEPRECATED_VERSION(5, 66, "Unused") KSERVICE_EXPORT void deleteServiceTypeProfile(const QString &serviceType); /** * @internal, for KServiceTypeTrader */ +KSERVICE_DEPRECATED_VERSION(5, 66, "Unused") KSERVICE_EXPORT bool hasProfile(const QString &serviceType); /** * Clear all cached information * @internal, for KServiceTypeFactory */ void clearCache(); } +#endif #endif