24 #include <QReadWriteLock> 29 #include <QSharedData> 31 #include <kcompletion.h> 32 #include <kconfiggroup.h> 34 #include <kmimetype.h> 36 #include <kstandarddirs.h> 38 #include <kprotocolinfo.h> 47 #define LOCK_FOR_READ(d) d->lock.lockForRead(); 48 #define LOCK_FOR_WRITE(d) d->lock.lockForWrite(); 49 #define UNLOCK(d) d->lock.unlock(); 66 if (QFile::exists(path)) {
67 correctCasePath = path;
72 const QFileInfo pathInfo(path);
74 const QDir fileDir = pathInfo.dir();
77 const QString filename = pathInfo.fileName();
82 const QStringList matchingFilenames = fileDir.entryList(QStringList(filename),
83 mustBeDir ? QDir::Dirs : QDir::NoFilter);
85 if (matchingFilenames.empty()) {
93 if (fileDir.path().endsWith(QDir::separator())) {
94 correctCasePath = fileDir.path() + matchingFilenames[0];
96 correctCasePath = fileDir.path() + QDir::separator() + matchingFilenames[0];
113 if (QFile::exists(path)) {
119 QStringList components = QString(path).split(QDir::separator());
121 if (components.size() < 1) {
125 const bool mustBeDir = components.back().isEmpty();
130 components.pop_back();
133 if (components.isEmpty()) {
138 const unsigned initialComponents = components.size();
139 for (
unsigned i = 0; i < initialComponents - 1; i ++) {
140 const QString tmp = components[0] + QDir::separator() + components[1];
147 components.removeFirst();
148 components[0] = correctPath;
151 corrected = correctPath;
155 class RunnerContextPrivate :
public QSharedData
162 singleRunnerQueryMode(
false)
166 RunnerContextPrivate(
const RunnerContextPrivate &p)
168 launchCounts(p.launchCounts),
171 singleRunnerQueryMode(
false)
176 ~RunnerContextPrivate()
190 QString path = QDir::cleanPath(KShell::tildeExpand(term));
192 int space = path.indexOf(
' ');
193 if (!KStandardDirs::findExe(path.left(space)).isEmpty()) {
203 const bool hasProtocol = !url.protocol().isEmpty();
204 const bool isLocalProtocol = KProtocolInfo::protocolClass(url.protocol()) ==
":local";
206 ((!isLocalProtocol && url.hasHost()) ||
207 (isLocalProtocol && url.protocol() !=
"file"))) {
211 }
else if (isLocalProtocol) {
215 path = QDir::cleanPath(url.toLocalFile());
217 if (hasProtocol || ((path.indexOf(
'/') != -1 || path.indexOf(
'\\') != -1))) {
218 QString correctCasePath;
220 path = correctCasePath;
221 QFileInfo info(path);
225 if (info.isSymLink()) {
226 path = info.canonicalFilePath();
227 info = QFileInfo(path);
231 mimeType =
"inode/folder";
232 }
else if (info.isFile()) {
234 KMimeType::Ptr mimeTypePtr = KMimeType::findByPath(path);
236 mimeType = mimeTypePtr->name();
253 QList<QueryMatch> matches;
254 QMap<QString, const QueryMatch*> matchesById;
255 QHash<QString, int> launchCounts;
261 bool singleRunnerQueryMode;
268 d(new RunnerContextPrivate(this))
287 if (this->d == other.d) {
291 QExplicitlySharedDataPointer<Plasma::RunnerContextPrivate> oldD = d;
321 if (!d->matches.isEmpty()) {
322 d->matchesById.clear();
330 d->singleRunnerQueryMode =
false;
338 if (term.isEmpty()) {
368 const bool valid = (d->q != &(d->s_dummyContext));
377 if (matches.isEmpty() || !
isValid()) {
386 if (
int count = d->launchCounts.value(match.
id())) {
390 d->matches.append(match);
392 if (d->matchesById.contains(match.
id())) {
393 kDebug() <<
"Duplicate match id " << match.
id() <<
"from" << match.
runner()->
name();
396 d->matchesById.insert(match.
id(), &d->matches.at(d->matches.size() - 1));
403 emit d->q->matchesChanged();
421 if (
int count = d->launchCounts.value(m.
id())) {
425 d->matches.append(m);
426 d->matchesById.insert(m.
id(), &d->matches.at(d->matches.size() - 1));
429 emit d->q->matchesChanged();
440 QStringList presentMatchIdList;
441 QList<const QueryMatch*> presentMatchList;
444 foreach(
const QString &matchId, matchIdList) {
447 presentMatchList <<
match;
448 presentMatchIdList << matchId;
453 if (presentMatchIdList.isEmpty()) {
459 d->matches.removeAll(*match);
461 foreach(
const QString &matchId, presentMatchIdList) {
462 d->matchesById.remove(matchId);
466 emit d->q->matchesChanged();
483 d->matches.removeAll(*match);
484 d->matchesById.remove(matchId);
486 emit d->q->matchesChanged();
497 QList<QueryMatch> presentMatchList;
501 if (match.
runner() == runner) {
502 presentMatchList <<
match;
507 if (presentMatchList.isEmpty()) {
512 foreach (
const QueryMatch &match, presentMatchList) {
513 d->matchesById.remove(match.
id());
514 d->matches.removeAll(match);
518 emit d->q->matchesChanged();
525 QList<QueryMatch>
matches = d->matches;
545 d->singleRunnerQueryMode = enabled;
550 return d->singleRunnerQueryMode;
555 const QStringList cfgList = config.readEntry(
"LaunchCounts", QStringList());
557 const QRegExp r(
"(\\d*) (.*)");
558 foreach (
const QString& entry, cfgList) {
560 int count = r.cap(1).toInt();
561 QString
id = r.cap(2);
562 d->launchCounts[id] = count;
568 QStringList countList;
570 typedef QHash<QString, int>::const_iterator Iterator;
571 Iterator end = d->launchCounts.constEnd();
572 for (Iterator i = d->launchCounts.constBegin(); i != end; ++i) {
573 countList << QString(
"%2 %1").arg(i.key()).arg(i.value());
576 config.writeEntry(
"LaunchCounts", countList);
582 ++d->launchCounts[match.
id()];
588 #include "runnercontext.moc"
Type type() const
The type of item the search term might refer to.
QList< QueryMatch > matches() const
Retrieves all available matches for the current search term.
void save(KConfigGroup &config)
An abstract base class for Plasma Runner plugins.
RunnerContext(QObject *parent=0)
void setSingleRunnerQueryMode(bool enabled)
Sets single runner query mode.
QString mimeType() const
The mimetype that the search term refers to, if discoverable.
Namespace for everything in libplasma.
qreal relevance() const
The relevance of this action to the search.
void run(const RunnerContext &context) const
Requests this match to activae using the given context.
RunnerContext & operator=(const RunnerContext &other)
Assignment operator.
bool removeMatches(const QStringList matchIdList)
Removes lists of matches from the existing list of matches.
QueryMatch match(const QString &id) const
Retrieves a match by id.
bool addMatch(const QString &term, const QueryMatch &match)
Appends a match to the existing list of matches.
void restore(const KConfigGroup &config)
Sets the launch counts for the associated match ids.
The RunnerContext class provides information related to a search, including the search term...
#define LOCK_FOR_WRITE(d)
AbstractRunner * runner() const
void run(const QueryMatch &match)
Run a match using the information from this context.
void reset()
Resets the search term for this object.
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
A match returned by an AbstractRunner in response to a given RunnerContext.
void setQuery(const QString &term)
Sets the query term for this object and attempts to determine the type of the search.
bool correctPathCase(const QString &path, QString &corrected)
bool addMatches(const QString &term, const QList< QueryMatch > &matches)
Appends lists of matches to the list of matches.
bool singleRunnerQueryMode() const
bool correctLastComponentCase(const QString &path, QString &correctCasePath, const bool mustBeDir)
void setRelevance(qreal relevance)
Sets the relevance of this action for the search it was created for.
bool removeMatch(const QString matchId)
Removes a match from the existing list of matches.
QString id() const
a string that can be used as an ID for this match, even between different queries.