From: hama Date: Mon, 2 Nov 2015 23:30:07 +0000 (+0100) Subject: Cntrl-C works in ReFileTable X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=56ae89bdd5f73598debd5c1e0ffdefd092b3e608;p=reqt Cntrl-C works in ReFileTable --- diff --git a/base/ReQStringUtils.cpp b/base/ReQStringUtils.cpp index d3b1ae0..264b16d 100644 --- a/base/ReQStringUtils.cpp +++ b/base/ReQStringUtils.cpp @@ -368,6 +368,38 @@ int ReQStringUtils::lengthOfReal(const ReString& text, int start, return found ? ix - start : 0; } +/** + * Returns the longest common prefix of a string list. + * + * @param list list to inspect + * + * @return the longest prefix which is common to all list entries + */ +QString ReQStringUtils::longestPrefix(const QStringList& list){ + QString rc; + if (list.length() > 0){ + rc.reserve(max(32, list.at(0).length())); + + QChar common; + bool found = true; + for (int ixPrefix = 0; found; ixPrefix++){ + if (ixPrefix >= list.at(0).length()) + found = false; + else { + common = list.at(0).at(ixPrefix); + for (int ixList = 1; found && ixList < list.length(); ++ixList){ + if (list.at(ixList).length() <= ixPrefix + || list.at(ixList).at(ixPrefix) != common) + found = false; + } + if (found) + rc.append(common); + } + } + } + return rc; +} + /** * Replaces placeholders by their values. * diff --git a/base/ReQStringUtils.hpp b/base/ReQStringUtils.hpp index 6f0e1cb..0a9da6d 100644 --- a/base/ReQStringUtils.hpp +++ b/base/ReQStringUtils.hpp @@ -33,6 +33,7 @@ public: 10, uint64_t* value = NULL); static int lengthOfUInt(const ReString& text, int start, int radix, uint* pValue); + static QString longestPrefix(const QStringList& list); static bool match(const QString& heap, const QStringList& needles); /** * Returns the path with native path separators. diff --git a/cunit/cuReFileSystem.cpp b/cunit/cuReFileSystem.cpp index d1b6d09..6c0da08 100644 --- a/cunit/cuReFileSystem.cpp +++ b/cunit/cuReFileSystem.cpp @@ -58,7 +58,7 @@ protected: ReFileMetaDataList nodes; ReIncludeExcludeMatcher matcher(ReListMatcher::allMatchingList(), ReQStringUtils::m_emptyList, Qt::CaseInsensitive, false); - fs.listInfos(matcher, nodes); + fs.listInfos(matcher, nodes, ReFileSystem::LO_UNDEF); testContains("dir1", nodes); testContains("test1.txt", nodes); testContains("test7.txt", nodes); @@ -75,7 +75,7 @@ protected: names.append("abc.txt"); ReIncludeExcludeMatcher matcher(names, ReQStringUtils::m_emptyList, Qt::CaseInsensitive, true); - checkEqu(1, fs.listInfos(matcher, nodes)); + checkEqu(1, fs.listInfos(matcher, nodes, ReFileSystem::LO_UNDEF)); checkEqu(1, nodes.size()); checkEqu(0, fs.read(nodes.at(0), 0LL, 3, buffer2)); checkEqu("abc", buffer2); diff --git a/cunit/cuReQStringUtils.cpp b/cunit/cuReQStringUtils.cpp index cdfa81f..5281f4c 100644 --- a/cunit/cuReQStringUtils.cpp +++ b/cunit/cuReQStringUtils.cpp @@ -17,7 +17,7 @@ class TestReQStringUtil: public ReTest { public: TestReQStringUtil() : - ReTest("ReQStringUtil") { + ReTest("ReQStringUtil") { doIt(); } @@ -35,20 +35,20 @@ public: void testLengthOfUInt64() { quint64 value = -3; checkEqu(1, - ReQStringUtils::lengthOfUInt64(ReString("0"), 0, 10, &value)); + ReQStringUtils::lengthOfUInt64(ReString("0"), 0, 10, &value)); checkEqu(int64_t(0), value); checkEqu(3, ReQStringUtils::lengthOfUInt64("x432", 1, 10, &value)); checkEqu(int64_t(432LL), value); checkEqu(3, ReQStringUtils::lengthOfUInt64("x432 x", 1, 10, &value)); checkEqu(int64_t(432LL), value); checkEqu(3, - ReQStringUtils::lengthOfUInt64("x432fabc x", 1, 10, &value)); + ReQStringUtils::lengthOfUInt64("x432fabc x", 1, 10, &value)); checkEqu(int64_t(432LL), value); checkEqu(16, - ReQStringUtils::lengthOfUInt64("a1234567890123567", 1, 10, &value)); + ReQStringUtils::lengthOfUInt64("a1234567890123567", 1, 10, &value)); checkEqu(int64_t(1234567890123567LL), value); checkEqu(10, - ReQStringUtils::lengthOfUInt64("x1234abcdef", 1, 16, &value)); + ReQStringUtils::lengthOfUInt64("x1234abcdef", 1, 16, &value)); checkEqu(int64_t(0x1234abcdefLL), value); checkEqu(3, ReQStringUtils::lengthOfUInt64("432", 0, 8, &value)); checkEqu(int64_t(0432LL), value); @@ -85,19 +85,19 @@ public: checkEqu(1, ReQStringUtils::lengthOfReal(ReString(" 0"), 1, &value)); checkEqu(0.0, value); checkEqu(17, - ReQStringUtils::lengthOfReal(ReString("X12345678901234567"), 1, - &value)); + ReQStringUtils::lengthOfReal(ReString("X12345678901234567"), 1, + &value)); checkEqu(12345678901234567.0, value); checkEqu(2, ReQStringUtils::lengthOfReal(ReString(".5"), 0, &value)); checkEqu(0.5, value); checkEqu(5, - ReQStringUtils::lengthOfReal(ReString("2.5e2x"), 0, &value)); + ReQStringUtils::lengthOfReal(ReString("2.5e2x"), 0, &value)); checkEqu(250.0, value); checkEqu(6, - ReQStringUtils::lengthOfReal(ReString("2.5e+2"), 0, &value)); + ReQStringUtils::lengthOfReal(ReString("2.5e+2"), 0, &value)); checkEqu(250.0, value); checkEqu(7, - ReQStringUtils::lengthOfReal(ReString("2.5E-33"), 0, &value)); + ReQStringUtils::lengthOfReal(ReString("2.5E-33"), 0, &value)); checkEqu(2.5e-33, value); checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E"), 0, &value)); @@ -105,7 +105,7 @@ public: checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E+"), 0, &value)); checkEqu(2.5, value); checkEqu(3, - ReQStringUtils::lengthOfReal(ReString("2.5E-a"), 0, &value)); + ReQStringUtils::lengthOfReal(ReString("2.5E-a"), 0, &value)); checkEqu(2.5, value); } @@ -128,7 +128,7 @@ public: ReString name = "Heinz Müller"; char buffer[32]; checkEqu("Heinz Müller", - ReQStringUtils::utf8(name, buffer, sizeof buffer)); + ReQStringUtils::utf8(name, buffer, sizeof buffer)); memset(buffer, 'x', sizeof buffer); checkEqu("Heinz", ReQStringUtils::utf8(name, buffer, (size_t)(5 + 1))); checkEqu(buffer[6], 'x'); @@ -186,8 +186,28 @@ public: checkEqu(8, ReQStringUtils::lengthOfTime("301:02:09x", 1, &time)); checkEqu(QTime(1, 2, 9), time); } + void testLongestPrefix(){ + QStringList list; + list << "def" << "demask" << "destruct"; + checkEqu("de", ReQStringUtils::longestPrefix(list)); + list.clear(); + list << "demask" << "def" << "destruct"; + checkEqu("de", ReQStringUtils::longestPrefix(list)); + list.clear(); + list << "demask" << "destruct" << "de"; + checkEqu("de", ReQStringUtils::longestPrefix(list)); + list.clear(); + list << "de" << "demask" << "destruct"; + checkEqu("de", ReQStringUtils::longestPrefix(list)); + list.clear(); + list << "destruct"; + checkEqu("destruct", ReQStringUtils::longestPrefix(list)); + list.clear(); + checkEqu("", ReQStringUtils::longestPrefix(list)); + } virtual void run(void) { + testLongestPrefix(); testLengtOfTime(); testLengtOfDate(); testDateTimeParser(); diff --git a/guiwidget/ReFileTable.cpp b/guiwidget/ReFileTable.cpp index c95dc1d..c1fe2e1 100644 --- a/guiwidget/ReFileTable.cpp +++ b/guiwidget/ReFileTable.cpp @@ -66,6 +66,84 @@ ReFileTable::~ReFileTable() } +/** + * Gets the absolute path of the file in the given row. + * + * @param row the row number + * @param withNode true: the node will be appended to the result + * @param uriFormat true: example: file:///u:/tmp/file.txt
+ * false: example: u:\tmp\file.txt + * @return the absolute path of the file given by the row + */ +QString ReFileTable::buildAbsPath(int row, bool withNode, bool uriFormat){ + QString rc; + QString node = cellAsText(row, NAME); + rc.reserve(7 + fileSystem->directory().length() + node.length()); + rc = "file://"; + rc.append(fileSystem->directory()); + if (withNode) + rc.append(node); + if (uriFormat){ +#if defined WIN32 + rc = rc.replace('\\', '/'); +#endif + } + return rc; +} + +/** + * Gets the content of the given cell as string. + * + * @param row the row number: 0..R-1 + * @param col the column number: 0..C-1 + * @return the text of the given cell + */ +QString ReFileTable::cellAsText(int row, int col){ + QTableWidgetItem* widget = tableWidget->item(row, col); + QString rc; + if (widget != NULL) + rc = widget->text(); + return rc; +} + +/** + * Copies the selected files into the clipboard. + * + * @param currentRow the row where the context menu is called + * @param full the full name of the current row + */ +void ReFileTable::copyToClipboard(int currentRow, const QString& full){ + QMimeData *mimeData = new QMimeData; + QList < QUrl > urls; + bool isInSelection = currentRow == -1; + QList < QTableWidgetSelectionRange > ranges = + tableWidget->selectedRanges(); + QList ::iterator it; + QString textList; + textList.reserve(tableWidget->rowCount() * 80); + for (it = ranges.begin(); it != ranges.end(); ++it){ + for (int row = (*it).topRow(); row <= (*it).bottomRow(); row++){ + if (currentRow != -1) + isInSelection = isInSelection || row == currentRow; + QString name(buildAbsPath(row, true)); + QUrl url(name); + textList += name + '\n'; + urls.append(url); + } + } + if (!isInSelection){ + urls.clear(); + urls.append(QUrl(full)); + textList = full; + } + mimeData->setUrls(urls); + mimeData->setText(textList); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setMimeData(mimeData); + say(LOG_INFO, + tr("%1 entry/entries copied to clipboard").arg(urls.length())); +} + /** * Fills the table with the file data of the filesystem. * @@ -171,6 +249,8 @@ void ReFileTable::keyPressEvent(QKeyEvent* event){ } else if (sender == tableWidget){ if (key == Qt::Key_Return && modifiers == Qt::NoModifier) openEntry(tableWidget->currentRow()); + else if (key == Qt::Key_C && modifiers == Qt::ControlModifier) + copyToClipboard(); } } diff --git a/guiwidget/ReFileTable.hpp b/guiwidget/ReFileTable.hpp index 66b6cac..379b163 100644 --- a/guiwidget/ReFileTable.hpp +++ b/guiwidget/ReFileTable.hpp @@ -35,6 +35,10 @@ public slots: void pushButtonUpClicked(); void pushButtonRootClicked(); protected: + QString buildAbsPath(int row, bool withNode = false, bool uriFormat = false); + QString cellAsText(int row, int col); + void copyToClipboard(int currentRow = -1, + const QString& full = ReQStringUtils::m_empty); void openEntry(int row); protected: QVBoxLayout* mainLayout; diff --git a/guiwidget/reguiwidget.hpp b/guiwidget/reguiwidget.hpp index 1c927f5..0325f8f 100644 --- a/guiwidget/reguiwidget.hpp +++ b/guiwidget/reguiwidget.hpp @@ -27,6 +27,9 @@ #include "QHeaderView" #include "QKeyEvent" #include "QApplication" +#include "QClipboard" +#include "QMimeData" +#include "QUrl" #include "guiwidget/ReFileTable.hpp" #endif // REGUIWIDGET_HPP diff --git a/os/ReCryptFileSystem.cpp b/os/ReCryptFileSystem.cpp index 42d00f5..0bb63ab 100644 --- a/os/ReCryptFileSystem.cpp +++ b/os/ReCryptFileSystem.cpp @@ -71,7 +71,7 @@ void ReCryptFileSystem::close() * @return the count of the found entries (list.size()) */ int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list) { + ReFileMetaDataList& list, ListOptions options) { return 0; } @@ -380,7 +380,7 @@ bool ReCryptDirectory::writeMetaFile() FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb"); if (fp == NULL){ m_logger->logv(LOG_ERROR, LOC_WRITE_META_1, "cannot write (%d): %s", - errno, fnMetaFile.constData()); + errno, fnMetaFile.constData()); } else { m_fileBuffer.append(header); int ixList = 0; diff --git a/os/ReCryptFileSystem.hpp b/os/ReCryptFileSystem.hpp index 15181db..42c49cc 100644 --- a/os/ReCryptFileSystem.hpp +++ b/os/ReCryptFileSystem.hpp @@ -89,7 +89,7 @@ public: public: virtual void close(); virtual int listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list); + ReFileMetaDataList& list, ListOptions options = LO_UNDEF); virtual ErrorCode makeDir(const QString& node); virtual ErrorCode read(const ReFileMetaData& source, int64_t offset, int size, QByteArray& buffer); diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index 33aa0fc..7638e6d 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -57,6 +57,15 @@ ReFileSystem::ReFileSystem(const QString& name, ReLogger* logger) : ReFileSystem::~ReFileSystem() { } +/** + * Returns the current blocksize (for copy operations). + * + * @return the current blocksize + */ +int ReFileSystem::blocksize() const { + return m_blocksize; +} + /** * Copy a file from a source filesystem to the current directory of the instance. * @@ -87,6 +96,15 @@ ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source, return rc; } +/** + * Returns the name of the current directory. + * + * @return the name of the current directory + */ +const QString& ReFileSystem::directory() const { + return m_directory; +} + /** * Returns a message describing the given error code. * @@ -147,22 +165,56 @@ QString ReFileSystem::errorMessage(ReFileSystem::ErrorCode errorCode) } /** - * Returns the name of the current directory. + * Finds the first file given by a pattern. * - * @return the name of the current directory + * @param pattern pattern to find + * @param file OUT: the found file (valid only if return code is true + * @return true: at least one file found
+ * false: no file found */ -const QString& ReFileSystem::directory() const { - return m_directory; +bool ReFileSystem::first(const QString& pattern, ReFileMetaData& file) { + ReFileMetaDataList list; + QStringList names; + names.append(pattern); + ReIncludeExcludeMatcher matcher(names, ReQStringUtils::m_emptyList, + Qt::CaseInsensitive, true); + listInfos(matcher, list); + bool rc = list.size() > 0; + if (rc) + file = list.at(0); + return rc; } /** - * Returns whether the filesystem is writeable. + * Finds all nodes with a given prefix. * - * @return true: modification in the filesystem are possible - * false: read only filesystem + * @param prefix IN: prefix to search OUT: common prefix of all found nodes, + * prefix "on", found nodes: 'onFilterA', 'onFilterB' + * result prefix: 'onFilter' + * @param options LO_FILES or LO_DIRS or both (or-combined) + * @param list list with the nodes starting with the prefix + * @return list.length() */ -bool ReFileSystem::writeable() const { - return m_writeable; +int ReFileSystem::nodesByPrefix(QString& prefix, ListOptions options, + QStringList& list) +{ + int rc = 0; + list.clear(); + + ReFileMetaDataList entries; + ReIncludeExcludeMatcher matcher(prefix + "*", Qt::CaseInsensitive, true); + if (listInfos(matcher, entries, options) > 0){ + ReFileMetaDataList::const_iterator it; + for (it = entries.cbegin(); it != entries.cend(); ++it) + list.append(it->m_node); + if (list.length() == 1) + prefix = list.at(0); + else { + prefix = ReQStringUtils::longestPrefix(list); + } + } + + return rc; } ReOSPermissions ReFileSystem::osPermissions() const @@ -184,42 +236,22 @@ void ReFileSystem::setWriteable(bool writeable) { m_writeable = writeable; } /** - * Returns the current blocksize (for copy operations). - * - * @return the current blocksize - */ -int ReFileSystem::blocksize() const { - return m_blocksize; -} - -/** - * Finds the first file given by a pattern. + * Sets the size of the internal buffer for copy operations. * - * @param pattern pattern to find - * @param file OUT: the found file (valid only if return code is true - * @return true: at least one file found
- * false: no file found + * @param blocksize the new blocksize */ -bool ReFileSystem::first(const QString& pattern, ReFileMetaData& file) { - ReFileMetaDataList list; - QStringList names; - names.append(pattern); - ReIncludeExcludeMatcher matcher(names, ReQStringUtils::m_emptyList, - Qt::CaseInsensitive, true); - listInfos(matcher, list); - bool rc = list.size() > 0; - if (rc) - file = list.at(0); - return rc; +void ReFileSystem::setBlocksize(int blocksize) { + m_blocksize = blocksize; } /** - * Sets the size of the internal buffer for copy operations. + * Returns whether the filesystem is writeable. * - * @param blocksize the new blocksize + * @return true: modification in the filesystem are possible + * false: read only filesystem */ -void ReFileSystem::setBlocksize(int blocksize) { - m_blocksize = blocksize; +bool ReFileSystem::writeable() const { + return m_writeable; } /** diff --git a/os/ReFileSystem.hpp b/os/ReFileSystem.hpp index 243aa41..01f9795 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -154,6 +154,7 @@ public: QByteArray fullNameAsUTF8(const QString& node) const { return (m_directory + node).toUtf8(); } + int nodesByPrefix(QString& prefix, ListOptions options, QStringList& list); ReOSPermissions osPermissions() const; void setBlocksize(int blocksize); void setOsPermissions(const ReOSPermissions& osPermissions);