Remove KRunner from Plasma-Framework

Have it as a separate KRunner framework instead
This commit is contained in:
Aleix Pol 2014-02-11 17:40:09 +01:00
parent dbbb1ed513
commit 18473c9e9e
47 changed files with 6 additions and 5445 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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})

View File

@ -1,2 +0,0 @@
#! /usr/bin/env bash
$XGETTEXT *.cpp -o $podir/plasma_runner_example_homefiles.pot

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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");

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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();
}

View File

@ -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)

View File

@ -1,3 +0,0 @@
module org.kde.runnermodel
plugin runnermodelplugin

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +0,0 @@
#include "../../plasma/scripting/runnerscript.h"

View File

@ -33,7 +33,6 @@
#endif
#include "applet.h"
#include "abstractrunner.h"
#include "containment.h"
#include "containmentactions.h"
#include "dataengine.h"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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('.', "_");

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -40,7 +40,7 @@ unsigned int versionMinor()
unsigned int versionRelease()
{
return PLASMA_VERSION_RELEASE;
return PLASMA_VERSION_PATCH;
}
const char *versionString()

View File

@ -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.

View File

@ -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})