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
158 RunnerContextPrivate(RunnerContext *context)
160 type(RunnerContext::UnknownType),
162 singleRunnerQueryMode(false)
166 RunnerContextPrivate(
const RunnerContextPrivate &p)
168 launchCounts(p.launchCounts),
169 type(RunnerContext::None),
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;
260 static RunnerContext s_dummyContext;
261 bool singleRunnerQueryMode;
264 RunnerContext RunnerContextPrivate::s_dummyContext;
268 d(new RunnerContextPrivate(this))
287 if (this->d == other.d) {
291 QExplicitlySharedDataPointer<Plasma::RunnerContextPrivate> oldD = d;
319 if (!d->matches.isEmpty()) {
320 d->matchesById.clear();
328 d->singleRunnerQueryMode =
false;
336 if (term.isEmpty()) {
365 return (d->q != &(d->s_dummyContext));
372 if (matches.isEmpty() || !
isValid()) {
381 if (
int count = d->launchCounts.value(match.
id())) {
385 d->matches.append(match);
387 if (d->matchesById.contains(match.
id())) {
388 kDebug() <<
"Duplicate match id " << match.
id() <<
"from" << match.
runner()->
name();
391 d->matchesById.insert(match.
id(), &d->matches.at(d->matches.size() - 1));
398 emit d->q->matchesChanged();
416 if (
int count = d->launchCounts.value(m.
id())) {
420 d->matches.append(m);
421 d->matchesById.insert(m.
id(), &d->matches.at(d->matches.size() - 1));
424 emit d->q->matchesChanged();
435 QStringList presentMatchIdList;
436 QList<const QueryMatch*> presentMatchList;
439 foreach(
const QString &matchId, matchIdList) {
442 presentMatchList <<
match;
443 presentMatchIdList << matchId;
448 if (presentMatchIdList.isEmpty()) {
454 d->matches.removeAll(*match);
456 foreach(
const QString &matchId, presentMatchIdList) {
457 d->matchesById.remove(matchId);
461 emit d->q->matchesChanged();
478 d->matches.removeAll(*match);
479 d->matchesById.remove(matchId);
481 emit d->q->matchesChanged();
492 QList<QueryMatch> presentMatchList;
496 if (match.
runner() == runner) {
497 presentMatchList <<
match;
502 if (presentMatchList.isEmpty()) {
507 foreach (
const QueryMatch &match, presentMatchList) {
508 d->matchesById.remove(match.
id());
509 d->matches.removeAll(match);
513 emit d->q->matchesChanged();
520 QList<QueryMatch>
matches = d->matches;
540 d->singleRunnerQueryMode = enabled;
545 return d->singleRunnerQueryMode;
550 const QStringList cfgList = config.readEntry(
"LaunchCounts", QStringList());
552 const QRegExp r(
"(\\d*) (.*)");
553 foreach (
const QString& entry, cfgList) {
555 int count = r.cap(1).toInt();
556 QString
id = r.cap(2);
557 d->launchCounts[id] = count;
563 QStringList countList;
565 typedef QHash<QString, int>::const_iterator Iterator;
566 Iterator end = d->launchCounts.constEnd();
567 for (Iterator i = d->launchCounts.constBegin(); i != end; ++i) {
568 countList << QString(
"%2 %1").arg(i.key()).arg(i.value());
571 config.writeEntry(
"LaunchCounts", countList);
577 ++d->launchCounts[match.
id()];
583 #include "runnercontext.moc"