]> gitweb.hamatoma.de Git - reqt/commitdiff
Cntrl-C works in ReFileTable
authorhama <hama@siduction.net>
Mon, 2 Nov 2015 23:30:07 +0000 (00:30 +0100)
committerhama <hama@siduction.net>
Mon, 2 Nov 2015 23:30:07 +0000 (00:30 +0100)
base/ReQStringUtils.cpp
base/ReQStringUtils.hpp
cunit/cuReFileSystem.cpp
cunit/cuReQStringUtils.cpp
guiwidget/ReFileTable.cpp
guiwidget/ReFileTable.hpp
guiwidget/reguiwidget.hpp
os/ReCryptFileSystem.cpp
os/ReCryptFileSystem.hpp
os/ReFileSystem.cpp
os/ReFileSystem.hpp

index d3b1ae07530d90e1761095a5160ef28fa2ea7761..264b16d95a7dcb2b4dd1cd2eefb54d485f1972c4 100644 (file)
@@ -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.
  *
index 6f0e1cb6babc438b0861859e7a61c5475f1646ef..0a9da6d195635529af086bcccb9b0ab187aca276 100644 (file)
@@ -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.
index d1b6d0911f299c4182777fe6507b1109c7297b46..6c0da088fb05423a9a99d6a84c18651f14ce640d 100644 (file)
@@ -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);
index cdfa81f0623c8384f6cb038b9350654cd8c3f3a7..5281f4cbded7c7bcfa456e71d6de4ac3dfb558ab 100644 (file)
@@ -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();
index c95dc1d14b5e9e9009062a4a48ae0f5ef400c574..c1fe2e12a3a77fae6b4b79726af805c8c0afb221 100644 (file)
@@ -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<br>
+ *                  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 <QTableWidgetSelectionRange>::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();
        }
 
 }
index 66b6cac240084794e79dbdd0df6814555ce21577..379b16316da0b0f2b4bb338edc6b4a213b7bdd6e 100644 (file)
@@ -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;
index 1c927f5cf3d58af22349b0efe9c3144d3c839e2e..0325f8f9e3237ae1b1ccec420576b022f84eeab6 100644 (file)
@@ -27,6 +27,9 @@
 #include "QHeaderView"
 #include "QKeyEvent"
 #include "QApplication"
+#include "QClipboard"
+#include "QMimeData"
+#include "QUrl"
 #include "guiwidget/ReFileTable.hpp"
 #endif // REGUIWIDGET_HPP
 
index 42d00f573db748456beb7b2cfc1ad701f5fb2aad..0bb63abf7f9e930f21bf2429755ee3dc4438ecbf 100644 (file)
@@ -71,7 +71,7 @@ void ReCryptFileSystem::close()
  * @return                     the count of the found entries (<code>list.size()</code>)
  */
 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;
index 15181dba397f85bbccbb043b1d755f0f2f2ebb07..42c49cc0233dd4be987297406e0c3ec947747d23 100644 (file)
@@ -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);
index 33aa0fccd157addb9589a17764c5fb81083da080..7638e6d89d377494a47d6b8a448ca1f1bc7dd0cb 100644 (file)
@@ -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 <code>true</code>
+ * @return                     <code>true</code>: at least one file found<br>
+ *                                     <code>false</code>: 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     <code>true</code>: modification in the filesystem are possible
- *                     <code>false</code>: 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                     <code>list.length()</code>
  */
-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 <code>true</code>
- * @return                     <code>true</code>: at least one file found<br>
- *                                     <code>false</code>: 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     <code>true</code>: modification in the filesystem are possible
+ *                     <code>false</code>: read only filesystem
  */
-void ReFileSystem::setBlocksize(int blocksize) {
-       m_blocksize = blocksize;
+bool ReFileSystem::writeable() const {
+       return m_writeable;
 }
 
 /**
index 243aa41681b7adb49cee5b38c7dd93abf7e24cbd..01f9795ca6bc7b4e402493456d7871f2e0e86ff9 100644 (file)
@@ -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);