Warning, file /utilities/mangonel/providers/Paths.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Copyright 2010-2012 Bart Kroon <bart@tarmack.eu>
0003  * 
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  * 
0008  * 1. Redistributions of source code must retain the above copyright
0009  *   notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *   notice, this list of conditions and the following disclaimer in the
0012  *   documentation and/or other materials provided with the distribution.
0013  * 
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0016  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0017  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0018  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0019  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0020  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0021  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0023  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 
0026 #include "Paths.h"
0027 
0028 #include <KLocalizedString>
0029 
0030 #include <QDateTime>
0031 #include <QDesktopServices>
0032 #include <QDir>
0033 #include <QUrl>
0034 #include <QDebug>
0035 
0036 #include <sys/stat.h>
0037 #include <dirent.h>
0038 
0039 Paths::Paths(QObject *parent) :
0040     Provider(parent)
0041 {
0042 }
0043 
0044 Paths::~Paths()
0045 {}
0046 
0047 // QDir::entryList is very slow, so we do it ourself (on Linux, someone who knows the others need to fix them)
0048 static QStringList sortedDirList(const QString &dirPath, const QString &matchPrefix)
0049 {
0050 #ifdef Q_OS_LINUX
0051     QByteArray path = dirPath.toLocal8Bit();
0052     if (!path.endsWith('/')) {
0053         path += '/';
0054     }
0055     DIR *dir = opendir(path.constData());
0056     if (!dir) {
0057         qWarning() << "Error opening dir:" << strerror(errno);
0058         return {};
0059     }
0060     QHash<QString, qint64> entries;
0061     struct stat statbuf;
0062     dirent *ent;
0063     while ((ent = readdir(dir))) {
0064         if (ent->d_name[0] == '.') {
0065             continue;
0066         }
0067         const QString name = QString::fromLocal8Bit(ent->d_name);
0068         if (!name.startsWith(matchPrefix, Qt::CaseInsensitive)) {
0069             continue;
0070         }
0071         QByteArray new_path = path + static_cast<const char*>(ent->d_name);
0072         if (lstat(new_path.constData(), &statbuf) == -1) {
0073             qWarning() << "Error stating file:" << strerror(errno);
0074             continue;
0075         }
0076         if (S_ISCHR(statbuf.st_mode) ||
0077                 S_ISBLK(statbuf.st_mode) ||
0078                 S_ISFIFO(statbuf.st_mode)||
0079                 S_ISSOCK(statbuf.st_mode)) {
0080             continue;
0081         }
0082         entries[name] = statbuf.st_mtime;
0083     }
0084     closedir(dir);
0085     QStringList names = entries.keys();
0086     std::sort(names.begin(), names.end(), [&](const QString &a, const QString &b) {
0087             return entries[a] > entries[b];
0088             });
0089     return names;
0090 #else
0091     return QDir(dirPath).entryList(QStringList(matchPrefix + '*'), QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files, QDir::Time);
0092 #endif
0093 }
0094 
0095 QList<ProviderResult *> Paths::getResults(QString query)
0096 {
0097     QList<ProviderResult*> list;
0098 
0099     QDir dir;
0100     if (query.startsWith("/")) {
0101         dir = QDir::root();
0102         query.remove(0, 1);
0103     } else {
0104         dir = QDir::home();
0105 
0106         if (query.startsWith('~')) {
0107             query.remove(0, 1);
0108         }
0109     }
0110 
0111 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
0112     QStringList walk = query.split("/", QString::SkipEmptyParts);
0113 #else
0114     QStringList walk = query.split("/", Qt::SkipEmptyParts);
0115 #endif
0116 
0117     if (walk.isEmpty() || query.endsWith('/')) {
0118         walk.append("");
0119     }
0120 
0121     QString part = walk.takeFirst();
0122     while (walk.length() > 0) {
0123         if (!dir.exists(part)) {
0124             return list;
0125         }
0126 
0127         dir.cd(part);
0128         part = walk.takeFirst();
0129     }
0130 
0131     QStringList paths = sortedDirList(dir.path(), part);
0132 
0133     if (paths.size() > 100) {
0134         paths = paths.mid(0, 100);
0135     }
0136 
0137     qint64 currentSecsSinceEpoch = QDateTime::currentSecsSinceEpoch();
0138 
0139     static const QString homePath = QDir::homePath();
0140 
0141     for(const QString &name : paths) {
0142         const QFileInfo path(dir.filePath(name));
0143         ProviderResult *result = new ProviderResult();
0144 
0145         result->program = path.absoluteFilePath();
0146 
0147         if (result->program.startsWith(homePath)) {
0148             result->name = result->program.mid(homePath.length());
0149             result->completion = "~" + result->name.left(result->name.lastIndexOf("/")) + "/" + path.fileName();
0150         } else {
0151             result->name = result->program;
0152             result->completion = result->name.left(result->name.lastIndexOf("/")) + "/" + path.fileName();
0153         }
0154         result->priority = currentSecsSinceEpoch - path.lastModified().toSecsSinceEpoch();
0155         if (path.isDir()) {
0156             result->completion += "/";
0157             result->icon = "system-file-manager";
0158         } else {
0159             result->icon = m_mimeDb.mimeTypeForFile(path).iconName();
0160         }
0161 
0162         result->object = this;
0163         result->type = i18n("Open path");
0164         list.append(result);
0165     }
0166 
0167     return list;
0168 }
0169 
0170 int Paths::launch(const QString &exec)
0171 {
0172     QDesktopServices::openUrl(QUrl::fromLocalFile(exec));
0173     return 0;
0174 }
0175 
0176 
0177 
0178 // kate: indent-mode cstyle; space-indent on; indent-width 4;