generic: remove KService profile feature

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-06-15 15:07:13 +03:00
parent a697e92048
commit d4fb9c2bb2
18 changed files with 7 additions and 490 deletions

View file

@ -288,7 +288,6 @@ install(
KServiceAction
KServiceGroup
KServiceType
KServiceTypeProfile
KServiceTypeTrader
KSessionManager
KSharedConfig

View file

@ -1 +0,0 @@
#include "../kservicetypeprofile.h"

View file

@ -191,7 +191,6 @@ set(kdecore_LIB_SRCS
services/kserviceoffer.cpp
services/kservicetype.cpp
services/kservicetypefactory.cpp
services/kservicetypeprofile.cpp
services/kservicetypetrader.cpp
services/ktraderparse.cpp
services/ktraderparsetree.cpp
@ -397,7 +396,6 @@ install(
#services/kservicefactory.h: do not install, internal API
services/kservicetype.h
#services/kservicetypefactory.h: do not install, internal API
services/kservicetypeprofile.h
services/kservicetypetrader.h
#services/kserviceoffer.h: do not install, internal API
services/kplugininfo.h

View file

@ -122,7 +122,6 @@ services/ David Faure <faure@kde.org>
kserviceoffer.cpp
kservicetype.cpp
kservicetypefactory.cpp
kservicetypeprofile.cpp
kservicetypetrader.cpp
ktraderparse.cpp
ktraderparsetree.cpp

View file

@ -19,7 +19,6 @@
#include "kmimetypetrader.h"
#include "kservicetypeprofile.h"
#include "kservicetype.h"
#include "kservicetypetrader.h"
#include "kmimetype.h"

View file

@ -23,7 +23,6 @@
#include "kservice.h"
#include "kservicetypefactory.h"
#include "kservicefactory.h"
#include "kservicetypeprofile.h"
#include <assert.h>
#include <kdebug.h>
#include <kdesktopfile.h>

View file

@ -20,7 +20,6 @@
#include "ksycoca.h"
#include "ksycocatype.h"
#include "ksycocadict_p.h"
#include "kservicetypeprofile.h"
#include <kdebug.h>
#include <assert.h>
@ -55,7 +54,6 @@ KServiceTypeFactory::KServiceTypeFactory()
KServiceTypeFactory::~KServiceTypeFactory()
{
KServiceTypeProfile::clearCache();
if (kServiceTypeFactoryInstance) {
kServiceTypeFactoryInstance = 0;
}

View file

@ -1,241 +0,0 @@
/* This file is part of the KDE libraries
* Copyright (C) 1999 Torben Weis <weis@kde.org>
* Copyright (C) 2006 David Faure <faure@kde.org>
*
* 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 <QMutex>
#include "kservice.h"
#include "kservicetype.h"
#include "kservicetypefactory.h"
#include "kservicefactory.h"
#include <kconfig.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kconfiggroup.h>
#include <QtCore/QHash>
#include <QtCore/qalgorithms.h>
// servicetype -> profile
class KServiceTypeProfiles : public QHash<QString, KServiceTypeProfileEntry *>
{
public:
KServiceTypeProfiles() { m_parsed = false; ensureParsed(); }
~KServiceTypeProfiles() { clear(); }
void clear() {
QMutexLocker lock(&m_mutex);
qDeleteAll( *this );
QHash<QString, KServiceTypeProfileEntry *>::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;
};
K_GLOBAL_STATIC(KServiceTypeProfiles, s_serviceTypeProfiles)
static bool s_configurationMode = false;
void KServiceTypeProfiles::ensureParsed()
{
if (m_parsed)
return;
m_parsed = true;
// Make sure that a KServiceTypeFactory gets created.
(void) KServiceTypeFactory::self();
// Read the service type profiles from servicetype_profilerc (new in kde4)
// 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( QString::fromLatin1("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, 0 );
if ( !p ) {
p = new KServiceTypeProfileEntry();
this->insert( type, p );
}
for ( int i = 0; i < count; ++i ) {
const QString num = QString::fromLatin1("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 );
//kDebug(7014) << "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, 0);
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();
//kDebug(7014) << "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<QString,int>::ConstIterator it2 = profile->m_mapServices.constFind( servPtr->storageId() );
if( it2 != profile->m_mapServices.constEnd() )
{
const int pref = it2.value();
//kDebug(7014) << "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
//kDebug(7014) << "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() ) );
}
}
qStableSort( offers );
//kDebug(7014) << "KServiceTypeProfile::offers returning " << offers.count() << " offers";
return offers;
}
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( QString::fromLatin1("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->isNull()) {
const QString num = QString::fromLatin1("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->isNull()) {
const QString num = QString::fromLatin1("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(QString::fromLatin1("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 );
}
}
void KServiceTypeProfile::setConfigurationMode()
{
s_configurationMode = true;
}
bool KServiceTypeProfile::configurationMode()
{
return s_configurationMode;
}

View file

@ -1,89 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
Copyright 2007 David Faure <faure@kde.org>
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 <kservicetypetrader.h>
/**
* 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
*/
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.
*/
KDECORE_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.
*/
KDECORE_EXPORT void deleteServiceTypeProfile( const QString& serviceType );
/**
* This method activates a special mode of KServiceTypeProfile, in which all/all
* and all/allfiles are excluded from the results of the queries.
* It is meant for the configuration module _only_.
* @internal
*/
KDECORE_EXPORT void setConfigurationMode();
/**
* @internal
*/
KDECORE_EXPORT bool configurationMode();
/**
* @internal, for KServiceTypeTrader
*/
KDECORE_EXPORT bool hasProfile( const QString& serviceType );
/**
* Clear all cached information
* @internal, for KServiceTypeFactory
*/
void clearCache();
}
#endif

View file

@ -1,54 +0,0 @@
/* This file is part of the KDE libraries
* Copyright (C) 1999 Torben Weis <weis@kde.org>
* Copyright (C) 2006 David Faure <faure@kde.org>
*
* 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.
*/
#ifndef KSERVICETYPEPROFILE_P_H
#define KSERVICETYPEPROFILE_P_H
#include <QMap>
/**
* @internal
*/
class KServiceTypeProfileEntry
{
public:
explicit KServiceTypeProfileEntry() {}
/**
* Add a service to this profile.
* @param _service the name of the service
* @param _preference the user's preference value, must be positive,
* bigger is better
* @param _allow_as_default true if the service should be used as
* default
*/
void addService( const QString& service, int preference = 1 ) {
m_mapServices.insert( service, preference );
}
/**
* Map of all services for which we have assessments.
* Key: service ID
* Value: preference
*/
QMap<QString,int> m_mapServices;
};
#endif /* KSERVICETYPEPROFILE_P_H */

View file

@ -20,7 +20,6 @@
#include "kservicetypetrader.h"
#include "ktraderparsetree_p.h"
#include <kservicetypeprofile.h>
#include <kdebug.h>
#include "kservicetype.h"
#include "kservicetypefactory.h"
@ -30,10 +29,6 @@ using namespace KTraderParse;
// --------------------------------------------------
namespace KServiceTypeProfile {
KServiceOfferList sortServiceTypeOffers( const KServiceOfferList& list, const QString& servicetype );
}
KServiceTypeTrader* KServiceTypeTrader::self()
{
K_GLOBAL_STATIC(KServiceTypeTrader, s_globalServiceTypeTrader)
@ -98,10 +93,10 @@ static KServiceOfferList weightedOffers( const QString& serviceType )
return KServiceOfferList();
// First, get all offers known to ksycoca.
const KServiceOfferList services = KServiceFactory::self()->offers( servTypePtr->offset(), servTypePtr->serviceOffersOffset() );
KServiceOfferList offers = KServiceFactory::self()->offers( servTypePtr->offset(), servTypePtr->serviceOffersOffset() );
const KServiceOfferList offers = KServiceTypeProfile::sortServiceTypeOffers( services, serviceType );
//kDebug(7014) << "Found profile: " << offers.count() << " offers";
qStableSort( offers );
//kDebug(7014) << "Found offers: " << offers.count() << " offers";
#if 0
dumpOfferList( offers );
@ -134,27 +129,7 @@ KService::List KServiceTypeTrader::defaultOffers( const QString& serviceType,
KService::List KServiceTypeTrader::query( const QString& serviceType,
const QString& constraint ) const
{
if ( !KServiceTypeProfile::hasProfile( serviceType ) )
{
// Fast path: skip the profile stuff if there's none (to avoid kservice->serviceoffer->kservice)
// The ordering according to initial preferences is done by kbuildsycoca
return defaultOffers( serviceType, constraint );
}
KService::List lst;
// Get all services of this service type.
const KServiceOfferList offers = weightedOffers( serviceType );
// Now extract only the services; the weighting was only used for sorting.
KServiceOfferList::const_iterator itOff = offers.begin();
for( ; itOff != offers.end(); ++itOff )
lst.append( (*itOff).service() );
applyConstraints( lst, constraint );
//kDebug(7014) << "query for serviceType " << serviceType << constraint
// << " : returning " << lst.count() << " offers" << endl;
return lst;
return defaultOffers( serviceType, constraint );
}
KService::Ptr KServiceTypeTrader::preferredService( const QString & serviceType ) const

View file

@ -34,24 +34,12 @@
#include <kservicegroup.h>
#include <kservicetypetrader.h>
#include <kservicetype.h>
#include <kservicetypeprofile.h>
#include <QtCore/qprocess.h>
#include <QtCore/qthread.h>
QTEST_KDEMAIN_CORE( KServiceTest )
static void eraseProfiles()
{
QString profilerc = KStandardDirs::locateLocal( "config", "profilerc" );
if ( !profilerc.isEmpty() )
QFile::remove( profilerc );
profilerc = KStandardDirs::locateLocal( "config", "servicetype_profilerc" );
if ( !profilerc.isEmpty() )
QFile::remove( profilerc );
}
void KServiceTest::initTestCase()
{
// A non-C locale is necessary for some tests.
@ -65,7 +53,6 @@ void KServiceTest::initTestCase()
}
m_hasKde4Konsole = false;
eraseProfiles();
// Create some fake services for the tests below, and ensure they are in ksycoca.
@ -371,58 +358,13 @@ void KServiceTest::testHasServiceType2() // with services coming from ksycoca
QVERIFY( !faketextPlugin->hasServiceType( "KParts/ReadOnlyPart" ) );
}
void KServiceTest::testWriteServiceTypeProfile()
{
const QString serviceType = "KParts/ReadOnlyPart";
KService::List services, disabledServices;
services.append(KService::serviceByDesktopPath("fakepart.desktop"));
disabledServices.append(KService::serviceByDesktopPath("kwebkitpart.desktop"));
KService::List::ConstIterator servit = services.constBegin();
for( ; servit != services.constEnd(); ++servit) {
QVERIFY(!servit->isNull());
}
KServiceTypeProfile::writeServiceTypeProfile( serviceType, services, disabledServices );
// Check that the file got written
QString profilerc = KStandardDirs::locateLocal( "config", "servicetype_profilerc" );
QVERIFY(!profilerc.isEmpty());
QVERIFY(QFile::exists(profilerc));
KService::List offers = KServiceTypeTrader::self()->query( serviceType );
QVERIFY( offers.count() > 0 ); // not empty
//foreach( KService::Ptr service, offers )
// qDebug( "%s %s", qPrintable( service->name() ), qPrintable( service->entryPath() ) );
QVERIFY( offers.count() >= 1 ); // at least 1, even
QCOMPARE( offers[0]->entryPath(), QString("fakepart.desktop") );
QVERIFY( !offerListHasService( offers, "kwebkitpart.desktop" ) ); // it got disabled above
}
void KServiceTest::testDefaultOffers()
{
// Now that we have a user-profile, let's see if defaultOffers indeed gives us the default ordering.
// Let's see if defaultOffers indeed gives us the default ordering.
const QString serviceType = "KParts/ReadOnlyPart";
KService::List offers = KServiceTypeTrader::self()->defaultOffers( serviceType );
QVERIFY( offers.count() > 0 ); // not empty
QVERIFY( offerListHasService( offers, "kwebkitpart.desktop" ) ); // it's here even though it's disabled in the profile
if ( m_firstOffer.isEmpty() )
QSKIP( "testServiceTypeTraderForReadOnlyPart not run", SkipAll );
QCOMPARE( offers[0]->entryPath(), m_firstOffer );
}
void KServiceTest::testDeleteServiceTypeProfile()
{
const QString serviceType = "KParts/ReadOnlyPart";
KServiceTypeProfile::deleteServiceTypeProfile( serviceType );
KService::List offers = KServiceTypeTrader::self()->query( serviceType );
QVERIFY( offers.count() > 0 ); // not empty
QVERIFY( offerListHasService( offers, "kwebkitpart.desktop" ) ); // it's back
QVERIFY( offerListHasService( offers, "kwebkitpart.desktop" ) );
if ( m_firstOffer.isEmpty() )
QSKIP( "testServiceTypeTraderForReadOnlyPart not run", SkipAll );
QCOMPARE( offers[0]->entryPath(), m_firstOffer );

View file

@ -37,9 +37,7 @@ private Q_SLOTS:
void testTraderConstraints();
void testHasServiceType1();
void testHasServiceType2();
void testWriteServiceTypeProfile();
void testDefaultOffers();
void testDeleteServiceTypeProfile();
void testDBUSStartupType();
void testByStorageId();
void testActionsAndDataStream();

View file

@ -33,7 +33,6 @@
#include <kdebug.h>
#include <kservicetype.h>
#include <kservicetypeprofile.h>
#include <QtCore/qprocess.h>
#include <QtCore/qthread.h>

View file

@ -75,8 +75,6 @@ Offer list
| * mimetype offset, service offset
| * 0
This allows to quickly find services associated with a servicetype.
It does NOT reflect the user profile, which is stored in profilerc and
implemented in KServiceTypeProfile.
Mimetype patterns
| Fast patterns (fixed size)

View file

@ -156,7 +156,7 @@ void KBuildServiceFactory::collectInheritedServices()
Q_FOREACH(const QString& mimeType, allMimeTypes) {
collectInheritedServices(mimeType, visitedMimes);
}
// TODO do the same for all/all and all/allfiles, if (!KServiceTypeProfile::configurationMode())
// TODO do the same for all/all and all/allfiles
}
void KBuildServiceFactory::collectInheritedServices(const QString& mimeTypeName, QSet<QString>& visitedMimes)

View file

@ -1,4 +1,3 @@
#include <kservicetypeprofile.h>
#include <kservice.h>
#include <kmimetype.h>
#include <assert.h>

View file

@ -26,7 +26,6 @@
#include <kservicegroup.h>
#include <kstandarddirs.h>
#include <kmimetypetrader.h>
#include <kservicetypeprofile.h>
#include <assert.h>
#include <stdio.h>