Remove KRunner from Plasma-Framework
Have it as a separate KRunner framework instead
This commit is contained in:
parent
dbbb1ed513
commit
18473c9e9e
@ -28,7 +28,6 @@ PLASMA_UNIT_TESTS(
|
||||
packagestructuretest
|
||||
pluginloadertest
|
||||
# plasmoidpackagetest
|
||||
#runnercontexttest
|
||||
)
|
||||
|
||||
add_executable(storagetest storagetest.cpp ../src/plasma/private/storage.cpp ../src/plasma/private/storagethread.cpp)
|
||||
|
@ -1,60 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2010 Aaron Seigo <aseigo@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. *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "runnercontexttest.h"
|
||||
|
||||
#include <kprotocolinfo.h>
|
||||
#include "plasma/runnercontext.h"
|
||||
|
||||
Q_DECLARE_METATYPE(Plasma::RunnerContext::Type)
|
||||
|
||||
void RunnerContextTest::typeDetection_data()
|
||||
{
|
||||
QTest::addColumn<QString>("url");
|
||||
QTest::addColumn<Plasma::RunnerContext::Type>("type");
|
||||
|
||||
if (KProtocolInfo::isKnownProtocol("man")) {
|
||||
QTest::newRow("man page listing") << "man:/" << Plasma::RunnerContext::NetworkLocation;
|
||||
QTest::newRow("ls man page listing") << "man://ls" << Plasma::RunnerContext::NetworkLocation;
|
||||
}
|
||||
QTest::newRow("http without host") << "http://" << Plasma::RunnerContext::UnknownType;
|
||||
QTest::newRow("http with host") << "http://kde.org" << Plasma::RunnerContext::NetworkLocation;
|
||||
QTest::newRow("file double slash") << "file://home" << Plasma::RunnerContext::Directory;
|
||||
QTest::newRow("file triple slash") << "file:///home" << Plasma::RunnerContext::Directory;
|
||||
QTest::newRow("file single slash") << "file:/home" << Plasma::RunnerContext::Directory;
|
||||
QTest::newRow("file multiple path") << "file://usr/bin" << Plasma::RunnerContext::Directory;
|
||||
QTest::newRow("invalid file path") << "file://bad/path" << Plasma::RunnerContext::UnknownType;
|
||||
QTest::newRow("executable") << "ls" << Plasma::RunnerContext::Executable;
|
||||
QTest::newRow("executable with params") << "ls -R" << Plasma::RunnerContext::ShellCommand;
|
||||
QTest::newRow("full path executable") << "ls -R" << Plasma::RunnerContext::ShellCommand;
|
||||
QTest::newRow("full path executable with params") << "/bin/ls -R" << Plasma::RunnerContext::ShellCommand;
|
||||
QTest::newRow("protocol-less path") << "/home" << Plasma::RunnerContext::Directory;
|
||||
QTest::newRow("invalid protocol-less path") << "/bad/path" << Plasma::RunnerContext::UnknownType;
|
||||
}
|
||||
|
||||
void RunnerContextTest::typeDetection()
|
||||
{
|
||||
QFETCH(QString, url);
|
||||
QFETCH(Plasma::RunnerContext::Type, type);
|
||||
|
||||
m_context.setQuery(url);
|
||||
QCOMPARE(int(m_context.type()), int(type));
|
||||
}
|
||||
|
||||
QTEST_MAIN(RunnerContextTest)
|
@ -1,39 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2010 Aaron Seigo <aseigo@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 PACKAGEMETADATATEST_H
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include "plasma/runnercontext.h"
|
||||
|
||||
class RunnerContextTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void typeDetection_data();
|
||||
void typeDetection();
|
||||
|
||||
private:
|
||||
Plasma::RunnerContext m_context;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Project Needs a name, of course
|
||||
project(RunnerExample)
|
||||
|
||||
# We add our source code here
|
||||
set(example_SRCS homefilesrunner.cpp)
|
||||
|
||||
# Now make sure all files get to the right place
|
||||
add_library(plasma_runner_example_homefiles MODULE ${example_SRCS})
|
||||
target_link_libraries(plasma_runner_example_homefiles KF5::Plasma KF5::KIOCore KF5::KIOWidgets)
|
||||
|
||||
# Install the library and .desktop file
|
||||
install(TARGETS plasma_runner_example_homefiles DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
install(FILES plasma-runner-example-homefiles.desktop DESTINATION ${SERVICES_INSTALL_DIR})
|
@ -1,2 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
$XGETTEXT *.cpp -o $podir/plasma_runner_example_homefiles.pot
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
Copyright 2009 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "homefilesrunner.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <KDebug>
|
||||
#include <KMimeType>
|
||||
#include <KRun>
|
||||
|
||||
HomeFilesRunner::HomeFilesRunner(QObject *parent, const QVariantList &args)
|
||||
: AbstractRunner(parent, args)
|
||||
{
|
||||
setIgnoredTypes(Plasma::RunnerContext::NetworkLocation |
|
||||
Plasma::RunnerContext::Executable |
|
||||
Plasma::RunnerContext::ShellCommand);
|
||||
setSpeed(SlowSpeed);
|
||||
setPriority(LowPriority);
|
||||
setHasRunOptions(true);
|
||||
}
|
||||
|
||||
void HomeFilesRunner::init()
|
||||
{
|
||||
reloadConfiguration();
|
||||
connect(this, SIGNAL(prepare()), this, SLOT(prepareForMatchSession()));
|
||||
connect(this, SIGNAL(teardown()), this, SLOT(matchSessionFinished()));
|
||||
}
|
||||
|
||||
void HomeFilesRunner::reloadConfiguration()
|
||||
{
|
||||
KConfigGroup c = config();
|
||||
m_triggerWord = c.readEntry("trigger", QString());
|
||||
if (!m_triggerWord.isEmpty()) {
|
||||
m_triggerWord.append(' ');
|
||||
}
|
||||
|
||||
m_path = c.readPathEntry("path", QDir::homePath());
|
||||
QFileInfo pathInfo(m_path);
|
||||
if (!pathInfo.isDir()) {
|
||||
m_path = QDir::homePath();
|
||||
}
|
||||
|
||||
QList<Plasma::RunnerSyntax> syntaxes;
|
||||
Plasma::RunnerSyntax syntax(QString("%1:q:").arg(m_triggerWord),
|
||||
i18n("Finds files matching :q: in the %1 folder", m_path));
|
||||
syntaxes.append(syntax);
|
||||
setSyntaxes(syntaxes);
|
||||
}
|
||||
|
||||
void HomeFilesRunner::prepareForMatchSession()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HomeFilesRunner::match(Plasma::RunnerContext &context)
|
||||
{
|
||||
QString query = context.query();
|
||||
if (query == QChar('.') || query == "..") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_triggerWord.isEmpty()) {
|
||||
if (!query.startsWith(m_triggerWord)) {
|
||||
return;
|
||||
}
|
||||
|
||||
query.remove(0, m_triggerWord.length());
|
||||
}
|
||||
|
||||
if (query.length() > 2) {
|
||||
query.prepend('*').append('*');
|
||||
}
|
||||
|
||||
QDir dir(m_path);
|
||||
QList<Plasma::QueryMatch> matches;
|
||||
|
||||
foreach (const QString &file, dir.entryList(QStringList(query))) {
|
||||
const QString path = dir.absoluteFilePath(file);
|
||||
if (!path.startsWith(m_path)) {
|
||||
// this file isn't in our directory; looks like we got a query with some
|
||||
// ..'s in it!
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!context.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Plasma::QueryMatch match(this);
|
||||
match.setText(i18n("Open %1", path));
|
||||
match.setData(path);
|
||||
match.setId(path);
|
||||
if (m_iconCache.contains(path)) {
|
||||
match.setIcon(m_iconCache.value(path));
|
||||
} else {
|
||||
KIcon icon(KMimeType::iconNameForUrl(path));
|
||||
m_iconCache.insert(path, icon);
|
||||
match.setIcon(icon);
|
||||
}
|
||||
|
||||
if (file.compare(query, Qt::CaseInsensitive)) {
|
||||
match.setRelevance(1.0);
|
||||
match.setType(Plasma::QueryMatch::ExactMatch);
|
||||
} else {
|
||||
match.setRelevance(0.8);
|
||||
}
|
||||
|
||||
matches.append(match);
|
||||
}
|
||||
|
||||
context.addMatches(context.query(), matches);
|
||||
}
|
||||
|
||||
void HomeFilesRunner::matchSessionFinished()
|
||||
{
|
||||
m_iconCache.clear();
|
||||
}
|
||||
|
||||
void HomeFilesRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
|
||||
{
|
||||
Q_UNUSED(context)
|
||||
// KRun autodeletes itself, so we can just create it and forget it!
|
||||
KRun *opener = new KRun(match.data().toString(), 0);
|
||||
opener->setRunExecutables(false);
|
||||
}
|
||||
|
||||
void HomeFilesRunner::createRunOptions(QWidget *widget)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(widget);
|
||||
QCheckBox *cb = new QCheckBox(widget);
|
||||
cb->setText(i18n("This is just for show"));
|
||||
layout->addWidget(cb);
|
||||
}
|
||||
|
||||
K_EXPORT_PLASMA_RUNNER(example-homefiles, HomeFilesRunner)
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
Copyright 2009 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HOMEFILES_H
|
||||
#define HOMEFILES_H
|
||||
|
||||
#include <Plasma/AbstractRunner>
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include <KIcon>
|
||||
|
||||
class HomeFilesRunner : public Plasma::AbstractRunner
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HomeFilesRunner(QObject *parent, const QVariantList &args);
|
||||
|
||||
void match(Plasma::RunnerContext &context);
|
||||
void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match);
|
||||
void createRunOptions(QWidget *widget);
|
||||
void reloadConfiguration();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void init();
|
||||
void prepareForMatchSession();
|
||||
void matchSessionFinished();
|
||||
|
||||
private:
|
||||
QHash<QString, KIcon> m_iconCache;
|
||||
QString m_path;
|
||||
QString m_triggerWord;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,38 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Home Files
|
||||
Name[bs]=Lične datoteke
|
||||
Name[de]=Persönliche Dateien
|
||||
Name[fi]=Kodin tiedostot
|
||||
Name[fr]=Fichiers personnels
|
||||
Name[nl]=Persoonlijke bestanden
|
||||
Name[pt]=Ficheiros Pessoais
|
||||
Name[pt_BR]=Arquivos pessoais
|
||||
Name[sk]=Domáce súbory
|
||||
Name[sv]=Hemfiler
|
||||
Name[uk]=Файли у домашній теці
|
||||
Name[x-test]=xxHome Filesxx
|
||||
Comment=Part of a tutorial demonstrating how to create Runner plugins
|
||||
Comment[bs]=Dio tutorijala demonstrira kako se kreiraju Runner priključci
|
||||
Comment[de]=Teil einer Anleitung zur Demonstration, wie Runner-Module erstellt werden
|
||||
Comment[fr]=Éléments d'un tutoriel montrant comment créer des modules « Runner »
|
||||
Comment[nl]=Deel van een inleiding die demonstreert hoe Runner-plug-ins te maken
|
||||
Comment[pt]=Parte de um tutorial que demonstra como criar 'plugins' do Runner
|
||||
Comment[pt_BR]=Parte de um tutorial que demonstra como criar plugins do Runner
|
||||
Comment[sk]=Časť kurzu demonštrujúceho ako vytvoriť pluginy Runnera
|
||||
Comment[sv]=Del av en handledning som demonstrerar hur insticksprogram till Runner skapas
|
||||
Comment[uk]=Частина підручника, який демонструє створення додатків до засобу запуску
|
||||
Comment[x-test]=xxPart of a tutorial demonstrating how to create Runner pluginsxx
|
||||
Icon=user-home
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=Plasma/Runner
|
||||
|
||||
X-KDE-Library=plasma_runner_example_homefiles
|
||||
X-KDE-PluginInfo-Author=Aaron Seigo
|
||||
X-KDE-PluginInfo-Email=aseigo@kde.org
|
||||
X-KDE-PluginInfo-Name=example-homefiles
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://plasma.kde.org/
|
||||
X-KDE-PluginInfo-Category=Examples
|
||||
X-KDE-PluginInfo-Depends=
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
@ -2,7 +2,6 @@ add_subdirectory(accessdenied)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(dirmodel)
|
||||
add_subdirectory(draganddrop)
|
||||
#add_subdirectory(krunnermodel)
|
||||
add_subdirectory(qtextracomponents)
|
||||
add_subdirectory(plasmacomponents)
|
||||
add_subdirectory(plasmaextracomponents)
|
||||
|
@ -29,13 +29,10 @@
|
||||
|
||||
#include <plasma/framesvg.h>
|
||||
#include <plasma/svg.h>
|
||||
#include <Plasma/QueryMatch>
|
||||
#include <Plasma/ServiceJob>
|
||||
|
||||
#include "datasource.h"
|
||||
#include "datamodel.h"
|
||||
#include "framesvgitem.h"
|
||||
#include "runnermodel.h"
|
||||
#include "svgitem.h"
|
||||
#include "theme.h"
|
||||
#include "dialog.h"
|
||||
@ -46,6 +43,7 @@
|
||||
#include "tooltip.h"
|
||||
#include "units.h"
|
||||
#include "windowthumbnail.h"
|
||||
#include <plasma/servicejob.h>
|
||||
|
||||
// #include "dataenginebindings_p.h"
|
||||
|
||||
@ -101,11 +99,7 @@ void CoreBindingsPlugin::registerTypes(const char *uri)
|
||||
qmlRegisterType<Formats>(uri, 2, 0, "Formats");
|
||||
qmlRegisterType<ServiceOperationStatus>(uri, 2, 0, "ServiceOperationStatus");
|
||||
qmlRegisterType<QAbstractItemModel>();
|
||||
#if 0
|
||||
qmlRegisterType<RunnerModel>(uri, 2, 0, "RunnerModel");
|
||||
qmlRegisterInterface<Plasma::QueryMatch>("QueryMatch");
|
||||
qRegisterMetaType<Plasma::QueryMatch *>("QueryMatch");
|
||||
#endif
|
||||
|
||||
qmlRegisterType<QQmlPropertyMap>();
|
||||
qmlRegisterType<IconItem>(uri, 2, 0, "IconItem");
|
||||
|
||||
|
@ -1,251 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 Aaron Seigo <aseigo@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.
|
||||
*/
|
||||
|
||||
#include "runnermodel.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QAction>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
RunnerModel::RunnerModel(QObject *parent)
|
||||
: QAbstractListModel(parent),
|
||||
m_manager(0),
|
||||
m_startQueryTimer(new QTimer(this)),
|
||||
m_runningChangedTimeout(new QTimer(this)),
|
||||
m_running(false)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(Label, "label");
|
||||
roles.insert(Icon, "icon");
|
||||
roles.insert(Type, "type");
|
||||
roles.insert(Relevance, "relevance");
|
||||
roles.insert(Data, "data");
|
||||
roles.insert(Id, "id");
|
||||
roles.insert(SubText, "description");
|
||||
roles.insert(Enabled, "enabled");
|
||||
roles.insert(RunnerId, "runnerid");
|
||||
roles.insert(RunnerName, "runnerName");
|
||||
roles.insert(Actions, "actions");
|
||||
setRoleNames(roles);
|
||||
|
||||
m_startQueryTimer->setSingleShot(true);
|
||||
m_startQueryTimer->setInterval(10);
|
||||
connect(m_startQueryTimer, SIGNAL(timeout()), this, SLOT(startQuery()));
|
||||
|
||||
//FIXME: HACK: some runners stay in a running but finished state, not possible to say if it's actually over
|
||||
m_runningChangedTimeout->setSingleShot(true);
|
||||
connect(m_runningChangedTimeout, SIGNAL(timeout()), this, SLOT(queryHasFinished()));
|
||||
}
|
||||
|
||||
int RunnerModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
return index.isValid() ? 0 : m_matches.count();
|
||||
}
|
||||
|
||||
int RunnerModel::count() const
|
||||
{
|
||||
return m_matches.count();
|
||||
}
|
||||
|
||||
QStringList RunnerModel::runners() const
|
||||
{
|
||||
return m_manager ? m_manager->allowedRunners() : m_pendingRunnersList;
|
||||
}
|
||||
|
||||
void RunnerModel::setRunners(const QStringList &allowedRunners)
|
||||
{
|
||||
//use sets to ensure comparison is order-independent
|
||||
if (allowedRunners.toSet() == runners().toSet()) {
|
||||
return;
|
||||
}
|
||||
if (m_manager) {
|
||||
m_manager->setAllowedRunners(allowedRunners);
|
||||
|
||||
//automagically enter single runner mode if there's only 1 allowed runner
|
||||
m_manager->setSingleMode(allowedRunners.count() == 1);
|
||||
} else {
|
||||
m_pendingRunnersList = allowedRunners;
|
||||
// qDebug() << "runners set" << m_pendingRunnersList.count();
|
||||
}
|
||||
|
||||
// to trigger single runner fun!
|
||||
if (allowedRunners.count() == 1) {
|
||||
m_singleRunnerId = allowedRunners.first();
|
||||
scheduleQuery(QString());
|
||||
} else {
|
||||
m_singleRunnerId.clear();
|
||||
}
|
||||
emit runnersChanged();
|
||||
}
|
||||
|
||||
void RunnerModel::run(int index)
|
||||
{
|
||||
if (index >= 0 && index < m_matches.count()) {
|
||||
m_manager->run(m_matches.at(index));
|
||||
}
|
||||
}
|
||||
|
||||
bool RunnerModel::isRunning() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
QVariant RunnerModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.parent().isValid() ||
|
||||
index.column() > 0 || index.row() < 0 || index.row() >= m_matches.count()) {
|
||||
// index requested must be valid, but we have no child items!
|
||||
//qDebug() << "invalid index requested";
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole || role == Label) {
|
||||
return m_matches.at(index.row()).text();
|
||||
} else if (role == Qt::DecorationRole || role == Icon) {
|
||||
return m_matches.at(index.row()).icon();
|
||||
} else if (role == Type) {
|
||||
return m_matches.at(index.row()).type();
|
||||
} else if (role == Relevance) {
|
||||
return m_matches.at(index.row()).relevance();
|
||||
} else if (role == Data) {
|
||||
return m_matches.at(index.row()).data();
|
||||
} else if (role == Id) {
|
||||
return m_matches.at(index.row()).id();
|
||||
} else if (role == SubText) {
|
||||
return m_matches.at(index.row()).subtext();
|
||||
} else if (role == Enabled) {
|
||||
return m_matches.at(index.row()).isEnabled();
|
||||
} else if (role == RunnerId) {
|
||||
return m_matches.at(index.row()).runner()->id();
|
||||
} else if (role == RunnerName) {
|
||||
return m_matches.at(index.row()).runner()->name();
|
||||
} else if (role == Actions) {
|
||||
QVariantList actions;
|
||||
Plasma::QueryMatch amatch = m_matches.at(index.row());
|
||||
QList<QAction*> theactions = m_manager->actionsForMatch(amatch);
|
||||
foreach(QAction* action, theactions) {
|
||||
actions += qVariantFromValue<QObject*>(action);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString RunnerModel::currentQuery() const
|
||||
{
|
||||
return m_manager ? m_manager->query() : QString();
|
||||
}
|
||||
|
||||
void RunnerModel::scheduleQuery(const QString &query)
|
||||
{
|
||||
m_pendingQuery = query;
|
||||
m_startQueryTimer->start();
|
||||
}
|
||||
|
||||
void RunnerModel::startQuery()
|
||||
{
|
||||
// avoid creating a manager just so we can run nothing
|
||||
// however, if we have one pending runner, then we'll be in single query mode
|
||||
// and a null query is a valid query
|
||||
if (!m_manager && m_pendingRunnersList.count() != 1 && m_pendingQuery.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//qDebug() << "!!!!!!!!!!!!!" << m_pendingQuery << m_manager;
|
||||
|
||||
if (createManager() || m_pendingQuery != m_manager->query()) {
|
||||
//qDebug() << "running query" << m_pendingQuery << m_manager;
|
||||
m_manager->launchQuery(m_pendingQuery, m_singleRunnerId);
|
||||
emit queryChanged();
|
||||
m_running = true;
|
||||
emit runningChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool RunnerModel::createManager()
|
||||
{
|
||||
if (!m_manager) {
|
||||
m_manager = new Plasma::RunnerManager(this);
|
||||
connect(m_manager, SIGNAL(matchesChanged(QList<Plasma::QueryMatch>)),
|
||||
this, SLOT(matchesChanged(QList<Plasma::QueryMatch>)));
|
||||
connect(m_manager, SIGNAL(queryFinished()),
|
||||
this, SLOT(queryHasFinished()));
|
||||
|
||||
if (!m_pendingRunnersList.isEmpty()) {
|
||||
setRunners(m_pendingRunnersList);
|
||||
m_pendingRunnersList.clear();
|
||||
}
|
||||
//connect(m_manager, SIGNAL(queryFinished()), this, SLOT(queryFinished()));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RunnerModel::matchesChanged(const QList<Plasma::QueryMatch> &matches)
|
||||
{
|
||||
//qDebug() << "got matches:" << matches.count();
|
||||
bool fullReset = false;
|
||||
int oldCount = m_matches.count();
|
||||
int newCount = matches.count();
|
||||
if (newCount > oldCount) {
|
||||
// We received more matches than we had. If all common matches are the
|
||||
// same, we can just append new matches instead of resetting the whole
|
||||
// model
|
||||
for (int row = 0; row < oldCount; ++row) {
|
||||
if (!(m_matches.at(row) == matches.at(row))) {
|
||||
fullReset = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!fullReset) {
|
||||
// Not a full reset, inserting rows
|
||||
beginInsertRows(QModelIndex(), oldCount, newCount-1);
|
||||
m_matches = matches;
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
} else {
|
||||
fullReset = true;
|
||||
}
|
||||
|
||||
if (fullReset) {
|
||||
beginResetModel();
|
||||
m_matches = matches;
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
}
|
||||
m_runningChangedTimeout->start(3000);
|
||||
}
|
||||
|
||||
void RunnerModel::queryHasFinished()
|
||||
{
|
||||
m_running = false;
|
||||
emit runningChanged(false);
|
||||
}
|
||||
|
||||
#include "runnermodel.moc"
|
||||
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 Aaron Seigo <aseigo@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 RUNNERMODEL_H
|
||||
#define RUNNERMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QStringList>
|
||||
|
||||
#include <Plasma/QueryMatch>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class RunnerManager;
|
||||
class QueryMatch;
|
||||
} // namespace Plasma
|
||||
|
||||
class QTimer;
|
||||
|
||||
/**
|
||||
* This model provides bindings to use KRunner from QML
|
||||
*
|
||||
* @author Aaron Seigo <aseigo@kde.org>
|
||||
*/
|
||||
class RunnerModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @property string set the KRunner query
|
||||
*/
|
||||
Q_PROPERTY(QString query WRITE scheduleQuery READ currentQuery NOTIFY queryChanged)
|
||||
|
||||
/**
|
||||
* @property Array The list of all allowed runner plugins that will be executed
|
||||
*/
|
||||
Q_PROPERTY(QStringList runners WRITE setRunners READ runners NOTIFY runnersChanged)
|
||||
|
||||
/**
|
||||
* @property int The number of rows of the model
|
||||
*/
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
|
||||
/**
|
||||
* @property bool running: true when queries are in execution
|
||||
*/
|
||||
Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @enum Roles of the model, they will be accessible from delegates
|
||||
*/
|
||||
enum Roles {
|
||||
Type = Qt::UserRole + 1,
|
||||
Label,
|
||||
Icon,
|
||||
Relevance,
|
||||
Data,
|
||||
Id,
|
||||
SubText,
|
||||
Enabled,
|
||||
RunnerId,
|
||||
RunnerName,
|
||||
Actions
|
||||
};
|
||||
|
||||
RunnerModel(QObject *parent = 0);
|
||||
|
||||
QString currentQuery() const;
|
||||
|
||||
QStringList runners() const;
|
||||
void setRunners(const QStringList &allowedRunners);
|
||||
|
||||
Q_SCRIPTABLE void run(int row);
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
int rowCount(const QModelIndex&) const;
|
||||
int count() const;
|
||||
QVariant data(const QModelIndex&, int) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void scheduleQuery(const QString &query);
|
||||
|
||||
Q_SIGNALS:
|
||||
void queryChanged();
|
||||
void countChanged();
|
||||
void runnersChanged();
|
||||
void runningChanged(bool running);
|
||||
|
||||
private Q_SLOTS:
|
||||
void startQuery();
|
||||
|
||||
private:
|
||||
bool createManager();
|
||||
|
||||
private Q_SLOTS:
|
||||
void matchesChanged(const QList<Plasma::QueryMatch> &matches);
|
||||
void queryHasFinished();
|
||||
|
||||
private:
|
||||
Plasma::RunnerManager *m_manager;
|
||||
QList<Plasma::QueryMatch> m_matches;
|
||||
QStringList m_pendingRunnersList;
|
||||
QString m_singleRunnerId;
|
||||
QString m_pendingQuery;
|
||||
QTimer *m_startQueryTimer;
|
||||
QTimer *m_runningChangedTimeout;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
#endif
|
@ -23,14 +23,3 @@ target_link_libraries(sortfiltermodeltest
|
||||
|
||||
add_test(plasma-sortfiltermodeltest sortfiltermodeltest)
|
||||
ecm_mark_as_test(sortfiltermodeltest)
|
||||
|
||||
#set(runnermodeltest_SRCS
|
||||
# main.cpp
|
||||
# dynamictreemodel.cpp
|
||||
# modeltest.cpp
|
||||
# ../runnermodel.cpp
|
||||
# )
|
||||
|
||||
#add_executable(runnermodeltest ${runnermodeltest_SRCS})
|
||||
#target_link_libraries(runnermodeltest Qt5::Test ${plasma_LIBRARIES} plasma)
|
||||
#ecm_mark_as_test(runnermodeltest)
|
||||
|
@ -1,35 +0,0 @@
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../runnermodel.h"
|
||||
#include "modeltest.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QWidget *widget = new QWidget;
|
||||
QVBoxLayout *layout = new QVBoxLayout(widget);
|
||||
|
||||
RunnerModel *runnerModel = new RunnerModel(widget);
|
||||
new ModelTest(runnerModel, widget);
|
||||
|
||||
QLineEdit *input = new QLineEdit(widget);
|
||||
QObject::connect(input, SIGNAL(textChanged(QString)), runnerModel, SLOT(startQuery(QString)));
|
||||
layout->addWidget(input);
|
||||
|
||||
QTreeView *view = new QTreeView(widget);
|
||||
view->setModel(runnerModel);
|
||||
layout->addWidget(view);
|
||||
|
||||
QAction *quit = new QAction(widget);
|
||||
quit->setShortcut(Qt::CTRL + Qt::Key_Q);
|
||||
QObject::connect(quit, SIGNAL(triggered()), &app, SLOT(quit()));
|
||||
|
||||
widget->addAction(quit);
|
||||
widget->show();
|
||||
return app.exec();
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
project(runnermodel)
|
||||
|
||||
set(runnermodel_SRCS
|
||||
../core/runnermodel.cpp
|
||||
runnermodelplugin.cpp
|
||||
)
|
||||
|
||||
add_library(runnermodelplugin SHARED ${runnermodel_SRCS})
|
||||
target_link_libraries(runnermodelplugin
|
||||
Qt5::Quick
|
||||
Qt5::Qml
|
||||
KF5::I18n
|
||||
KF5::Plasma
|
||||
)
|
||||
|
||||
install(TARGETS runnermodelplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/runnermodel)
|
||||
install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/runnermodel)
|
||||
|
@ -1,3 +0,0 @@
|
||||
module org.kde.runnermodel
|
||||
plugin runnermodelplugin
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 by Marco Martin <mart@kde.org>
|
||||
|
||||
* 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 Library 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 "runnermodelplugin.h"
|
||||
|
||||
#include <QtQml>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <Plasma/QueryMatch>
|
||||
|
||||
#include "../core/runnermodel.h"
|
||||
|
||||
void RunnerModelPlugin::registerTypes(const char *uri)
|
||||
{
|
||||
qWarning() << "Using deprecated import org.kde.runnermodel, please port to org.kde.plasma.core";
|
||||
Q_ASSERT(uri == QLatin1String("org.kde.runnermodel"));
|
||||
qmlRegisterType<RunnerModel>(uri, 2, 0, "RunnerModel");
|
||||
qmlRegisterInterface<Plasma::QueryMatch>("QueryMatch");
|
||||
qRegisterMetaType<Plasma::QueryMatch *>("QueryMatch");
|
||||
}
|
||||
|
||||
#include "runnermodelplugin.moc"
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 by Marco Martin <mart@kde.org>
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
|
||||
* 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 Library 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 RUNNERMODELPLUGIN_H
|
||||
#define RUNNERMODELPLUGIN_H
|
||||
|
||||
#include <QQmlExtensionPlugin>
|
||||
|
||||
/*
|
||||
* FIXME: This plugin is deprecated, it should be removed for plasma2
|
||||
*/
|
||||
class RunnerModelPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri);
|
||||
};
|
||||
|
||||
#endif
|
@ -47,14 +47,6 @@ set(Plasma_LIB_SRCS
|
||||
version.cpp
|
||||
private/componentinstaller.cpp
|
||||
|
||||
#runners
|
||||
abstractrunner.cpp
|
||||
querymatch.cpp
|
||||
runnercontext.cpp
|
||||
runnermanager.cpp
|
||||
runnersyntax.cpp
|
||||
private/runnerjobs.cpp
|
||||
|
||||
#applets,containments,corona
|
||||
applet.cpp
|
||||
configloader.cpp
|
||||
@ -92,7 +84,6 @@ set(Plasma_LIB_SRCS
|
||||
#scripting
|
||||
scripting/appletscript.cpp
|
||||
scripting/dataenginescript.cpp
|
||||
scripting/runnerscript.cpp
|
||||
scripting/scriptengine.cpp
|
||||
)
|
||||
|
||||
@ -166,7 +157,6 @@ set_target_properties(KF5Plasma PROPERTIES
|
||||
generate_export_header(KF5Plasma BASE_NAME Plasma)
|
||||
|
||||
set(Plasma_LIB_INCLUDES
|
||||
abstractrunner.h
|
||||
applet.h
|
||||
configloader.h
|
||||
containment.h
|
||||
@ -181,10 +171,6 @@ set(Plasma_LIB_INCLUDES
|
||||
packagestructure.h
|
||||
plasma.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/plasma_export.h
|
||||
querymatch.h
|
||||
runnercontext.h
|
||||
runnermanager.h
|
||||
runnersyntax.h
|
||||
service.h
|
||||
servicejob.h
|
||||
svg.h
|
||||
@ -204,7 +190,6 @@ install(DIRECTORY
|
||||
install(FILES
|
||||
scripting/appletscript.h
|
||||
scripting/dataenginescript.h
|
||||
#scripting/runnerscript.h
|
||||
scripting/scriptengine.h
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/scripting COMPONENT Devel)
|
||||
|
||||
@ -215,7 +200,6 @@ install(FILES
|
||||
data/servicetypes/plasma-dataengine.desktop
|
||||
data/servicetypes/plasma-generic.desktop
|
||||
data/servicetypes/plasma-packagestructure.desktop
|
||||
data/servicetypes/plasma-runner.desktop
|
||||
data/servicetypes/plasma-scriptengine.desktop
|
||||
data/servicetypes/plasma-service.desktop
|
||||
data/servicetypes/plasma-shell.desktop
|
||||
|
@ -1,458 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 "abstractrunner.h"
|
||||
|
||||
#include <QtWidgets/QAction>
|
||||
#include <QHash>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QDebug>
|
||||
#include <kplugininfo.h>
|
||||
#include <kservicetypetrader.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kiconloader.h>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#include "package.h"
|
||||
#include "pluginloader.h"
|
||||
#include "private/abstractrunner_p.h"
|
||||
#include "querymatch.h"
|
||||
#include "runnercontext.h"
|
||||
#include "scripting/runnerscript.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
AbstractRunner::AbstractRunner(QObject *parent, const QString &path)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
d->init(path);
|
||||
}
|
||||
|
||||
AbstractRunner::AbstractRunner(const KService::Ptr service, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
d->init(service);
|
||||
}
|
||||
|
||||
AbstractRunner::AbstractRunner(QObject *parent, const QVariantList &args)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
if (args.count() > 0) {
|
||||
KService::Ptr service = KService::serviceByStorageId(args[0].toString());
|
||||
if (service) {
|
||||
d->init(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AbstractRunner::~AbstractRunner()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
KConfigGroup AbstractRunner::config() const
|
||||
{
|
||||
QString group = id();
|
||||
if (group.isEmpty()) {
|
||||
group = "UnnamedRunner";
|
||||
}
|
||||
|
||||
KConfigGroup runners(KSharedConfig::openConfig(), "Runners");
|
||||
return KConfigGroup(&runners, group);
|
||||
}
|
||||
|
||||
void AbstractRunner::reloadConfiguration()
|
||||
{
|
||||
if (d->script) {
|
||||
emit d->script->reloadConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunner::addSyntax(const RunnerSyntax &syntax)
|
||||
{
|
||||
d->syntaxes.append(syntax);
|
||||
}
|
||||
|
||||
void AbstractRunner::setDefaultSyntax(const RunnerSyntax &syntax)
|
||||
{
|
||||
d->syntaxes.append(syntax);
|
||||
d->defaultSyntax = &(d->syntaxes.last());
|
||||
}
|
||||
|
||||
void AbstractRunner::setSyntaxes(const QList<RunnerSyntax> &syntaxes)
|
||||
{
|
||||
d->syntaxes = syntaxes;
|
||||
}
|
||||
|
||||
QList<RunnerSyntax> AbstractRunner::syntaxes() const
|
||||
{
|
||||
return d->syntaxes;
|
||||
}
|
||||
|
||||
RunnerSyntax *AbstractRunner::defaultSyntax() const
|
||||
{
|
||||
return d->defaultSyntax;
|
||||
}
|
||||
|
||||
void AbstractRunner::performMatch(Plasma::RunnerContext &localContext)
|
||||
{
|
||||
static const int reasonableRunTime = 1500;
|
||||
static const int fastEnoughTime = 250;
|
||||
|
||||
if (d->suspendMatching) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
time.restart();
|
||||
|
||||
//The local copy is already obtained in the job
|
||||
match(localContext);
|
||||
|
||||
// automatically rate limit runners that become slooow
|
||||
const int runtime = time.elapsed();
|
||||
bool slowed = speed() == SlowSpeed;
|
||||
|
||||
if (!slowed && runtime > reasonableRunTime) {
|
||||
// we punish runners that return too slowly, even if they don't bring
|
||||
// back matches
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << id() << "runner is too slow, putting it on the back burner.";
|
||||
#endif
|
||||
d->fastRuns = 0;
|
||||
setSpeed(SlowSpeed);
|
||||
}
|
||||
|
||||
if (slowed && runtime < fastEnoughTime && localContext.query().size() > 2) {
|
||||
++d->fastRuns;
|
||||
|
||||
if (d->fastRuns > 2) {
|
||||
// we reward slowed runners who bring back matches fast enough
|
||||
// 3 times in a row
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << id() << "runner is faster than we thought, kicking it up a notch";
|
||||
#endif
|
||||
setSpeed(NormalSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> AbstractRunner::actionsForMatch(const Plasma::QueryMatch &match)
|
||||
{
|
||||
Q_UNUSED(match)
|
||||
QList<QAction*> ret;
|
||||
if (d->script) {
|
||||
emit d->script->actionsForMatch(match, &ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QAction* AbstractRunner::addAction(const QString &id, const QIcon &icon, const QString &text)
|
||||
{
|
||||
QAction *a = new QAction(icon, text, this);
|
||||
d->actions.insert(id, a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void AbstractRunner::addAction(const QString &id, QAction *action)
|
||||
{
|
||||
d->actions.insert(id, action);
|
||||
}
|
||||
|
||||
void AbstractRunner::removeAction(const QString &id)
|
||||
{
|
||||
QAction *a = d->actions.take(id);
|
||||
delete a;
|
||||
}
|
||||
|
||||
QAction* AbstractRunner::action(const QString &id) const
|
||||
{
|
||||
return d->actions.value(id);
|
||||
}
|
||||
|
||||
QHash<QString, QAction*> AbstractRunner::actions() const
|
||||
{
|
||||
return d->actions;
|
||||
}
|
||||
|
||||
void AbstractRunner::clearActions()
|
||||
{
|
||||
qDeleteAll(d->actions);
|
||||
d->actions.clear();
|
||||
}
|
||||
|
||||
QMimeData *AbstractRunner::mimeDataForMatch(const QueryMatch &match)
|
||||
{
|
||||
Q_UNUSED(match)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AbstractRunner::hasRunOptions()
|
||||
{
|
||||
return d->hasRunOptions;
|
||||
}
|
||||
|
||||
void AbstractRunner::setHasRunOptions(bool hasRunOptions)
|
||||
{
|
||||
d->hasRunOptions = hasRunOptions;
|
||||
}
|
||||
|
||||
void AbstractRunner::createRunOptions(QWidget *parent)
|
||||
{
|
||||
if (d->script) {
|
||||
emit d->script->createRunOptions(parent);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractRunner::Speed AbstractRunner::speed() const
|
||||
{
|
||||
// the only time the read lock will fail is if we were slow are going to speed up
|
||||
// or if we were fast and are going to slow down; so don't wait in this case, just
|
||||
// say we're slow. we either will be soon or were just a moment ago and it doesn't
|
||||
// hurt to do one more run the slow way
|
||||
if (!d->speedLock.tryLockForRead()) {
|
||||
return SlowSpeed;
|
||||
}
|
||||
Speed s = d->speed;
|
||||
d->speedLock.unlock();
|
||||
return s;
|
||||
}
|
||||
|
||||
void AbstractRunner::setSpeed(Speed speed)
|
||||
{
|
||||
d->speedLock.lockForWrite();
|
||||
d->speed = speed;
|
||||
d->speedLock.unlock();
|
||||
}
|
||||
|
||||
AbstractRunner::Priority AbstractRunner::priority() const
|
||||
{
|
||||
return d->priority;
|
||||
}
|
||||
|
||||
void AbstractRunner::setPriority(Priority priority)
|
||||
{
|
||||
d->priority = priority;
|
||||
}
|
||||
|
||||
RunnerContext::Types AbstractRunner::ignoredTypes() const
|
||||
{
|
||||
return d->blackListed;
|
||||
}
|
||||
|
||||
void AbstractRunner::setIgnoredTypes(RunnerContext::Types types)
|
||||
{
|
||||
d->blackListed = types;
|
||||
}
|
||||
|
||||
void AbstractRunner::run(const Plasma::RunnerContext &search, const Plasma::QueryMatch &action)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->run(search, action);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunner::match(Plasma::RunnerContext &search)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->match(search);
|
||||
}
|
||||
}
|
||||
|
||||
QString AbstractRunner::name() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.name();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
QIcon AbstractRunner::icon() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return QIcon::fromTheme(d->runnerDescription.icon());
|
||||
}
|
||||
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
QString AbstractRunner::id() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.pluginName();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
QString AbstractRunner::description() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.property("Comment").toString();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
Package AbstractRunner::package() const
|
||||
{
|
||||
return d->package ? *d->package : Package();
|
||||
}
|
||||
|
||||
|
||||
void AbstractRunner::init()
|
||||
{
|
||||
if (d->script) {
|
||||
d->setupScriptSupport();
|
||||
d->script->init();
|
||||
}
|
||||
|
||||
reloadConfiguration();
|
||||
}
|
||||
|
||||
DataEngine *AbstractRunner::dataEngine(const QString &name) const
|
||||
{
|
||||
return d->dataEngine(name);
|
||||
}
|
||||
|
||||
bool AbstractRunner::isMatchingSuspended() const
|
||||
{
|
||||
return d->suspendMatching;
|
||||
}
|
||||
|
||||
void AbstractRunner::suspendMatching(bool suspend)
|
||||
{
|
||||
if (d->suspendMatching == suspend) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->suspendMatching = suspend;
|
||||
emit matchingSuspended(suspend);
|
||||
}
|
||||
|
||||
AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
|
||||
: priority(AbstractRunner::NormalPriority),
|
||||
speed(AbstractRunner::NormalSpeed),
|
||||
blackListed(0),
|
||||
script(0),
|
||||
runner(r),
|
||||
fastRuns(0),
|
||||
package(0),
|
||||
defaultSyntax(0),
|
||||
hasRunOptions(false),
|
||||
suspendMatching(false)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractRunnerPrivate::~AbstractRunnerPrivate()
|
||||
{
|
||||
delete script;
|
||||
script = 0;
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::init(const KService::Ptr service)
|
||||
{
|
||||
runnerDescription = KPluginInfo(service);
|
||||
if (runnerDescription.isValid()) {
|
||||
const QString api = runnerDescription.property("X-Plasma-API").toString();
|
||||
if (!api.isEmpty()) {
|
||||
const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "plasma/runners/" + runnerDescription.pluginName() + '/');
|
||||
prepScripting(path, api);
|
||||
if (!script) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "Could not create a(n)" << api << "ScriptEngine for the" << runnerDescription.name() << "Runner.";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::init(const QString &path)
|
||||
{
|
||||
runnerDescription = KPluginInfo(path + "/metadata.desktop");
|
||||
const QString api = runnerDescription.property("X-Plasma-API").toString();
|
||||
prepScripting(path, api);
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::prepScripting(const QString &path, const QString &api)
|
||||
{
|
||||
if (script) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete package;
|
||||
package = 0;
|
||||
|
||||
if (api.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
package = new Package(PluginLoader::self()->loadPackage("Plasma/Runner", api));
|
||||
package->setPath(path);
|
||||
|
||||
if (!package->isValid()) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "Invalid Runner package at" << path;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
script = Plasma::loadScriptEngine(api, runner);
|
||||
if (!script) {
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// put all setup routines for script here. at this point we can assume that
|
||||
// package exists and that we have a script engine
|
||||
void AbstractRunnerPrivate::setupScriptSupport()
|
||||
{
|
||||
if (!package) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "setting up script support, package is in" << package->path()
|
||||
// << ", main script is" << package->filePath("mainscript");
|
||||
#endif
|
||||
|
||||
// FIXME: Replace with ki18n functionality once semantics is clear.
|
||||
// const QString translationsPath = package->filePath("translations");
|
||||
// if (!translationsPath.isEmpty()) {
|
||||
// KGlobal::dirs()->addResourceDir("locale", translationsPath);
|
||||
// }
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
#include "moc_abstractrunner.cpp"
|
@ -1,472 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 Library 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 PLASMA_ABSTRACTRUNNER_H
|
||||
#define PLASMA_ABSTRACTRUNNER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QIcon>
|
||||
|
||||
#include <kconfiggroup.h>
|
||||
#include <kservice.h>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/querymatch.h>
|
||||
#include <plasma/runnercontext.h>
|
||||
#include <plasma/runnersyntax.h>
|
||||
#include <plasma/version.h>
|
||||
|
||||
class QAction;
|
||||
class QMimeData;
|
||||
|
||||
class KCompletion;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class Package;
|
||||
class RunnerScript;
|
||||
class QueryMatch;
|
||||
class AbstractRunnerPrivate;
|
||||
|
||||
/**
|
||||
* @class AbstractRunner plasma/abstractrunner.h <Plasma/AbstractRunner>
|
||||
*
|
||||
* @short An abstract base class for Plasma Runner plugins.
|
||||
*
|
||||
* Be aware that runners have to be thread-safe. This is due to the fact that
|
||||
* each runner is executed in its own thread for each new term. Thus, a runner
|
||||
* may be executed more than once at the same time. See match() for details.
|
||||
* To let krunner expose a global shortcut for the single runner query mode, the runner
|
||||
* must set the "X-Plasma-AdvertiseSingleRunnerMode" key to true in the .desktop file
|
||||
* and set a default syntax. See setDefaultSyntax() for details.
|
||||
*
|
||||
*/
|
||||
class PLASMA_EXPORT AbstractRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspended)
|
||||
Q_PROPERTY(QString id READ id)
|
||||
Q_PROPERTY(QString description READ description)
|
||||
Q_PROPERTY(QString name READ name)
|
||||
Q_PROPERTY(QIcon icon READ icon)
|
||||
public:
|
||||
/** Specifies a nominal speed for the runner */
|
||||
enum Speed {
|
||||
SlowSpeed,
|
||||
NormalSpeed
|
||||
};
|
||||
|
||||
/** Specifies a priority for the runner */
|
||||
enum Priority {
|
||||
LowestPriority = 0,
|
||||
LowPriority,
|
||||
NormalPriority,
|
||||
HighPriority,
|
||||
HighestPriority
|
||||
};
|
||||
|
||||
/** An ordered list of runners */
|
||||
typedef QList<AbstractRunner*> List;
|
||||
|
||||
virtual ~AbstractRunner();
|
||||
|
||||
/**
|
||||
* This is the main query method. It should trigger creation of
|
||||
* QueryMatch instances through RunnerContext::addMatch and
|
||||
* RunnerContext::addMatches. It is called internally by performMatch().
|
||||
*
|
||||
* If the runner can run precisely the requested term (RunnerContext::query()),
|
||||
* it should create an exact match by setting the type to RunnerContext::ExactMatch.
|
||||
* The first runner that creates a QueryMatch will be the
|
||||
* default runner. Other runner's matches will be suggested in the
|
||||
* interface. Non-exact matches should be offered via RunnerContext::PossibleMatch.
|
||||
*
|
||||
* The match will be activated via run() if the user selects it.
|
||||
*
|
||||
* Each runner is executed in its own thread. Whenever the user input changes this
|
||||
* method is called again. Thus, it needs to be thread-safe. Also, all matches need
|
||||
* to be reported once this method returns. Asynchronous runners therefore need
|
||||
* to make use of a local event loop to wait for all matches.
|
||||
*
|
||||
* It is recommended to use local status data in async runners. The simplest way is
|
||||
* to have a separate class doing all the work like so:
|
||||
*
|
||||
* \code
|
||||
* void MyFancyAsyncRunner::match( RunnerContext& context )
|
||||
* {
|
||||
* QEventLoop loop;
|
||||
* MyAsyncWorker worker( context );
|
||||
* connect( &worker, SIGNAL(finished()),
|
||||
* &loop, SLOT(quit()) );
|
||||
* worker.work();
|
||||
* loop.exec();
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Here MyAsyncWorker creates all the matches and calls RunnerContext::addMatch
|
||||
* in some internal slot. It emits the finished() signal once done which will
|
||||
* quit the loop and make the match() method return. The local status is kept
|
||||
* entirely in MyAsyncWorker which makes match() trivially thread-safe.
|
||||
*
|
||||
* If a particular match supports multiple actions, set up the corresponding
|
||||
* actions in the actionsForMatch method. Do not call any of the action methods
|
||||
* within this method!
|
||||
*
|
||||
* Execution of the correct action should be handled in the run method.
|
||||
* @caution This method needs to be thread-safe since KRunner will simply
|
||||
* start a new thread for each new term.
|
||||
*
|
||||
* @warning Returning from this method means to end execution of the runner.
|
||||
*
|
||||
* @sa run(), RunnerContext::addMatch, RunnerContext::addMatches, QueryMatch
|
||||
*/
|
||||
virtual void match(Plasma::RunnerContext &context);
|
||||
|
||||
/**
|
||||
* Triggers a call to match. This will call match() internally.
|
||||
*
|
||||
* @param context the search context used in executing this match.
|
||||
*/
|
||||
void performMatch(Plasma::RunnerContext &context);
|
||||
|
||||
/**
|
||||
* If the runner has options that the user can interact with to modify
|
||||
* what happens when run or one of the actions created in match
|
||||
* is called, the runner should return true
|
||||
*/
|
||||
bool hasRunOptions();
|
||||
|
||||
/**
|
||||
* If hasRunOptions() returns true, this method may be called to get
|
||||
* a widget displaying the options the user can interact with to modify
|
||||
* the behaviour of what happens when a given match is selected.
|
||||
*
|
||||
* @param widget the parent of the options widgets.
|
||||
*/
|
||||
virtual void createRunOptions(QWidget *widget);
|
||||
|
||||
/**
|
||||
* Called whenever an exact or possible match associated with this
|
||||
* runner is triggered.
|
||||
*
|
||||
* @param context The context in which the match is triggered, i.e. for which
|
||||
* the match was created.
|
||||
* @param match The actual match to run/execute.
|
||||
*/
|
||||
virtual void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match);
|
||||
|
||||
/**
|
||||
* The nominal speed of the runner.
|
||||
* @see setSpeed
|
||||
*/
|
||||
Speed speed() const;
|
||||
|
||||
/**
|
||||
* The priority of the runner.
|
||||
* @see setPriority
|
||||
*/
|
||||
Priority priority() const;
|
||||
|
||||
/**
|
||||
* Returns the OR'ed value of all the Information types (as defined in RunnerContext::Type)
|
||||
* this runner is not interested in.
|
||||
* @return OR'ed value of black listed types
|
||||
*/
|
||||
RunnerContext::Types ignoredTypes() const;
|
||||
|
||||
/**
|
||||
* Sets the types this runner will ignore
|
||||
* @param types OR'ed listed of ignored types
|
||||
*/
|
||||
void setIgnoredTypes(RunnerContext::Types types);
|
||||
|
||||
/**
|
||||
* @return the user visible engine name for the Runner
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* @return an id string for the Runner
|
||||
*/
|
||||
QString id() const;
|
||||
|
||||
/**
|
||||
* @return the description of this Runner
|
||||
*/
|
||||
QString description() const;
|
||||
|
||||
/**
|
||||
* @return the icon for this Runner
|
||||
*/
|
||||
QIcon icon() const;
|
||||
|
||||
/**
|
||||
* Accessor for the associated Package object if any.
|
||||
*
|
||||
* Note that the returned pointer is only valid for the lifetime of
|
||||
* the runner.
|
||||
*
|
||||
* @return the Package object, which may be invalid
|
||||
**/
|
||||
Package package() const;
|
||||
|
||||
/**
|
||||
* Signal runner to reload its configuration.
|
||||
*/
|
||||
virtual void reloadConfiguration();
|
||||
|
||||
/**
|
||||
* @return the syntaxes the runner has registered that it accepts and understands
|
||||
* @since 4.3
|
||||
*/
|
||||
QList<RunnerSyntax> syntaxes() const;
|
||||
|
||||
/**
|
||||
* @return the default syntax for the runner or 0 if no default syntax has been defined
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
RunnerSyntax *defaultSyntax() const;
|
||||
|
||||
/**
|
||||
* @return true if the runner is currently busy with non-interuptable work, signaling that
|
||||
* new threads should not be created for it at this time
|
||||
* @since 4.6
|
||||
*/
|
||||
bool isMatchingSuspended() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when matching is about to commence, giving runners
|
||||
* an opportunity to prepare themselves, e.g. loading data sets or preparing
|
||||
* IPC or network connections. This method should be fast so as not to cause
|
||||
* slow downs. Things that take longer or which should be loaded once and
|
||||
* remain extant for the lifespan of the AbstractRunner should be done in init().
|
||||
* @see init()
|
||||
* @since 4.4
|
||||
*/
|
||||
void prepare();
|
||||
|
||||
/**
|
||||
* This signal is emitted when a session of matches is complete, giving runners
|
||||
* the opportunity to tear down anything set up as a result of the prepare()
|
||||
* method.
|
||||
* @since 4.4
|
||||
*/
|
||||
void teardown();
|
||||
|
||||
/**
|
||||
* Emitted when the runner enters or exits match suspension
|
||||
* @see matchingSuspended
|
||||
* @since 4.6
|
||||
*/
|
||||
void matchingSuspended(bool suspended);
|
||||
|
||||
protected:
|
||||
friend class RunnerManager;
|
||||
friend class RunnerManagerPrivate;
|
||||
|
||||
explicit AbstractRunner(QObject *parent = 0, const QString &path = QString());
|
||||
explicit AbstractRunner(const KService::Ptr service, QObject *parent = 0);
|
||||
|
||||
AbstractRunner(QObject *parent, const QVariantList &args);
|
||||
|
||||
/**
|
||||
* Sets whether or not the runner is available for match requests. Useful to
|
||||
* prevent more thread spawning when the thread is in a busy state.
|
||||
*/
|
||||
void suspendMatching(bool suspend);
|
||||
|
||||
/**
|
||||
* Provides access to the runner's configuration object.
|
||||
*/
|
||||
KConfigGroup config() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the runner has options for matches
|
||||
*/
|
||||
void setHasRunOptions(bool hasRunOptions);
|
||||
|
||||
/**
|
||||
* Sets the nominal speed of the runner. Only slow runners need
|
||||
* to call this within their constructor because the default
|
||||
* speed is NormalSpeed. Runners that use DBUS should call
|
||||
* this within their constructors.
|
||||
*/
|
||||
void setSpeed(Speed newSpeed);
|
||||
|
||||
/**
|
||||
* Sets the priority of the runner. Lower priority runners are executed
|
||||
* only after higher priority runners.
|
||||
*/
|
||||
void setPriority(Priority newPriority);
|
||||
|
||||
/**
|
||||
* A given match can have more than action that can be performed on it.
|
||||
* For example, a song match returned by a music player runner can be queued,
|
||||
* added to the playlist, or played.
|
||||
*
|
||||
* Call this method to add actions that can be performed by the runner.
|
||||
* Actions must first be added to the runner's action registry.
|
||||
* Note: execution of correct action is left up to the runner.
|
||||
*/
|
||||
virtual QList<QAction*> actionsForMatch(const Plasma::QueryMatch &match);
|
||||
|
||||
/**
|
||||
* Creates and then adds an action to the action registry.
|
||||
* AbstractRunner assumes ownership of the created action.
|
||||
*
|
||||
* @param id A unique identifier string
|
||||
* @param icon The icon to display
|
||||
* @param text The text to display
|
||||
* @return the created QAction
|
||||
*/
|
||||
QAction* addAction(const QString &id, const QIcon &icon, const QString &text);
|
||||
|
||||
/**
|
||||
* Adds an action to the runner's action registry.
|
||||
*
|
||||
* The QAction must be created within the GUI thread;
|
||||
* do not create it within the match method of AbstractRunner.
|
||||
*
|
||||
* @param id A unique identifier string
|
||||
* @param action The QAction to be stored
|
||||
*/
|
||||
void addAction(const QString &id, QAction *action);
|
||||
|
||||
/**
|
||||
* Removes the action from the action registry.
|
||||
* AbstractRunner deletes the action once removed.
|
||||
*
|
||||
* @param id The id of the action to be removed
|
||||
*/
|
||||
void removeAction(const QString &id);
|
||||
|
||||
/**
|
||||
* Returns the action associated with the id
|
||||
*/
|
||||
QAction* action(const QString &id) const;
|
||||
|
||||
/**
|
||||
* Returns all registered actions
|
||||
*/
|
||||
QHash<QString, QAction*> actions() const;
|
||||
|
||||
/**
|
||||
* Clears the action registry.
|
||||
* The action pool deletes the actions.
|
||||
*/
|
||||
void clearActions();
|
||||
|
||||
/**
|
||||
* Adds a registered syntax that this runner understands. This is used to
|
||||
* display to the user what this runner can understand and how it can be
|
||||
* used.
|
||||
*
|
||||
* @param syntax the syntax to register
|
||||
* @since 4.3
|
||||
*/
|
||||
void addSyntax(const RunnerSyntax &syntax);
|
||||
|
||||
/**
|
||||
* Set @p syntax as the default syntax for the runner; the default syntax will be
|
||||
* substituted to the empty query in single runner mode. This is also used to
|
||||
* display to the user what this runner can understand and how it can be
|
||||
* used.
|
||||
* The default syntax is automatically added to the list of registered syntaxes, there
|
||||
* is no need to add it using addSyntax.
|
||||
* Note that there can be only one default syntax; if called more than once, the last
|
||||
* call will determine the default syntax.
|
||||
* A default syntax (even trivial) is required to advertise single runner mode
|
||||
*
|
||||
* @param syntax the syntax to register and to set as default
|
||||
* @since 4.4
|
||||
**/
|
||||
void setDefaultSyntax(const RunnerSyntax &syntax);
|
||||
|
||||
/**
|
||||
* Sets the list of syntaxes; passing in an empty list effectively clears
|
||||
* the syntaxes.
|
||||
*
|
||||
* @param the syntaxes to register for this runner
|
||||
* @since 4.3
|
||||
*/
|
||||
void setSyntaxes(const QList<RunnerSyntax> &syns);
|
||||
|
||||
/**
|
||||
* Loads the given DataEngine
|
||||
*
|
||||
* Tries to load the data engine given by @p name. Each engine is
|
||||
* only loaded once, and that instance is re-used on all subsequent
|
||||
* requests.
|
||||
*
|
||||
* If the data engine was not found, an invalid data engine is returned
|
||||
* (see DataEngine::isValid()).
|
||||
*
|
||||
* Note that you should <em>not</em> delete the returned engine.
|
||||
*
|
||||
* @param name Name of the data engine to load
|
||||
* @return pointer to the data engine if it was loaded,
|
||||
* or an invalid data engine if the requested engine
|
||||
* could not be loaded
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
Q_INVOKABLE DataEngine *dataEngine(const QString &name) const;
|
||||
|
||||
/**
|
||||
* Reimplement this slot to run any initialization routines on first load.
|
||||
* By default, it calls reloadConfiguration(); for scripted Runners this
|
||||
* method also sets up the ScriptEngine.
|
||||
*/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* Reimplement this slot if you want your runner
|
||||
* to support serialization and drag and drop
|
||||
* @since 4.5
|
||||
*/
|
||||
virtual QMimeData *mimeDataForMatch(const Plasma::QueryMatch &match);
|
||||
|
||||
private:
|
||||
friend class RunnerScript;
|
||||
|
||||
AbstractRunnerPrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#define K_EXPORT_PLASMA_RUNNER( libname, classname ) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
/**
|
||||
* These plugins are Used by the plugin selector dialog to show
|
||||
* configuration options specific to this runner. These options
|
||||
* must be runner global and not pertain to a specific match.
|
||||
*/
|
||||
#define K_EXPORT_RUNNER_CONFIG( name, classname ) \
|
||||
K_PLUGIN_FACTORY(ConfigFactory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/Runner
|
||||
|
||||
Comment=KRunner plugin
|
||||
Comment[bs]=Priključak za KRunner
|
||||
Comment[cs]=Modul KRunneru
|
||||
Comment[de]=KRunner-Modul
|
||||
Comment[es]=Complemento para KRunner
|
||||
Comment[fi]=KRunner-liitännäinen
|
||||
Comment[fr]=Module externe de KRunner
|
||||
Comment[mr]=KRunner प्लगइन
|
||||
Comment[nl]=KRunner-plugin
|
||||
Comment[pl]=Wtyczka KRunner
|
||||
Comment[pt]='Plugin' do KRunner
|
||||
Comment[pt_BR]=Plugin do KRunner
|
||||
Comment[sk]=KRunner modul
|
||||
Comment[sv]=Krunner-insticksprogram
|
||||
Comment[tr]=KRunner eklentisi
|
||||
Comment[ug]=KRunner قىستۇرما
|
||||
Comment[uk]=Додаток до KRunner
|
||||
Comment[x-test]=xxKRunner pluginxx
|
||||
|
||||
[PropertyDef::X-Plasma-AdvertiseSingleRunnerQueryMode]
|
||||
Type=bool
|
||||
|
||||
[PropertyDef::TryExec]
|
||||
Type=QString
|
||||
|
||||
[PropertyDef::X-Plasma-Args]
|
||||
Type=QStringList
|
||||
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/abstractrunner.h"
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/querymatch.h"
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/runnercontext.h"
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/runnermanager.h"
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/scripting/runnerscript.h"
|
@ -33,7 +33,6 @@
|
||||
#endif
|
||||
|
||||
#include "applet.h"
|
||||
#include "abstractrunner.h"
|
||||
#include "containment.h"
|
||||
#include "containmentactions.h"
|
||||
#include "dataengine.h"
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2009 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 ABSTRACTRUNNER_P_H
|
||||
#define ABSTRACTRUNNER_P_H
|
||||
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include "dataengineconsumer.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AbstractRunner;
|
||||
|
||||
class AbstractRunnerPrivate : public DataEngineConsumer
|
||||
{
|
||||
public:
|
||||
AbstractRunnerPrivate(AbstractRunner *r);
|
||||
~AbstractRunnerPrivate();
|
||||
void init(const KService::Ptr service);
|
||||
void init(const QString &path);
|
||||
void prepScripting(const QString &path, const QString &api);
|
||||
void setupScriptSupport();
|
||||
|
||||
AbstractRunner::Priority priority;
|
||||
AbstractRunner::Speed speed;
|
||||
RunnerContext::Types blackListed;
|
||||
RunnerScript *script;
|
||||
KPluginInfo runnerDescription;
|
||||
AbstractRunner *runner;
|
||||
int fastRuns;
|
||||
QReadWriteLock speedLock;
|
||||
Package *package;
|
||||
QHash<QString, QAction*> actions;
|
||||
QList<RunnerSyntax> syntaxes;
|
||||
RunnerSyntax *defaultSyntax;
|
||||
bool hasRunOptions : 1;
|
||||
bool suspendMatching : 1;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
#endif
|
||||
|
||||
|
@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007, 2009 Ryan P. Bitanga <ryan.bitanga@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 "runnerjobs_p.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "runnermanager.h"
|
||||
#include "plasma/querymatch.h"
|
||||
|
||||
using ThreadWeaver::Job;
|
||||
using ThreadWeaver::Queue;
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
DelayedRunnerPolicy::DelayedRunnerPolicy()
|
||||
: QueuePolicy()
|
||||
{}
|
||||
|
||||
DelayedRunnerPolicy::~DelayedRunnerPolicy()
|
||||
{}
|
||||
|
||||
DelayedRunnerPolicy& DelayedRunnerPolicy::instance()
|
||||
{
|
||||
static DelayedRunnerPolicy policy;
|
||||
return policy;
|
||||
}
|
||||
|
||||
bool DelayedRunnerPolicy::canRun(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
QSharedPointer<FindMatchesJob> aJob(job.dynamicCast<FindMatchesJob>());
|
||||
if (QTimer *t = aJob->delayTimer()) {
|
||||
// If the timer is active, the required delay has not been reached
|
||||
//qDebug() << "delayed timer" << aJob->runner()->name() << !t->isActive();
|
||||
return !t->isActive();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DelayedRunnerPolicy::free(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
}
|
||||
|
||||
void DelayedRunnerPolicy::release(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
free(job);
|
||||
}
|
||||
|
||||
void DelayedRunnerPolicy::destructed(ThreadWeaver::JobInterface* job)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
}
|
||||
|
||||
DefaultRunnerPolicy::DefaultRunnerPolicy()
|
||||
: QueuePolicy(),
|
||||
m_cap(2)
|
||||
{}
|
||||
|
||||
DefaultRunnerPolicy::~DefaultRunnerPolicy()
|
||||
{}
|
||||
|
||||
DefaultRunnerPolicy& DefaultRunnerPolicy::instance()
|
||||
{
|
||||
static DefaultRunnerPolicy policy;
|
||||
return policy;
|
||||
}
|
||||
|
||||
bool DefaultRunnerPolicy::canRun(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
Plasma::AbstractRunner *runner = job.dynamicCast<FindMatchesJob>()->runner();
|
||||
QMutexLocker l(&m_mutex);
|
||||
|
||||
if (m_runCounts[runner->name()] > m_cap) {
|
||||
return false;
|
||||
} else {
|
||||
++m_runCounts[runner->name()];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultRunnerPolicy::free(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
Plasma::AbstractRunner *runner = job.dynamicCast<FindMatchesJob>()->runner();
|
||||
QMutexLocker l(&m_mutex);
|
||||
|
||||
--m_runCounts[runner->name()];
|
||||
}
|
||||
|
||||
void DefaultRunnerPolicy::release(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
free(job);
|
||||
}
|
||||
|
||||
void DefaultRunnerPolicy::destructed(ThreadWeaver::JobInterface* job)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Jobs
|
||||
////////////////////
|
||||
|
||||
FindMatchesJob::FindMatchesJob(Plasma::AbstractRunner *runner,
|
||||
Plasma::RunnerContext *context, QObject *parent)
|
||||
: ThreadWeaver::Job(),
|
||||
m_context(*context, 0),
|
||||
m_runner(runner),
|
||||
m_timer(0),
|
||||
m_decorator(new ThreadWeaver::QObjectDecorator(this, true))
|
||||
{
|
||||
if (runner->speed() == Plasma::AbstractRunner::SlowSpeed) {
|
||||
assignQueuePolicy(&DelayedRunnerPolicy::instance());
|
||||
} else {
|
||||
assignQueuePolicy(&DefaultRunnerPolicy::instance());
|
||||
}
|
||||
}
|
||||
|
||||
FindMatchesJob::~FindMatchesJob()
|
||||
{
|
||||
}
|
||||
|
||||
QTimer* FindMatchesJob::delayTimer() const
|
||||
{
|
||||
return m_timer;
|
||||
}
|
||||
|
||||
void FindMatchesJob::setDelayTimer(QTimer *timer)
|
||||
{
|
||||
m_timer = timer;
|
||||
}
|
||||
|
||||
void FindMatchesJob::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*)
|
||||
{
|
||||
// qDebug() << "Running match for " << m_runner->objectName()
|
||||
// << " in Thread " << thread()->id() << endl;
|
||||
if (m_context.isValid()) {
|
||||
m_runner->performMatch(m_context);
|
||||
}
|
||||
}
|
||||
|
||||
int FindMatchesJob::priority() const
|
||||
{
|
||||
return m_runner->priority();
|
||||
}
|
||||
|
||||
Plasma::AbstractRunner* FindMatchesJob::runner() const
|
||||
{
|
||||
return m_runner;
|
||||
}
|
||||
|
||||
DelayedJobCleaner::DelayedJobCleaner(const QSet<QSharedPointer<FindMatchesJob> > &jobs, const QSet<AbstractRunner *> &runners)
|
||||
: QObject(Queue::instance()),
|
||||
m_weaver(Queue::instance()),
|
||||
m_jobs(jobs),
|
||||
m_runners(runners)
|
||||
{
|
||||
connect(m_weaver, SIGNAL(finished()), this, SLOT(checkIfFinished()));
|
||||
|
||||
for (auto it = m_jobs.constBegin(); it != m_jobs.constEnd(); ++it) {
|
||||
connect((*it)->decorator(), &ThreadWeaver::QObjectDecorator::done, this, &DelayedJobCleaner::jobDone);
|
||||
}
|
||||
}
|
||||
|
||||
DelayedJobCleaner::~DelayedJobCleaner()
|
||||
{
|
||||
qDeleteAll(m_runners);
|
||||
}
|
||||
|
||||
void DelayedJobCleaner::jobDone(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
auto runJob = job.dynamicCast<FindMatchesJob>();
|
||||
|
||||
if (!runJob) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_jobs.remove(runJob);
|
||||
|
||||
if (m_jobs.isEmpty()) {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void DelayedJobCleaner::checkIfFinished()
|
||||
{
|
||||
if (m_weaver->isIdle()) {
|
||||
m_jobs.clear();
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // Plasma namespace
|
||||
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007, 2009 Ryan P. Bitanga <ryan.bitanga@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 PLASMA_RUNNERJOBS_P_H
|
||||
#define PLASMA_RUNNERJOBS_P_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QSet>
|
||||
|
||||
#include <ThreadWeaver/Job>
|
||||
#include <ThreadWeaver/QueuePolicy>
|
||||
#include <ThreadWeaver/Queue>
|
||||
#include <ThreadWeaver/QObjectDecorator>
|
||||
|
||||
#include "abstractrunner.h"
|
||||
|
||||
using ThreadWeaver::Job;
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Plasma {
|
||||
// Queue policies
|
||||
|
||||
// QueuePolicy that only allows a job to be executed after
|
||||
// waiting in the queue for the specified timeout
|
||||
class DelayedRunnerPolicy : public ThreadWeaver::QueuePolicy
|
||||
{
|
||||
public:
|
||||
~DelayedRunnerPolicy();
|
||||
|
||||
static DelayedRunnerPolicy &instance();
|
||||
|
||||
bool canRun(ThreadWeaver::JobPointer job);
|
||||
void free(ThreadWeaver::JobPointer job);
|
||||
void release(ThreadWeaver::JobPointer job);
|
||||
virtual void destructed(ThreadWeaver::JobInterface* job);
|
||||
|
||||
private:
|
||||
DelayedRunnerPolicy();
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
// QueuePolicy that limits the instances of a particular runner
|
||||
class DefaultRunnerPolicy : public ThreadWeaver::QueuePolicy
|
||||
{
|
||||
public:
|
||||
~DefaultRunnerPolicy();
|
||||
|
||||
static DefaultRunnerPolicy &instance();
|
||||
|
||||
void setCap(int cap)
|
||||
{
|
||||
m_cap = cap;
|
||||
}
|
||||
int cap() const
|
||||
{
|
||||
return m_cap;
|
||||
}
|
||||
|
||||
bool canRun(ThreadWeaver::JobPointer job);
|
||||
void free(ThreadWeaver::JobPointer job);
|
||||
void release(ThreadWeaver::JobPointer job);
|
||||
void destructed(ThreadWeaver::JobInterface* job);
|
||||
private:
|
||||
DefaultRunnerPolicy();
|
||||
|
||||
int m_cap;
|
||||
QHash<QString, int> m_runCounts;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
* FindMatchesJob class
|
||||
* Class to run queries in different threads
|
||||
*/
|
||||
class FindMatchesJob : public Job
|
||||
{
|
||||
public:
|
||||
FindMatchesJob(Plasma::AbstractRunner *runner,
|
||||
Plasma::RunnerContext *context, QObject *parent = 0);
|
||||
~FindMatchesJob();
|
||||
|
||||
int priority() const;
|
||||
Plasma::AbstractRunner* runner() const;
|
||||
|
||||
QTimer* delayTimer() const;
|
||||
void setDelayTimer(QTimer *timer);
|
||||
ThreadWeaver::QObjectDecorator* decorator() const { return m_decorator; }
|
||||
|
||||
protected:
|
||||
virtual void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread);
|
||||
|
||||
private:
|
||||
Plasma::RunnerContext m_context;
|
||||
Plasma::AbstractRunner *m_runner;
|
||||
QTimer *m_timer;
|
||||
ThreadWeaver::QObjectDecorator* m_decorator;
|
||||
};
|
||||
|
||||
class DelayedJobCleaner : public QObject
|
||||
{
|
||||
public:
|
||||
DelayedJobCleaner(const QSet<QSharedPointer<FindMatchesJob> > &jobs, const QSet<AbstractRunner *> &runners = QSet<AbstractRunner *>());
|
||||
~DelayedJobCleaner();
|
||||
|
||||
private Q_SLOTS:
|
||||
void jobDone(ThreadWeaver::JobPointer);
|
||||
void checkIfFinished();
|
||||
|
||||
private:
|
||||
ThreadWeaver::Queue *m_weaver;
|
||||
QSet<QSharedPointer<FindMatchesJob> > m_jobs;
|
||||
QSet<AbstractRunner *> m_runners;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PLASMA_RUNNERJOBS_P_H
|
@ -36,7 +36,6 @@
|
||||
//Plasma
|
||||
#include "applet.h"
|
||||
#include "dataengine.h"
|
||||
#include "abstractrunner.h"
|
||||
#include "storagethread_p.h"
|
||||
|
||||
|
||||
@ -137,12 +136,6 @@ Storage::Storage(QObject* parent)
|
||||
m_clientName = engine->pluginInfo().pluginName();
|
||||
break;
|
||||
}
|
||||
|
||||
Plasma::AbstractRunner *runner = qobject_cast<Plasma::AbstractRunner *>(parentObject);
|
||||
if (runner) {
|
||||
m_clientName = runner->id();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_clientName = m_clientName.replace('.', "_");
|
||||
|
@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 "querymatch.h"
|
||||
|
||||
#include <QtWidgets/QAction>
|
||||
#include <QIcon>
|
||||
#include <QReadWriteLock>
|
||||
#include <QSharedData>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "abstractrunner.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class QueryMatchPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
QueryMatchPrivate(AbstractRunner *r)
|
||||
: QSharedData(),
|
||||
lock(new QReadWriteLock(QReadWriteLock::Recursive)),
|
||||
runner(r),
|
||||
type(QueryMatch::ExactMatch),
|
||||
relevance(.7),
|
||||
selAction(0),
|
||||
enabled(true),
|
||||
idSetByData(false)
|
||||
{
|
||||
}
|
||||
|
||||
QueryMatchPrivate(const QueryMatchPrivate &other)
|
||||
: QSharedData(other),
|
||||
lock(new QReadWriteLock(QReadWriteLock::Recursive))
|
||||
{
|
||||
QReadLocker lock(other.lock);
|
||||
runner = other.runner;
|
||||
type = other.type;
|
||||
relevance = other.relevance;
|
||||
selAction = other.selAction;
|
||||
enabled = other.enabled;
|
||||
idSetByData = other.idSetByData;
|
||||
id = other.id;
|
||||
text = other.text;
|
||||
subtext = other.subtext;
|
||||
icon = other.icon;
|
||||
data = other.data;
|
||||
mimeType = other.mimeType;
|
||||
urls = other.urls;
|
||||
}
|
||||
|
||||
~QueryMatchPrivate()
|
||||
{
|
||||
delete lock;
|
||||
}
|
||||
|
||||
QReadWriteLock *lock;
|
||||
QWeakPointer<AbstractRunner> runner;
|
||||
QueryMatch::Type type;
|
||||
QString id;
|
||||
QString text;
|
||||
QString subtext;
|
||||
QString mimeType;
|
||||
QList<QUrl> urls;
|
||||
QIcon icon;
|
||||
QVariant data;
|
||||
qreal relevance;
|
||||
QAction *selAction;
|
||||
bool enabled : 1;
|
||||
bool idSetByData : 1;
|
||||
};
|
||||
|
||||
QueryMatch::QueryMatch(AbstractRunner *runner)
|
||||
: d(new QueryMatchPrivate(runner))
|
||||
{
|
||||
// qDebug() << "new match created";
|
||||
}
|
||||
|
||||
QueryMatch::QueryMatch(const QueryMatch &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
QueryMatch::~QueryMatch()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryMatch::isValid() const
|
||||
{
|
||||
return d->runner != 0;
|
||||
}
|
||||
|
||||
QString QueryMatch::id() const
|
||||
{
|
||||
if (d->id.isEmpty() && d->runner) {
|
||||
return d->runner.data()->id();
|
||||
}
|
||||
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void QueryMatch::setType(Type type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
QueryMatch::Type QueryMatch::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void QueryMatch::setRelevance(qreal relevance)
|
||||
{
|
||||
d->relevance = qMax(qreal(0.0), relevance);
|
||||
}
|
||||
|
||||
qreal QueryMatch::relevance() const
|
||||
{
|
||||
return d->relevance;
|
||||
}
|
||||
|
||||
AbstractRunner* QueryMatch::runner() const
|
||||
{
|
||||
return d->runner.data();
|
||||
}
|
||||
|
||||
void QueryMatch::setText(const QString &text)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->text = text;
|
||||
}
|
||||
|
||||
void QueryMatch::setSubtext(const QString &subtext)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->subtext = subtext;
|
||||
}
|
||||
|
||||
void QueryMatch::setData(const QVariant & data)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->data = data;
|
||||
|
||||
if (d->id.isEmpty() || d->idSetByData) {
|
||||
const QString id = data.toString();
|
||||
if (!id.isEmpty()) {
|
||||
setId(data.toString());
|
||||
d->idSetByData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QueryMatch::setId(const QString &id)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
if (d->runner) {
|
||||
d->id = d->runner.data()->id();
|
||||
}
|
||||
|
||||
if (!id.isEmpty()) {
|
||||
d->id.append('_').append(id);
|
||||
}
|
||||
|
||||
d->idSetByData = false;
|
||||
}
|
||||
|
||||
void QueryMatch::setIcon(const QIcon &icon)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->icon = icon;
|
||||
}
|
||||
|
||||
QVariant QueryMatch::data() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->data;
|
||||
}
|
||||
|
||||
QString QueryMatch::text() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->text;
|
||||
}
|
||||
|
||||
QString QueryMatch::subtext() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->subtext;
|
||||
}
|
||||
|
||||
QIcon QueryMatch::icon() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->icon;
|
||||
}
|
||||
|
||||
void QueryMatch::setMimeType(const QString &mimeType)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->mimeType = mimeType;
|
||||
}
|
||||
|
||||
QString QueryMatch::mimeType() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->mimeType;
|
||||
}
|
||||
|
||||
void QueryMatch::setUrls(const QList<QUrl> &urls)
|
||||
{
|
||||
QWriteLocker locker(d->lock);
|
||||
d->urls = urls;
|
||||
}
|
||||
|
||||
QList<QUrl> QueryMatch::urls() const
|
||||
{
|
||||
QReadLocker locker(d->lock);
|
||||
return d->urls;
|
||||
}
|
||||
|
||||
void QueryMatch::setEnabled(bool enabled)
|
||||
{
|
||||
d->enabled = enabled;
|
||||
}
|
||||
|
||||
bool QueryMatch::isEnabled() const
|
||||
{
|
||||
return d->enabled && d->runner;
|
||||
}
|
||||
|
||||
QAction* QueryMatch::selectedAction() const
|
||||
{
|
||||
return d->selAction;
|
||||
}
|
||||
|
||||
void QueryMatch::setSelectedAction(QAction *action)
|
||||
{
|
||||
d->selAction = action;
|
||||
}
|
||||
|
||||
bool QueryMatch::operator<(const QueryMatch &other) const
|
||||
{
|
||||
if (d->type == other.d->type) {
|
||||
if (isEnabled() != other.isEnabled()) {
|
||||
return other.isEnabled();
|
||||
}
|
||||
|
||||
if (d->relevance != other.d->relevance) {
|
||||
return d->relevance < other.d->relevance;
|
||||
}
|
||||
|
||||
QReadLocker locker(d->lock);
|
||||
QReadLocker otherLocker(other.d->lock);
|
||||
// when resorting to sort by alpha, we want the
|
||||
// reverse sort order!
|
||||
return d->text > other.d->text;
|
||||
}
|
||||
|
||||
return d->type < other.d->type;
|
||||
}
|
||||
|
||||
QueryMatch &QueryMatch::operator=(const QueryMatch &other)
|
||||
{
|
||||
if (d != other.d) {
|
||||
d = other.d;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool QueryMatch::operator==(const QueryMatch &other) const
|
||||
{
|
||||
return (d == other.d);
|
||||
}
|
||||
|
||||
bool QueryMatch::operator!=(const QueryMatch &other) const
|
||||
{
|
||||
return (d != other.d);
|
||||
}
|
||||
|
||||
void QueryMatch::run(const RunnerContext &context) const
|
||||
{
|
||||
//qDebug() << "we run the term" << context->query() << "whose type is" << context->mimetype();
|
||||
if (d->runner) {
|
||||
d->runner.data()->run(context, *this);
|
||||
}
|
||||
}
|
||||
|
||||
bool QueryMatch::hasConfigurationInterface() const
|
||||
{
|
||||
return d->runner && d->runner.data()->hasRunOptions();
|
||||
}
|
||||
|
||||
void QueryMatch::createConfigurationInterface(QWidget *parent)
|
||||
{
|
||||
if (hasConfigurationInterface()) {
|
||||
d->runner.data()->createRunOptions(parent);
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 PLASMA_QUERYMATCH_H
|
||||
#define PLASMA_QUERYMATCH_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QSharedDataPointer>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class QAction;
|
||||
class QIcon;
|
||||
class QString;
|
||||
class QVariant;
|
||||
class QWidget;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class RunnerContext;
|
||||
class AbstractRunner;
|
||||
class QueryMatchPrivate;
|
||||
|
||||
/**
|
||||
* @class QueryMatch plasma/querymatch.h <Plasma/QueryMatch>
|
||||
*
|
||||
* @short A match returned by an AbstractRunner in response to a given
|
||||
* RunnerContext.
|
||||
*/
|
||||
class PLASMA_EXPORT QueryMatch
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The type of match. Value is important here as it is used for sorting
|
||||
*/
|
||||
enum Type {
|
||||
NoMatch = 0, /**< Null match */
|
||||
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,
|
||||
such as the answer to a question or calculation*/
|
||||
HelperMatch = 70, /**< A match that represents an action not directly related
|
||||
to activating the given search term, such as a search
|
||||
in an external tool or a command learning trigger. Helper
|
||||
matches tend to be generic to the query and should not
|
||||
be autoactivated just because the user hits "Enter"
|
||||
while typing. They must be explicitly selected to
|
||||
be activated, but unlike InformationalMatch cause
|
||||
an action to be triggered. */
|
||||
ExactMatch = 100 /**< An exact match to the query */
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a PossibleMatch associated with a given RunnerContext
|
||||
* and runner.
|
||||
*
|
||||
* @param runner the runner this match belongs to
|
||||
*/
|
||||
explicit QueryMatch(AbstractRunner *runner);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
QueryMatch(const QueryMatch &other);
|
||||
|
||||
~QueryMatch();
|
||||
QueryMatch &operator=(const QueryMatch &other);
|
||||
bool operator==(const QueryMatch &other) const;
|
||||
bool operator!=(const QueryMatch &other) const;
|
||||
bool operator<(const QueryMatch &other) const;
|
||||
|
||||
|
||||
/**
|
||||
* @return the runner associated with this action
|
||||
*/
|
||||
AbstractRunner *runner() const;
|
||||
|
||||
/**
|
||||
* Requests this match to activae using the given context
|
||||
*
|
||||
* @param context the context to use in conjunction with this run
|
||||
*
|
||||
* @sa AbstractRunner::run
|
||||
*/
|
||||
void run(const RunnerContext &context) const;
|
||||
|
||||
/**
|
||||
* @return true if the match is valid and can therefore be run,
|
||||
* an invalid match does not have an associated AbstractRunner
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Sets the type of match this action represents.
|
||||
*/
|
||||
void setType(Type type);
|
||||
|
||||
/**
|
||||
* The type of action this is. Defaults to PossibleMatch.
|
||||
*/
|
||||
Type type() const;
|
||||
|
||||
/**
|
||||
* Sets the relevance of this action for the search
|
||||
* it was created for.
|
||||
*
|
||||
* @param relevance a number between 0 and 1.
|
||||
*/
|
||||
void setRelevance(qreal relevance);
|
||||
|
||||
/**
|
||||
* The relevance of this action to the search. By default,
|
||||
* the relevance is 1.
|
||||
*
|
||||
* @return a number between 0 and 1
|
||||
*/
|
||||
qreal relevance() const;
|
||||
|
||||
/**
|
||||
* Sets data to be used internally by the associated
|
||||
* AbstractRunner.
|
||||
*
|
||||
* When set, it is also used to form
|
||||
* part of the id() for this match. If that is innapropriate
|
||||
* as an id, the runner may generate its own id and set that
|
||||
* with setId(const QString&) directly after calling setData
|
||||
*/
|
||||
void setData(const QVariant &data);
|
||||
|
||||
/**
|
||||
* @return the data associated with this match; usually runner-specific
|
||||
*/
|
||||
QVariant data() const;
|
||||
|
||||
/**
|
||||
* Sets the id for this match; useful if the id does not
|
||||
* match data().toString(). The id must be unique to all
|
||||
* matches from this runner, and should remain constant
|
||||
* for the same query for best results.
|
||||
*
|
||||
* @param id the new identifying string to use to refer
|
||||
* to this entry
|
||||
*/
|
||||
void setId(const QString &id);
|
||||
|
||||
/**
|
||||
* @ruetnr a string that can be used as an ID for this match,
|
||||
* even between different queries. It is based in part
|
||||
* on the source of the match (the AbstractRunner) and
|
||||
* distinguishing information provided by the runner,
|
||||
* ensuring global uniqueness as well as consistency
|
||||
* between query matches.
|
||||
*/
|
||||
QString id() const;
|
||||
|
||||
/**
|
||||
* Sets the main title text for this match; should be short
|
||||
* enough to fit nicely on one line in a user interface
|
||||
*
|
||||
* @param text the text to use as the title
|
||||
*/
|
||||
void setText(const QString &text);
|
||||
|
||||
/**
|
||||
* @return the title text for this match
|
||||
*/
|
||||
QString text() const;
|
||||
|
||||
/**
|
||||
* Sets the descriptive text for this match; can be longer
|
||||
* than the main title text
|
||||
*
|
||||
* @param text the text to use as the description
|
||||
*/
|
||||
void setSubtext(const QString &text);
|
||||
|
||||
/**
|
||||
* @return the descriptive text for this match
|
||||
*/
|
||||
QString subtext() const;
|
||||
|
||||
/**
|
||||
* Sets the icon associated with this match
|
||||
*
|
||||
* @param icon the icon to show along with the match
|
||||
*/
|
||||
void setIcon(const QIcon &icon);
|
||||
|
||||
/**
|
||||
* @return the icon for this match
|
||||
*/
|
||||
QIcon icon() const;
|
||||
|
||||
/**
|
||||
* Sets the MimeType, if any, associated with this match.
|
||||
* This overrides the MimeType provided by QueryContext, and should only be
|
||||
* set when it is different from the QueryContext MimeType
|
||||
*/
|
||||
void setMimeType(const QString &mimeType);
|
||||
|
||||
/**
|
||||
* @return the mimtype for this match, or QString() is none
|
||||
*/
|
||||
QString mimeType() const;
|
||||
|
||||
/**
|
||||
* Sets the urls, if any, associated with this match
|
||||
*/
|
||||
void setUrls(const QList<QUrl> &urls);
|
||||
|
||||
/**
|
||||
* @return the mimtype for this match, or QString() is none
|
||||
*/
|
||||
QList<QUrl> urls() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not this match can be activited
|
||||
*
|
||||
* @param enable true if the match is enabled and therefore runnable
|
||||
*/
|
||||
void setEnabled(bool enable);
|
||||
|
||||
/**
|
||||
* @return true if the match is enabled and therefore runnable, otherwise false
|
||||
*/
|
||||
bool isEnabled() const;
|
||||
|
||||
/**
|
||||
* The current action.
|
||||
*/
|
||||
QAction* selectedAction() const;
|
||||
|
||||
/**
|
||||
* Sets the selected action
|
||||
*/
|
||||
void setSelectedAction(QAction *action);
|
||||
|
||||
/**
|
||||
* @return true if this match can be configured before being run
|
||||
* @since 4.3
|
||||
*/
|
||||
bool hasConfigurationInterface() const;
|
||||
|
||||
/**
|
||||
* If hasConfigurationInterface() returns true, this method may be called to get
|
||||
* a widget displaying the options the user can interact with to modify
|
||||
* the behaviour of what happens when the match is run.
|
||||
*
|
||||
* @param widget the parent of the options widgets.
|
||||
* @since 4.3
|
||||
*/
|
||||
void createConfigurationInterface(QWidget *parent);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<QueryMatchPrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,583 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 "runnercontext.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSharedData>
|
||||
|
||||
#include <kcompletion.h>
|
||||
#include <kconfiggroup.h>
|
||||
#include <QDebug>
|
||||
#include <qmimedatabase.h>
|
||||
#include <kshell.h>
|
||||
#include <qstandardpaths.h>
|
||||
#include <qurl.h>
|
||||
#include <kprotocolinfo.h>
|
||||
|
||||
#include "abstractrunner.h"
|
||||
#include "querymatch.h"
|
||||
|
||||
//#define LOCK_FOR_READ(d) if (d->policy == Shared) { d->lock.lockForRead(); }
|
||||
//#define LOCK_FOR_WRITE(d) if (d->policy == Shared) { d->lock.lockForWrite(); }
|
||||
//#define UNLOCK(d) if (d->policy == Shared) { d->lock.unlock(); }
|
||||
|
||||
#define LOCK_FOR_READ(d) d->lock.lockForRead();
|
||||
#define LOCK_FOR_WRITE(d) d->lock.lockForWrite();
|
||||
#define UNLOCK(d) d->lock.unlock();
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
/*
|
||||
Corrects the case of the last component in a path (e.g. /usr/liB -> /usr/lib)
|
||||
path: The path to be processed.
|
||||
correctCasePath: The corrected-case path
|
||||
mustBeDir: Tells whether the last component is a folder or doesn't matter
|
||||
Returns true on success and false on error, in case of error, correctCasePath is not modified
|
||||
*/
|
||||
bool correctLastComponentCase(const QString &path, QString &correctCasePath, const bool mustBeDir)
|
||||
{
|
||||
//qDebug() << "Correcting " << path;
|
||||
|
||||
// If the file already exists then no need to search for it.
|
||||
if (QFile::exists(path)) {
|
||||
correctCasePath = path;
|
||||
//qDebug() << "Correct path is" << correctCasePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
const QFileInfo pathInfo(path);
|
||||
|
||||
const QDir fileDir = pathInfo.dir();
|
||||
//qDebug() << "Directory is" << fileDir;
|
||||
|
||||
const QString filename = pathInfo.fileName();
|
||||
//qDebug() << "Filename is" << filename;
|
||||
|
||||
//qDebug() << "searching for a" << (mustBeDir ? "directory" : "directory/file");
|
||||
|
||||
const QStringList matchingFilenames = fileDir.entryList(QStringList(filename),
|
||||
mustBeDir ? QDir::Dirs : QDir::NoFilter);
|
||||
|
||||
if (matchingFilenames.empty()) {
|
||||
//qDebug() << "No matches found!!\n";
|
||||
return false;
|
||||
} else {
|
||||
/*if (matchingFilenames.size() > 1) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "Found multiple matches!!\n";
|
||||
#endif
|
||||
}*/
|
||||
|
||||
if (fileDir.path().endsWith(QDir::separator())) {
|
||||
correctCasePath = fileDir.path() + matchingFilenames[0];
|
||||
} else {
|
||||
correctCasePath = fileDir.path() + QDir::separator() + matchingFilenames[0];
|
||||
}
|
||||
|
||||
//qDebug() << "Correct path is" << correctCasePath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Corrects the case of a path (e.g. /uSr/loCAL/bIN -> /usr/local/bin)
|
||||
path: The path to be processed.
|
||||
corrected: The corrected-case path
|
||||
Returns true on success and false on error, in case of error, corrected is not modified
|
||||
*/
|
||||
bool correctPathCase(const QString& path, QString &corrected)
|
||||
{
|
||||
// early exit check
|
||||
if (QFile::exists(path)) {
|
||||
corrected = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
// path components
|
||||
QStringList components = QString(path).split(QDir::separator());
|
||||
|
||||
if (components.size() < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool mustBeDir = components.back().isEmpty();
|
||||
|
||||
//qDebug() << "Components are" << components;
|
||||
|
||||
if (mustBeDir) {
|
||||
components.pop_back();
|
||||
}
|
||||
|
||||
if (components.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString correctPath;
|
||||
const unsigned initialComponents = components.size();
|
||||
for (unsigned i = 0; i < initialComponents - 1; i ++) {
|
||||
const QString tmp = components[0] + QDir::separator() + components[1];
|
||||
|
||||
if (!correctLastComponentCase(tmp, correctPath, components.size() > 2 || mustBeDir)) {
|
||||
//qDebug() << "search was not successful";
|
||||
return false;
|
||||
}
|
||||
|
||||
components.removeFirst();
|
||||
components[0] = correctPath;
|
||||
}
|
||||
|
||||
corrected = correctPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
class RunnerContextPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
RunnerContextPrivate(RunnerContext *context)
|
||||
: QSharedData(),
|
||||
type(RunnerContext::UnknownType),
|
||||
q(context),
|
||||
singleRunnerQueryMode(false)
|
||||
{
|
||||
}
|
||||
|
||||
RunnerContextPrivate(const RunnerContextPrivate &p)
|
||||
: QSharedData(),
|
||||
launchCounts(p.launchCounts),
|
||||
type(RunnerContext::None),
|
||||
q(p.q),
|
||||
singleRunnerQueryMode(false)
|
||||
{
|
||||
//qDebug() << "¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿boo yeah" << type;
|
||||
}
|
||||
|
||||
~RunnerContextPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines type of query
|
||||
&&
|
||||
*/
|
||||
void determineType()
|
||||
{
|
||||
// NOTE! this method must NEVER be called from
|
||||
// code that may be running in multiple threads
|
||||
// with the same data.
|
||||
type = RunnerContext::UnknownType;
|
||||
QString path = QDir::cleanPath(KShell::tildeExpand(term));
|
||||
|
||||
int space = path.indexOf(' ');
|
||||
if (!QStandardPaths::findExecutable(path.left(space)).isEmpty()) {
|
||||
// it's a shell command if there's a space because that implies
|
||||
// that it has arguments!
|
||||
type = (space > 0) ? RunnerContext::ShellCommand :
|
||||
RunnerContext::Executable;
|
||||
} else {
|
||||
QUrl url = QUrl::fromUserInput(term);
|
||||
// check for a normal URL first
|
||||
//qDebug() << url << KProtocolInfo::protocolClass(url.scheme()) << url.hasHost() <<
|
||||
// url.host() << url.isLocalFile() << path << path.indexOf('/');
|
||||
const bool hasProtocol = !url.scheme().isEmpty();
|
||||
const bool isLocalProtocol = KProtocolInfo::protocolClass(url.scheme()) == ":local";
|
||||
if (hasProtocol &&
|
||||
((!isLocalProtocol && !url.host().isEmpty()) ||
|
||||
(isLocalProtocol && url.scheme() != "file"))) {
|
||||
// we either have a network protocol with a host, so we can show matches for it
|
||||
// or we have a non-file url that may be local so a host isn't required
|
||||
type = RunnerContext::NetworkLocation;
|
||||
} else if (isLocalProtocol) {
|
||||
// at this point in the game, we assume we have a path,
|
||||
// but if a path doesn't have any slashes
|
||||
// it's too ambiguous to be sure we're in a filesystem context
|
||||
path = QDir::cleanPath(url.toLocalFile());
|
||||
//qDebug()<< "slash check" << path;
|
||||
if (hasProtocol || ((path.indexOf('/') != -1 || path.indexOf('\\') != -1))) {
|
||||
QString correctCasePath;
|
||||
if (correctPathCase(path, correctCasePath)) {
|
||||
path = correctCasePath;
|
||||
QFileInfo info(path);
|
||||
//qDebug()<< "correct cas epath is" << correctCasePath << info.isSymLink() <<
|
||||
// info.isDir() << info.isFile();
|
||||
|
||||
if (info.isSymLink()) {
|
||||
path = info.canonicalFilePath();
|
||||
info = QFileInfo(path);
|
||||
}
|
||||
if (info.isDir()) {
|
||||
type = RunnerContext::Directory;
|
||||
mimeType = "inode/folder";
|
||||
} else if (info.isFile()) {
|
||||
type = RunnerContext::File;
|
||||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForFile(path);
|
||||
if (!mime.isDefault()) {
|
||||
mimeType = mime.name();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << "term2type" << term << type;
|
||||
}
|
||||
|
||||
void invalidate()
|
||||
{
|
||||
q = &s_dummyContext;
|
||||
}
|
||||
|
||||
QReadWriteLock lock;
|
||||
QList<QueryMatch> matches;
|
||||
QMap<QString, const QueryMatch*> matchesById;
|
||||
QHash<QString, int> launchCounts;
|
||||
QString term;
|
||||
QString mimeType;
|
||||
RunnerContext::Type type;
|
||||
RunnerContext * q;
|
||||
static RunnerContext s_dummyContext;
|
||||
bool singleRunnerQueryMode;
|
||||
};
|
||||
|
||||
RunnerContext RunnerContextPrivate::s_dummyContext;
|
||||
|
||||
RunnerContext::RunnerContext(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new RunnerContextPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
//copy ctor
|
||||
RunnerContext::RunnerContext(RunnerContext &other, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
LOCK_FOR_READ(other.d)
|
||||
d = other.d;
|
||||
UNLOCK(other.d)
|
||||
}
|
||||
|
||||
RunnerContext::~RunnerContext()
|
||||
{
|
||||
}
|
||||
|
||||
RunnerContext &RunnerContext::operator=(const RunnerContext &other)
|
||||
{
|
||||
if (this->d == other.d) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
QExplicitlySharedDataPointer<Plasma::RunnerContextPrivate> oldD = d;
|
||||
LOCK_FOR_WRITE(d)
|
||||
LOCK_FOR_READ(other.d)
|
||||
d = other.d;
|
||||
UNLOCK(other.d)
|
||||
UNLOCK(oldD)
|
||||
return *this;
|
||||
}
|
||||
|
||||
void RunnerContext::reset()
|
||||
{
|
||||
// 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 RunnerContext makes all the copies obsolete.
|
||||
|
||||
// We need to mark the q pointer of the detached RunnerContextPrivate
|
||||
// as dirty on detach to avoid receiving results for old queries
|
||||
d->invalidate();
|
||||
|
||||
d.detach();
|
||||
|
||||
// Now that we detached the d pointer we need to reset its q pointer
|
||||
|
||||
d->q = this;
|
||||
|
||||
// we still have to remove all the matches, since if the
|
||||
// ref count was 1 (e.g. only the RunnerContext is using
|
||||
// the dptr) then we won't get a copy made
|
||||
if (!d->matches.isEmpty()) {
|
||||
d->matchesById.clear();
|
||||
d->matches.clear();
|
||||
emit matchesChanged();
|
||||
}
|
||||
|
||||
d->term.clear();
|
||||
d->mimeType.clear();
|
||||
d->type = UnknownType;
|
||||
d->singleRunnerQueryMode = false;
|
||||
//qDebug() << "match count" << d->matches.count();
|
||||
}
|
||||
|
||||
void RunnerContext::setQuery(const QString &term)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (term.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->term = term;
|
||||
d->determineType();
|
||||
}
|
||||
|
||||
QString RunnerContext::query() const
|
||||
{
|
||||
// the query term should never be set after
|
||||
// a search starts. in fact, reset() ensures this
|
||||
// and setQuery(QString) calls reset()
|
||||
return d->term;
|
||||
}
|
||||
|
||||
RunnerContext::Type RunnerContext::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
QString RunnerContext::mimeType() const
|
||||
{
|
||||
return d->mimeType;
|
||||
}
|
||||
|
||||
bool RunnerContext::isValid() const
|
||||
{
|
||||
// if our qptr is dirty, we aren't useful anymore
|
||||
return (d->q != &(d->s_dummyContext));
|
||||
}
|
||||
|
||||
bool RunnerContext::addMatches(const QList<QueryMatch> &matches)
|
||||
{
|
||||
if (matches.isEmpty() || !isValid()) {
|
||||
//Bail out if the query is empty or the qptr is dirty
|
||||
return false;
|
||||
}
|
||||
|
||||
LOCK_FOR_WRITE(d)
|
||||
foreach (QueryMatch match, matches) {
|
||||
// Give previously launched matches a slight boost in relevance
|
||||
// The boost smoothly saturates to 0.5;
|
||||
if (int count = d->launchCounts.value(match.id())) {
|
||||
match.setRelevance(match.relevance() + 0.5 * (1-exp(-count*0.3)));
|
||||
}
|
||||
|
||||
d->matches.append(match);
|
||||
#ifndef NDEBUG
|
||||
if (d->matchesById.contains(match.id())) {
|
||||
// qDebug() << "Duplicate match id " << match.id() << "from" << match.runner()->name();
|
||||
}
|
||||
#endif
|
||||
d->matchesById.insert(match.id(), &d->matches.at(d->matches.size() - 1));
|
||||
}
|
||||
UNLOCK(d);
|
||||
//qDebug()<< "add matches";
|
||||
// A copied searchContext may share the d pointer,
|
||||
// we always want to sent the signal of the object that created
|
||||
// the d pointer
|
||||
emit d->q->matchesChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunnerContext::addMatch(const QueryMatch &match)
|
||||
{
|
||||
if (!isValid()) {
|
||||
// Bail out if the qptr is dirty
|
||||
return false;
|
||||
}
|
||||
|
||||
QueryMatch m(match); // match must be non-const to modify relevance
|
||||
|
||||
LOCK_FOR_WRITE(d)
|
||||
|
||||
if (int count = d->launchCounts.value(m.id())) {
|
||||
m.setRelevance(m.relevance() + 0.05 * count);
|
||||
}
|
||||
|
||||
d->matches.append(m);
|
||||
d->matchesById.insert(m.id(), &d->matches.at(d->matches.size() - 1));
|
||||
UNLOCK(d);
|
||||
//qDebug()<< "added match" << match->text();
|
||||
emit d->q->matchesChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunnerContext::removeMatches(const QStringList matchIdList)
|
||||
{
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList presentMatchIdList;
|
||||
QList<const QueryMatch*> presentMatchList;
|
||||
|
||||
LOCK_FOR_READ(d)
|
||||
foreach(const QString &matchId, matchIdList) {
|
||||
const QueryMatch* match = d->matchesById.value(matchId, 0);
|
||||
if (match) {
|
||||
presentMatchList << match;
|
||||
presentMatchIdList << matchId;
|
||||
}
|
||||
}
|
||||
UNLOCK(d)
|
||||
|
||||
if (presentMatchIdList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOCK_FOR_WRITE(d)
|
||||
foreach(const QueryMatch *match, presentMatchList) {
|
||||
d->matches.removeAll(*match);
|
||||
}
|
||||
foreach(const QString &matchId, presentMatchIdList) {
|
||||
d->matchesById.remove(matchId);
|
||||
}
|
||||
UNLOCK(d)
|
||||
|
||||
emit d->q->matchesChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunnerContext::removeMatch(const QString matchId)
|
||||
{
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
LOCK_FOR_READ(d)
|
||||
const QueryMatch* match = d->matchesById.value(matchId, 0);
|
||||
UNLOCK(d)
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
LOCK_FOR_WRITE(d)
|
||||
d->matches.removeAll(*match);
|
||||
d->matchesById.remove(matchId);
|
||||
UNLOCK(d)
|
||||
emit d->q->matchesChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunnerContext::removeMatches(Plasma::AbstractRunner *runner)
|
||||
{
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QueryMatch> presentMatchList;
|
||||
|
||||
LOCK_FOR_READ(d)
|
||||
foreach(const QueryMatch &match, d->matches) {
|
||||
if (match.runner() == runner) {
|
||||
presentMatchList << match;
|
||||
}
|
||||
}
|
||||
UNLOCK(d)
|
||||
|
||||
if (presentMatchList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOCK_FOR_WRITE(d)
|
||||
foreach (const QueryMatch &match, presentMatchList) {
|
||||
d->matchesById.remove(match.id());
|
||||
d->matches.removeAll(match);
|
||||
}
|
||||
UNLOCK(d)
|
||||
|
||||
emit d->q->matchesChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QueryMatch> RunnerContext::matches() const
|
||||
{
|
||||
LOCK_FOR_READ(d)
|
||||
QList<QueryMatch> matches = d->matches;
|
||||
UNLOCK(d);
|
||||
return matches;
|
||||
}
|
||||
|
||||
QueryMatch RunnerContext::match(const QString &id) const
|
||||
{
|
||||
LOCK_FOR_READ(d)
|
||||
const QueryMatch *match = d->matchesById.value(id, 0);
|
||||
UNLOCK(d)
|
||||
|
||||
if (match) {
|
||||
return *match;
|
||||
}
|
||||
|
||||
return QueryMatch(0);
|
||||
}
|
||||
|
||||
void RunnerContext::setSingleRunnerQueryMode(bool enabled)
|
||||
{
|
||||
d->singleRunnerQueryMode = enabled;
|
||||
}
|
||||
|
||||
bool RunnerContext::singleRunnerQueryMode() const
|
||||
{
|
||||
return d->singleRunnerQueryMode;
|
||||
}
|
||||
|
||||
void RunnerContext::restore(const KConfigGroup &config)
|
||||
{
|
||||
const QStringList cfgList = config.readEntry("LaunchCounts", QStringList());
|
||||
|
||||
const QRegExp r("(\\d*) (.*)");
|
||||
foreach (const QString& entry, cfgList) {
|
||||
r.indexIn(entry);
|
||||
int count = r.cap(1).toInt();
|
||||
QString id = r.cap(2);
|
||||
d->launchCounts[id] = count;
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerContext::save(KConfigGroup &config)
|
||||
{
|
||||
QStringList countList;
|
||||
|
||||
typedef QHash<QString, int>::const_iterator Iterator;
|
||||
Iterator end = d->launchCounts.constEnd();
|
||||
for (Iterator i = d->launchCounts.constBegin(); i != end; ++i) {
|
||||
countList << QString("%2 %1").arg(i.key()).arg(i.value());
|
||||
}
|
||||
|
||||
config.writeEntry("LaunchCounts", countList);
|
||||
config.sync();
|
||||
}
|
||||
|
||||
void RunnerContext::run(const QueryMatch &match)
|
||||
{
|
||||
++d->launchCounts[match.id()];
|
||||
match.run(*this);
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
#include "moc_runnercontext.cpp"
|
@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 PLASMA_RUNNERCONTEXT_H
|
||||
#define PLASMA_RUNNERCONTEXT_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedDataPointer>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class KCompletion;
|
||||
class KConfigGroup;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class QueryMatch;
|
||||
class AbstractRunner;
|
||||
class RunnerContextPrivate;
|
||||
|
||||
/**
|
||||
* @class RunnerContext plasma/runnercontext.h <Plasma/RunnerContext>
|
||||
*
|
||||
* @short The RunnerContext class provides information related to a search,
|
||||
* including the search term, metadata on the search term and collected
|
||||
* matches.
|
||||
*/
|
||||
class PLASMA_EXPORT RunnerContext : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
None = 0,
|
||||
UnknownType = 1,
|
||||
Directory = 2,
|
||||
File = 4,
|
||||
NetworkLocation = 8,
|
||||
Executable = 16,
|
||||
ShellCommand = 32,
|
||||
Help = 64,
|
||||
FileSystem = Directory | File | Executable | ShellCommand
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(Types, Type)
|
||||
|
||||
explicit RunnerContext(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
RunnerContext(RunnerContext &other, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Assignment operator
|
||||
* @since 4.4
|
||||
*/
|
||||
RunnerContext &operator=(const RunnerContext &other);
|
||||
|
||||
~RunnerContext();
|
||||
|
||||
/**
|
||||
* Resets the search term for this object.
|
||||
* This removes all current matches in the process and
|
||||
* turns off single runner query mode.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Sets the query term for this object and attempts to determine
|
||||
* the type of the search.
|
||||
*/
|
||||
void setQuery(const QString &term);
|
||||
|
||||
/**
|
||||
* @return the current search query term.
|
||||
*/
|
||||
QString query() const;
|
||||
|
||||
/**
|
||||
* The type of item the search term might refer to.
|
||||
* @see Type
|
||||
*/
|
||||
Type type() const;
|
||||
|
||||
/**
|
||||
* The mimetype that the search term refers to, if discoverable.
|
||||
*
|
||||
* @return QString() if the mimetype can not be determined, otherwise
|
||||
* the mimetype of the object being referred to by the search
|
||||
* string.
|
||||
*/
|
||||
QString mimeType() const;
|
||||
|
||||
/**
|
||||
* @returns true if this context is no longer valid and therefore
|
||||
* matching using it should abort. Most useful as an optimization technique
|
||||
* inside of AbstractRunner subclasses in the match method, e.g.:
|
||||
*
|
||||
* while (.. a possibly large iteration) {
|
||||
* if (!context.isValid()) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* ... some processing ...
|
||||
* }
|
||||
*
|
||||
* While not required to be used within runners, it provies a nice way
|
||||
* to avoid unnecessary processing in runners that may run for an extended
|
||||
* period (as measured in 10s of ms) and therefore improve the user experience.
|
||||
* @since 4.2.3
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Appends lists of matches to the list of matches.
|
||||
*
|
||||
* @param matches the matches to add
|
||||
* @return true if matches were added, false if matches were e.g. outdated
|
||||
*/
|
||||
bool addMatches(const QList<QueryMatch> &matches);
|
||||
|
||||
/**
|
||||
* Appends a match to the existing list of matches.
|
||||
*
|
||||
* If you are going to be adding multiple matches, use @see addMatches instead.
|
||||
*
|
||||
* @param match the match to add
|
||||
* @return true if the match was added, false otherwise.
|
||||
*/
|
||||
bool addMatch(const QueryMatch &match);
|
||||
|
||||
/**
|
||||
* Removes a match from the existing list of matches.
|
||||
*
|
||||
* If you are going to be removing multiple matches, use removeMatches instead.
|
||||
*
|
||||
* @param matchId the id of match to remove
|
||||
*
|
||||
* @return true if the match was removed, false otherwise.
|
||||
* @since 4.4
|
||||
*/
|
||||
bool removeMatch(const QString matchId);
|
||||
|
||||
/**
|
||||
* Removes lists of matches from the existing list of matches.
|
||||
*
|
||||
* This method is thread safe and causes the matchesChanged() signal to be emitted.
|
||||
*
|
||||
* @param matchIdList the list of matches id to remove
|
||||
*
|
||||
* @return true if at least one match was removed, false otherwise.
|
||||
* @since 4.4
|
||||
*/
|
||||
bool removeMatches(const QStringList matchIdList);
|
||||
|
||||
/**
|
||||
* Removes lists of matches from a given AbstractRunner
|
||||
*
|
||||
* This method is thread safe and causes the matchesChanged() signal to be emitted.
|
||||
*
|
||||
* @param runner the AbstractRunner from which to remove matches
|
||||
*
|
||||
* @return true if at least one match was removed, false otherwise.
|
||||
* @since 4.10
|
||||
*/
|
||||
bool removeMatches(AbstractRunner *runner);
|
||||
|
||||
/**
|
||||
* Retrieves all available matches for the current search term.
|
||||
*
|
||||
* @return a list of matches
|
||||
*/
|
||||
QList<QueryMatch> matches() const;
|
||||
|
||||
/**
|
||||
* Retrieves a match by id.
|
||||
*
|
||||
* @param id the id of the match to return
|
||||
* @return the match associated with this id, or an invalid QueryMatch object
|
||||
* if the id does not eixst
|
||||
*/
|
||||
QueryMatch match(const QString &id) const;
|
||||
|
||||
/**
|
||||
* Sets single runner query mode. Note that a call to reset() will
|
||||
* turn off single runner query mode.
|
||||
*
|
||||
* @see reset()
|
||||
* @since 4.4
|
||||
*/
|
||||
void setSingleRunnerQueryMode(bool enabled);
|
||||
|
||||
/**
|
||||
* @return true if the current query is a single runner query
|
||||
* @since 4.4
|
||||
*/
|
||||
bool singleRunnerQueryMode() const;
|
||||
|
||||
/**
|
||||
* Sets the launch counts for the associated match ids
|
||||
*
|
||||
* If a runner adds a match to this context, the context will check if the
|
||||
* match id has been launched before and increase the matches relevance
|
||||
* correspondingly. In this manner, any front end can implement adaptive search
|
||||
* by sorting items according to relevance.
|
||||
*
|
||||
* @param config the config group where launch data was stored
|
||||
*/
|
||||
void restore(const KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* @param config the config group where launch data should be stored
|
||||
*/
|
||||
void save(KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* Run a match using the information from this context
|
||||
*
|
||||
* The context will also keep track of the number of times the match was
|
||||
* launched to sort future matches according to user habits
|
||||
*
|
||||
* @param match the match to run
|
||||
*/
|
||||
void run(const QueryMatch &match);
|
||||
|
||||
Q_SIGNALS:
|
||||
void matchesChanged();
|
||||
|
||||
private:
|
||||
QExplicitlySharedDataPointer<RunnerContextPrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::RunnerContext::Types)
|
||||
|
||||
#endif
|
@ -1,801 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright (C) 2007, 2009 Ryan P. Bitanga <ryan.bitanga@gmail.com>
|
||||
* Copyright (C) 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 "runnermanager.h"
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QTimer>
|
||||
#include <QCoreApplication>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <kplugininfo.h>
|
||||
#include <kservicetypetrader.h>
|
||||
|
||||
#if !PLASMA_NO_SOLID
|
||||
#include <solid/device.h>
|
||||
#include <solid/deviceinterface.h>
|
||||
#endif
|
||||
|
||||
#include <ThreadWeaver/DebuggingAids>
|
||||
#include <ThreadWeaver/Queue>
|
||||
#include <ThreadWeaver/Thread>
|
||||
|
||||
#include "private/runnerjobs_p.h"
|
||||
#include "pluginloader.h"
|
||||
#include "querymatch.h"
|
||||
|
||||
using ThreadWeaver::Queue;
|
||||
using ThreadWeaver::Job;
|
||||
|
||||
//#define MEASURE_PREPTIME
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
/*****************************************************
|
||||
* RunnerManager::Private class
|
||||
*
|
||||
*****************************************************/
|
||||
class RunnerManagerPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
RunnerManagerPrivate(RunnerManager *parent)
|
||||
: q(parent),
|
||||
deferredRun(0),
|
||||
currentSingleRunner(0),
|
||||
prepped(false),
|
||||
allRunnersPrepped(false),
|
||||
singleRunnerPrepped(false),
|
||||
teardownRequested(false),
|
||||
singleMode(false),
|
||||
singleRunnerWasLoaded(false)
|
||||
{
|
||||
matchChangeTimer.setSingleShot(true);
|
||||
delayTimer.setSingleShot(true);
|
||||
|
||||
QObject::connect(&matchChangeTimer, SIGNAL(timeout()), q, SLOT(matchesChanged()));
|
||||
QObject::connect(&context, SIGNAL(matchesChanged()), q, SLOT(scheduleMatchesChanged()));
|
||||
QObject::connect(&delayTimer, SIGNAL(timeout()), q, SLOT(unblockJobs()));
|
||||
}
|
||||
|
||||
~RunnerManagerPrivate()
|
||||
{
|
||||
KConfigGroup config = configGroup();
|
||||
context.save(config);
|
||||
}
|
||||
|
||||
void scheduleMatchesChanged()
|
||||
{
|
||||
matchChangeTimer.start(100);
|
||||
}
|
||||
|
||||
void matchesChanged()
|
||||
{
|
||||
emit q->matchesChanged(context.matches());
|
||||
}
|
||||
|
||||
void loadConfiguration()
|
||||
{
|
||||
KConfigGroup config = configGroup();
|
||||
|
||||
//The number of threads used scales with the number of processors.
|
||||
#if !PLASMA_NO_SOLID
|
||||
const int numProcs =
|
||||
qMax(Solid::Device::listFromType(Solid::DeviceInterface::Processor).count(), 1);
|
||||
#else
|
||||
const int numProcs = 1;
|
||||
#endif
|
||||
//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));
|
||||
//qDebug() << "setting up" << numThreads << "threads for" << numProcs << "processors";
|
||||
if (numThreads > Queue::instance()->maximumNumberOfThreads()) {
|
||||
Queue::instance()->setMaximumNumberOfThreads(numThreads);
|
||||
}
|
||||
// Limit the number of instances of a single normal speed runner and all of the slow runners
|
||||
// to half the number of threads
|
||||
const int cap = qMax(2, numThreads/2);
|
||||
DefaultRunnerPolicy::instance().setCap(cap);
|
||||
|
||||
context.restore(config);
|
||||
}
|
||||
|
||||
KConfigGroup configGroup()
|
||||
{
|
||||
return conf.isValid() ? conf : KConfigGroup(KSharedConfig::openConfig(), "PlasmaRunnerManager");
|
||||
}
|
||||
|
||||
void clearSingleRunner()
|
||||
{
|
||||
if (singleRunnerWasLoaded) {
|
||||
delete currentSingleRunner;
|
||||
}
|
||||
|
||||
currentSingleRunner = 0;
|
||||
}
|
||||
|
||||
void loadSingleRunner()
|
||||
{
|
||||
if (!singleMode || singleModeRunnerId.isEmpty()) {
|
||||
clearSingleRunner();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSingleRunner) {
|
||||
if (currentSingleRunner->id() == singleModeRunnerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearSingleRunner();
|
||||
}
|
||||
|
||||
AbstractRunner *loadedRunner = q->runner(singleModeRunnerId);
|
||||
if (loadedRunner) {
|
||||
singleRunnerWasLoaded = false;
|
||||
currentSingleRunner = loadedRunner;
|
||||
return;
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", QString("[X-KDE-PluginInfo-Name] == '%1'").arg(singleModeRunnerId));
|
||||
if (!offers.isEmpty()) {
|
||||
const KService::Ptr &service = offers[0];
|
||||
currentSingleRunner = loadInstalledRunner(service);
|
||||
|
||||
if (currentSingleRunner) {
|
||||
emit currentSingleRunner->prepare();
|
||||
singleRunnerWasLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadRunners()
|
||||
{
|
||||
KConfigGroup config = configGroup();
|
||||
KPluginInfo::List offers = RunnerManager::listRunnerInfo();
|
||||
|
||||
const bool loadAll = config.readEntry("loadAll", false);
|
||||
const QStringList whiteList = config.readEntry("pluginWhiteList", QStringList());
|
||||
const bool noWhiteList = whiteList.isEmpty();
|
||||
KConfigGroup pluginConf;
|
||||
if (conf.isValid()) {
|
||||
pluginConf = KConfigGroup(&conf, "Plugins");
|
||||
} else {
|
||||
pluginConf = KConfigGroup(KSharedConfig::openConfig(), "Plugins");
|
||||
}
|
||||
|
||||
advertiseSingleRunnerIds.clear();
|
||||
|
||||
QSet<AbstractRunner *> deadRunners;
|
||||
QMutableListIterator<KPluginInfo> it(offers);
|
||||
while (it.hasNext()) {
|
||||
KPluginInfo &description = it.next();
|
||||
//qDebug() << "Loading runner: " << service->name() << service->storageId();
|
||||
QString tryExec = description.property("TryExec").toString();
|
||||
//qDebug() << "TryExec is" << tryExec;
|
||||
if (!tryExec.isEmpty() && QStandardPaths::findExecutable(tryExec).isEmpty()) {
|
||||
// we don't actually have this application!
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString runnerName = description.pluginName();
|
||||
description.load(pluginConf);
|
||||
|
||||
const bool loaded = runners.contains(runnerName);
|
||||
const bool selected = loadAll || (description.isPluginEnabled() && (noWhiteList || whiteList.contains(runnerName)));
|
||||
|
||||
const bool singleQueryModeEnabled = description.property("X-Plasma-AdvertiseSingleRunnerQueryMode").toBool();
|
||||
|
||||
if (singleQueryModeEnabled) {
|
||||
advertiseSingleRunnerIds.insert(runnerName, description.name());
|
||||
}
|
||||
|
||||
//qDebug() << loadAll << description.isPluginEnabled() << noWhiteList << whiteList.contains(runnerName);
|
||||
if (selected) {
|
||||
if (!loaded) {
|
||||
AbstractRunner *runner = loadInstalledRunner(description.service());
|
||||
|
||||
if (runner) {
|
||||
runners.insert(runnerName, runner);
|
||||
}
|
||||
}
|
||||
} else if (loaded) {
|
||||
//Remove runner
|
||||
deadRunners.insert(runners.take(runnerName));
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "Removing runner: " << runnerName;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!deadRunners.isEmpty()) {
|
||||
QSet<QSharedPointer<FindMatchesJob> > deadJobs;
|
||||
auto it = searchJobs.begin();
|
||||
while (it != searchJobs.end()) {
|
||||
auto &job = (*it);
|
||||
if (deadRunners.contains(job->runner())) {
|
||||
QObject::disconnect(job->decorator(), SIGNAL(done(ThreadWeaver::JobPointer)), q, SLOT(jobDone(ThreadWeaver::JobPointer)));
|
||||
it = searchJobs.erase(it);
|
||||
deadJobs.insert(job);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
it = oldSearchJobs.begin();
|
||||
while (it != oldSearchJobs.end()) {
|
||||
auto &job = (*it);
|
||||
if (deadRunners.contains(job->runner())) {
|
||||
it = oldSearchJobs.erase(it);
|
||||
deadJobs.insert(job);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
if (deadJobs.isEmpty()) {
|
||||
qDeleteAll(deadRunners);
|
||||
} else {
|
||||
new DelayedJobCleaner(deadJobs, deadRunners);
|
||||
}
|
||||
}
|
||||
|
||||
if (!singleRunnerWasLoaded) {
|
||||
// in case we deleted it up above
|
||||
clearSingleRunner();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "All runners loaded, total:" << runners.count();
|
||||
#endif
|
||||
}
|
||||
|
||||
AbstractRunner *loadInstalledRunner(const KService::Ptr service)
|
||||
{
|
||||
if (!service) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AbstractRunner *runner = PluginLoader::self()->loadRunner(service->property("X-KDE-PluginInfo-Name", QVariant::String).toString());
|
||||
|
||||
if (runner) {
|
||||
runner->setParent(q);
|
||||
} else {
|
||||
const QString api = service->property("X-Plasma-API").toString();
|
||||
|
||||
if (api.isEmpty()) {
|
||||
QVariantList args;
|
||||
args << service->storageId();
|
||||
if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
|
||||
QString error;
|
||||
runner = service->createInstance<AbstractRunner>(q, args, &error);
|
||||
if (!runner) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "Failed to load runner:" << service->name() << ". error reported:" << error;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//qDebug() << "got a script runner known as" << api;
|
||||
runner = new AbstractRunner(service, q);
|
||||
}
|
||||
}
|
||||
|
||||
if (runner) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "================= loading runner:" << service->name() << "=================";
|
||||
#endif
|
||||
QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool)));
|
||||
runner->init();
|
||||
if (prepped) {
|
||||
emit runner->prepare();
|
||||
}
|
||||
}
|
||||
|
||||
return runner;
|
||||
}
|
||||
|
||||
void jobDone(ThreadWeaver::JobPointer job)
|
||||
{
|
||||
auto runJob = job.dynamicCast<FindMatchesJob>();
|
||||
|
||||
if (!runJob) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (deferredRun.isEnabled() && runJob->runner() == deferredRun.runner()) {
|
||||
//qDebug() << "job actually done, running now **************";
|
||||
QueryMatch tmpRun = deferredRun;
|
||||
deferredRun = QueryMatch(0);
|
||||
tmpRun.run(context);
|
||||
}
|
||||
|
||||
searchJobs.remove(runJob);
|
||||
oldSearchJobs.remove(runJob);
|
||||
|
||||
if (searchJobs.isEmpty() && context.matches().isEmpty()) {
|
||||
// we finished our run, and there are no valid matches, and so no
|
||||
// signal will have been sent out. so we need to emit the signal
|
||||
// ourselves here
|
||||
emit q->matchesChanged(context.matches());
|
||||
}
|
||||
|
||||
checkTearDown();
|
||||
}
|
||||
|
||||
void checkTearDown()
|
||||
{
|
||||
//qDebug() << prepped << teardownRequested << searchJobs.count() << oldSearchJobs.count();
|
||||
|
||||
if (!prepped || !teardownRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Queue::instance()->isIdle()) {
|
||||
searchJobs.clear();
|
||||
oldSearchJobs.clear();
|
||||
}
|
||||
|
||||
if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) {
|
||||
if (allRunnersPrepped) {
|
||||
foreach (AbstractRunner *runner, runners) {
|
||||
emit runner->teardown();
|
||||
}
|
||||
|
||||
allRunnersPrepped = false;
|
||||
}
|
||||
|
||||
if (singleRunnerPrepped) {
|
||||
if (currentSingleRunner) {
|
||||
emit currentSingleRunner->teardown();
|
||||
}
|
||||
|
||||
singleRunnerPrepped = false;
|
||||
}
|
||||
|
||||
emit q->queryFinished();
|
||||
|
||||
prepped = false;
|
||||
teardownRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
void unblockJobs()
|
||||
{
|
||||
if (searchJobs.isEmpty() && Queue::instance()->isIdle()) {
|
||||
oldSearchJobs.clear();
|
||||
checkTearDown();
|
||||
return;
|
||||
}
|
||||
|
||||
Queue::instance()->reschedule();
|
||||
}
|
||||
|
||||
void runnerMatchingSuspended(bool suspended)
|
||||
{
|
||||
if (suspended || !prepped || teardownRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractRunner *runner = qobject_cast<AbstractRunner *>(q->sender());
|
||||
|
||||
if (runner) {
|
||||
startJob(runner);
|
||||
}
|
||||
}
|
||||
|
||||
void startJob(AbstractRunner *runner)
|
||||
{
|
||||
if ((runner->ignoredTypes() & context.type()) == 0) {
|
||||
QSharedPointer<FindMatchesJob> job(new FindMatchesJob(runner, &context, Queue::instance()));
|
||||
QObject::connect(job->decorator(), SIGNAL(done(ThreadWeaver::JobPointer)), q, SLOT(jobDone(ThreadWeaver::JobPointer)));
|
||||
if (runner->speed() == AbstractRunner::SlowSpeed) {
|
||||
job->setDelayTimer(&delayTimer);
|
||||
}
|
||||
Queue::instance()->enqueue(job);
|
||||
searchJobs.insert(job);
|
||||
}
|
||||
}
|
||||
|
||||
// Delay in ms before slow runners are allowed to run
|
||||
static const int slowRunDelay = 400;
|
||||
|
||||
RunnerManager *q;
|
||||
QueryMatch deferredRun;
|
||||
RunnerContext context;
|
||||
QTimer matchChangeTimer;
|
||||
QTimer delayTimer; // Timer to control when to run slow runners
|
||||
QHash<QString, AbstractRunner*> runners;
|
||||
QHash<QString, QString> advertiseSingleRunnerIds;
|
||||
AbstractRunner* currentSingleRunner;
|
||||
QSet<QSharedPointer<FindMatchesJob> > searchJobs;
|
||||
QSet<QSharedPointer<FindMatchesJob> > oldSearchJobs;
|
||||
KConfigGroup conf;
|
||||
QString singleModeRunnerId;
|
||||
bool loadAll : 1;
|
||||
bool prepped : 1;
|
||||
bool allRunnersPrepped : 1;
|
||||
bool singleRunnerPrepped : 1;
|
||||
bool teardownRequested : 1;
|
||||
bool singleMode : 1;
|
||||
bool singleRunnerWasLoaded : 1;
|
||||
};
|
||||
|
||||
/*****************************************************
|
||||
* RunnerManager::Public class
|
||||
*
|
||||
*****************************************************/
|
||||
RunnerManager::RunnerManager(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new RunnerManagerPrivate(this))
|
||||
{
|
||||
d->loadConfiguration();
|
||||
//ThreadWeaver::setDebugLevel(true, 4);
|
||||
}
|
||||
|
||||
RunnerManager::RunnerManager(KConfigGroup &c, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new RunnerManagerPrivate(this))
|
||||
{
|
||||
// Should this be really needed? Maybe d->loadConfiguration(c) would make
|
||||
// more sense.
|
||||
d->conf = KConfigGroup(&c, "PlasmaRunnerManager");
|
||||
d->loadConfiguration();
|
||||
//ThreadWeaver::setDebugLevel(true, 4);
|
||||
}
|
||||
|
||||
RunnerManager::~RunnerManager()
|
||||
{
|
||||
if (!qApp->closingDown() && (!d->searchJobs.isEmpty() || !d->oldSearchJobs.isEmpty())) {
|
||||
new DelayedJobCleaner(d->searchJobs + d->oldSearchJobs);
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
void RunnerManager::reloadConfiguration()
|
||||
{
|
||||
d->loadConfiguration();
|
||||
d->loadRunners();
|
||||
}
|
||||
|
||||
void RunnerManager::setAllowedRunners(const QStringList &runners)
|
||||
{
|
||||
KConfigGroup config = d->configGroup();
|
||||
config.writeEntry("pluginWhiteList", runners);
|
||||
|
||||
if (!d->runners.isEmpty()) {
|
||||
// this has been called with runners already created. so let's do an instant reload
|
||||
d->loadRunners();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList RunnerManager::allowedRunners() const
|
||||
{
|
||||
KConfigGroup config = d->configGroup();
|
||||
return config.readEntry("pluginWhiteList", QStringList());
|
||||
}
|
||||
|
||||
void RunnerManager::loadRunner(const KService::Ptr service)
|
||||
{
|
||||
KPluginInfo description(service);
|
||||
const QString runnerName = description.pluginName();
|
||||
if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
|
||||
AbstractRunner *runner = d->loadInstalledRunner(service);
|
||||
if (runner) {
|
||||
d->runners.insert(runnerName, runner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerManager::loadRunner(const QString &path)
|
||||
{
|
||||
if (!d->runners.contains(path)) {
|
||||
AbstractRunner *runner = new AbstractRunner(this, path);
|
||||
connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
|
||||
d->runners.insert(path, runner);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractRunner* RunnerManager::runner(const QString &name) const
|
||||
{
|
||||
if (d->runners.isEmpty()) {
|
||||
d->loadRunners();
|
||||
}
|
||||
|
||||
return d->runners.value(name, 0);
|
||||
}
|
||||
|
||||
AbstractRunner *RunnerManager::singleModeRunner() const
|
||||
{
|
||||
return d->currentSingleRunner;
|
||||
}
|
||||
|
||||
void RunnerManager::setSingleModeRunnerId(const QString &id)
|
||||
{
|
||||
d->singleModeRunnerId = id;
|
||||
d->loadSingleRunner();
|
||||
}
|
||||
|
||||
QString RunnerManager::singleModeRunnerId() const
|
||||
{
|
||||
return d->singleModeRunnerId;
|
||||
}
|
||||
|
||||
bool RunnerManager::singleMode() const
|
||||
{
|
||||
return d->singleMode;
|
||||
}
|
||||
|
||||
void RunnerManager::setSingleMode(bool singleMode)
|
||||
{
|
||||
if (d->singleMode == singleMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Plasma::AbstractRunner *prevSingleRunner = d->currentSingleRunner;
|
||||
d->singleMode = singleMode;
|
||||
d->loadSingleRunner();
|
||||
d->singleMode = d->currentSingleRunner;
|
||||
|
||||
if (prevSingleRunner != d->currentSingleRunner) {
|
||||
if (d->prepped) {
|
||||
matchSessionComplete();
|
||||
|
||||
if (d->singleMode) {
|
||||
setupMatchSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<AbstractRunner *> RunnerManager::runners() const
|
||||
{
|
||||
return d->runners.values();
|
||||
}
|
||||
|
||||
QStringList RunnerManager::singleModeAdvertisedRunnerIds() const
|
||||
{
|
||||
return d->advertiseSingleRunnerIds.keys();
|
||||
}
|
||||
|
||||
QString RunnerManager::runnerName(const QString &id) const
|
||||
{
|
||||
if (runner(id)) {
|
||||
return runner(id)->name();
|
||||
} else {
|
||||
return d->advertiseSingleRunnerIds.value(id, QString());
|
||||
}
|
||||
}
|
||||
|
||||
RunnerContext* RunnerManager::searchContext() const
|
||||
{
|
||||
return &d->context;
|
||||
}
|
||||
|
||||
//Reordering is here so data is not reordered till strictly needed
|
||||
QList<QueryMatch> RunnerManager::matches() const
|
||||
{
|
||||
return d->context.matches();
|
||||
}
|
||||
|
||||
void RunnerManager::run(const QString &matchId)
|
||||
{
|
||||
run(d->context.match(matchId));
|
||||
}
|
||||
|
||||
void RunnerManager::run(const QueryMatch &match)
|
||||
{
|
||||
if (!match.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: this function is not const as it may be used for learning
|
||||
AbstractRunner *runner = match.runner();
|
||||
|
||||
for (auto it = d->searchJobs.constBegin(); it != d->searchJobs.constEnd(); ++it) {
|
||||
if ((*it)->runner() == runner && !(*it)->isFinished()) {
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << "deferred run";
|
||||
#endif
|
||||
d->deferredRun = match;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->deferredRun.isValid()) {
|
||||
d->deferredRun = QueryMatch(0);
|
||||
}
|
||||
|
||||
d->context.run(match);
|
||||
}
|
||||
|
||||
QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match)
|
||||
{
|
||||
AbstractRunner *runner = match.runner();
|
||||
if (runner) {
|
||||
return runner->actionsForMatch(match);
|
||||
}
|
||||
|
||||
return QList<QAction*>();
|
||||
}
|
||||
|
||||
QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
|
||||
{
|
||||
return mimeDataForMatch(d->context.match(id));
|
||||
}
|
||||
|
||||
|
||||
QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
|
||||
{
|
||||
AbstractRunner *runner = match.runner();
|
||||
if (runner) {
|
||||
return runner->mimeDataForMatch(match);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
KPluginInfo::List RunnerManager::listRunnerInfo(const QString &parentApp)
|
||||
{
|
||||
return PluginLoader::self()->listRunnerInfo(parentApp);
|
||||
}
|
||||
|
||||
void RunnerManager::setupMatchSession()
|
||||
{
|
||||
d->teardownRequested = false;
|
||||
|
||||
if (d->prepped) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->prepped = true;
|
||||
if (d->singleMode) {
|
||||
if (d->currentSingleRunner) {
|
||||
emit d->currentSingleRunner->prepare();
|
||||
d->singleRunnerPrepped = true;
|
||||
}
|
||||
} else {
|
||||
foreach (AbstractRunner *runner, d->runners) {
|
||||
#ifdef MEASURE_PREPTIME
|
||||
QTime t;
|
||||
t.start();
|
||||
#endif
|
||||
emit runner->prepare();
|
||||
#ifdef MEASURE_PREPTIME
|
||||
#ifndef NDEBUG
|
||||
// qDebug() << t.elapsed() << runner->name();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
d->allRunnersPrepped = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerManager::matchSessionComplete()
|
||||
{
|
||||
if (!d->prepped) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->teardownRequested = true;
|
||||
d->checkTearDown();
|
||||
}
|
||||
|
||||
void RunnerManager::launchQuery(const QString &term)
|
||||
{
|
||||
launchQuery(term, QString());
|
||||
}
|
||||
|
||||
void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &runnerName)
|
||||
{
|
||||
setupMatchSession();
|
||||
QString term = untrimmedTerm.trimmed();
|
||||
|
||||
setSingleModeRunnerId(runnerName);
|
||||
setSingleMode(d->currentSingleRunner);
|
||||
if (!runnerName.isEmpty() && !d->currentSingleRunner) {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (term.isEmpty()) {
|
||||
if (d->singleMode && d->currentSingleRunner->defaultSyntax()) {
|
||||
term = d->currentSingleRunner->defaultSyntax()->exampleQueries().first().remove(QRegExp(":q:"));
|
||||
} else {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->context.query() == term) {
|
||||
// we already are searching for this!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!d->singleMode && d->runners.isEmpty()) {
|
||||
d->loadRunners();
|
||||
}
|
||||
|
||||
reset();
|
||||
// qDebug() << "runners searching for" << term << "on" << runnerName;
|
||||
d->context.setQuery(term);
|
||||
|
||||
QHash<QString, AbstractRunner*> runable;
|
||||
|
||||
//if the name is not empty we will launch only the specified runner
|
||||
if (d->singleMode) {
|
||||
runable.insert(QString(), d->currentSingleRunner);
|
||||
d->context.setSingleRunnerQueryMode(true);
|
||||
} else {
|
||||
runable = d->runners;
|
||||
}
|
||||
|
||||
foreach (Plasma::AbstractRunner *r, runable) {
|
||||
if (r->isMatchingSuspended()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
d->startJob(r);
|
||||
}
|
||||
|
||||
// Start timer to unblock slow runners
|
||||
d->delayTimer.start(RunnerManagerPrivate::slowRunDelay);
|
||||
}
|
||||
|
||||
QString RunnerManager::query() const
|
||||
{
|
||||
return d->context.query();
|
||||
}
|
||||
|
||||
void RunnerManager::reset()
|
||||
{
|
||||
// If ThreadWeaver is idle, it is safe to clear previous jobs
|
||||
if (Queue::instance()->isIdle()) {
|
||||
d->oldSearchJobs.clear();
|
||||
} else {
|
||||
for (auto it = d->searchJobs.constBegin(); it != d->searchJobs.constEnd(); ++it) {
|
||||
Queue::instance()->dequeue((*it));
|
||||
}
|
||||
d->oldSearchJobs += d->searchJobs;
|
||||
}
|
||||
|
||||
d->searchJobs.clear();
|
||||
|
||||
if (d->deferredRun.isEnabled()) {
|
||||
//qDebug() << "job actually done, running now **************";
|
||||
QueryMatch tmpRun = d->deferredRun;
|
||||
d->deferredRun = QueryMatch(0);
|
||||
tmpRun.run(d->context);
|
||||
}
|
||||
|
||||
d->context.reset();
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
#include "moc_runnermanager.cpp"
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright (C) 2007 Ryan P. Bitanga <ryan.bitanga@gmail.com>
|
||||
* Copyright (C) 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 PLASMA_RUNNERMANAGER_H
|
||||
#define PLASMA_RUNNERMANAGER_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include "abstractrunner.h"
|
||||
|
||||
class QAction;
|
||||
class KConfigGroup;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class QueryMatch;
|
||||
class AbstractRunner;
|
||||
class RunnerContext;
|
||||
class RunnerManagerPrivate;
|
||||
|
||||
/**
|
||||
* @class RunnerManager plasma/runnermanager.h <Plasma/RunnerManager>
|
||||
*
|
||||
* @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
|
||||
* @param pluginName the name of the runner plugin
|
||||
* @return Pointer to the runner
|
||||
*/
|
||||
AbstractRunner *runner(const QString &pluginName) const;
|
||||
|
||||
/**
|
||||
* @return the currently active "single mode" runner, or null if none
|
||||
* @since 4.4
|
||||
*/
|
||||
AbstractRunner *singleModeRunner() const;
|
||||
|
||||
/**
|
||||
* Puts the manager into "single runner" mode using the given
|
||||
* runner; if the runner does not exist or can not be loaded then
|
||||
* the single runner mode will not be started and singleModeRunner()
|
||||
* will return NULL
|
||||
* @param id the id of the runner to use
|
||||
* @since 4.4
|
||||
*/
|
||||
void setSingleModeRunnerId(const QString &id);
|
||||
|
||||
/**
|
||||
* @return the id of the runner to use in single mode
|
||||
* @since 4.4
|
||||
*/
|
||||
QString singleModeRunnerId() const;
|
||||
|
||||
/**
|
||||
* @return true if the manager is set to run in single runner mode
|
||||
* @since 4.4
|
||||
*/
|
||||
bool singleMode() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the manager is in single mode.
|
||||
*
|
||||
* @param singleMode true if the manager should be in single mode, false otherwise
|
||||
* @since 4.4
|
||||
*/
|
||||
void setSingleMode(bool singleMode);
|
||||
|
||||
/**
|
||||
* Returns the translated name of a runner
|
||||
* @param id the id of the runner
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
QString runnerName(const QString &id) const;
|
||||
|
||||
/**
|
||||
* @return the list of all currently loaded runners
|
||||
*/
|
||||
QList<AbstractRunner *> runners() const;
|
||||
|
||||
/**
|
||||
* @return the names of all runners that advertise single query mode
|
||||
* @since 4.4
|
||||
*/
|
||||
QStringList singleModeAdvertisedRunnerIds() const;
|
||||
|
||||
/**
|
||||
* Retrieves the current context
|
||||
* @return pointer to the current context
|
||||
*/
|
||||
RunnerContext *searchContext() const;
|
||||
|
||||
/**
|
||||
* Retrieves all available matches found so far for the previously launched query
|
||||
* @return List of matches
|
||||
*/
|
||||
QList<QueryMatch> matches() const;
|
||||
|
||||
/**
|
||||
* Runs a given match
|
||||
* @param match the match to be executed
|
||||
*/
|
||||
void run(const QueryMatch &match);
|
||||
|
||||
/**
|
||||
* Runs a given match
|
||||
* @param id the id of the match to run
|
||||
*/
|
||||
void run(const QString &id);
|
||||
|
||||
/**
|
||||
* Retrieves the list of actions, if any, for a match
|
||||
*/
|
||||
QList<QAction*> actionsForMatch(const QueryMatch &match);
|
||||
|
||||
/**
|
||||
* @return the current query term
|
||||
*/
|
||||
QString query() const;
|
||||
|
||||
/**
|
||||
* Causes a reload of the current configuration
|
||||
*/
|
||||
void reloadConfiguration();
|
||||
|
||||
/**
|
||||
* Sets a whitelist for the plugins that can be loaded
|
||||
*
|
||||
* @param plugins the plugin names of allowed runners
|
||||
* @since 4.4
|
||||
*/
|
||||
void setAllowedRunners(const QStringList &runners);
|
||||
|
||||
/**
|
||||
* Attempts to add the AbstractRunner plugin represented
|
||||
* by the KService passed in. Usually one can simply let
|
||||
* the configuration of plugins handle loading Runner plugins,
|
||||
* but in cases where specific runners should be loaded this
|
||||
* allows for that to take place
|
||||
*
|
||||
* @param service the service to use to load the plugin
|
||||
* @since 4.5
|
||||
*/
|
||||
void loadRunner(const KService::Ptr service);
|
||||
|
||||
/**
|
||||
* Attempts to add the AbstractRunner from a Plasma::Package on disk.
|
||||
* Usually one can simply let the configuration of plugins
|
||||
* handle loading Runner plugins, but in cases where specific
|
||||
* runners should be loaded this allows for that to take place
|
||||
*
|
||||
* @param path the path to a Runner package to load
|
||||
* @since 4.5
|
||||
*/
|
||||
void loadRunner(const QString &path);
|
||||
|
||||
/**
|
||||
* @return the list of allowed plugins
|
||||
* @since 4.4
|
||||
*/
|
||||
QStringList allowedRunners() const;
|
||||
|
||||
/**
|
||||
* @return mime data of the specified match
|
||||
* @since 4.5
|
||||
*/
|
||||
QMimeData * mimeDataForMatch(const QueryMatch &match) const;
|
||||
|
||||
/**
|
||||
* @return mime data of the specified match
|
||||
* @since 4.5
|
||||
*/
|
||||
QMimeData * mimeDataForMatch(const QString &matchId) const;
|
||||
|
||||
/**
|
||||
* Returns a list of all known Runner implementations
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of AbstractRunners
|
||||
* @since 4.6
|
||||
**/
|
||||
static KPluginInfo::List listRunnerInfo(const QString &parentApp = QString());
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Call this method when the runners should be prepared for a query session.
|
||||
* Call matchSessionComplete when the query session is finished for the time
|
||||
* being.
|
||||
* @since 4.4
|
||||
* @see matchSessionComplete
|
||||
*/
|
||||
void setupMatchSession();
|
||||
|
||||
/**
|
||||
* Call this method when the query session is finished for the time
|
||||
* being.
|
||||
* @since 4.4
|
||||
* @see prepareForMatchSession
|
||||
*/
|
||||
void matchSessionComplete();
|
||||
|
||||
/**
|
||||
* Launch a query, this will create threads and return inmediately.
|
||||
* When the information will be available can be known using the
|
||||
* matchesChanged signal.
|
||||
*
|
||||
* @param term the term we want to find matches for
|
||||
* @param runnerId optional, if only one specific runner is to be used;
|
||||
* providing an id will put the manager into single runner mode
|
||||
*/
|
||||
void launchQuery(const QString &term, const QString &runnerId);
|
||||
|
||||
/**
|
||||
* Convenience version of above
|
||||
*/
|
||||
void launchQuery(const QString &term);
|
||||
|
||||
/**
|
||||
* Reset the current data and stops the query
|
||||
*/
|
||||
void reset();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted each time a new match is added to the list
|
||||
*/
|
||||
void matchesChanged(const QList<Plasma::QueryMatch> &matches);
|
||||
|
||||
/**
|
||||
* Emitted when the launchQuery finish
|
||||
* @since 4.5
|
||||
*/
|
||||
void queryFinished();
|
||||
|
||||
private:
|
||||
Q_PRIVATE_SLOT(d, void scheduleMatchesChanged())
|
||||
Q_PRIVATE_SLOT(d, void matchesChanged())
|
||||
Q_PRIVATE_SLOT(d, void jobDone(ThreadWeaver::JobPointer))
|
||||
Q_PRIVATE_SLOT(d, void unblockJobs())
|
||||
Q_PRIVATE_SLOT(d, void runnerMatchingSuspended(bool))
|
||||
|
||||
RunnerManagerPrivate * const d;
|
||||
|
||||
friend class RunnerManagerPrivate;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 "runnersyntax.h"
|
||||
|
||||
#include <klocalizedstring.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class RunnerSyntaxPrivate
|
||||
{
|
||||
public:
|
||||
RunnerSyntaxPrivate(const QString &s, const QString &d)
|
||||
: description(d)
|
||||
{
|
||||
exampleQueries.append(s);
|
||||
}
|
||||
|
||||
QStringList exampleQueries;
|
||||
QString description;
|
||||
QString termDescription;
|
||||
};
|
||||
|
||||
RunnerSyntax::RunnerSyntax(const QString &exampleQuery, const QString &description)
|
||||
: d(new RunnerSyntaxPrivate(exampleQuery, description))
|
||||
{
|
||||
}
|
||||
|
||||
RunnerSyntax::RunnerSyntax(const RunnerSyntax &other)
|
||||
: d(new RunnerSyntaxPrivate(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
RunnerSyntax::~RunnerSyntax()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
RunnerSyntax &RunnerSyntax::operator=(const RunnerSyntax &rhs)
|
||||
{
|
||||
*d = *rhs.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void RunnerSyntax::addExampleQuery(const QString &exampleQuery)
|
||||
{
|
||||
d->exampleQueries.append(exampleQuery);
|
||||
}
|
||||
|
||||
QStringList RunnerSyntax::exampleQueries() const
|
||||
{
|
||||
return d->exampleQueries;
|
||||
}
|
||||
|
||||
QStringList RunnerSyntax::exampleQueriesWithTermDescription() const
|
||||
{
|
||||
QStringList queries;
|
||||
const QString termDesc('<' + searchTermDescription() + '>');
|
||||
foreach (QString query, d->exampleQueries) {
|
||||
queries << query.replace(":q:", termDesc);
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
void RunnerSyntax::setDescription(const QString &description)
|
||||
{
|
||||
d->description = description;
|
||||
}
|
||||
|
||||
QString RunnerSyntax::description() const
|
||||
{
|
||||
QString description = d->description;
|
||||
description.replace(":q:", '<' + searchTermDescription() + '>');
|
||||
return description;
|
||||
}
|
||||
|
||||
void RunnerSyntax::setSearchTermDescription(const QString &description)
|
||||
{
|
||||
d->termDescription = description;
|
||||
}
|
||||
|
||||
QString RunnerSyntax::searchTermDescription() const
|
||||
{
|
||||
if (d->termDescription.isEmpty()) {
|
||||
return i18n("search term");
|
||||
}
|
||||
|
||||
return d->termDescription;
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 PLASMA_RUNNERSYNTAX_H
|
||||
#define PLASMA_RUNNERSYNTAX_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class RunnerSyntaxPrivate;
|
||||
/**
|
||||
* @class RunnerSyntax
|
||||
* @since 4.3
|
||||
*
|
||||
* Represents a query prototype that the runner accepts. These can be
|
||||
* created and registered with AbstractRunner::addSyntax(Syntax &) to
|
||||
* allow applications to show to the user what the runner is currently
|
||||
* capable of doing
|
||||
*/
|
||||
class PLASMA_EXPORT RunnerSyntax
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a simple syntax object
|
||||
*
|
||||
* @param exampleQuery an example of the query, with :q: placed wherever
|
||||
* search term text might appear. e.g. if the runner
|
||||
* accepts "keyword some random text" then the value
|
||||
* of this parameter should be "keyword :q:"
|
||||
* @param descrition A description of what the described syntax does from
|
||||
* the user's point of view.
|
||||
*/
|
||||
RunnerSyntax(const QString &exampleQuery, const QString &description);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
RunnerSyntax(const RunnerSyntax &other);
|
||||
|
||||
~RunnerSyntax();
|
||||
|
||||
/**
|
||||
* Assignment operator
|
||||
*/
|
||||
RunnerSyntax &operator=(const RunnerSyntax &rhs);
|
||||
|
||||
/**
|
||||
* Adds a synonymous example query to this Syntax. Some runners may
|
||||
* accept multiple formulations of keywords to trigger the same behaviour.
|
||||
* This allows the runner to show these relationships by grouping the
|
||||
* example queries into one Syntax object
|
||||
*
|
||||
* @param exampleQuery an example of the query, with :q: placed wherever
|
||||
* search term text might appear. e.g. if the runner
|
||||
* accepts "keyword some random text" then the value
|
||||
* of this parameter should be "keyword :q:"
|
||||
*/
|
||||
void addExampleQuery(const QString &exampleQuery);
|
||||
|
||||
/**
|
||||
* @return the example queries associated with this Syntax object
|
||||
*/
|
||||
QStringList exampleQueries() const;
|
||||
|
||||
/**
|
||||
* @return the example queries associated with this Syntax object, with
|
||||
* the searchTermDescription replacing instances of :q:. Used for showing
|
||||
* the queries in the user interface.
|
||||
*/
|
||||
QStringList exampleQueriesWithTermDescription() const;
|
||||
|
||||
/**
|
||||
* Sets the description for the syntax, describing what it does from
|
||||
* the user's point of view.
|
||||
*/
|
||||
void setDescription(const QString &description);
|
||||
|
||||
/**
|
||||
* @return the description of what the syntax does from the user's
|
||||
* point of view
|
||||
*/
|
||||
QString description() const;
|
||||
|
||||
/**
|
||||
* Sets the text that should be used to replace instances of :q:
|
||||
* in the text. By default this is the generic phrase "search term".
|
||||
* If the syntax expects a specific kind of input, it may be defined
|
||||
* here. A syntax used by a runner that changes the brightness of the display
|
||||
* may set this to "brightness" for instance.
|
||||
*/
|
||||
void setSearchTermDescription(const QString &description);
|
||||
|
||||
/**
|
||||
* @return a description of the search term for this syntax
|
||||
*/
|
||||
QString searchTermDescription() const;
|
||||
|
||||
private:
|
||||
RunnerSyntaxPrivate *const d;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // multiple inclusion guard
|
||||
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 "scripting/runnerscript.h"
|
||||
|
||||
#include "abstractrunner.h"
|
||||
#include "package.h"
|
||||
#include "private/dataenginemanager_p.h"
|
||||
#include "private/abstractrunner_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class RunnerScriptPrivate
|
||||
{
|
||||
public:
|
||||
RunnerScriptPrivate()
|
||||
: runner(0)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractRunner *runner;
|
||||
};
|
||||
|
||||
RunnerScript::RunnerScript(QObject *parent)
|
||||
: ScriptEngine(parent),
|
||||
d(new RunnerScriptPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
RunnerScript::~RunnerScript()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void RunnerScript::setRunner(AbstractRunner *runner)
|
||||
{
|
||||
d->runner = runner;
|
||||
connect(runner, SIGNAL(prepare()), this, SIGNAL(prepare()));
|
||||
connect(runner, SIGNAL(teardown()), this, SIGNAL(teardown()));
|
||||
}
|
||||
|
||||
AbstractRunner *RunnerScript::runner() const
|
||||
{
|
||||
return d->runner;
|
||||
}
|
||||
|
||||
void RunnerScript::match(Plasma::RunnerContext &search)
|
||||
{
|
||||
Q_UNUSED(search);
|
||||
}
|
||||
|
||||
void RunnerScript::run(const Plasma::RunnerContext &search, const Plasma::QueryMatch &action)
|
||||
{
|
||||
Q_UNUSED(search);
|
||||
Q_UNUSED(action);
|
||||
}
|
||||
|
||||
DataEngine *RunnerScript::dataEngine(const QString &name)
|
||||
{
|
||||
if (d->runner) {
|
||||
return d->runner->dataEngine(name);
|
||||
}
|
||||
|
||||
return DataEngineManager::self()->engine(QString());
|
||||
}
|
||||
|
||||
KConfigGroup RunnerScript::config() const
|
||||
{
|
||||
if (d->runner) {
|
||||
return d->runner->config();
|
||||
}
|
||||
return KConfigGroup();
|
||||
}
|
||||
|
||||
void RunnerScript::setIgnoredTypes(RunnerContext::Types types)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->setIgnoredTypes(types);
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::setHasRunOptions(bool hasRunOptions)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->setHasRunOptions(hasRunOptions);
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::setSpeed(AbstractRunner::Speed newSpeed)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->setSpeed(newSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::setPriority(AbstractRunner::Priority newPriority)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->setPriority(newPriority);
|
||||
}
|
||||
}
|
||||
|
||||
QAction* RunnerScript::addAction(const QString &id, const QIcon &icon, const QString &text)
|
||||
{
|
||||
if (d->runner) {
|
||||
return d->runner->addAction(id, icon, text);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RunnerScript::addAction(const QString &id, QAction *action)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->addAction(id, action);
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::removeAction(const QString &id)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->removeAction(id);
|
||||
}
|
||||
}
|
||||
|
||||
QAction* RunnerScript::action(const QString &id) const
|
||||
{
|
||||
if (d->runner) {
|
||||
return d->runner->action(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QHash<QString, QAction*> RunnerScript::actions() const
|
||||
{
|
||||
if (d->runner) {
|
||||
return d->runner->actions();
|
||||
}
|
||||
return QHash<QString, QAction*>();
|
||||
}
|
||||
|
||||
void RunnerScript::clearActions()
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->clearActions();
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::addSyntax(const RunnerSyntax &syntax)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->addSyntax(syntax);
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerScript::setSyntaxes(const QList<RunnerSyntax> &syns)
|
||||
{
|
||||
if (d->runner) {
|
||||
d->runner->setSyntaxes(syns);
|
||||
}
|
||||
}
|
||||
|
||||
Package RunnerScript::package() const
|
||||
{
|
||||
return d->runner ? d->runner->package() : Package();
|
||||
}
|
||||
|
||||
KPluginInfo RunnerScript::description() const
|
||||
{
|
||||
return d->runner ? d->runner->d->runnerDescription : KPluginInfo();
|
||||
}
|
||||
|
||||
QString RunnerScript::mainScript() const
|
||||
{
|
||||
return package().filePath("mainscript");
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 PLASMA_RUNNERSCRIPT_H
|
||||
#define PLASMA_RUNNERSCRIPT_H
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/abstractrunner.h>
|
||||
#include <plasma/scripting/scriptengine.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class RunnerScriptPrivate;
|
||||
|
||||
/**
|
||||
* @class RunnerScript plasma/scripting/runnerscript.h <Plasma/Scripting/RunnerScript>
|
||||
*
|
||||
* @short Provides a restricted interface for scripting a runner.
|
||||
*/
|
||||
class PLASMA_EXPORT RunnerScript : public ScriptEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor for a RunnerScript.
|
||||
* Subclasses should not attempt to access the Plasma::AbstractRunner
|
||||
* associated with this RunnerScript in the constructor. All
|
||||
* such set up that requires the AbstractRunner itself should be done
|
||||
* in the init() method.
|
||||
*/
|
||||
explicit RunnerScript(QObject *parent = 0);
|
||||
~RunnerScript();
|
||||
|
||||
/**
|
||||
* Sets the Plasma::AbstractRunner associated with this RunnerScript
|
||||
*/
|
||||
void setRunner(AbstractRunner *runner);
|
||||
|
||||
/**
|
||||
* Returns the Plasma::AbstractRunner associated with this script component
|
||||
*/
|
||||
AbstractRunner *runner() const;
|
||||
|
||||
/**
|
||||
* Called when the script should create QueryMatch instances through
|
||||
* RunnerContext::addInformationalMatch, RunnerContext::addExactMatch, and
|
||||
* RunnerContext::addPossibleMatch.
|
||||
*/
|
||||
virtual void match(Plasma::RunnerContext &search);
|
||||
|
||||
/**
|
||||
* Called whenever an exact or possible match associated with this
|
||||
* runner is triggered.
|
||||
*/
|
||||
virtual void run(const Plasma::RunnerContext &search, const Plasma::QueryMatch &action);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
void prepare();
|
||||
void teardown();
|
||||
void createRunOptions(QWidget *widget);
|
||||
void reloadConfiguration();
|
||||
void actionsForMatch(const Plasma::QueryMatch &match, QList<QAction*>* actions);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @return absolute path to the main script file for this plasmoid
|
||||
*/
|
||||
QString mainScript() const;
|
||||
|
||||
/**
|
||||
* @return the Package associated with this plasmoid which can
|
||||
* be used to request resources, such as images and
|
||||
* interface files.
|
||||
*/
|
||||
Package package() const;
|
||||
|
||||
/**
|
||||
* @return the KPluginInfo associated with this plasmoid
|
||||
*/
|
||||
KPluginInfo description() const;
|
||||
|
||||
/**
|
||||
* @return a Plasma::DataEngine matchin name
|
||||
* @since 4.4
|
||||
*/
|
||||
DataEngine *dataEngine(const QString &name);
|
||||
|
||||
KConfigGroup config() const;
|
||||
void setIgnoredTypes(RunnerContext::Types types);
|
||||
void setHasRunOptions(bool hasRunOptions);
|
||||
void setSpeed(AbstractRunner::Speed newSpeed);
|
||||
void setPriority(AbstractRunner::Priority newPriority);
|
||||
QAction* addAction(const QString &id, const QIcon &icon, const QString &text);
|
||||
void addAction(const QString &id, QAction *action);
|
||||
void removeAction(const QString &id);
|
||||
QAction* action(const QString &id) const;
|
||||
QHash<QString, QAction*> actions() const;
|
||||
void clearActions();
|
||||
void addSyntax(const RunnerSyntax &syntax);
|
||||
void setSyntaxes(const QList<RunnerSyntax> &syns);
|
||||
|
||||
private:
|
||||
friend class AbstractRunner;
|
||||
|
||||
RunnerScriptPrivate *const d;
|
||||
};
|
||||
|
||||
#define K_EXPORT_PLASMA_RUNNERSCRIPTENGINE(libname, classname) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();)
|
||||
|
||||
} //Plasma namespace
|
||||
|
||||
#endif
|
@ -23,14 +23,12 @@
|
||||
#include <kservice.h>
|
||||
#include <kservicetypetrader.h>
|
||||
|
||||
#include "abstractrunner.h"
|
||||
#include "applet.h"
|
||||
#include "dataengine.h"
|
||||
#include "package.h"
|
||||
#include "private/componentinstaller_p.h"
|
||||
#include "scripting/appletscript.h"
|
||||
#include "scripting/dataenginescript.h"
|
||||
#include "scripting/runnerscript.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
@ -218,17 +216,6 @@ DataEngineScript *loadScriptEngine(const QString &language, DataEngine *dataEngi
|
||||
return engine;
|
||||
}
|
||||
|
||||
RunnerScript *loadScriptEngine(const QString &language, AbstractRunner *runner)
|
||||
{
|
||||
RunnerScript *engine = static_cast<RunnerScript*>(loadEngine(language, Types::RunnerComponent, runner));
|
||||
|
||||
if (engine) {
|
||||
//engine->setRunner(runner);
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include "moc_scriptengine.cpp"
|
||||
|
@ -106,16 +106,6 @@ PLASMA_EXPORT AppletScript *loadScriptEngine(const QString &language, Applet *ap
|
||||
**/
|
||||
PLASMA_EXPORT DataEngineScript *loadScriptEngine(const QString &language, DataEngine *dataEngine);
|
||||
|
||||
/**
|
||||
* Loads an Applet script engine for the given language.
|
||||
*
|
||||
* @param language the language to load for
|
||||
* @param runner the Plasma::AbstractRunner for this script
|
||||
* @return pointer to the RunnerScript or 0 on failure; the caller is responsible
|
||||
* for the return object which will be parented to the AbstractRunner
|
||||
**/
|
||||
PLASMA_EXPORT RunnerScript *loadScriptEngine(const QString &language, AbstractRunner *runner);
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
@ -40,7 +40,7 @@ unsigned int versionMinor()
|
||||
|
||||
unsigned int versionRelease()
|
||||
{
|
||||
return PLASMA_VERSION_RELEASE;
|
||||
return PLASMA_VERSION_PATCH;
|
||||
}
|
||||
|
||||
const char *versionString()
|
||||
|
@ -17,34 +17,16 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_VERSION_H
|
||||
#define PLASMA_VERSION_H
|
||||
#ifndef PLASMAVERSION_H
|
||||
#define PLASMAVERSION_H
|
||||
|
||||
/** @file plasma/version.h <Plasma/Version> */
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
/**
|
||||
* String version of libplasma version, suitable for use in
|
||||
* file formats or network protocols
|
||||
*/
|
||||
#define PLASMA_VERSION_STRING "3.80.0"
|
||||
|
||||
/// @brief Major version of libplasma, at compile time
|
||||
#define PLASMA_VERSION_MAJOR 3
|
||||
/// @brief Minor version of libplasma, at compile time
|
||||
#define PLASMA_VERSION_MINOR 80
|
||||
/// @brief Release version of libplasma, at compile time
|
||||
#define PLASMA_VERSION_RELEASE 0
|
||||
#include <plasma_version.h>
|
||||
|
||||
#define PLASMA_MAKE_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c))
|
||||
|
||||
/**
|
||||
* Compile time macro for the version number of libplasma
|
||||
*/
|
||||
#define PLASMA_VERSION \
|
||||
PLASMA_MAKE_VERSION(PLASMA_VERSION_MAJOR, PLASMA_VERSION_MINOR, PLASMA_VERSION_RELEASE)
|
||||
|
||||
/**
|
||||
* Compile-time macro for checking the plasma version. Not useful for
|
||||
* detecting the version of libplasma at runtime.
|
||||
|
@ -5,7 +5,6 @@ include(PythonMacros)
|
||||
# install the library, .desktop, and plasma.py
|
||||
python_install(plasma_importer.py ${DATA_INSTALL_DIR}/plasma_scriptengine_python)
|
||||
python_install(pydataengine.py ${DATA_INSTALL_DIR}/plasma_scriptengine_python)
|
||||
python_install(pyrunner.py ${DATA_INSTALL_DIR}/plasma_scriptengine_python)
|
||||
|
||||
# remove the following three lines once we branch 4.5, they are only necessary as long
|
||||
# as people update kdebase but not yet kdelibs (PYTHON_SITE_PACKAGES_INSTALL_DIR has just
|
||||
@ -18,6 +17,4 @@ python_install(plasmascript.py ${PYTHON_SITE_PACKAGES_INSTALL_DIR}/PyKDE4)
|
||||
|
||||
install(FILES plasma-scriptengine-dataengine-python.desktop
|
||||
DESTINATION ${SERVICES_INSTALL_DIR})
|
||||
install(FILES plasma-scriptengine-runner-python.desktop
|
||||
DESTINATION ${SERVICES_INSTALL_DIR})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user