• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
kurlcompletion.cpp
Go to the documentation of this file.
1/* -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset:4 -*-
2
3 This file is part of the KDE libraries
4 Copyright (C) 2000 David Smith <dsmith@algonet.se>
5 Copyright (C) 2004 Scott Wheeler <wheeler@kde.org>
6
7 This class was inspired by a previous KUrlCompletion by
8 Henner Zeller <zeller@think.de>
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA.
24*/
25
26#include "kurlcompletion.h"
27
28#include <config.h>
29
30#include <stdlib.h>
31#include <assert.h>
32#include <limits.h>
33
34#include <QtCore/QCoreApplication>
35#include <QtCore/QMutableStringListIterator>
36#include <QtCore/QRegExp>
37#include <QtCore/QTimer>
38#include <QtCore/QDir>
39#include <QtCore/QDirIterator>
40#include <QtCore/QFile>
41#include <QtCore/QTextIStream>
42#include <QtCore/QThread>
43#include <QtGui/QActionEvent>
44
45#include <kauthorized.h>
46#include <kdebug.h>
47#include <kurl.h>
48#include <kio/job.h>
49#include <kprotocolmanager.h>
50#include <kconfig.h>
51#include <kglobal.h>
52#include <kglobalsettings.h>
53#include <kde_file.h>
54
55#include <sys/types.h>
56#include <dirent.h>
57#include <unistd.h>
58#include <sys/stat.h>
59#include <pwd.h>
60#include <time.h>
61#include <sys/param.h>
62#include <kconfiggroup.h>
63
64#ifdef Q_WS_WIN
65#include <kkernel_win.h>
66#endif
67
68static bool expandTilde(QString&);
69static bool expandEnv(QString&);
70
71static QString unescape(const QString& text);
72
73// Permission mask for files that are executable by
74// user, group or other
75#define MODE_EXE (S_IXUSR | S_IXGRP | S_IXOTH)
76
77// Constants for types of completion
78enum ComplType {CTNone = 0, CTEnv, CTUser, CTMan, CTExe, CTFile, CTUrl, CTInfo};
79
80class CompletionThread;
81
84// KUrlCompletionPrivate
85//
86class KUrlCompletionPrivate
87{
88public:
89 KUrlCompletionPrivate(KUrlCompletion* parent)
90 : q(parent),
91 url_auto_completion(true),
92 userListThread(0),
93 dirListThread(0) {
94 }
95
96 ~KUrlCompletionPrivate();
97
98 void _k_slotEntries(KIO::Job*, const KIO::UDSEntryList&);
99 void _k_slotIOFinished(KJob*);
100
101 class MyURL;
102 bool userCompletion(const MyURL& url, QString* match);
103 bool envCompletion(const MyURL& url, QString* match);
104 bool exeCompletion(const MyURL& url, QString* match);
105 bool fileCompletion(const MyURL& url, QString* match);
106 bool urlCompletion(const MyURL& url, QString* match);
107
108 bool isAutoCompletion();
109
110 // List the next dir in m_dirs
111 QString listDirectories(const QStringList&,
112 const QString&,
113 bool only_exe = false,
114 bool only_dir = false,
115 bool no_hidden = false,
116 bool stat_files = true);
117
118 void listUrls(const QList<KUrl> &urls,
119 const QString& filter = QString(),
120 bool only_exe = false,
121 bool no_hidden = false);
122
123 void addMatches(const QStringList&);
124 QString finished();
125
126 void init();
127
128 void setListedUrl(int compl_type /* enum ComplType */,
129 const QString& dir = QString(),
130 const QString& filter = QString(),
131 bool no_hidden = false);
132
133 bool isListedUrl(int compl_type /* enum ComplType */,
134 const QString& dir = QString(),
135 const QString& filter = QString(),
136 bool no_hidden = false);
137
138 KUrlCompletion* q;
139 QList<KUrl> list_urls;
140
141 bool onlyLocalProto;
142
143 // urlCompletion() in Auto/Popup mode?
144 bool url_auto_completion;
145
146 // Append '/' to directories in Popup mode?
147 // Doing that stat's all files and is slower
148 bool popup_append_slash;
149
150 // Keep track of currently listed files to avoid reading them again
151 QString last_path_listed;
152 QString last_file_listed;
153 QString last_prepend;
154 int last_compl_type;
155 int last_no_hidden;
156
157 QString cwd; // "current directory" = base dir for completion
158
159 KUrlCompletion::Mode mode; // ExeCompletion, FileCompletion, DirCompletion
160 bool replace_env;
161 bool replace_home;
162 bool complete_url; // if true completing a URL (i.e. 'prepend' is a URL), otherwise a path
163
164 KIO::ListJob* list_job; // kio job to list directories
165
166 QString prepend; // text to prepend to listed items
167 QString compl_text; // text to pass on to KCompletion
168
169 // Filters for files read with kio
170 bool list_urls_only_exe; // true = only list executables
171 bool list_urls_no_hidden;
172 QString list_urls_filter; // filter for listed files
173
174 CompletionThread* userListThread;
175 CompletionThread* dirListThread;
176};
177
183class CompletionMatchEvent : public QEvent
184{
185public:
186 CompletionMatchEvent(CompletionThread* thread) :
187 QEvent(uniqueType()),
188 m_completionThread(thread)
189 {}
190
191 CompletionThread* completionThread() const {
192 return m_completionThread;
193 }
194 static Type uniqueType() {
195 return Type(User + 61080);
196 }
197
198private:
199 CompletionThread* m_completionThread;
200};
201
202class CompletionThread : public QThread
203{
204protected:
205 CompletionThread(KUrlCompletionPrivate* receiver) :
206 QThread(),
207 m_prepend(receiver->prepend),
208 m_complete_url(receiver->complete_url),
209 m_receiver(receiver),
210 m_terminationRequested(false)
211 {}
212
213public:
214 void requestTermination() {
215 m_terminationRequested = true;
216 }
217 QStringList matches() const {
218 return m_matches;
219 }
220
221protected:
222 void addMatch(const QString& match) {
223 m_matches.append(match);
224 }
225 bool terminationRequested() const {
226 return m_terminationRequested;
227 }
228 void done() {
229 if (!m_terminationRequested)
230 qApp->postEvent(m_receiver->q, new CompletionMatchEvent(this));
231 else
232 deleteLater();
233 }
234
235 const QString m_prepend;
236 const bool m_complete_url; // if true completing a URL (i.e. 'm_prepend' is a URL), otherwise a path
237
238private:
239 KUrlCompletionPrivate* m_receiver;
240 QStringList m_matches;
241 bool m_terminationRequested;
242};
243
249class UserListThread : public CompletionThread
250{
251public:
252 UserListThread(KUrlCompletionPrivate* receiver) :
253 CompletionThread(receiver)
254 {}
255
256protected:
257 virtual void run() {
258 static const QChar tilde = '~';
259
260 // we don't need to handle prepend here, right? ~user is always at pos 0
261 assert(m_prepend.isEmpty());
262 struct passwd* pw;
263 while ((pw = ::getpwent()) && !terminationRequested())
264 addMatch(tilde + QString::fromLocal8Bit(pw->pw_name));
265
266 ::endpwent();
267
268 addMatch(QString(tilde));
269
270 done();
271 }
272};
273
274class DirectoryListThread : public CompletionThread
275{
276public:
277 DirectoryListThread(KUrlCompletionPrivate* receiver,
278 const QStringList& dirList,
279 const QString& filter,
280 bool onlyExe,
281 bool onlyDir,
282 bool noHidden,
283 bool appendSlashToDir) :
284 CompletionThread(receiver),
285 m_dirList(dirList),
286 m_filter(filter),
287 m_onlyExe(onlyExe),
288 m_onlyDir(onlyDir),
289 m_noHidden(noHidden),
290 m_appendSlashToDir(appendSlashToDir)
291 {}
292
293 virtual void run();
294
295private:
296 QStringList m_dirList;
297 QString m_filter;
298 bool m_onlyExe;
299 bool m_onlyDir;
300 bool m_noHidden;
301 bool m_appendSlashToDir;
302};
303
304void DirectoryListThread::run()
305{
306 // Thread safety notes:
307 //
308 // There very possibly may be thread safety issues here, but I've done a check
309 // of all of the things that would seem to be problematic. Here are a few
310 // things that I have checked to be safe here (some used indirectly):
311 //
312 // QDir::currentPath(), QDir::setCurrent(), QFile::decodeName(), QFile::encodeName()
313 // QString::fromLocal8Bit(), QString::toLocal8Bit(), QTextCodec::codecForLocale()
314 //
315 // Also see (for POSIX functions):
316 // http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html
317
318 // kDebug() << "Entered DirectoryListThread::run(), m_filter=" << m_filter << ", m_onlyExe=" << m_onlyExe << ", m_onlyDir=" << m_onlyDir << ", m_appendSlashToDir=" << m_appendSlashToDir << ", m_dirList.size()=" << m_dirList.size();
319
320 QStringList::ConstIterator end = m_dirList.constEnd();
321 for (QStringList::ConstIterator it = m_dirList.constBegin();
322 it != end && !terminationRequested();
323 ++it) {
324 // kDebug() << "Scanning directory" << *it;
325
326 // A trick from KIO that helps performance by a little bit:
327 // chdir to the directory so we won't have to deal with full paths
328 // with stat()
329
330 QString path = QDir::currentPath();
331 QDir::setCurrent(*it);
332
333 QDir::Filters iterator_filter = (m_noHidden ? QDir::Filter(0) : QDir::Hidden) | QDir::Readable | QDir::NoDotAndDotDot;
334
335 if (m_onlyExe)
336 iterator_filter |= (QDir::Dirs | QDir::Files | QDir::Executable);
337 else if (m_onlyDir)
338 iterator_filter |= QDir::Dirs;
339 else
340 iterator_filter |= (QDir::Dirs | QDir::Files);
341
342 QDirIterator current_dir_iterator(*it, iterator_filter);
343
344 while (current_dir_iterator.hasNext()) {
345 current_dir_iterator.next();
346
347 QFileInfo file_info = current_dir_iterator.fileInfo();
348 const QString file_name = file_info.fileName();
349
350 //kDebug() << "Found" << file_name;
351
352 if (m_filter.isEmpty() || file_name.startsWith(m_filter)) {
353
354 QString toAppend = file_name;
355 // Add '/' to directories
356 if (m_appendSlashToDir && file_info.isDir())
357 toAppend.append(QLatin1Char('/'));
358
359 if (m_complete_url) {
360 KUrl url(m_prepend);
361 url.addPath(toAppend);
362 addMatch(url.prettyUrl());
363 } else {
364 addMatch(m_prepend + toAppend);
365 }
366 }
367 }
368
369 // chdir to the original directory
370 QDir::setCurrent(path);
371 }
372
373 done();
374}
375
376KUrlCompletionPrivate::~KUrlCompletionPrivate()
377{
378 if (userListThread)
379 userListThread->requestTermination();
380 if (dirListThread)
381 dirListThread->requestTermination();
382}
383
386// MyURL - wrapper for KUrl with some different functionality
387//
388
389class KUrlCompletionPrivate::MyURL
390{
391public:
392 MyURL(const QString& url, const QString& cwd);
393 MyURL(const MyURL& url);
394 ~MyURL();
395
396 KUrl kurl() const {
397 return m_kurl;
398 }
399
400 QString protocol() const {
401 return m_kurl.protocol();
402 }
403 // The directory with a trailing '/'
404 QString dir() const {
405 return m_kurl.directory(KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash);
406 }
407 QString file() const {
408 return m_kurl.fileName(KUrl::ObeyTrailingSlash);
409 }
410
411 // The initial, unparsed, url, as a string.
412 QString url() const {
413 return m_url;
414 }
415
416 // Is the initial string a URL, or just a path (whether absolute or relative)
417 bool isURL() const {
418 return m_isURL;
419 }
420
421 void filter(bool replace_user_dir, bool replace_env);
422
423private:
424 void init(const QString& url, const QString& cwd);
425
426 KUrl m_kurl;
427 QString m_url;
428 bool m_isURL;
429};
430
431KUrlCompletionPrivate::MyURL::MyURL(const QString& _url, const QString& cwd)
432{
433 init(_url, cwd);
434}
435
436KUrlCompletionPrivate::MyURL::MyURL(const MyURL& _url)
437 : m_kurl(_url.m_kurl)
438{
439 m_url = _url.m_url;
440 m_isURL = _url.m_isURL;
441}
442
443void KUrlCompletionPrivate::MyURL::init(const QString& _url, const QString& cwd)
444{
445 // Save the original text
446 m_url = _url;
447
448 // Non-const copy
449 QString url_copy = _url;
450
451 // Special shortcuts for "man:" and "info:"
452 if (url_copy.startsWith(QLatin1Char('#'))) {
453 if (url_copy.length() > 1 && url_copy.at(1) == QLatin1Char('#'))
454 url_copy.replace(0, 2, QLatin1String("info:"));
455 else
456 url_copy.replace(0, 1, QLatin1String("man:"));
457 }
458
459 // Look for a protocol in 'url'
460 QRegExp protocol_regex = QRegExp("^(?![A-Za-z]:)[^/\\s\\\\]*:");
461
462 // Assume "file:" or whatever is given by 'cwd' if there is
463 // no protocol. (KUrl does this only for absolute paths)
464 if (protocol_regex.indexIn(url_copy) == 0) {
465 m_kurl = KUrl(url_copy);
466 m_isURL = true;
467 } else { // relative path or ~ or $something
468 m_isURL = false;
469 if (!QDir::isRelativePath(url_copy) ||
470 url_copy.startsWith(QLatin1Char('~')) ||
471 url_copy.startsWith(QLatin1Char('$'))) {
472 m_kurl = KUrl();
473 m_kurl.setPath(url_copy);
474 } else {
475 if (cwd.isEmpty()) {
476 m_kurl = KUrl(url_copy);
477 } else {
478 m_kurl = KUrl(cwd);
479 m_kurl.addPath(url_copy);
480 }
481 }
482 }
483}
484
485KUrlCompletionPrivate::MyURL::~MyURL()
486{
487}
488
489void KUrlCompletionPrivate::MyURL::filter(bool replace_user_dir, bool replace_env)
490{
491 QString d = dir() + file();
492 if (replace_user_dir) expandTilde(d);
493 if (replace_env) expandEnv(d);
494 m_kurl.setPath(d);
495}
496
499// KUrlCompletion
500//
501
502KUrlCompletion::KUrlCompletion() : KCompletion(), d(new KUrlCompletionPrivate(this))
503{
504 d->init();
505}
506
507
508KUrlCompletion::KUrlCompletion(Mode _mode)
509 : KCompletion(),
510 d(new KUrlCompletionPrivate(this))
511{
512 d->init();
513 setMode(_mode);
514}
515
516KUrlCompletion::~KUrlCompletion()
517{
518 stop();
519 delete d;
520}
521
522
523void KUrlCompletionPrivate::init()
524{
525 cwd = QDir::homePath();
526
527 replace_home = true;
528 replace_env = true;
529 last_no_hidden = false;
530 last_compl_type = 0;
531 list_job = 0L;
532 mode = KUrlCompletion::FileCompletion;
533
534 // Read settings
535 KConfigGroup cg(KGlobal::config(), "URLCompletion");
536
537 url_auto_completion = cg.readEntry("alwaysAutoComplete", true);
538 popup_append_slash = cg.readEntry("popupAppendSlash", true);
539 onlyLocalProto = cg.readEntry("LocalProtocolsOnly", false);
540
541 q->setIgnoreCase(true);
542}
543
544void KUrlCompletion::setDir(const QString& _dir)
545{
546 d->cwd = _dir;
547}
548
549QString KUrlCompletion::dir() const
550{
551 return d->cwd;
552}
553
554KUrlCompletion::Mode KUrlCompletion::mode() const
555{
556 return d->mode;
557}
558
559void KUrlCompletion::setMode(Mode _mode)
560{
561 d->mode = _mode;
562}
563
564bool KUrlCompletion::replaceEnv() const
565{
566 return d->replace_env;
567}
568
569void KUrlCompletion::setReplaceEnv(bool replace)
570{
571 d->replace_env = replace;
572}
573
574bool KUrlCompletion::replaceHome() const
575{
576 return d->replace_home;
577}
578
579void KUrlCompletion::setReplaceHome(bool replace)
580{
581 d->replace_home = replace;
582}
583
584/*
585 * makeCompletion()
586 *
587 * Entry point for file name completion
588 */
589QString KUrlCompletion::makeCompletion(const QString& text)
590{
591 //kDebug() << text << "d->cwd=" << d->cwd;
592
593 KUrlCompletionPrivate::MyURL url(text, d->cwd);
594
595 d->compl_text = text;
596
597 // Set d->prepend to the original URL, with the filename [and ref/query] stripped.
598 // This is what gets prepended to the directory-listing matches.
599 int toRemove = url.file().length() - url.kurl().query().length();
600 if (url.kurl().hasRef())
601 toRemove += url.kurl().ref().length() + 1;
602 d->prepend = text.left(text.length() - toRemove);
603 d->complete_url = url.isURL();
604
605 QString aMatch;
606
607 // Environment variables
608 //
609 if (d->replace_env && d->envCompletion(url, &aMatch))
610 return aMatch;
611
612 // User directories
613 //
614 if (d->replace_home && d->userCompletion(url, &aMatch))
615 return aMatch;
616
617 // Replace user directories and variables
618 url.filter(d->replace_home, d->replace_env);
619
620 //kDebug() << "Filtered: proto=" << url.protocol()
621 // << ", dir=" << url.dir()
622 // << ", file=" << url.file()
623 // << ", kurl url=" << *url.kurl();
624
625 if (d->mode == ExeCompletion) {
626 // Executables
627 //
628 if (d->exeCompletion(url, &aMatch))
629 return aMatch;
630
631 // KRun can run "man:" and "info:" etc. so why not treat them
632 // as executables...
633
634 if (d->urlCompletion(url, &aMatch))
635 return aMatch;
636 } else {
637 // Local files, directories
638 //
639 if (d->fileCompletion(url, &aMatch))
640 return aMatch;
641
642 // All other...
643 //
644 if (d->urlCompletion(url, &aMatch))
645 return aMatch;
646 }
647
648 d->setListedUrl(CTNone);
649 stop();
650
651 return QString();
652}
653
654/*
655 * finished
656 *
657 * Go on and call KCompletion.
658 * Called when all matches have been added
659 */
660QString KUrlCompletionPrivate::finished()
661{
662 if (last_compl_type == CTInfo)
663 return q->KCompletion::makeCompletion(compl_text.toLower());
664 else
665 return q->KCompletion::makeCompletion(compl_text);
666}
667
668/*
669 * isRunning
670 *
671 * Return true if either a KIO job or the DirLister
672 * is running
673 */
674bool KUrlCompletion::isRunning() const
675{
676 return d->list_job || (d->dirListThread && !d->dirListThread->isFinished());
677}
678
679/*
680 * stop
681 *
682 * Stop and delete a running KIO job or the DirLister
683 */
684void KUrlCompletion::stop()
685{
686 if (d->list_job) {
687 d->list_job->kill();
688 d->list_job = 0L;
689 }
690
691 if (d->dirListThread) {
692 d->dirListThread->requestTermination();
693 d->dirListThread = 0;
694 }
695}
696
697/*
698 * Keep track of the last listed directory
699 */
700void KUrlCompletionPrivate::setListedUrl(int complType,
701 const QString& directory,
702 const QString& filter,
703 bool no_hidden)
704{
705 last_compl_type = complType;
706 last_path_listed = directory;
707 last_file_listed = filter;
708 last_no_hidden = (int) no_hidden;
709 last_prepend = prepend;
710}
711
712bool KUrlCompletionPrivate::isListedUrl(int complType,
713 const QString& directory,
714 const QString& filter,
715 bool no_hidden)
716{
717 return last_compl_type == complType
718 && (last_path_listed == directory
719 || (directory.isEmpty() && last_path_listed.isEmpty()))
720 && (filter.startsWith (last_file_listed)
721 || (filter.isEmpty() && last_file_listed.isEmpty()))
722 && last_no_hidden == (int) no_hidden
723 && last_prepend == prepend; // e.g. relative path vs absolute
724}
725
726/*
727 * isAutoCompletion
728 *
729 * Returns true if completion mode is Auto or Popup
730 */
731bool KUrlCompletionPrivate::isAutoCompletion()
732{
733 return q->completionMode() == KGlobalSettings::CompletionAuto
734 || q->completionMode() == KGlobalSettings::CompletionPopup
735 || q->completionMode() == KGlobalSettings::CompletionMan
736 || q->completionMode() == KGlobalSettings::CompletionPopupAuto;
737}
740// User directories
741//
742
743bool KUrlCompletionPrivate::userCompletion(const KUrlCompletionPrivate::MyURL& url, QString* pMatch)
744{
745 if (url.protocol() != QLatin1String("file")
746 || !url.dir().isEmpty()
747 || !url.file().startsWith(QLatin1Char('~')))
748 return false;
749
750 if (!isListedUrl(CTUser)) {
751 q->stop();
752 q->clear();
753
754 if (!userListThread) {
755 userListThread = new UserListThread(this);
756 userListThread->start();
757
758 // If the thread finishes quickly make sure that the results
759 // are added to the first matching case.
760
761 userListThread->wait(200);
762 const QStringList l = userListThread->matches();
763 addMatches(l);
764 }
765 }
766 *pMatch = finished();
767 return true;
768}
769
772// Environment variables
773//
774
775#ifndef Q_OS_WIN
776extern char** environ; // Array of environment variables
777#endif
778
779bool KUrlCompletionPrivate::envCompletion(const KUrlCompletionPrivate::MyURL& url, QString* pMatch)
780{
781 if (url.file().isEmpty() || url.file().at(0) != QLatin1Char('$'))
782 return false;
783
784 if (!isListedUrl(CTEnv)) {
785 q->stop();
786 q->clear();
787
788 char** env = environ;
789
790 QString dollar = QLatin1String("$");
791
792 QStringList l;
793
794 while (*env) {
795 QString s = QString::fromLocal8Bit(*env);
796
797 int pos = s.indexOf(QLatin1Char('='));
798
799 if (pos == -1)
800 pos = s.length();
801
802 if (pos > 0)
803 l.append(prepend + dollar + s.left(pos));
804
805 env++;
806 }
807
808 addMatches(l);
809 }
810
811 setListedUrl(CTEnv);
812
813 *pMatch = finished();
814 return true;
815}
816
819// Executables
820//
821
822bool KUrlCompletionPrivate::exeCompletion(const KUrlCompletionPrivate::MyURL& url, QString* pMatch)
823{
824 if (url.protocol() != QLatin1String("file"))
825 return false;
826
827 QString directory = unescape(url.dir()); // remove escapes
828
829 // Find directories to search for completions, either
830 //
831 // 1. complete path given in url
832 // 2. current directory (d->cwd)
833 // 3. $PATH
834 // 4. no directory at all
835
836 QStringList dirList;
837
838 if (!url.file().isEmpty()) {
839 // $PATH
840 dirList = QString::fromLocal8Bit(qgetenv("PATH")).split(
841 KPATH_SEPARATOR, QString::SkipEmptyParts);
842
843 QStringList::Iterator it = dirList.begin();
844
845 for (; it != dirList.end(); ++it)
846 it->append(QLatin1Char('/'));
847 } else if (!QDir::isRelativePath(directory)) {
848 // complete path in url
849 dirList.append(directory);
850 } else if (!directory.isEmpty() && !cwd.isEmpty()) {
851 // current directory
852 dirList.append(cwd + QLatin1Char('/') + directory);
853 }
854
855 // No hidden files unless the user types "."
856 bool no_hidden_files = url.file().isEmpty() || url.file().at(0) != QLatin1Char('.');
857
858 // List files if needed
859 //
860 if (!isListedUrl(CTExe, directory, url.file(), no_hidden_files)) {
861 q->stop();
862 q->clear();
863
864 setListedUrl(CTExe, directory, url.file(), no_hidden_files);
865
866 *pMatch = listDirectories(dirList, url.file(), true, false, no_hidden_files);
867 } else if (!q->isRunning()) {
868 *pMatch = finished();
869 } else {
870 if (dirListThread)
871 setListedUrl(CTExe, directory, url.file(), no_hidden_files);
872 pMatch->clear();
873 }
874
875 return true;
876}
877
880// Local files
881//
882
883bool KUrlCompletionPrivate::fileCompletion(const KUrlCompletionPrivate::MyURL& url, QString* pMatch)
884{
885 if (url.protocol() != QLatin1String("file"))
886 return false;
887
888 QString directory = unescape(url.dir());
889
890 if (url.url().length() && url.url().at(0) == QLatin1Char('.')) {
891 if (url.url().length() == 1) {
892 *pMatch = (q->completionMode() == KGlobalSettings::CompletionMan) ?
893 QLatin1String(".") :
894 QLatin1String("..");
895 return true;
896 } else if (url.url().length() == 2 && url.url().at(1) == QLatin1Char('.')) {
897 *pMatch = QLatin1String("..");
898 return true;
899 }
900 }
901
902 //kDebug() << "fileCompletion" << url << "dir=" << dir;
903
904 // Find directories to search for completions, either
905 //
906 // 1. complete path given in url
907 // 2. current directory (d->cwd)
908 // 3. no directory at all
909
910 QStringList dirList;
911
912 if (!QDir::isRelativePath(directory)) {
913 // complete path in url
914 dirList.append(directory);
915 } else if (!cwd.isEmpty()) {
916 // current directory
917 QString dirToAdd = cwd;
918 if (!directory.isEmpty()) {
919 if (!cwd.endsWith('/'))
920 dirToAdd.append(QLatin1Char('/'));
921 dirToAdd.append(directory);
922 }
923 dirList.append(dirToAdd);
924 }
925
926 // No hidden files unless the user types "."
927 bool no_hidden_files = !url.file().startsWith(QLatin1Char('.'));
928
929 // List files if needed
930 //
931 if (!isListedUrl(CTFile, directory, QString(), no_hidden_files)) {
932 q->stop();
933 q->clear();
934
935 setListedUrl(CTFile, directory, QString(), no_hidden_files);
936
937 // Append '/' to directories in Popup mode?
938 bool append_slash = (popup_append_slash
939 && (q->completionMode() == KGlobalSettings::CompletionPopup ||
940 q->completionMode() == KGlobalSettings::CompletionPopupAuto));
941
942 bool only_dir = (mode == KUrlCompletion::DirCompletion);
943
944 *pMatch = listDirectories(dirList, QString(), false, only_dir, no_hidden_files,
945 append_slash);
946 } else if (!q->isRunning()) {
947 *pMatch = finished();
948 } else {
949 pMatch->clear();
950 }
951
952 return true;
953}
954
957// URLs not handled elsewhere...
958//
959
960static bool isLocalProtocol(const QString& protocol)
961{
962 return (KProtocolInfo::protocolClass(protocol) == QLatin1String(":local"));
963}
964
965bool KUrlCompletionPrivate::urlCompletion(const KUrlCompletionPrivate::MyURL& url, QString* pMatch)
966{
967 //kDebug() << *url.kurl();
968 if (onlyLocalProto && isLocalProtocol(url.protocol()))
969 return false;
970
971 // Use d->cwd as base url in case url is not absolute
972 KUrl url_dir = url.kurl();
973 if (url_dir.isRelative() && !cwd.isEmpty()) {
974 const KUrl url_cwd (cwd);
975 // Create an URL with the directory to be listed
976 url_dir = KUrl(url_cwd, url_dir.url());
977 }
978
979 // url is malformed
980 if (!url_dir.isValid())
981 return false;
982
983 // non local urls
984 if (!isLocalProtocol(url.protocol())) {
985 // url does not specify host
986 if (url_dir.host().isEmpty())
987 return false;
988
989 // url does not specify a valid directory
990 if (url_dir.directory(KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash).isEmpty())
991 return false;
992
993 // automatic completion is disabled
994 if (isAutoCompletion() && !url_auto_completion)
995 return false;
996 }
997
998 // url handler doesn't support listing
999 if (!KProtocolManager::supportsListing(url_dir))
1000 return false;
1001
1002 url_dir.setFileName(QString()); // not really nesseccary, but clear the filename anyway...
1003
1004 // Remove escapes
1005 QString directory = unescape(url_dir.directory(KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash));
1006
1007 url_dir.setPath(directory);
1008
1009 // List files if needed
1010 //
1011 if (!isListedUrl(CTUrl, url_dir.prettyUrl(), url.file())) {
1012 q->stop();
1013 q->clear();
1014
1015 setListedUrl(CTUrl, url_dir.prettyUrl(), QString());
1016
1017 QList<KUrl> url_list;
1018 url_list.append(url_dir);
1019
1020 listUrls(url_list, QString(), false);
1021
1022 pMatch->clear();
1023 } else if (!q->isRunning()) {
1024 *pMatch = finished();
1025 } else {
1026 pMatch->clear();
1027 }
1028
1029 return true;
1030}
1031
1034// Directory and URL listing
1035//
1036
1037/*
1038 * addMatches
1039 *
1040 * Called to add matches to KCompletion
1041 */
1042void KUrlCompletionPrivate::addMatches(const QStringList& matchList)
1043{
1044 q->insertItems(matchList);
1045}
1046
1047/*
1048 * listDirectories
1049 *
1050 * List files starting with 'filter' in the given directories,
1051 * either using DirLister or listURLs()
1052 *
1053 * In either case, addMatches() is called with the listed
1054 * files, and eventually finished() when the listing is done
1055 *
1056 * Returns the match if available, or QString() if
1057 * DirLister timed out or using kio
1058 */
1059QString KUrlCompletionPrivate::listDirectories(
1060 const QStringList& dirList,
1061 const QString& filter,
1062 bool only_exe,
1063 bool only_dir,
1064 bool no_hidden,
1065 bool append_slash_to_dir)
1066{
1067 assert(!q->isRunning());
1068
1069 if (qgetenv("KURLCOMPLETION_LOCAL_KIO").isEmpty()) {
1070
1071 //kDebug() << "Listing (listDirectories):" << dirList << "filter=" << filter << "without KIO";
1072
1073 // Don't use KIO
1074
1075 if (dirListThread)
1076 dirListThread->requestTermination();
1077
1078 QStringList dirs;
1079
1080 QStringList::ConstIterator end = dirList.constEnd();
1081 for (QStringList::ConstIterator it = dirList.constBegin();
1082 it != end;
1083 ++it) {
1084 KUrl url;
1085 url.setPath(*it);
1086 if (KAuthorized::authorizeUrlAction(QLatin1String("list"), KUrl(), url))
1087 dirs.append(*it);
1088 }
1089
1090 dirListThread = new DirectoryListThread(this, dirs, filter, only_exe, only_dir,
1091 no_hidden, append_slash_to_dir);
1092 dirListThread->start();
1093 dirListThread->wait(200);
1094 addMatches(dirListThread->matches());
1095
1096 return finished();
1097 }
1098
1099 // Use KIO
1100 //kDebug() << "Listing (listDirectories):" << dirList << "with KIO";
1101
1102 QList<KUrl> url_list;
1103
1104 QStringList::ConstIterator it = dirList.constBegin();
1105 QStringList::ConstIterator end = dirList.constEnd();
1106
1107 for (; it != end; ++it) {
1108 url_list.append(KUrl(*it));
1109 }
1110
1111 listUrls(url_list, filter, only_exe, no_hidden);
1112 // Will call addMatches() and finished()
1113
1114 return QString();
1115}
1116
1117/*
1118 * listURLs
1119 *
1120 * Use KIO to list the given urls
1121 *
1122 * addMatches() is called with the listed files
1123 * finished() is called when the listing is done
1124 */
1125void KUrlCompletionPrivate::listUrls(
1126 const QList<KUrl> &urls,
1127 const QString& filter,
1128 bool only_exe,
1129 bool no_hidden)
1130{
1131 assert(list_urls.isEmpty());
1132 assert(list_job == 0L);
1133
1134 list_urls = urls;
1135 list_urls_filter = filter;
1136 list_urls_only_exe = only_exe;
1137 list_urls_no_hidden = no_hidden;
1138
1139 //kDebug() << "Listing URLs:" << *urls[0] << ",...";
1140
1141 // Start it off by calling _k_slotIOFinished
1142 //
1143 // This will start a new list job as long as there
1144 // are urls in d->list_urls
1145 //
1146 _k_slotIOFinished(0);
1147}
1148
1149/*
1150 * _k_slotEntries
1151 *
1152 * Receive files listed by KIO and call addMatches()
1153 */
1154void KUrlCompletionPrivate::_k_slotEntries(KIO::Job*, const KIO::UDSEntryList& entries)
1155{
1156 QStringList matchList;
1157
1158 KIO::UDSEntryList::ConstIterator it = entries.constBegin();
1159 const KIO::UDSEntryList::ConstIterator end = entries.constEnd();
1160
1161 QString filter = list_urls_filter;
1162
1163 int filter_len = filter.length();
1164
1165 // Iterate over all files
1166 //
1167 for (; it != end; ++it) {
1168 const KIO::UDSEntry& entry = *it;
1169 const QString url = entry.stringValue(KIO::UDSEntry::UDS_URL);
1170
1171 QString entry_name;
1172 if (!url.isEmpty()) {
1173 // kDebug() << "url:" << url;
1174 entry_name = KUrl(url).fileName();
1175 } else {
1176 entry_name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
1177 }
1178
1179 // kDebug() << "name:" << name;
1180
1181 if ((!entry_name.isEmpty() && entry_name.at(0) == QLatin1Char('.')) &&
1182 (list_urls_no_hidden ||
1183 entry_name.length() == 1 ||
1184 (entry_name.length() == 2 && entry_name.at(1) == QLatin1Char('.'))))
1185 continue;
1186
1187 const bool isDir = entry.isDir();
1188
1189 if (mode == KUrlCompletion::DirCompletion && !isDir)
1190 continue;
1191
1192 if (filter_len == 0 || entry_name.left(filter_len) == filter) {
1193
1194 QString toAppend = entry_name;
1195
1196 if (isDir)
1197 toAppend.append(QLatin1Char('/'));
1198
1199 if (!list_urls_only_exe ||
1200 (entry.numberValue(KIO::UDSEntry::UDS_ACCESS) & MODE_EXE) // true if executable
1201 ) {
1202 if (complete_url) {
1203 KUrl url(prepend);
1204 url.addPath(toAppend);
1205 matchList.append(url.prettyUrl());
1206 } else {
1207 matchList.append(prepend + toAppend);
1208 }
1209 }
1210 }
1211 }
1212
1213 addMatches(matchList);
1214}
1215
1216/*
1217 * _k_slotIOFinished
1218 *
1219 * Called when a KIO job is finished.
1220 *
1221 * Start a new list job if there are still urls in
1222 * list_urls, otherwise call finished()
1223 */
1224void KUrlCompletionPrivate::_k_slotIOFinished(KJob* job)
1225{
1226 assert(job == list_job); Q_UNUSED(job)
1227
1228 if (list_urls.isEmpty()) {
1229
1230 list_job = 0L;
1231
1232 finished(); // will call KCompletion::makeCompletion()
1233
1234 } else {
1235
1236 KUrl kurl(list_urls.takeFirst());
1237
1238// list_urls.removeAll( kurl );
1239
1240// kDebug() << "Start KIO::listDir" << kurl;
1241
1242 list_job = KIO::listDir(kurl, KIO::HideProgressInfo);
1243 list_job->addMetaData("no-auth-prompt", "true");
1244
1245 assert(list_job);
1246
1247 q->connect(list_job,
1248 SIGNAL(result(KJob*)),
1249 SLOT(_k_slotIOFinished(KJob*)));
1250
1251 q->connect(list_job,
1252 SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)),
1253 SLOT(_k_slotEntries(KIO::Job*,KIO::UDSEntryList)));
1254 }
1255}
1256
1259
1260/*
1261 * postProcessMatch, postProcessMatches
1262 *
1263 * Called by KCompletion before emitting match() and matches()
1264 *
1265 * Append '/' to directories for file completion. This is
1266 * done here to avoid stat()'ing a lot of files
1267 */
1268void KUrlCompletion::postProcessMatch(QString* pMatch) const
1269{
1270// kDebug() << *pMatch;
1271
1272 if (!pMatch->isEmpty()) {
1273
1274 // Add '/' to directories in file completion mode
1275 // unless it has already been done
1276 if (d->last_compl_type == CTFile
1277 && pMatch->at(pMatch->length() - 1) != QLatin1Char('/')) {
1278 QString copy;
1279
1280 if (pMatch->startsWith(QLatin1String("file:")))
1281 copy = KUrl(*pMatch).toLocalFile();
1282 else
1283 copy = *pMatch;
1284
1285 expandTilde(copy);
1286 expandEnv(copy);
1287#ifdef Q_WS_WIN
1288 DWORD dwAttr = GetFileAttributesW((LPCWSTR) copy.utf16());
1289 if (dwAttr == INVALID_FILE_ATTRIBUTES) {
1290 kDebug() << "Could not get file attribs ( "
1291 << GetLastError()
1292 << " ) for "
1293 << copy;
1294 } else if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
1295 pMatch->append(QLatin1Char('/'));
1296#else
1297 if (QDir::isRelativePath(copy))
1298 copy.prepend(d->cwd + QLatin1Char('/'));
1299
1300// kDebug() << "stat'ing" << copy;
1301
1302 KDE_struct_stat sbuff;
1303
1304 QByteArray file = QFile::encodeName(copy);
1305
1306 if (KDE_stat(file.data(), &sbuff) == 0) {
1307 if (S_ISDIR(sbuff.st_mode))
1308 pMatch->append(QLatin1Char('/'));
1309 } else {
1310 kDebug() << "Could not stat file" << copy;
1311 }
1312#endif
1313 }
1314 }
1315}
1316
1317void KUrlCompletion::postProcessMatches(QStringList* /*matches*/) const
1318{
1319 // Maybe '/' should be added to directories here as in
1320 // postProcessMatch() but it would slow things down
1321 // when there are a lot of matches...
1322}
1323
1324void KUrlCompletion::postProcessMatches(KCompletionMatches* /*matches*/) const
1325{
1326 // Maybe '/' should be added to directories here as in
1327 // postProcessMatch() but it would slow things down
1328 // when there are a lot of matches...
1329}
1330
1331void KUrlCompletion::customEvent(QEvent* e)
1332{
1333 if (e->type() == CompletionMatchEvent::uniqueType()) {
1334
1335 CompletionMatchEvent* matchEvent = static_cast<CompletionMatchEvent*>(e);
1336
1337 matchEvent->completionThread()->wait();
1338
1339 if (!d->isListedUrl(CTUser)) {
1340 stop();
1341 clear();
1342 d->addMatches(matchEvent->completionThread()->matches());
1343 } else {
1344 d->setListedUrl(CTUser);
1345 }
1346
1347 if (d->userListThread == matchEvent->completionThread())
1348 d->userListThread = 0;
1349
1350 if (d->dirListThread == matchEvent->completionThread())
1351 d->dirListThread = 0;
1352
1353 delete matchEvent->completionThread();
1354 }
1355}
1356
1357// static
1358QString KUrlCompletion::replacedPath(const QString& text, bool replaceHome, bool replaceEnv)
1359{
1360 if (text.isEmpty())
1361 return text;
1362
1363 KUrlCompletionPrivate::MyURL url(text, QString()); // no need to replace something of our current cwd
1364 if (!url.kurl().isLocalFile())
1365 return text;
1366
1367 url.filter(replaceHome, replaceEnv);
1368 return url.dir() + url.file();
1369}
1370
1371
1372QString KUrlCompletion::replacedPath(const QString& text) const
1373{
1374 return replacedPath(text, d->replace_home, d->replace_env);
1375}
1376
1379// Static functions
1380
1381/*
1382 * expandEnv
1383 *
1384 * Expand environment variables in text. Escaped '$' are ignored.
1385 * Return true if expansion was made.
1386 */
1387static bool expandEnv(QString& text)
1388{
1389 // Find all environment variables beginning with '$'
1390 //
1391 int pos = 0;
1392
1393 bool expanded = false;
1394
1395 while ((pos = text.indexOf(QLatin1Char('$'), pos)) != -1) {
1396
1397 // Skip escaped '$'
1398 //
1399 if (pos > 0 && text.at(pos - 1) == QLatin1Char('\\')) {
1400 pos++;
1401 }
1402 // Variable found => expand
1403 //
1404 else {
1405 // Find the end of the variable = next '/' or ' '
1406 //
1407 int pos2 = text.indexOf(QLatin1Char(' '), pos + 1);
1408 int pos_tmp = text.indexOf(QLatin1Char('/'), pos + 1);
1409
1410 if (pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2))
1411 pos2 = pos_tmp;
1412
1413 if (pos2 == -1)
1414 pos2 = text.length();
1415
1416 // Replace if the variable is terminated by '/' or ' '
1417 // and defined
1418 //
1419 if (pos2 >= 0) {
1420 int len = pos2 - pos;
1421 QString key = text.mid(pos + 1, len - 1);
1422 QString value =
1423 QString::fromLocal8Bit(qgetenv(key.toLocal8Bit()));
1424
1425 if (!value.isEmpty()) {
1426 expanded = true;
1427 text.replace(pos, len, value);
1428 pos = pos + value.length();
1429 } else {
1430 pos = pos2;
1431 }
1432 }
1433 }
1434 }
1435
1436 return expanded;
1437}
1438
1439/*
1440 * expandTilde
1441 *
1442 * Replace "~user" with the users home directory
1443 * Return true if expansion was made.
1444 */
1445static bool expandTilde(QString& text)
1446{
1447 if (text.isEmpty() || (text.at(0) != QLatin1Char('~')))
1448 return false;
1449
1450 bool expanded = false;
1451
1452 // Find the end of the user name = next '/' or ' '
1453 //
1454 int pos2 = text.indexOf(QLatin1Char(' '), 1);
1455 int pos_tmp = text.indexOf(QLatin1Char('/'), 1);
1456
1457 if (pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2))
1458 pos2 = pos_tmp;
1459
1460 if (pos2 == -1)
1461 pos2 = text.length();
1462
1463 // Replace ~user if the user name is terminated by '/' or ' '
1464 //
1465 if (pos2 >= 0) {
1466
1467 QString user = text.mid(1, pos2 - 1);
1468 QString dir;
1469
1470 // A single ~ is replaced with $HOME
1471 //
1472 if (user.isEmpty()) {
1473 dir = QDir::homePath();
1474 }
1475 // ~user is replaced with the dir from passwd
1476 //
1477 else {
1478 struct passwd* pw = ::getpwnam(user.toLocal8Bit());
1479
1480 if (pw)
1481 dir = QFile::decodeName(pw->pw_dir);
1482
1483 ::endpwent();
1484 }
1485
1486 if (!dir.isEmpty()) {
1487 expanded = true;
1488 text.replace(0, pos2, dir);
1489 }
1490 }
1491
1492 return expanded;
1493}
1494
1495/*
1496 * unescape
1497 *
1498 * Remove escapes and return the result in a new string
1499 *
1500 */
1501static QString unescape(const QString& text)
1502{
1503 QString result;
1504
1505 for (int pos = 0; pos < text.length(); pos++)
1506 if (text.at(pos) != QLatin1Char('\\'))
1507 result.insert(result.length(), text.at(pos));
1508
1509 return result;
1510}
1511
1512#include "kurlcompletion.moc"
KCompletionMatches
KCompletion
KCompletion::clear
virtual void clear()
KConfigGroup
KGlobalSettings::CompletionPopup
CompletionPopup
KGlobalSettings::CompletionMan
CompletionMan
KGlobalSettings::CompletionAuto
CompletionAuto
KGlobalSettings::CompletionPopupAuto
CompletionPopupAuto
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition: jobclasses.h:936
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:59
KIO::UDSEntry::stringValue
QString stringValue(uint field) const
Definition: udsentry.cpp:73
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
KIO::UDSEntry::UDS_URL
@ UDS_URL
An alternative URL (If different from the caption).
Definition: udsentry.h:190
KIO::UDSEntry::UDS_NAME
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition: udsentry.h:163
KIO::UDSEntry::UDS_ACCESS
@ UDS_ACCESS
Access permissions (part of the mode returned by stat)
Definition: udsentry.h:171
KIO::UDSEntry::isDir
bool isDir() const
Definition: udsentry.cpp:84
KJob
KProtocolManager::supportsListing
static bool supportsListing(const KUrl &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolmanager.cpp:1033
KUrlCompletion
This class does completion of URLs including user directories (~user) and environment variables.
Definition: kurlcompletion.h:42
KUrlCompletion::setMode
virtual void setMode(Mode mode)
Changes the completion mode: exe or file completion.
Definition: kurlcompletion.cpp:559
KUrlCompletion::dir
virtual QString dir() const
Returns the current directory, as it was given in setDir.
Definition: kurlcompletion.cpp:549
KUrlCompletion::~KUrlCompletion
virtual ~KUrlCompletion()
Destructs the KUrlCompletion object.
Definition: kurlcompletion.cpp:516
KUrlCompletion::replaceEnv
virtual bool replaceEnv() const
Checks whether environment variables are completed and whether they are replaced internally while fin...
Definition: kurlcompletion.cpp:564
KUrlCompletion::stop
virtual void stop()
Stops asynchronous completion.
Definition: kurlcompletion.cpp:684
KUrlCompletion::replaceHome
virtual bool replaceHome() const
Returns whether ~username is completed and whether ~username is replaced internally with the user's h...
Definition: kurlcompletion.cpp:574
KUrlCompletion::customEvent
virtual void customEvent(QEvent *e)
Definition: kurlcompletion.cpp:1331
KUrlCompletion::setReplaceHome
virtual void setReplaceHome(bool replace)
Enables/disables completion of ~username and replacement (internally) of ~username with the user's ho...
Definition: kurlcompletion.cpp:579
KUrlCompletion::KUrlCompletion
KUrlCompletion()
Constructs a KUrlCompletion object in FileCompletion mode.
Definition: kurlcompletion.cpp:502
KUrlCompletion::setReplaceEnv
virtual void setReplaceEnv(bool replace)
Enables/disables completion and replacement (internally) of environment variables in URLs.
Definition: kurlcompletion.cpp:569
KUrlCompletion::postProcessMatch
void postProcessMatch(QString *match) const
Definition: kurlcompletion.cpp:1268
KUrlCompletion::Mode
Mode
Determines how completion is done.
Definition: kurlcompletion.h:53
KUrlCompletion::ExeCompletion
@ ExeCompletion
Definition: kurlcompletion.h:53
KUrlCompletion::DirCompletion
@ DirCompletion
Definition: kurlcompletion.h:53
KUrlCompletion::FileCompletion
@ FileCompletion
Definition: kurlcompletion.h:53
KUrlCompletion::makeCompletion
virtual QString makeCompletion(const QString &text)
Finds completions to the given text.
Definition: kurlcompletion.cpp:589
KUrlCompletion::mode
virtual Mode mode() const
Returns the completion mode: exe or file completion (default FileCompletion).
Definition: kurlcompletion.cpp:554
KUrlCompletion::setDir
virtual void setDir(const QString &dir)
Sets the current directory (used as base for completion).
Definition: kurlcompletion.cpp:544
KUrlCompletion::isRunning
virtual bool isRunning() const
Check whether asynchronous completion is in progress.
Definition: kurlcompletion.cpp:674
KUrlCompletion::postProcessMatches
void postProcessMatches(QStringList *matches) const
Definition: kurlcompletion.cpp:1317
KUrlCompletion::replacedPath
QString replacedPath(const QString &text) const
Replaces username and/or environment variables, depending on the current settings and returns the fil...
Definition: kurlcompletion.cpp:1372
KUrl
KUrl::prettyUrl
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::ObeyTrailingSlash
ObeyTrailingSlash
KUrl::AppendTrailingSlash
AppendTrailingSlash
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::setFileName
void setFileName(const QString &_txt)
KUrl::directory
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
KUrl::setPath
void setPath(const QString &path)
KUrl::fileName
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
KUrl::protocol
QString protocol() const
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
QList< UDSEntry >
QThread
kDebug
#define kDebug
job.h
kauthorized.h
kconfig.h
kconfiggroup.h
kdebug.h
kglobal.h
kglobalsettings.h
kkernel_win.h
kprotocolmanager.h
kurl.h
isLocalProtocol
static bool isLocalProtocol(const QString &protocol)
Definition: kurlcompletion.cpp:960
expandEnv
static bool expandEnv(QString &)
Definition: kurlcompletion.cpp:1387
ComplType
ComplType
Definition: kurlcompletion.cpp:78
CTInfo
@ CTInfo
Definition: kurlcompletion.cpp:78
CTFile
@ CTFile
Definition: kurlcompletion.cpp:78
CTMan
@ CTMan
Definition: kurlcompletion.cpp:78
CTExe
@ CTExe
Definition: kurlcompletion.cpp:78
CTUrl
@ CTUrl
Definition: kurlcompletion.cpp:78
CTEnv
@ CTEnv
Definition: kurlcompletion.cpp:78
CTUser
@ CTUser
Definition: kurlcompletion.cpp:78
CTNone
@ CTNone
Definition: kurlcompletion.cpp:78
unescape
static QString unescape(const QString &text)
Definition: kurlcompletion.cpp:1501
MODE_EXE
#define MODE_EXE
Definition: kurlcompletion.cpp:75
expandTilde
static bool expandTilde(QString &)
Definition: kurlcompletion.cpp:1445
kurlcompletion.h
KAuthorized::authorizeUrlAction
bool authorizeUrlAction(const QString &action, const KUrl &baseUrl, const KUrl &destUrl)
KDesktopFileActions::run
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kdesktopfileactions.cpp:54
Type
Type
dirs
KStandardDirs * dirs()
KGlobal::config
KSharedConfigPtr config()
KIO::listDir
ListJob * listDir(const KUrl &url, JobFlags flags=DefaultFlags, bool includeHidden=true)
List the contents of url, which is assumed to be a directory.
Definition: job.cpp:2735
KIO::HideProgressInfo
@ HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KRecentDirs::dir
QString dir(const QString &fileClass)
Returns the most recently used directory accociated with this file-class.
Definition: krecentdirs.cpp:68
replace
KAction * replace(const QObject *recvr, const char *slot, QObject *parent)
copy
KAction * copy(const QObject *recvr, const char *slot, QObject *parent)
end
const KShortcut & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal