Big patch with several internal changes to krunner:
-New RunnerManager class, it manages runners at high level and gives a simple API for interfaces to use. - AbstractRunners gains description, setIgnoredTypes, ignoredTypes methods. Now runners can specify what SearchContext::Types they are not going to process. - SearchContext tries shared data between the original context and any local context. It doesn't have its own completer no more. - SearchMatch has a new type of match, CompleterMatch. Instead of using a hard coded completer in SearchContext - Interface class on krunner has its own completer and other changes done to accomodate the above changes in libplasma. -A new configuration option blacklist for runnermanager and krunner instead of the whitelist of krunner. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=802903
This commit is contained in:
parent
207968b217
commit
95157e20c4
@ -41,6 +41,7 @@ set(plasma_LIB_SRCS
|
|||||||
packages.cpp
|
packages.cpp
|
||||||
plasma.cpp
|
plasma.cpp
|
||||||
plasma_export.h
|
plasma_export.h
|
||||||
|
runnermanager.cpp
|
||||||
searchmatch.cpp
|
searchmatch.cpp
|
||||||
searchcontext.cpp
|
searchcontext.cpp
|
||||||
shadowitem.cpp
|
shadowitem.cpp
|
||||||
@ -77,7 +78,8 @@ endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND)
|
|||||||
|
|
||||||
kde4_add_library(plasma SHARED ${plasma_LIB_SRCS})
|
kde4_add_library(plasma SHARED ${plasma_LIB_SRCS})
|
||||||
|
|
||||||
target_link_libraries(plasma ${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS} ${QT_QTUITOOLS_LIBRARY} ${QT_QTWEBKIT_LIBRARY})
|
target_link_libraries(plasma ${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS}
|
||||||
|
${QT_QTUITOOLS_LIBRARY} ${QT_QTWEBKIT_LIBRARY} ${KDE4_THREADWEAVER_LIBRARIES})
|
||||||
|
|
||||||
if(QT_QTOPENGL_FOUND AND OPENGL_FOUND)
|
if(QT_QTOPENGL_FOUND AND OPENGL_FOUND)
|
||||||
target_link_libraries(plasma ${QT_QTOPENGL_LIBRARY} ${OPENGL_gl_LIBRARY})
|
target_link_libraries(plasma ${QT_QTOPENGL_LIBRARY} ${OPENGL_gl_LIBRARY})
|
||||||
@ -112,6 +114,7 @@ set(plasma_LIB_INCLUDES
|
|||||||
dialog.h
|
dialog.h
|
||||||
plasma.h
|
plasma.h
|
||||||
plasma_export.h
|
plasma_export.h
|
||||||
|
runnermanager.h
|
||||||
searchmatch.h
|
searchmatch.h
|
||||||
searchcontext.h
|
searchcontext.h
|
||||||
shadowitem_p.h
|
shadowitem_p.h
|
||||||
|
@ -28,8 +28,11 @@
|
|||||||
#include <KStandardDirs>
|
#include <KStandardDirs>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "package.h"
|
#include <plasma/searchmatch.h>
|
||||||
|
#include <plasma/package.h>
|
||||||
|
|
||||||
#include "scripting/runnerscript.h"
|
#include "scripting/runnerscript.h"
|
||||||
|
|
||||||
#include "searchcontext.h"
|
#include "searchcontext.h"
|
||||||
|
|
||||||
namespace Plasma
|
namespace Plasma
|
||||||
@ -41,6 +44,7 @@ public:
|
|||||||
Private(AbstractRunner* r, KService::Ptr service)
|
Private(AbstractRunner* r, KService::Ptr service)
|
||||||
: priority(NormalPriority),
|
: priority(NormalPriority),
|
||||||
speed(NormalSpeed),
|
speed(NormalSpeed),
|
||||||
|
blackListed(0),
|
||||||
script(0),
|
script(0),
|
||||||
runnerDescription(service),
|
runnerDescription(service),
|
||||||
runner(r),
|
runner(r),
|
||||||
@ -73,6 +77,7 @@ public:
|
|||||||
bool hasConfig;
|
bool hasConfig;
|
||||||
Priority priority;
|
Priority priority;
|
||||||
Speed speed;
|
Speed speed;
|
||||||
|
SearchContext::Types blackListed;
|
||||||
RunnerScript* script;
|
RunnerScript* script;
|
||||||
KPluginInfo runnerDescription;
|
KPluginInfo runnerDescription;
|
||||||
AbstractRunner* runner;
|
AbstractRunner* runner;
|
||||||
@ -119,10 +124,9 @@ void AbstractRunner::performMatch( Plasma::SearchContext &globalContext )
|
|||||||
static const int fastEnoughTime = 250;
|
static const int fastEnoughTime = 250;
|
||||||
|
|
||||||
d->runtime.restart();
|
d->runtime.restart();
|
||||||
SearchContext localContext(0, globalContext);
|
//TODO :this is a copy ctor
|
||||||
|
SearchContext localContext(globalContext,0);
|
||||||
match(&localContext);
|
match(&localContext);
|
||||||
|
|
||||||
// automatically rate limit runners that become slooow
|
// automatically rate limit runners that become slooow
|
||||||
const int runtime = d->runtime.elapsed();
|
const int runtime = d->runtime.elapsed();
|
||||||
bool slowed = speed() == SlowSpeed;
|
bool slowed = speed() == SlowSpeed;
|
||||||
@ -136,8 +140,7 @@ void AbstractRunner::performMatch( Plasma::SearchContext &globalContext )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//If matches were not added, delete items on the heap
|
//If matches were not added, delete items on the heap
|
||||||
if (localContext.moveMatchesTo(globalContext) &&
|
if (slowed && runtime < fastEnoughTime) {
|
||||||
slowed && runtime < fastEnoughTime) {
|
|
||||||
++d->fastRuns;
|
++d->fastRuns;
|
||||||
|
|
||||||
if (d->fastRuns > 2) {
|
if (d->fastRuns > 2) {
|
||||||
@ -199,12 +202,24 @@ void AbstractRunner::setPriority(Priority priority)
|
|||||||
d->priority = priority;
|
d->priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchContext::Types AbstractRunner::ignoredTypes() const
|
||||||
|
{
|
||||||
|
return d->blackListed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractRunner::setIgnoredTypes(SearchContext::Types types)
|
||||||
|
{
|
||||||
|
d->blackListed = types;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KService::List AbstractRunner::serviceQuery(const QString &serviceType, const QString &constraint) const
|
KService::List AbstractRunner::serviceQuery(const QString &serviceType, const QString &constraint) const
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&Private::bigLock);
|
QMutexLocker lock(&Private::bigLock);
|
||||||
return KServiceTypeTrader::self()->query(serviceType, constraint);
|
return KServiceTypeTrader::self()->query(serviceType, constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutex* AbstractRunner::bigLock() const
|
QMutex* AbstractRunner::bigLock() const
|
||||||
{
|
{
|
||||||
return &Private::bigLock;
|
return &Private::bigLock;
|
||||||
@ -232,6 +247,15 @@ QString AbstractRunner::name() const
|
|||||||
return d->runnerDescription.property("X-Plasma-RunnerName").toString();
|
return d->runnerDescription.property("X-Plasma-RunnerName").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString AbstractRunner::description() const
|
||||||
|
{
|
||||||
|
if (!d->runnerDescription.isValid()) {
|
||||||
|
return objectName();
|
||||||
|
}
|
||||||
|
return d->runnerDescription.property("Comment").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Package* AbstractRunner::package() const
|
const Package* AbstractRunner::package() const
|
||||||
{
|
{
|
||||||
return d->package;
|
return d->package;
|
||||||
@ -244,47 +268,6 @@ void AbstractRunner::init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractRunner::List AbstractRunner::loadAll(QObject* parent, const QStringList& whitelist)
|
|
||||||
{
|
|
||||||
List firstRunners;
|
|
||||||
List runners;
|
|
||||||
List lastRunners;
|
|
||||||
|
|
||||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner");
|
|
||||||
QString error;
|
|
||||||
foreach (const KService::Ptr &service, offers) {
|
|
||||||
if (whitelist.empty() || whitelist.contains(service->name())) {
|
|
||||||
QString api = service->property("X-Plasma-API").toString();
|
|
||||||
AbstractRunner* runner = 0;
|
|
||||||
|
|
||||||
if (api.isEmpty()) {
|
|
||||||
QVariantList args;
|
|
||||||
args << service->storageId();
|
|
||||||
runner = service->createInstance<AbstractRunner>(parent, args, &error);
|
|
||||||
} else {
|
|
||||||
runner = new AbstractRunner(parent, service->storageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runner) {
|
|
||||||
//kDebug() << "loaded runner : " << service->name();
|
|
||||||
QString phase = service->property("X-Plasma-RunnerPhase").toString();
|
|
||||||
if (phase == "last") {
|
|
||||||
lastRunners.append(runner);
|
|
||||||
} else if (phase == "first") {
|
|
||||||
firstRunners.append(runner);
|
|
||||||
} else {
|
|
||||||
runners.append(runner);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kDebug() << "failed to load runner : " << service->name() << ". error reported: " << error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
firstRunners << runners << lastRunners;
|
|
||||||
return firstRunners;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Plasma namespace
|
} // Plasma namespace
|
||||||
|
|
||||||
#include "abstractrunner.moc"
|
#include "abstractrunner.moc"
|
||||||
|
@ -28,9 +28,8 @@
|
|||||||
#include <KDE/KService>
|
#include <KDE/KService>
|
||||||
|
|
||||||
#include <plasma/plasma_export.h>
|
#include <plasma/plasma_export.h>
|
||||||
#include <plasma/package.h>
|
|
||||||
#include <plasma/searchmatch.h>
|
|
||||||
#include <plasma/searchcontext.h>
|
#include <plasma/searchcontext.h>
|
||||||
|
#include <plasma/searchmatch.h>
|
||||||
|
|
||||||
class KCompletion;
|
class KCompletion;
|
||||||
|
|
||||||
@ -39,6 +38,7 @@ namespace Plasma
|
|||||||
|
|
||||||
class Package;
|
class Package;
|
||||||
class RunnerScript;
|
class RunnerScript;
|
||||||
|
class SearchMatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class for Plasma Runner plugins
|
* An abstract base class for Plasma Runner plugins
|
||||||
@ -63,16 +63,9 @@ class PLASMA_EXPORT AbstractRunner : public QObject
|
|||||||
HighPriority,
|
HighPriority,
|
||||||
HighestPriority
|
HighestPriority
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QList<AbstractRunner*> List;
|
typedef QList<AbstractRunner*> List;
|
||||||
|
|
||||||
/**
|
|
||||||
* Static method is called to load and get a list available of Runners.
|
|
||||||
*
|
|
||||||
* @param whitelist An optional whitelist of runners to load
|
|
||||||
*/
|
|
||||||
static List loadAll(QObject* parent, const QStringList& whitelist = QStringList());
|
|
||||||
|
|
||||||
virtual ~AbstractRunner();
|
virtual ~AbstractRunner();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,11 +146,29 @@ class PLASMA_EXPORT AbstractRunner : public QObject
|
|||||||
*/
|
*/
|
||||||
Priority priority() const;
|
Priority priority() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OR'ed value of all the Information types (as defined in SearchContext::Type)
|
||||||
|
* this runner is not interested in.
|
||||||
|
* @return OR'ed value of black listed types
|
||||||
|
*/
|
||||||
|
SearchContext::Types ignoredTypes() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the types this runner will ignore
|
||||||
|
* @param types OR'ed listed of ignored types
|
||||||
|
*/
|
||||||
|
void setIgnoredTypes(SearchContext::Types types);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the engine name for the Runner
|
* Returns the engine name for the Runner
|
||||||
*/
|
*/
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the description of this Runner
|
||||||
|
*/
|
||||||
|
QString description() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accessor for the associated Package object if any.
|
* Accessor for the associated Package object if any.
|
||||||
*
|
*
|
||||||
|
431
runnermanager.cpp
Normal file
431
runnermanager.cpp
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006-2007 Ryan P. Bitanga <ryan.bitanga@gmail.com>
|
||||||
|
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
|
||||||
|
* Copyright 2008 Jordi Polo <mumismo@gmail.com>
|
||||||
|
*
|
||||||
|
* This program 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, 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 Library 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 <KServiceTypeTrader>
|
||||||
|
#include <KPluginInfo>
|
||||||
|
#include <KDebug>
|
||||||
|
|
||||||
|
#include <Solid/Device>
|
||||||
|
#include <Solid/DeviceInterface>
|
||||||
|
|
||||||
|
#include <threadweaver/DebuggingAids.h>
|
||||||
|
#include <ThreadWeaver/Thread>
|
||||||
|
#include <ThreadWeaver/Job>
|
||||||
|
#include <ThreadWeaver/State>
|
||||||
|
#include <ThreadWeaver/QueuePolicy>
|
||||||
|
#include <ThreadWeaver/Weaver>
|
||||||
|
#include <ThreadWeaver/WeaverObserver>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include <Plasma/SearchMatch>
|
||||||
|
|
||||||
|
#include "runnermanager.h"
|
||||||
|
|
||||||
|
using ThreadWeaver::Weaver;
|
||||||
|
using ThreadWeaver::Job;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Plasma
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************
|
||||||
|
* RunnerRestrictionPolicy class
|
||||||
|
* Restricts simultaneous jobs of the same type
|
||||||
|
* Similar to ResourceRestrictionPolicy but check the object type first
|
||||||
|
******************************************************/
|
||||||
|
class RunnerRestrictionPolicy : public ThreadWeaver::QueuePolicy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~RunnerRestrictionPolicy();
|
||||||
|
|
||||||
|
static RunnerRestrictionPolicy& instance();
|
||||||
|
|
||||||
|
void setCap(int cap)
|
||||||
|
{
|
||||||
|
m_cap = cap;
|
||||||
|
}
|
||||||
|
int cap() const
|
||||||
|
{
|
||||||
|
return m_cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canRun(Job* job);
|
||||||
|
void free(Job* job);
|
||||||
|
void release(Job* job);
|
||||||
|
void destructed(Job* job);
|
||||||
|
private:
|
||||||
|
RunnerRestrictionPolicy();
|
||||||
|
|
||||||
|
// QHash<QString, int> m_runCounts;
|
||||||
|
int m_count;
|
||||||
|
int m_cap;
|
||||||
|
QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
RunnerRestrictionPolicy::RunnerRestrictionPolicy()
|
||||||
|
: QueuePolicy(),
|
||||||
|
m_cap(2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RunnerRestrictionPolicy::~RunnerRestrictionPolicy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RunnerRestrictionPolicy& RunnerRestrictionPolicy::instance()
|
||||||
|
{
|
||||||
|
static RunnerRestrictionPolicy policy;
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunnerRestrictionPolicy::canRun(Job* job)
|
||||||
|
{
|
||||||
|
Q_UNUSED(job)
|
||||||
|
QMutexLocker l(&m_mutex);
|
||||||
|
// QString type = job->objectName();
|
||||||
|
if (m_count/*m_runCounts.value(type)*/ > m_cap) {
|
||||||
|
// kDebug() << "Denying job " << type << " because of " << m_count/*m_runCounts[type]*/ << " current jobs" << endl;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// m_runCounts[type]++;
|
||||||
|
++m_count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerRestrictionPolicy::free(Job* job)
|
||||||
|
{
|
||||||
|
Q_UNUSED(job)
|
||||||
|
QMutexLocker l(&m_mutex);
|
||||||
|
// QString type = job->objectName();
|
||||||
|
--m_count;
|
||||||
|
// if (m_runCounts.value(type)) {
|
||||||
|
// m_runCounts[type]--;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerRestrictionPolicy::release(Job* job)
|
||||||
|
{
|
||||||
|
free(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerRestrictionPolicy::destructed(Job* job)
|
||||||
|
{
|
||||||
|
Q_UNUSED(job)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************
|
||||||
|
* FindMatchesJob class
|
||||||
|
* Class to run queries in different threads
|
||||||
|
******************************************************/
|
||||||
|
class FindMatchesJob : public Job
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FindMatchesJob(const QString& term, Plasma::AbstractRunner* runner, Plasma::SearchContext* context, QObject* parent = 0);
|
||||||
|
|
||||||
|
int priority() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
private:
|
||||||
|
QString m_term;
|
||||||
|
Plasma::SearchContext* m_context;
|
||||||
|
Plasma::AbstractRunner* m_runner;
|
||||||
|
};
|
||||||
|
|
||||||
|
FindMatchesJob::FindMatchesJob( const QString& term, Plasma::AbstractRunner* runner,
|
||||||
|
Plasma::SearchContext* context, QObject* parent )
|
||||||
|
: ThreadWeaver::Job(parent),
|
||||||
|
m_term(term),
|
||||||
|
m_context(context),
|
||||||
|
m_runner(runner)
|
||||||
|
{
|
||||||
|
// setObjectName( runner->objectName() );
|
||||||
|
if (runner->speed() == Plasma::AbstractRunner::SlowSpeed) {
|
||||||
|
assignQueuePolicy(&RunnerRestrictionPolicy::instance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindMatchesJob::run()
|
||||||
|
{
|
||||||
|
// kDebug() << "Running match for " << m_runner->objectName() << " in Thread " << thread()->id() << endl;
|
||||||
|
m_runner->performMatch(*m_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FindMatchesJob::priority() const
|
||||||
|
{
|
||||||
|
return m_runner->priority();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************
|
||||||
|
* RunnerManager::Private class
|
||||||
|
*
|
||||||
|
*****************************************************/
|
||||||
|
class RunnerManager::Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Private(RunnerManager *parent)
|
||||||
|
: q(parent)
|
||||||
|
{
|
||||||
|
connect(&context, SIGNAL(matchesChanged()), q, SIGNAL(matchesChanged()));
|
||||||
|
connect(Weaver::instance(), SIGNAL(finished()), q, SIGNAL(matchesCompleted()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure(KConfigGroup& conf)
|
||||||
|
{
|
||||||
|
config=conf;
|
||||||
|
|
||||||
|
//The number of threads used scales with the number of processors.
|
||||||
|
const int numProcs = qMax(Solid::Device::listFromType(Solid::DeviceInterface::Processor).count(), 1);
|
||||||
|
//This entry allows to define a hard upper limit independent of the number of processors.
|
||||||
|
const int maxThreads = config.readEntry("maxThreads",16);
|
||||||
|
const int numThreads = qMin(maxThreads, 2 + ((numProcs - 1) * 2));
|
||||||
|
// kDebug() << "setting up" << numThreads << "threads for" << numProcs << "processors";
|
||||||
|
Weaver::instance()->setMaximumNumberOfThreads(numThreads);
|
||||||
|
|
||||||
|
//Preferred order of execution of runners
|
||||||
|
//prioritylist = config.readEntry("priority", QStringList());
|
||||||
|
|
||||||
|
//If set, this list defines which runners won't be used at runtime
|
||||||
|
blacklist = config.readEntry("blacklist", QStringList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadAll()
|
||||||
|
{
|
||||||
|
AbstractRunner::List firstRunners;
|
||||||
|
AbstractRunner::List normalRunners;
|
||||||
|
AbstractRunner::List lastRunners;
|
||||||
|
|
||||||
|
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner");
|
||||||
|
QString error;
|
||||||
|
foreach (const KService::Ptr &service, offers) {
|
||||||
|
KPluginInfo description(service);
|
||||||
|
QString runnerName = description.property("X-Plasma-RunnerName").toString();
|
||||||
|
if (blacklist.contains(runnerName)) {
|
||||||
|
kDebug() << "The plugin" << service->name() << "was blackListed and will not load";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString api = service->property("X-Plasma-API").toString();
|
||||||
|
AbstractRunner* runner = 0;
|
||||||
|
|
||||||
|
if (api.isEmpty()) {
|
||||||
|
QVariantList args;
|
||||||
|
args << service->storageId();
|
||||||
|
runner = service->createInstance<AbstractRunner>(q, args, &error);
|
||||||
|
} else {
|
||||||
|
//FIXME: this line should be uncommented, but the constructor is protected
|
||||||
|
//runner = new AbstractRunner(q, service->storageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runner) {
|
||||||
|
// kDebug() << "loading runner: " << service->name();
|
||||||
|
QString phase = service->property("X-Plasma-RunnerPhase").toString();
|
||||||
|
if (phase == "last") {
|
||||||
|
lastRunners.append(runner);
|
||||||
|
} else if (phase == "first") {
|
||||||
|
firstRunners.append(runner);
|
||||||
|
} else {
|
||||||
|
normalRunners.append(runner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kDebug() << "failed to load runner : " << service->name() << ". error reported: " << error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
firstRunners << normalRunners << lastRunners;
|
||||||
|
runners.clear();
|
||||||
|
runners = firstRunners;
|
||||||
|
kDebug() << "All runners loaded, total:" << runners.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
RunnerManager *q;
|
||||||
|
SearchContext context;
|
||||||
|
AbstractRunner::List runners;
|
||||||
|
QList<SearchMatch *> matches;
|
||||||
|
QList<ThreadWeaver::Job*> searchJobs;
|
||||||
|
QStringList prioritylist;
|
||||||
|
QStringList blacklist;
|
||||||
|
KConfigGroup config;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************
|
||||||
|
* RunnerManager::Public class
|
||||||
|
*
|
||||||
|
*****************************************************/
|
||||||
|
RunnerManager::RunnerManager(QObject *parent)
|
||||||
|
: QObject(parent),
|
||||||
|
d(new Private(this))
|
||||||
|
{
|
||||||
|
KConfigGroup config(KGlobal::config(), "PlasmaRunnerManager");
|
||||||
|
d->configure(config);
|
||||||
|
d->loadAll();
|
||||||
|
//ThreadWeaver::setDebugLevel(true, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RunnerManager::RunnerManager(KConfigGroup& config, QObject *parent)
|
||||||
|
: QObject(parent),
|
||||||
|
d(new Private(this))
|
||||||
|
{
|
||||||
|
d->configure(config);
|
||||||
|
d->loadAll();
|
||||||
|
//ThreadWeaver::setDebugLevel(true, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RunnerManager::~RunnerManager()
|
||||||
|
{
|
||||||
|
d->context.removeAllMatches();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbstractRunner* RunnerManager::runner(const QString &name) const
|
||||||
|
{
|
||||||
|
//TODO: using a list of runners, if this gets slow, switch to hash
|
||||||
|
foreach (Plasma::AbstractRunner* runner, d->runners) {
|
||||||
|
if (name == runner->name()) {
|
||||||
|
return runner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SearchContext* RunnerManager::searchContext() const
|
||||||
|
{
|
||||||
|
return &d->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reordering is here so data is not reordered till strictly needed
|
||||||
|
QList<SearchMatch *> RunnerManager::matches() const
|
||||||
|
{
|
||||||
|
return d->context.matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerManager::run(const SearchMatch *match)
|
||||||
|
{
|
||||||
|
//TODO: this function is not const as it may be used for learning
|
||||||
|
match->run(&d->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RunnerManager::launchQuery (const QString & term, const QString & runnerName)
|
||||||
|
{
|
||||||
|
if (term.isEmpty()) {
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->context.searchTerm() == term) {
|
||||||
|
// we already are searching for this!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
// kDebug() << "runners searching for" << term << "on" << runnerName;
|
||||||
|
d->context.setSearchTerm(term);
|
||||||
|
|
||||||
|
AbstractRunner::List runable;
|
||||||
|
|
||||||
|
//if the name is not empty we will launch only the specified runner
|
||||||
|
if (!runnerName.isEmpty()) {
|
||||||
|
runable.append(runner(runnerName));
|
||||||
|
} else {
|
||||||
|
runable = d->runners;
|
||||||
|
}
|
||||||
|
bool jobsLaunched=false;
|
||||||
|
foreach (Plasma::AbstractRunner* r, runable) {
|
||||||
|
if ((r->ignoredTypes() & d->context.type()) == 0) {
|
||||||
|
// kDebug() << "launching" << r->name();
|
||||||
|
jobsLaunched=true;
|
||||||
|
Job *job = new FindMatchesJob(term, r, &d->context, this);
|
||||||
|
Weaver::instance()->enqueue( job );
|
||||||
|
d->searchJobs.append( job );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!jobsLaunched) {
|
||||||
|
emit matchesCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunnerManager::execQuery (const QString & term, const QString & runnerName)
|
||||||
|
{
|
||||||
|
if (term.isEmpty()) {
|
||||||
|
reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->context.searchTerm() == term) {
|
||||||
|
// we already are searching for this!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
// kDebug() << "executing query about " << term << "on" << runnerName;
|
||||||
|
d->context.setSearchTerm(term);
|
||||||
|
|
||||||
|
AbstractRunner *r = runner(runnerName);
|
||||||
|
|
||||||
|
if (!r) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r->ignoredTypes() & d->context.type()) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->performMatch(d->context);
|
||||||
|
emit matchesCompleted();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerManager::reset()
|
||||||
|
{
|
||||||
|
// If ThreadWeaver is idle, it is safe to clear previous jobs
|
||||||
|
if ( Weaver::instance()->isIdle() ) {
|
||||||
|
qDeleteAll( d->searchJobs );
|
||||||
|
d->searchJobs.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Weaver::instance()->dequeue();
|
||||||
|
}
|
||||||
|
d->context.reset();
|
||||||
|
|
||||||
|
//FIXME: if the weaver is not idle we have a number of jobs that
|
||||||
|
// will eventually return their matches
|
||||||
|
// we need a way to stop them (Weaver::requestAbort() Job::requestAbort )
|
||||||
|
// or discard results
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "runnermanager.moc"
|
124
runnermanager.h
Normal file
124
runnermanager.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006-2007 Ryan P. Bitanga <ryan.bitanga@gmail.com>
|
||||||
|
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
|
||||||
|
* Copyright 2008 Jordi Polo <mumismo@gmail.com>
|
||||||
|
*
|
||||||
|
* This program 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, 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 Library 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RUNNERMANAGER_H
|
||||||
|
#define RUNNERMANAGER_H
|
||||||
|
|
||||||
|
#include <QtCore/QList>
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
#include <plasma/plasma_export.h>
|
||||||
|
#include "abstractrunner.h"
|
||||||
|
|
||||||
|
namespace Plasma
|
||||||
|
{
|
||||||
|
class SearchMatch;
|
||||||
|
class AbstractRunner;
|
||||||
|
class SearchContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @short The RunnerManager class decides what installed runners are runnable,
|
||||||
|
* and their ratings. It is the main proxy to the runners.
|
||||||
|
*/
|
||||||
|
class PLASMA_EXPORT RunnerManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit RunnerManager(QObject *parent=0);
|
||||||
|
explicit RunnerManager(KConfigGroup& config, QObject *parent=0);
|
||||||
|
~RunnerManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and returns a loaded runner or NULL
|
||||||
|
* @arg name the name of the runner
|
||||||
|
* @return Pointer to the runner
|
||||||
|
*/
|
||||||
|
AbstractRunner* runner(const QString &name) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current context
|
||||||
|
* @return pointer to the current context
|
||||||
|
*/
|
||||||
|
SearchContext* searchContext() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all available matches found so far for the previously launched query
|
||||||
|
* @return List of matches
|
||||||
|
*/
|
||||||
|
QList<SearchMatch *> matches() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a given match
|
||||||
|
* @arg pointer to the match to be executed
|
||||||
|
*/
|
||||||
|
void run(const SearchMatch *match);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a query, this will create threads and return inmediately.
|
||||||
|
* When the information will be available can be known using the
|
||||||
|
* matchesChanged, matchesUpdated, matchesCompleted signals
|
||||||
|
* The information can be retrieved calling matches
|
||||||
|
* @arg term the term we want to find matches for
|
||||||
|
* @arg runner optional, if only one specific runner is to be used
|
||||||
|
*/
|
||||||
|
void launchQuery(const QString &term, const QString & runnerName=QString());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a query, this method will only return when the query is executed
|
||||||
|
* This means that the method may be dangerous as it wait a variable amount
|
||||||
|
* of time for the runner to finish.
|
||||||
|
* The runner parameter is mandatory, to avoid launching unwanted runners.
|
||||||
|
* @arg term the term we want to find matches for
|
||||||
|
* @arg runner the runner we will use, it is mandatory
|
||||||
|
* @return 0 if nothing was launched, 1 if launched.
|
||||||
|
*/
|
||||||
|
bool execQuery(const QString &term, const QString & runnerName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the current data and stops the query
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emited each time a new match is added to the list
|
||||||
|
*/
|
||||||
|
void matchesChanged();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emited when all the matches have been found
|
||||||
|
*/
|
||||||
|
void matchesCompleted();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
Private * const d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QSharedData>
|
||||||
|
|
||||||
#include <KCompletion>
|
#include <KCompletion>
|
||||||
#include <KDebug>
|
#include <KDebug>
|
||||||
@ -36,34 +37,31 @@
|
|||||||
namespace Plasma
|
namespace Plasma
|
||||||
{
|
{
|
||||||
|
|
||||||
class SearchContext::Private
|
class SearchContext::Private : public QSharedData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Private(SearchContext::DataPolicy p)
|
Private(SearchContext *context, SearchContext::DataPolicy p)
|
||||||
: type(SearchContext::UnknownType),
|
: type(SearchContext::UnknownType),
|
||||||
completer(0),
|
q(context),
|
||||||
policy(p)
|
policy(p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Private(const SearchContext::Private& p)
|
||||||
|
: term(p.term),
|
||||||
|
mimeType(p.mimeType),
|
||||||
|
type(p.type),
|
||||||
|
q(p.q),
|
||||||
|
policy(p.policy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Private()
|
~Private()
|
||||||
{
|
{
|
||||||
|
lockForWrite();
|
||||||
qDeleteAll(matches);
|
qDeleteAll(matches);
|
||||||
matches.clear();
|
matches.clear();
|
||||||
delete completer;
|
unlock();
|
||||||
}
|
|
||||||
|
|
||||||
void resetState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
KCompletion* completionObject()
|
|
||||||
{
|
|
||||||
if (!completer) {
|
|
||||||
completer = new KCompletion;
|
|
||||||
}
|
|
||||||
|
|
||||||
return completer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lockForRead()
|
void lockForRead()
|
||||||
@ -87,61 +85,90 @@ class SearchContext::Private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines type of query
|
||||||
|
*/
|
||||||
|
void determineType()
|
||||||
|
{
|
||||||
|
lockForWrite();
|
||||||
|
QString path = KShell::tildeExpand(term);
|
||||||
|
|
||||||
|
int space = term.indexOf(' ');
|
||||||
|
if (space > 0) {
|
||||||
|
if (!KStandardDirs::findExe(path.left(space)).isEmpty()) {
|
||||||
|
type = ShellCommand;
|
||||||
|
}
|
||||||
|
} else if (!KStandardDirs::findExe(path.left(space)).isEmpty()) {
|
||||||
|
type = Executable;
|
||||||
|
} else {
|
||||||
|
KUrl url(term);
|
||||||
|
if (!url.protocol().isEmpty() && !url.host().isEmpty()) {
|
||||||
|
type = NetworkLocation;
|
||||||
|
} else if (QFile::exists(path)) {
|
||||||
|
QFileInfo info(path);
|
||||||
|
if (info.isDir()) {
|
||||||
|
type = Directory;
|
||||||
|
mimeType = "inode/folder";
|
||||||
|
} else {
|
||||||
|
type = File;
|
||||||
|
KMimeType::Ptr mimeTypePtr = KMimeType::findByPath(path);
|
||||||
|
if (mimeTypePtr) {
|
||||||
|
mimeType = mimeTypePtr->name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (term.contains('.')) {
|
||||||
|
// default to a network location so we can can do things like www.kde.org
|
||||||
|
type = NetworkLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
QReadWriteLock lock;
|
QReadWriteLock lock;
|
||||||
QList<SearchMatch *> matches;
|
QList<SearchMatch*> matches;
|
||||||
QString term;
|
QString term;
|
||||||
QString mimeType;
|
QString mimeType;
|
||||||
SearchContext::Type type;
|
SearchContext::Type type;
|
||||||
KCompletion *completer;
|
SearchContext * q;
|
||||||
const SearchContext::DataPolicy policy;
|
const SearchContext::DataPolicy policy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
SearchContext::SearchContext(QObject *parent, DataPolicy policy)
|
SearchContext::SearchContext(QObject *parent, DataPolicy policy)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
d(new Private(policy))
|
d(new Private(this, policy))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchContext::SearchContext(QObject *parent, const SearchContext &other)
|
//copy ctor
|
||||||
: QObject(parent),
|
SearchContext::SearchContext(SearchContext &other, QObject *parent)
|
||||||
d(new Private(SingleConsumer))
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
other.d->lockForRead();
|
other.d->lockForRead();
|
||||||
d->term = other.d->term;
|
d=other.d;
|
||||||
d->mimeType = other.d->mimeType;
|
|
||||||
d->type = other.d->type;
|
|
||||||
other.d->unlock();
|
other.d->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchContext::~SearchContext()
|
SearchContext::~SearchContext()
|
||||||
{
|
{
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchContext::reset()
|
void SearchContext::reset()
|
||||||
{
|
{
|
||||||
d->lockForWrite();
|
// Locks are needed as other contexts can be copied of this one
|
||||||
QList<SearchMatch*> matches = d->matches;
|
|
||||||
|
|
||||||
d->matches.clear();
|
// We will detach if we are a copy of someone. But we will reset
|
||||||
|
// if we are the 'main' context others copied from. Resetting
|
||||||
|
// one SearchContext makes all the copies oneobsolete.
|
||||||
|
d.detach();
|
||||||
|
|
||||||
|
//kDebug() << "reset searchContext";
|
||||||
|
d->lockForWrite();
|
||||||
d->type = SearchContext::UnknownType;
|
d->type = SearchContext::UnknownType;
|
||||||
d->term.clear();
|
d->term.clear();
|
||||||
d->mimeType.clear();
|
d->mimeType.clear();
|
||||||
|
|
||||||
if (d->completer) {
|
|
||||||
d->completer->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
d->unlock();
|
d->unlock();
|
||||||
|
removeAllMatches();
|
||||||
emit matchesChanged();
|
|
||||||
|
|
||||||
// in case someone is still holding on to the Matches
|
|
||||||
// when we emit the matchesChanged() signal, we don't
|
|
||||||
// delete the matches until after the signal is handled.
|
|
||||||
// a bit safer.
|
|
||||||
qDeleteAll(matches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchContext::setSearchTerm(const QString &term)
|
void SearchContext::setSearchTerm(const QString &term)
|
||||||
@ -153,46 +180,9 @@ void SearchContext::setSearchTerm(const QString &term)
|
|||||||
d->lockForWrite();
|
d->lockForWrite();
|
||||||
d->term = term;
|
d->term = term;
|
||||||
d->unlock();
|
d->unlock();
|
||||||
determineType();
|
d->determineType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchContext::determineType()
|
|
||||||
{
|
|
||||||
d->lockForWrite();
|
|
||||||
QString term = d->term;
|
|
||||||
QString path = KShell::tildeExpand(term);
|
|
||||||
|
|
||||||
int space = term.indexOf(' ');
|
|
||||||
if (space > 0) {
|
|
||||||
if (!KStandardDirs::findExe(path.left(space)).isEmpty()) {
|
|
||||||
d->type = ShellCommand;
|
|
||||||
}
|
|
||||||
} else if (!KStandardDirs::findExe(path.left(space)).isEmpty()) {
|
|
||||||
d->type = Executable;
|
|
||||||
} else {
|
|
||||||
KUrl url(term);
|
|
||||||
|
|
||||||
if (!url.protocol().isEmpty() && !url.host().isEmpty()) {
|
|
||||||
d->type = NetworkLocation;
|
|
||||||
} else if (QFile::exists(path)) {
|
|
||||||
QFileInfo info(path);
|
|
||||||
if (info.isDir()) {
|
|
||||||
d->type = Directory;
|
|
||||||
d->mimeType = "inode/folder";
|
|
||||||
} else {
|
|
||||||
d->type = File;
|
|
||||||
KMimeType::Ptr mimeType = KMimeType::findByPath(path);
|
|
||||||
if (mimeType) {
|
|
||||||
d->mimeType = mimeType->name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (term.contains('.')) {
|
|
||||||
// default to a network location so we can can do things like www.kde.org
|
|
||||||
d->type = NetworkLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SearchContext::searchTerm() const
|
QString SearchContext::searchTerm() const
|
||||||
{
|
{
|
||||||
@ -212,40 +202,6 @@ QString SearchContext::mimeType() const
|
|||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
KCompletion* SearchContext::completionObject() const
|
|
||||||
{
|
|
||||||
d->lockForRead();
|
|
||||||
KCompletion* comp = d->completionObject();
|
|
||||||
d->unlock();
|
|
||||||
return comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchContext::addStringCompletion(const QString &completion)
|
|
||||||
{
|
|
||||||
d->lockForWrite();
|
|
||||||
if (!d->completer) {
|
|
||||||
d->unlock();
|
|
||||||
// if the completion object isn't actually used, don't bother
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->completer->addItem(completion);
|
|
||||||
d->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchContext::addStringCompletions(const QStringList &completion)
|
|
||||||
{
|
|
||||||
d->lockForWrite();
|
|
||||||
if (!d->completer) {
|
|
||||||
d->unlock();
|
|
||||||
// if the completion object isn't actually used, don't bother
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->completer->insertItems(completion);
|
|
||||||
d->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SearchContext::addMatches(const QString& term, const QList<SearchMatch*> &matches)
|
bool SearchContext::addMatches(const QString& term, const QList<SearchMatch*> &matches)
|
||||||
{
|
{
|
||||||
if (searchTerm() != term || matches.isEmpty()) {
|
if (searchTerm() != term || matches.isEmpty()) {
|
||||||
@ -255,12 +211,11 @@ bool SearchContext::addMatches(const QString& term, const QList<SearchMatch*> &m
|
|||||||
d->lockForWrite();
|
d->lockForWrite();
|
||||||
d->matches << matches;
|
d->matches << matches;
|
||||||
d->unlock();
|
d->unlock();
|
||||||
|
//kDebug()<< "add matches";
|
||||||
// TODO: perhaps queue this signal so that it is only emitted after a small delay?
|
// A copied searchContext may share the d pointer,
|
||||||
// currently we do this in krunner's Interface class, but it would probably
|
// we always want to sent the signal of the object that created
|
||||||
// be better to move that detail to SearchContext so that other apps that
|
// the d pointer
|
||||||
// use SearchContext can also benefit from it
|
emit d->q->matchesChanged();
|
||||||
emit matchesChanged();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,30 +228,12 @@ bool SearchContext::addMatch(const QString &term, SearchMatch *match)
|
|||||||
d->lockForWrite();
|
d->lockForWrite();
|
||||||
d->matches << match;
|
d->matches << match;
|
||||||
d->unlock();
|
d->unlock();
|
||||||
emit matchesChanged();
|
//kDebug()<< "added match" << match->text();
|
||||||
|
emit d->q->matchesChanged();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchContext::moveMatchesTo(SearchContext &other)
|
|
||||||
{
|
|
||||||
//NOTE: we have moveMatchesTo instead of the more 'natural' addMatches
|
|
||||||
// because we can get away with one write lock on the local object
|
|
||||||
// this way, otherwise we'd need to lock once for searchTerm, once
|
|
||||||
// for matches() and again for removeAllMatches() (2 read, one write)
|
|
||||||
d->lockForWrite();
|
|
||||||
|
|
||||||
const bool success = other.addMatches(d->term, d->matches);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
// the matches no longer belong to this SearchContext,
|
|
||||||
// so remove them from the data
|
|
||||||
d->matches.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
d->unlock();
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<SearchMatch *> SearchContext::matches() const
|
QList<SearchMatch *> SearchContext::matches() const
|
||||||
{
|
{
|
||||||
@ -309,18 +246,19 @@ QList<SearchMatch *> SearchContext::matches() const
|
|||||||
void SearchContext::removeAllMatches()
|
void SearchContext::removeAllMatches()
|
||||||
{
|
{
|
||||||
d->lockForWrite();
|
d->lockForWrite();
|
||||||
|
bool emptyMatches = d->matches.isEmpty();
|
||||||
QList<SearchMatch*> matches = d->matches;
|
if (!emptyMatches) {
|
||||||
d->matches.clear();
|
d->matches.clear();
|
||||||
|
d->unlock();
|
||||||
|
emit d->q->matchesChanged();
|
||||||
|
// in case someone is still holding on to the Matches
|
||||||
|
// when we emit the matchesChanged() signal, we don't
|
||||||
|
// delete the matches until after the signal is handled.
|
||||||
|
// a bit safer.
|
||||||
|
d->lockForWrite();
|
||||||
|
qDeleteAll(d->matches);
|
||||||
|
}
|
||||||
d->unlock();
|
d->unlock();
|
||||||
|
|
||||||
emit matchesChanged();
|
|
||||||
|
|
||||||
// in case someone is still holding on to the Matches
|
|
||||||
// when we emit the matchesChanged() signal, we don't
|
|
||||||
// delete the matches until after the signal is handled.
|
|
||||||
// a bit safer.
|
|
||||||
qDeleteAll(matches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
#include <QSharedDataPointer>
|
||||||
|
#include <QFlags>
|
||||||
|
|
||||||
#include <plasma/plasma_export.h>
|
#include <plasma/plasma_export.h>
|
||||||
|
|
||||||
@ -43,19 +45,22 @@ class PLASMA_EXPORT SearchContext : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type { UnknownType = 0,
|
enum Type { None = 0,
|
||||||
Directory,
|
UnknownType = 1,
|
||||||
File,
|
Directory = 2,
|
||||||
NetworkLocation,
|
File = 4,
|
||||||
Executable,
|
NetworkLocation = 8,
|
||||||
ShellCommand,
|
Executable = 16,
|
||||||
Help
|
ShellCommand = 32,
|
||||||
|
Help = 64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_FLAGS(Types, Type)
|
||||||
|
|
||||||
enum DataPolicy { Shared = 0,
|
enum DataPolicy { Shared = 0,
|
||||||
SingleConsumer
|
SingleConsumer
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit SearchContext(QObject *parent = 0, DataPolicy policy = Shared);
|
explicit SearchContext(QObject *parent = 0, DataPolicy policy = Shared);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +69,8 @@ class PLASMA_EXPORT SearchContext : public QObject
|
|||||||
* matches) from the passed in SearchContext. Primarily useful for creating
|
* matches) from the passed in SearchContext. Primarily useful for creating
|
||||||
* a thread-local copy of a Shared SearchContext.
|
* a thread-local copy of a Shared SearchContext.
|
||||||
*/
|
*/
|
||||||
SearchContext(QObject *parent, const SearchContext& other);
|
explicit SearchContext(SearchContext& other, QObject *parent = 0);
|
||||||
|
|
||||||
~SearchContext();
|
~SearchContext();
|
||||||
|
|
||||||
|
|
||||||
@ -100,22 +106,7 @@ class PLASMA_EXPORT SearchContext : public QObject
|
|||||||
*/
|
*/
|
||||||
QString mimeType() const;
|
QString mimeType() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a completion object that can be used with UI elements
|
|
||||||
*/
|
|
||||||
KCompletion* completionObject() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an item to the completion object.
|
|
||||||
*/
|
|
||||||
void addStringCompletion(const QString& completion);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple items to the completion object.
|
|
||||||
*/
|
|
||||||
void addStringCompletions(const QStringList& completions);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends lists of matches to the list of matches.
|
* Appends lists of matches to the list of matches.
|
||||||
* The SearchContext takes over ownership of the matches on successful addition.
|
* The SearchContext takes over ownership of the matches on successful addition.
|
||||||
*
|
*
|
||||||
@ -154,11 +145,6 @@ class PLASMA_EXPORT SearchContext : public QObject
|
|||||||
*/
|
*/
|
||||||
QList<SearchMatch *> matches() const;
|
QList<SearchMatch *> matches() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines type of query
|
|
||||||
*/
|
|
||||||
void determineType();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all matches from this SearchContext.
|
* Removes all matches from this SearchContext.
|
||||||
*/
|
*/
|
||||||
@ -169,9 +155,11 @@ class PLASMA_EXPORT SearchContext : public QObject
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
class Private;
|
class Private;
|
||||||
Private * const d;
|
QExplicitlySharedDataPointer<Private> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS (Plasma::SearchContext::Types)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "searchmatch.h"
|
#include "searchmatch.h"
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@ -41,7 +42,7 @@ class SearchMatch::Private
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractRunner *runner;
|
QPointer<AbstractRunner> runner;
|
||||||
SearchMatch::Type type;
|
SearchMatch::Type type;
|
||||||
QString text;
|
QString text;
|
||||||
QString subtext;
|
QString subtext;
|
||||||
@ -55,6 +56,7 @@ class SearchMatch::Private
|
|||||||
SearchMatch::SearchMatch(AbstractRunner *runner)
|
SearchMatch::SearchMatch(AbstractRunner *runner)
|
||||||
: d(new Private(runner))
|
: d(new Private(runner))
|
||||||
{
|
{
|
||||||
|
// kDebug() << "new match created";
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchMatch::~SearchMatch()
|
SearchMatch::~SearchMatch()
|
||||||
@ -146,7 +148,7 @@ void SearchMatch::run(const SearchContext *context) const
|
|||||||
{
|
{
|
||||||
Q_ASSERT(context);
|
Q_ASSERT(context);
|
||||||
|
|
||||||
//kDebug() << "we have" << context->searchTerm() << context->mimetype();
|
//kDebug() << "we run the term" << context->searchTerm() << "whose type is" << context->mimetype();
|
||||||
if (d->runner) {
|
if (d->runner) {
|
||||||
//TODO: this could be dangerous if the runner is deleted behind our backs.
|
//TODO: this could be dangerous if the runner is deleted behind our backs.
|
||||||
d->runner->run(context, this);
|
d->runner->run(context, this);
|
||||||
|
@ -38,7 +38,8 @@ class PLASMA_EXPORT SearchMatch
|
|||||||
/**
|
/**
|
||||||
* The type of match. Value is important here as it is used for sorting
|
* The type of match. Value is important here as it is used for sorting
|
||||||
*/
|
*/
|
||||||
enum Type { PossibleMatch = 0 /**< Something that may match the query */,
|
enum Type { CompletionMatch = 10 /**< Possible completion for the data of the query */,
|
||||||
|
PossibleMatch = 30 /**< Something that may match the query */,
|
||||||
InformationalMatch = 50 /**< A purely informational, non-actionable match,
|
InformationalMatch = 50 /**< A purely informational, non-actionable match,
|
||||||
such as the answer to a question or calculation*/,
|
such as the answer to a question or calculation*/,
|
||||||
HelperMatch = 70 /**< A match that represents an action not directly related
|
HelperMatch = 70 /**< A match that represents an action not directly related
|
||||||
@ -51,6 +52,7 @@ class PLASMA_EXPORT SearchMatch
|
|||||||
an action to be triggered. */,
|
an action to be triggered. */,
|
||||||
ExactMatch = 100 /**< An exact match to the query */};
|
ExactMatch = 100 /**< An exact match to the query */};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a PossibleMatch associated with a given SearchContext
|
* Constructs a PossibleMatch associated with a given SearchContext
|
||||||
* and runner.
|
* and runner.
|
||||||
|
Loading…
Reference in New Issue
Block a user