From 8a0454983884f2a0a226bdaefa32f66e42ddfedb Mon Sep 17 00:00:00 2001 From: hama Date: Sun, 1 Nov 2015 23:37:08 +0100 Subject: [PATCH] reidos navigation works --- appl/reidos/idosmain.cpp | 3 ++ base/ReFileUtils.cpp | 82 ++++++++++++++++++++++--------------- base/ReFileUtils.hpp | 1 + base/ReMatcher.cpp | 10 ++++- base/ReMatcher.hpp | 4 +- base/rebase.hpp | 4 ++ cunit/allTests.cpp | 4 +- cunit/cuReFileUtils.cpp | 55 +++++++++++++++---------- gui/ReGuiValidator.cpp | 2 + guiwidget/ReFileTable.cpp | 69 ++++++++++++++++++++++++++----- guiwidget/ReFileTable.hpp | 11 +++-- os/ReFileSystem.cpp | 85 ++++++++++++++++++++++++++++++++++++++- os/ReFileSystem.hpp | 12 +++--- 13 files changed, 262 insertions(+), 80 deletions(-) diff --git a/appl/reidos/idosmain.cpp b/appl/reidos/idosmain.cpp index b36c481..fd94404 100644 --- a/appl/reidos/idosmain.cpp +++ b/appl/reidos/idosmain.cpp @@ -22,12 +22,15 @@ IDosMain::IDosMain(const QString& startDir, const QString& homeDir, ui->setupUi(this); initializeHome(); m_statusMessage = new QLabel(tr("Welcome at reidos")); + ui->statusBar->addWidget(m_statusMessage); if (!startDir.isEmpty()) ui->fileTableTop->comboBoxPath->setCurrentText(startDir); ui->fileTableTop->fileSystem = new ReLocalFileSystem("/", m_logger); ui->fileTableTop->fillTable(); + ui->fileTableTop->announcer = this; ui->fileTableBottom->fileSystem = new ReLocalFileSystem("/", m_logger); ui->fileTableBottom->fillTable(); + ui->fileTableTop->announcer = this; QString dir(ui->fileTableTop->comboBoxPath->currentText()); if (dir.isEmpty()) dir = startDir; diff --git a/base/ReFileUtils.cpp b/base/ReFileUtils.cpp index dc49094..dd93aec 100644 --- a/base/ReFileUtils.cpp +++ b/base/ReFileUtils.cpp @@ -67,7 +67,7 @@ QByteArray ReFileUtils::pathAppend(const char* base, const char* path) { } else { rc = path; } - return rc = cleanPath(rc); + return cleanPath(rc.constData()); } /** @@ -296,7 +296,8 @@ QString ReFileUtils::parentOf(const QString& filename) { /** Normalizes a file path. * - * Removes duplicated slashes and "." and "..", but not leading ".." + * Removes duplicated slashes and "." and "..", but not leading "..". + * Change the 2nd separator to the native separator, e.g. "/" to "\\" * * @param path path to clean * @return the path without duplicated separators and "." and ".." @@ -308,60 +309,77 @@ QByteArray ReFileUtils::cleanPath(const char* path) { int minLength = 0; #ifdef __WIN32__ // UNC path, e.g. "\\server\share"? - if (path[0] == OS_SEPARATOR && path[1] == OS_SEPARATOR) { + if ((path[0] == OS_SEPARATOR || path[0] == OS_2nd_SEPARATOR) + && (path[1] == OS_SEPARATOR || path[1] == OS_2nd_SEPARATOR)) { rc.append("\\\\"); path += 2; minLength = 2; } #endif - const char* ptr; - if (path[0] == OS_SEPARATOR) { - rc.append(OS_SEPARATOR); + char cc = *path; + int startNode = 0; + if (cc == OS_SEPARATOR || cc == OS_2nd_SEPARATOR){ path++; + startNode++; + rc.append(OS_SEPARATOR); } - while ((ptr = strchr(path, OS_SEPARATOR)) != NULL) { + while ((cc = *path++) != '\0') { + if (cc != OS_SEPARATOR && cc != OS_2nd_SEPARATOR) + rc.append(cc); // ignore duplicated slashes: - if (ptr != path) { - int length = ptr - path; - if (length == 1 && path[0] == '.') { - // ignore ".": do nothing - } else if (length == 2 && path[0] == '.' && path[1] == '.') { + else if (rc.length() > 0 && rc.at(rc.length() - 1) != OS_SEPARATOR){ + int length = rc.length() - startNode; + if (length == 1 && rc.at(startNode) == '.') { + // ignore ".": remove it: + rc.resize(startNode); + } else if (length == 2 && rc.at(startNode) == '.' &&rc.at(startNode + 1) == '.') { + // remove "..": + rc.resize(startNode); // remove the last slash and node if (rc.length() > minLength) { rc.resize(rc.size() - 1); int ix = rc.lastIndexOf(OS_SEPARATOR); if (ix > minLength) rc.resize(ix + 1); + startNode = rc.length(); } - } else { - // copy with separator: - rc.append(path, length + 1); + rc.append(OS_SEPARATOR); + startNode = rc.length(); } - } - path = ptr + 1; } - if (path[0] != '\0') { - if (path[0] == '.' && path[1] == '\0') { - if (rc.size() == 0) - rc.append('.'); - } else if (path[0] == '.' && path[1] == '.' && path[2] == '\0' && rc.length() > 0) { - // remove the last slash and node - if (rc.size() > minLength) { - rc.resize(rc.size() - 1); - int ix = rc.lastIndexOf(OS_SEPARATOR); - if (ix > minLength) - rc.resize(ix); - } - } else { - // copy with separator: - rc.append(path); + length = rc.length() - startNode; + if (length == 1 && rc.at(startNode) == '.') { + // ignore ".": remove it: + rc.resize(startNode); + } else if (length == 2 && rc.at(startNode) == '.' + && startNode > 0 &&rc.at(startNode + 1) == '.') { + // remove "..": + rc.resize(startNode); + // remove the last slash and node + if (rc.length() > minLength) { + rc.resize(rc.size() - 1); + int ix = rc.lastIndexOf(OS_SEPARATOR); + if (ix > minLength) + rc.resize(ix); } } return rc; } +/** Normalizes a file path. + * + * Removes duplicated slashes and "." and "..", but not leading "..". + * Change the 2nd separator to the native separator, e.g. "/" to "\\" + * + * @param path path to clean + * @return the path without duplicated separators and "." and ".." + */ +QString ReFileUtils::cleanPath(const QString& path) { + return (QString) cleanPath(path.toUtf8().constData()); +} + /** * Reads a string from a given file. * diff --git a/base/ReFileUtils.hpp b/base/ReFileUtils.hpp index 8fa57c4..1de0e25 100644 --- a/base/ReFileUtils.hpp +++ b/base/ReFileUtils.hpp @@ -31,6 +31,7 @@ public: static bool deleteTree(const QString& path, bool withBase, ReLogger* logger); static QByteArray cleanPath(const char* path); + static QString cleanPath(const QString& path); static QString extensionOf(const QString& filename); static QByteArray extensionOf(const char* filename); static bool isAbsolutPath(const QString& path); diff --git a/base/ReMatcher.cpp b/base/ReMatcher.cpp index 7506aa4..9ed1c91 100644 --- a/base/ReMatcher.cpp +++ b/base/ReMatcher.cpp @@ -273,7 +273,7 @@ bool ReListMatcher::empty() const { * matches the text
* false: none of the patterns matches */ -bool ReListMatcher::matches(const QString& text) { +bool ReListMatcher::matches(const QString& text) const { QList::const_iterator it; bool rc = m_list.size() == 0; for (it = m_list.cbegin(); !rc && it != m_list.cend(); ++it) { @@ -405,7 +405,7 @@ const ReListMatcher& ReIncludeExcludeMatcher::includes() const { * @return true: at least one of the include patterns * matches and none of the exclude patterns matches */ -bool ReIncludeExcludeMatcher::matches(const QString& text, bool excludeToo) { +bool ReIncludeExcludeMatcher::matches(const QString& text, bool excludeToo) const { bool rc = m_includes.matches(text); if (rc && excludeToo && !m_excludes.empty()) rc = !m_excludes.matches(text); @@ -449,6 +449,12 @@ void ReIncludeExcludeMatcher::setPatterns(const QString& patterns, } start = ix + 1; } + if (patterns.length() > start){ + if (patterns.at(start) == excludeMarker) + excludes.append(patterns.mid(start + 1)); + else + includes.append(patterns.mid(start)); + } m_includes.setPatterns(includes, m_includes.caseSensivitiy(), m_includes.anchored()); m_excludes.setPatterns(excludes, m_excludes.caseSensivitiy(), diff --git a/base/ReMatcher.hpp b/base/ReMatcher.hpp index 4c73658..57c43b2 100644 --- a/base/ReMatcher.hpp +++ b/base/ReMatcher.hpp @@ -53,7 +53,7 @@ public: bool allMatching() const; Qt::CaseSensitivity caseSensivitiy() const; bool empty() const; - bool matches(const QString& text); + bool matches(const QString& text) const; const QStringList& patterns() const; void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy); void setPatterns(const QStringList& patterns, @@ -89,7 +89,7 @@ public: Qt::CaseSensitive, bool anchored = false); public: Qt::CaseSensitivity caseSensivitiy() const; - bool matches(const QString& text, bool excludeToo = true); + bool matches(const QString& text, bool excludeToo = true) const; const ReListMatcher& includes() const; const ReListMatcher& excludes() const; void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy); diff --git a/base/rebase.hpp b/base/rebase.hpp index 322ccd7..0f265c3 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -62,12 +62,16 @@ typedef QString ReString; #define _strcasecmp strcasecmp #define OS_SEPARATOR '/' #define OS_SEPARATOR_STR "/" +#define OS_2nd_SEPARATOR '\\' +#define OS_2nd_SEPARATOR_STR "\\" #define _mkdir(path) mkdir(path, -1) #define _memicmp memicmp #else #define _strcasecmp _stricmp #define OS_SEPARATOR '\\' #define OS_SEPARATOR_STR "\\" +#define OS_2nd_SEPARATOR '/' +#define OS_2nd_SEPARATOR_STR "/" #endif #define UNUSED_VAR(var) (void) var diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index dbfea14..499b20b 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -37,9 +37,9 @@ static void testBase() { void testReException(); void testReQStringUtil(); void testReStringUtil(); + void testReFileUtils(); void testReWriter(); void testReFile(); - void testReFileUtils(); void testReMatcher(); testReFileUtils(); testReRandomizer(); @@ -94,8 +94,8 @@ static void testOs() { testReFileSystem(); } void allTests() { - testOs(); testBase(); + testOs(); testGui(); if (s_allTest) { testBase(); diff --git a/cunit/cuReFileUtils.cpp b/cunit/cuReFileUtils.cpp index c3d21e4..e58e839 100644 --- a/cunit/cuReFileUtils.cpp +++ b/cunit/cuReFileUtils.cpp @@ -17,7 +17,7 @@ class TestReFileUtils: public ReTest { public: TestReFileUtils() : - ReTest("ReFileUtils") { + ReTest("ReFileUtils") { doIt(); } @@ -42,7 +42,7 @@ public: } void testTempDirEmpty() { QByteArray dir( - ReFileUtils::tempDirEmpty("subdir2", "cuReFileUtils", true)); + ReFileUtils::tempDirEmpty("subdir2", "cuReFileUtils", true)); QByteArray subdir(dir); subdir.append("subdirX"); mkdir(subdir.constData(), ALLPERMS); @@ -133,10 +133,10 @@ public: QByteArray fn(ReFileUtils::tempFile("timetest.txt", NULL, true)); ReFileUtils::writeToFile(fn.constData(), ""); QDateTime time = QDateTime::fromString("03.09.2015 07:14:24.432", - "dd.MM.yyyy hh:mm:ss.zzz"); + "dd.MM.yyyy hh:mm:ss.zzz"); checkT( - ReFileUtils::setTimes(fn.constData(), time, - ReFileUtils::m_undefinedTime, &m_logger)); + ReFileUtils::setTimes(fn.constData(), time, + ReFileUtils::m_undefinedTime, &m_logger)); QFileInfo info(fn); checkEqu(time, info.lastModified()); } @@ -150,12 +150,15 @@ public: checkEqu("x/y/z.x/", ReFileUtils::cleanPath("x//y/////z.x//")); // remove "./" checkEqu("x/y/z.x", ReFileUtils::cleanPath("./x/././y/z.x")); + checkEqu("/x/y/z.x", ReFileUtils::cleanPath("/x/././y/z.x")); // remove "..": // inside... + checkEqu("x/a/b", ReFileUtils::cleanPath("x/y/../a/b")); checkEqu("x/y/a/b", ReFileUtils::cleanPath("x/y/z/../a/b")); checkEqu("x/a/b", ReFileUtils::cleanPath("x/y/z/../../a/b")); // at the end.. checkEqu("x", ReFileUtils::cleanPath("x/y/z/../..")); + checkEqu("x/", ReFileUtils::cleanPath("x/y/z/../../")); // wrong forms: checkEqu("..", ReFileUtils::cleanPath("..")); checkEqu("../..", ReFileUtils::cleanPath("../..")); @@ -177,8 +180,8 @@ public: assertEquals(QString(exp), ReFileUtils::extensionOf(QString(sArg1)), __FILE__, lineNo); assertEquals(exp.constData(), - ReFileUtils::extensionOf(sArg1.constData()), - __FILE__, lineNo); + ReFileUtils::extensionOf(sArg1.constData()), + __FILE__, lineNo); } void testExtensionOf() { @@ -225,11 +228,18 @@ public: checkNodeOf("", "", __LINE__); } + void testParentOf(){ + checkEqu("/abc/", ReFileUtils::parentOf("/abc/def")); + checkEqu("/abc/def/x.y/", ReFileUtils::parentOf("/abc/def/x.y/")); + checkEqu("/", ReFileUtils::parentOf("/")); + checkEqu("", ReFileUtils::parentOf("abc.def")); + } + void checkPathAppend(const char* expected, const char* arg1, - const char* arg2, int lineNo) { + const char* arg2, int lineNo) { assertEquals(QString(expected), - ReFileUtils::pathAppend(QString(arg1), QString(arg2)), - __FILE__, lineNo); + ReFileUtils::pathAppend(QString(arg1), QString(arg2)), + __FILE__, lineNo); assertEquals(expected, ReFileUtils::pathAppend(arg1, arg2), __FILE__, lineNo); QByteArray exp(expected); @@ -239,11 +249,11 @@ public: sArg1.replace("/", "\\"); sArg2.replace("/", "\\"); assertEquals(QString(exp), - ReFileUtils::pathAppend(QString(sArg1), QString(sArg2)), - __FILE__, lineNo); + ReFileUtils::pathAppend(QString(sArg1), QString(sArg2)), + __FILE__, lineNo); assertEquals(exp, - ReFileUtils::pathAppend(sArg1.constData(), sArg2.constData()), - __FILE__, lineNo); + ReFileUtils::pathAppend(sArg1.constData(), sArg2.constData()), + __FILE__, lineNo); } void testPathAppend() { @@ -260,10 +270,10 @@ public: checkPathAppend("/abc", "/", "bef", __LINE__); } void checkReplaceExt(const char* expected, const char* arg1, - const char* arg2, int lineNo) { + const char* arg2, int lineNo) { assertEquals(QString(expected), - ReFileUtils::replaceExtension(QString(arg1), QString(arg2)), - __FILE__, lineNo); + ReFileUtils::replaceExtension(QString(arg1), QString(arg2)), + __FILE__, lineNo); assertEquals(expected, ReFileUtils::replaceExtension(arg1, arg2), __FILE__, lineNo); QByteArray exp(expected); @@ -273,11 +283,11 @@ public: sArg1.replace("/", "\\"); sArg2.replace("/", "\\"); assertEquals(QString(exp), - ReFileUtils::replaceExtension(QString(sArg1), QString(sArg2)), - __FILE__, lineNo); + ReFileUtils::replaceExtension(QString(sArg1), QString(sArg2)), + __FILE__, lineNo); assertEquals(exp, - ReFileUtils::replaceExtension(sArg1.constData(), sArg2.constData()), - __FILE__, lineNo); + ReFileUtils::replaceExtension(sArg1.constData(), sArg2.constData()), + __FILE__, lineNo); } void testReplaceExtension() { @@ -288,10 +298,11 @@ public: } virtual void run() { + testParentOf(); + testCleanPath(); testReplaceExtension(); testNodeOf(); testExtensionOf(); - testCleanPath(); testSetTimes(); testSeekTell(); testIsAbsolutePath(); diff --git a/gui/ReGuiValidator.cpp b/gui/ReGuiValidator.cpp index 608cf83..d98fa3b 100644 --- a/gui/ReGuiValidator.cpp +++ b/gui/ReGuiValidator.cpp @@ -154,6 +154,8 @@ void ReGuiValidator::setInHistory(QComboBox* combo, const QString& value) { } if (combo->count() > 20) combo->removeItem(20); + if (combo->currentText() != value) + combo->setCurrentText(value); } } diff --git a/guiwidget/ReFileTable.cpp b/guiwidget/ReFileTable.cpp index c616776..c95dc1d 100644 --- a/guiwidget/ReFileTable.cpp +++ b/guiwidget/ReFileTable.cpp @@ -51,7 +51,8 @@ ReFileTable::ReFileTable(QWidget *parent) : tableWidget->setColumnWidth(MODIFIED, 175); connect(pushButtonUp, SIGNAL(clicked()), SLOT(pushButtonUpClicked())); connect(pushButtonRoot, SIGNAL(clicked()), SLOT(pushButtonRootClicked())); - + connect(tableWidget, SIGNAL(cellDoubleClicked(int, int)), this, + SLOT(tableDoubleClicked(int, int))); tableWidget->setHorizontalHeaderLabels(labels); tableWidget->horizontalHeader()->setStretchLastSection(true); tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -108,16 +109,35 @@ void ReFileTable::fillTable() } } +/** + * Change the include/exclude patterns of the file table. + * + * @param patterns a comma separated list of patterns + */ +void ReFileTable::changePatterns(const QString& patterns) +{ + // update the history: + comboText(comboBoxPatterns); + matcher.setPatterns(patterns, ',', '-'); + fillTable(); +} + /** * Changes the current directory. * * @param directory full path of the new directory + * @return true: success
+ * false: error */ -void ReFileTable::chDir(const QString& directory){ +bool ReFileTable::changeDirectory(QString directory){ + bool rc = true; + directory = ReFileUtils::cleanPath(directory); + ReQStringUtils::ensureLastChar(directory, OS_SEPARATOR); if (directory != fileSystem->directory()){ if (directory.indexOf('*') < 0){ - if (fileSystem->setDirectory(directory) != ReFileSystem::EC_SUCCESS){ - say(LOG_ERROR, tr("unknown directory:") + " " + directory); + ReFileSystem::ErrorCode rc2 = fileSystem->setDirectory(directory); + if (rc2 != ReFileSystem::EC_SUCCESS){ + rc = say(LOG_ERROR, fileSystem->errorMessage(rc2) + " " + directory); } else { comboBoxPath->setCurrentText(directory); // update the history: @@ -128,6 +148,7 @@ void ReFileTable::chDir(const QString& directory){ } } + return rc; } /** @@ -142,21 +163,42 @@ void ReFileTable::keyPressEvent(QKeyEvent* event){ if (sender == comboBoxPath){ if (key == Qt::Key_Return){ if (modifiers == Qt::NoModifier) - chDir(comboBoxPath->currentText()); + changeDirectory(comboBoxPath->currentText()); } } else if (sender == comboBoxPatterns){ - + if (key == Qt::Key_Return && modifiers == Qt::NoModifier) + changePatterns(comboBoxPatterns->currentText()); } else if (sender == tableWidget){ - + if (key == Qt::Key_Return && modifiers == Qt::NoModifier) + openEntry(tableWidget->currentRow()); } } + +/** + * Starts the standard program for the given table entry. + * + * @param row the row containing the entry to open + */ +void ReFileTable::openEntry(int row){ + bool isDir = tableWidget->item(row, TYPE)->text().startsWith('<'); + QString node = tableWidget->item(row, NAME)->text(); + if (isDir){ + changeDirectory(fileSystem->directory() + node); + } else { + + } +} + /** * Handles the event push button "up" clicked() */ void ReFileTable::pushButtonUpClicked() { - chDir(ReFileUtils::parentOf(comboBoxPath->currentText())); + QString path(fileSystem->directory()); + path.resize(max(0, path.length() - 1)); + if (! path.isEmpty()) + changeDirectory(ReFileUtils::parentOf(path)); } /** @@ -164,7 +206,7 @@ void ReFileTable::pushButtonUpClicked() */ void ReFileTable::pushButtonRootClicked() { - chDir("/"); + changeDirectory("/"); } /** @@ -182,4 +224,11 @@ bool ReFileTable::say(ReLoggerLevel level, const QString& message) return level >= LOG_INFO; } - +/** + * Handles the double click of a table cell. + * + * @param index the abstract index of the cell + */ +void ReFileTable::tableDoubleClicked(int row, int column){ + openEntry(row); +} diff --git a/guiwidget/ReFileTable.hpp b/guiwidget/ReFileTable.hpp index 150749b..66b6cac 100644 --- a/guiwidget/ReFileTable.hpp +++ b/guiwidget/ReFileTable.hpp @@ -26,11 +26,16 @@ public slots: public: void fillTable(); - void chDir(const QString& directory); -protected slots: - void keyPressEvent(QKeyEvent* event); + void changePatterns(const QString& patterns); + bool changeDirectory(QString directory); +public: + virtual void keyPressEvent(QKeyEvent* event); +public slots: + void tableDoubleClicked(int row, int column); void pushButtonUpClicked(); void pushButtonRootClicked(); +protected: + void openEntry(int row); protected: QVBoxLayout* mainLayout; QHBoxLayout* horizontalLayout; diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index bff8b78..33aa0fc 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -87,6 +87,65 @@ ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source, return rc; } +/** + * Returns a message describing the given error code. + * + * @param errorCode code to convert + * @return a description of the error code + */ +QString ReFileSystem::errorMessage(ReFileSystem::ErrorCode errorCode) +{ + QString rc; + switch(errorCode){ + case EC_SUCCESS: + rc = QObject::tr("Success"); + break; + case EC_PATH_NOT_FOUND: + rc = QObject::tr("Path not found"); + break; + case EC_NOT_ACCESSIBLE: + rc = QObject::tr("not accessable"); + break; + case EC_NOT_READABLE: + rc = QObject::tr("not readable"); + break; + case EC_READ: + rc = QObject::tr("cannot read"); + break; + case EC_FS_READ_ONLY: + rc = QObject::tr("file is read only"); + break; + case EC_NOT_WRITEABLE: + rc = QObject::tr("file is not writeable"); + break; + case EC_WRITE: + rc = QObject::tr("cannot write"); + break; + case EC_POSITION: + rc = QObject::tr("cannot set new file position"); + break; + case EC_ALREADY_EXISTS: + rc = QObject::tr("file already exists"); + break; + case EC_NOT_EXISTS: + rc = QObject::tr("file does not exist"); + break; + case EC_RENAME: + rc = QObject::tr("file cannot renamed"); + break; + case EC_HEADER_LENGTH: + rc = QObject::tr("Header length mismatch"); + break; + case EC_MARKER: + rc = QObject::tr("marker mismatch"); + break; + default: + rc = QObject::tr("unknown error code: ") + QString::number(errorCode); + break; + } + return rc; +} + /** * Returns the name of the current directory. * @@ -216,25 +275,47 @@ void ReLocalFileSystem::close() { * Fills a list with the items of the current directory. * * @param matcher the matching processor + * @param list OUT: the list of the found files + * @param options a set (bitmap) of options, e.g. LO_FILES | LO_DIRS * @return the count of the found entries (list.size()) */ int ReLocalFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list) { + ReFileMetaDataList& list, ListOptions options) { list.clear(); + bool withDirs = (options & LO_DIRS) != 0; + bool withFiles = (options & LO_FILES) != 0; + if (! (withDirs | withFiles)) + withDirs = withFiles = true; + bool matchDirs = (options & LO_NAME_FILTER_FOR_DIRS) != 0; + bool earlyMatching = matchDirs || ! withDirs; const QStringList& patterns = matcher.includes().patterns(); QStringList nodes = - patterns.size() == 0 ? m_dir.entryList() : m_dir.entryList(patterns); + ! earlyMatching || patterns.size() == 0 + ? m_dir.entryList() : m_dir.entryList(patterns); QStringList::const_iterator it; QByteArray full = m_directory.toUtf8(); full.append(OS_SEPARATOR); int pathLength = full.length(); struct stat info; + const ReListMatcher& excludeMatcher = matcher.excludes(); + bool excludeActive = excludeMatcher.patterns().length() > 0; for (it = nodes.cbegin(); it != nodes.cend(); it++) { QString node = *it; if (node != "." && node != ".."){ + if (earlyMatching){ + if (excludeActive && excludeMatcher.matches(node)) + continue; + } full.resize(pathLength); full.append(node.toUtf8()); if (stat(full.constData(), &info) == 0) { + bool isDir = S_ISDIR(info.st_mode); + if (isDir && ! withDirs || ! isDir && ! withFiles) + continue; + if (! earlyMatching){ + if ( (! isDir || matchDirs) && ! matcher.matches(node)) + continue; + } list.append( ReFileMetaData(node, QDateTime::fromTime_t(info.st_mtime), QDateTime::fromTime_t(info.st_ctime), info.st_uid, diff --git a/os/ReFileSystem.hpp b/os/ReFileSystem.hpp index 5aad978..243aa41 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -48,12 +48,11 @@ typedef QList ReFileMetaDataList; class ReFileSystem { public: - enum ListOption { + enum ListOptions { LO_UNDEF = 0, LO_FILES = 1, LO_DIRS = 2, - LO_EXCLUDE_MATCH_FILES = 4, - LO_EXCLUDE_MATCH_DIRS = 8 + LO_NAME_FILTER_FOR_DIRS = 4, }; enum ErrorCode { @@ -86,10 +85,12 @@ public: virtual const QString& directory() const; /** Fills a list with the items of the current directory. * @param matcher the matching processor + * @param options a set (bitmap) of options, e.g. LO_FILES | LO_DIRS * @return the count of the found entries (list.size()) */ virtual int listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list) = 0; + ReFileMetaDataList& list, ListOptions opts + = ListOptions(LO_FILES | LO_DIRS )) = 0; /** Creates a directory. * @param node the name without path (in the current directory) * @return EC_SUCCESS or error code @@ -135,6 +136,7 @@ public: const QByteArray& buffer) = 0; public: virtual ErrorCode copy(ReFileMetaData& source, ReFileSystem& sourceFS); + virtual QString errorMessage(ErrorCode rc); public: int blocksize() const; bool first(const QString& pattern, ReFileMetaData& file); @@ -187,7 +189,7 @@ public: // ReFileSystem interface virtual void close(); virtual int listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list); + ReFileMetaDataList& list, ListOptions options); ErrorCode makeDir(const QString& node); virtual ErrorCode read(const ReFileMetaData& source, int64_t offset, int size, QByteArray& buffer); -- 2.39.5