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.
*
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.
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);
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);
class TestReQStringUtil: public ReTest {
public:
TestReQStringUtil() :
- ReTest("ReQStringUtil") {
+ ReTest("ReQStringUtil") {
doIt();
}
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);
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));
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);
}
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');
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();
}
+/**
+ * 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.
*
} 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();
}
}
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;
#include "QHeaderView"
#include "QKeyEvent"
#include "QApplication"
+#include "QClipboard"
+#include "QMimeData"
+#include "QUrl"
#include "guiwidget/ReFileTable.hpp"
#endif // REGUIWIDGET_HPP
* @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;
}
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;
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);
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.
*
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.
*
}
/**
- * 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
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;
}
/**
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);