From 258fe58547dcdd0a04dae0c53e1841bde112a472 Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 23 Feb 2024 21:10:13 +0100 Subject: [PATCH 01/28] switch RsCollection to using RsfileTree as a base structure instead of a QDomDocument (not compiling yet) --- .../src/gui/common/RsCollection.cpp | 235 ++++++++++++++---- retroshare-gui/src/gui/common/RsCollection.h | 28 ++- retroshare-gui/src/retroshare-gui.pro | 2 + 3 files changed, 212 insertions(+), 53 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index c49296503..1baaed636 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -38,27 +38,20 @@ const QString RsCollection::ExtensionString = QString("rscollection") ; RsCollection::RsCollection(QObject *parent) - : QObject(parent), _xml_doc("RsCollection") + : QObject(parent) { - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); +// _root = _xml_doc.createElement("RsCollection"); +// _xml_doc.appendChild(_root); } -RsCollection::RsCollection(const RsFileTree& fr) - : _xml_doc("RsCollection") +RsCollection::RsCollection(const RsFileTree& ft) + : mFileTree(ft) { - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); - - recursAddElements(_xml_doc,fr,0,_root) ; } RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) - : QObject(parent), _xml_doc("RsCollection") + : QObject(parent) { - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); - if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) { std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; @@ -66,7 +59,7 @@ RsCollection::RsCollection(const std::vector& file_infos,FileSearchF } for(uint32_t i = 0;i colFileInfos; @@ -100,6 +96,7 @@ void RsCollection::autoDownloadFiles() const { autoDownloadFiles(colFileInfo, dlDir); } +#endif } void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const @@ -145,6 +142,8 @@ static QString purifyFileName(const QString& input,bool& bad) void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) { + mFileTree.addFile(mFileTree.root(),fname.toStdString(),hash,size); +#ifdef TO_REMOVE ColFileInfo info ; info.type = DIR_TYPE_FILE ; info.name = fname ; @@ -152,12 +151,45 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& info.hash = QString::fromStdString(hash.toStdString()) ; recursAddElements(_xml_doc,info,_root) ; +#endif } void RsCollection::merge_in(const RsFileTree& tree) { - recursAddElements(_xml_doc,tree,0,_root) ; + RsFileTree::DirData dd; + tree.getDirectoryContent(tree.root(),dd); + + recursMergeTree(mFileTree.root(),tree,dd) ; } +void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) +{ + for(uint32_t i=0;i& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const { QDomNode n = e.firstChild() ; @@ -211,43 +243,33 @@ void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vectorRequestDirDetails(details.children[i].ref, subDirDetails, flags)) + if (!rsFiles->RequestDirDetails(dd.children[i].ref, subDirDetails, flags)) continue; - recursAddElements(doc,subDirDetails,d,flags) ; + recursAddElements(new_dir_index,subDirDetails,flags) ; } - - e.appendChild(d) ; } } +#ifdef TO_REMOVE void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const { if (colFileInfo.type == DIR_TYPE_FILE) @@ -300,6 +322,7 @@ void RsCollection::recursAddElements( d.appendChild(f) ; } } +#endif static void showErrorBox(const QString& fileName, const QString& error) { @@ -322,16 +345,11 @@ bool RsCollection::load(const QString& fileName, bool showError /* = true*/) return false; } - bool ok = _xml_doc.setContent(&file) ; + QDomDocument xml_doc; + bool ok = xml_doc.setContent(&file) ; file.close(); - if (ok) { - _fileName = fileName; - } else { - if (showError) { - showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Error parsing xml file")); - } - } + return ok; } @@ -404,6 +422,8 @@ bool RsCollection::checkFile(const QString& fileName, bool showError) } return false; } + +#ifdef TO_REMOVE bool RsCollection::load(QWidget *parent) { QString fileName; @@ -414,6 +434,7 @@ bool RsCollection::load(QWidget *parent) return load(fileName, true); } +#endif bool RsCollection::save(const QString& fileName) const { @@ -425,16 +446,129 @@ bool RsCollection::save(const QString& fileName) const return false; } - QTextStream stream(&file) ; + QDomDocument xml_doc ; + QDomElement root = xml_doc.createElement("RsCollection"); + + RsFileTree::DirData root_data; + if(!mFileTree.getDirectoryContent(mFileTree.root(),root_data)) + return false; + + if(!recursExportToXml(xml_doc,root,root_data)) + return false; + + xml_doc.appendChild(root); + + QTextStream stream(&file) ; stream.setCodec("UTF-8") ; - stream << _xml_doc.toString() ; - + stream << xml_doc.toString() ; file.close(); return true; } +bool RsCollection::recursParseXml(QDomDocument& doc,const QDomElement& e,const RsFileTree::DirIndex parent) +{ + QDomNode n = e.firstChild() ; +#ifdef COLLECTION_DEBUG + std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; +#endif + + while(!n.isNull()) + { + QDomElement ee = n.toElement(); // try to convert the node to an element. + +#ifdef COLLECTION_DEBUG + std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl; +#endif + + if(ee.tagName() == QString("File")) + { + RsFileHash hash(ee.attribute(QString("sha1")).toStdString()) ; + + bool bad_chars_detected = false; + std::string name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected).toUtf8().constData() ; + uint64_t size = ee.attribute(QString("size")).toULongLong() ; + + mFileTree.addFile(parent,name,hash,size); +#ifdef TO_REMOVE + mFileTree.addFile(parent,) + ColFileInfo newChild ; + bool bad_chars_detected = false ; + newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; + newChild.size = ee.attribute(QString("size")).toULongLong() ; + newChild.path = current_path ; + newChild.type = DIR_TYPE_FILE ; + + colFileInfos.push_back(newChild) ; +#endif + } + else if(ee.tagName() == QString("Directory")) + { + bool bad_chars_detected = false ; + std::string cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected).toUtf8().constData() ; + + RsFileTree::DirIndex new_dir_index = mFileTree.addDirectory(parent,cleanDirName); + + recursParseXml(doc,ee,new_dir_index); +#ifdef TO_REMOVE + newParent.name=cleanDirName; + newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; + newParent.size = 0; + newParent.path = current_path ; + newParent.type = DIR_TYPE_DIR ; + + recursCollectColFileInfos(ee,newParent.children,current_path + "/" + cleanDirName, bad_chars_in_parent || bad_chars_detected) ; + uint32_t size = newParent.children.size(); + for(uint32_t i=0;i colFileInfos; @@ -548,6 +686,7 @@ qulonglong RsCollection::size() } return size; +#endif } bool RsCollection::isCollectionFile(const QString &fileName) @@ -557,6 +696,7 @@ bool RsCollection::isCollectionFile(const QString &fileName) return (ext == RsCollection::ExtensionString); } +#ifdef TO_REMOVE void RsCollection::saveColl(std::vector colFileInfos, const QString &fileName) { @@ -568,3 +708,4 @@ void RsCollection::saveColl(std::vector colFileInfos, const QString _saved=save(fileName); } +#endif diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 492d407d8..e21c118d2 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -62,7 +62,7 @@ public: RsCollection(QObject *parent = 0) ; // create from list of files and directories RsCollection(const std::vector& file_entries, FileSearchFlags flags, QObject *parent = 0) ; - RsCollection(const RsFileTree& fr); + RsCollection(const RsFileTree& ft); virtual ~RsCollection() ; void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ; @@ -70,12 +70,14 @@ public: static const QString ExtensionString ; - // Loads file from disk. +#ifdef TO_REMOVE bool load(QWidget *parent); - bool load(const QString& fileName, bool showError = true); + bool save(QWidget *parent) const ; +#endif + // Loads file from disk. + bool load(const QString& fileName, bool showError = true); // Save to disk - bool save(QWidget *parent) const ; bool save(const QString& fileName) const ; // Open new collection @@ -97,22 +99,36 @@ private slots: private: - void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ; + bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; + bool recursParseXml(QDomDocument& doc,const QDomElement& e,RsFileTree::DirIndex dd) ; + + // This function is used to populate a RsCollection from locally or remotly shared files. + void recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags) ; + + // This function is used to merge an existing RsFileTree into the RsCollection + void recursMergeTree(RsFileTree::DirIndex parent, const RsFileTree& tree, const RsFileTree::DirData &dd); + +#ifdef TO_REMOVE void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const; void recursAddElements( QDomDocument& doc, const RsFileTree& ft, uint32_t index, QDomElement& e ) const; void recursCollectColFileInfos(const QDomElement&,std::vector& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ; - // check that the file is a valid rscollection file, and not a lol bomb or some shit like this +#endif + + // check that the file is a valid rscollection file, and not a lol bomb or some shit like this static bool checkFile(const QString &fileName, bool showError); // Auto Download recursively. void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; + RsFileTree mFileTree; +#ifdef TO_REMOVE QDomDocument _xml_doc ; QString _fileName ; bool _saved; QDomElement _root ; +#endif friend class RsCollectionDialog ; }; diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index b27102d42..d73117b84 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -519,6 +519,7 @@ HEADERS += rshare.h \ gui/common/vmessagebox.h \ gui/common/RsUrlHandler.h \ gui/common/RsCollectionDialog.h \ + gui/common/RsCollectionModel.h \ gui/common/rwindow.h \ gui/common/rshtml.h \ gui/common/AvatarDefs.h \ @@ -845,6 +846,7 @@ SOURCES += main.cpp \ gui/common/ElidedLabel.cpp \ gui/common/vmessagebox.cpp \ gui/common/RsCollectionDialog.cpp \ + gui/common/RsCollectionModel.cpp \ gui/common/RsUrlHandler.cpp \ gui/common/rwindow.cpp \ gui/common/rshtml.cpp \ From 206da93d99ae119f9be121e2b5a604f12f9b33ca Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 24 Feb 2024 15:55:21 +0100 Subject: [PATCH 02/28] fixed a few compilation errors in RsCollection handling --- .../src/gui/FileTransfer/SearchDialog.cpp | 33 ++-- .../gui/FileTransfer/SharedFilesDialog.cpp | 23 ++- .../src/gui/FileTransfer/TransfersDialog.cpp | 45 ++--- retroshare-gui/src/gui/RetroShareLink.cpp | 10 +- .../src/gui/common/RsCollection.cpp | 169 +++++++++++------- retroshare-gui/src/gui/common/RsCollection.h | 22 ++- 6 files changed, 181 insertions(+), 121 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index 832970833..ed2498545 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -597,32 +597,35 @@ void SearchDialog::collOpen() if (rsFiles->FileDetails(hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE - | RS_FILE_HINTS_SPEC_ONLY, info)) { - + | RS_FILE_HINTS_SPEC_ONLY, info)) + { /* make path for downloaded files */ std::string path; path = info.path; /* open file with a suitable application */ QFileInfo qinfo; + RsCollection::RsCollectionErrorCode err; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath())) { - collection.downloadFiles(); - return; - } - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollection(qinfo.absoluteFilePath(),err).downloadFiles(); } } } - RsCollection collection; - if (collection.load(this)) { - collection.downloadFiles(); - }//if (collection.load(this)) + QString fileName; + if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + RsCollection::RsCollectionErrorCode err; + RsCollection collection(fileName, err); + + if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) + collection.downloadFiles(); + else + QMessageBox::information(nullptr,tr("Error open RsCollection file"),RsCollection::errorString(err)); } void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 5abe9ab39..4645841a9 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -652,7 +652,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList< QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); - RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ; + RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->totalFileSize(),ft->numFiles(),QString::fromStdString(ft->toRadix64())) ; if(link.valid()) urls.push_back(link) ; @@ -821,8 +821,12 @@ void SharedFilesDialog::collOpen() qinfo.setFile(QString::fromUtf8(path.c_str())); if (qinfo.exists()) { if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath())) { + + RsCollection::RsCollectionErrorCode err; + RsCollection collection(qinfo.absoluteFilePath(),err); + + if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) + { collection.downloadFiles(); return; } @@ -831,10 +835,17 @@ void SharedFilesDialog::collOpen() } } - RsCollection collection; - if (collection.load(this)) { + QString fileName; + if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + RsCollection::RsCollectionErrorCode err; + RsCollection collection(fileName,err); + + if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) collection.downloadFiles(); - } } void LocalSharedFilesDialog::playselectedfiles() diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index 6fc45a070..8dca82e28 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -2564,23 +2564,29 @@ void TransfersDialog::collOpen() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath())) { - collection.downloadFiles(); - return; - } - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + { + RsCollection::RsCollectionErrorCode code; + RsCollection(qinfo.absoluteFilePath(),code).downloadFiles(); + return; + } } } } - RsCollection collection; - if (collection.load(this)) { + QString fileName; + if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + RsCollection::RsCollectionErrorCode code; + RsCollection collection(fileName,code); + + if(code == RsCollection::RsCollectionErrorCode::NO_ERROR) collection.downloadFiles(); - } + else + QMessageBox::information(nullptr,tr("Error openning collection file"),RsCollection::errorString(code)); } void TransfersDialog::collAutoOpen(const QString &fileHash) @@ -2592,21 +2598,18 @@ void TransfersDialog::collAutoOpen(const QString &fileHash) if (rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info)) { /* make path for downloaded files */ - if (info.downloadStatus == FT_STATE_COMPLETE) { + if (info.downloadStatus == FT_STATE_COMPLETE) + { std::string path; path = info.path + "/" + info.fname; /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath(), false)) { - collection.autoDownloadFiles(); - } - } - } + RsCollection::RsCollectionErrorCode err; + + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollection(qinfo.absoluteFilePath(),err).autoDownloadFiles(); } } } diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 6e377f70e..f87c72760 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -1143,11 +1143,13 @@ QString RetroShareLink::toHtmlSize() const if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) { FileInfo finfo; - if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) { - RsCollection collection; - if (collection.load(QString::fromUtf8(finfo.path.c_str()), false)) { + if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) + { + RsCollection::RsCollectionErrorCode code; + RsCollection collection(QString::fromUtf8(finfo.path.c_str()), code) ; + + if(code == RsCollection::RsCollectionErrorCode::NO_ERROR) size += QString(" [%1]").arg(misc::friendlyUnit(collection.size())); - } } } QString link = QString("%2 %3").arg(toString()).arg(name()).arg(size); diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 1baaed636..08474fb19 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -330,97 +330,128 @@ static void showErrorBox(const QString& fileName, const QString& error) mb.exec(); } -bool RsCollection::load(const QString& fileName, bool showError /* = true*/) +QString RsCollection::errorString(RsCollectionErrorCode code) { + switch(code) + { + default: [[fallthrough]] ; + case RsCollectionErrorCode::UNKNOWN_ERROR: return tr("Unknown error"); + case RsCollectionErrorCode::NO_ERROR: return tr("No error"); + case RsCollectionErrorCode::FILE_READ_ERROR: return tr("Error while openning file"); + case RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS: return tr("Collection file contains potentially harmful code"); + case RsCollectionErrorCode::INVALID_ROOT_NODE: return tr("Invalid root node. RsCollection node was expected."); + case RsCollectionErrorCode::XML_PARSING_ERROR: return tr("XML parsing error in collection file"); + } +} - if (!checkFile(fileName,showError)) return false; - QFile file(fileName); +RsCollection::RsCollection(const QString& fileName, RsCollectionErrorCode& error) +{ + if (!checkFile(fileName,error)) + return ; - if (!file.open(QIODevice::ReadOnly)) - { - std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; - if (showError) { - showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName)); - } - return false; - } + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly)) + { + std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; + error = RsCollectionErrorCode::FILE_READ_ERROR; + //showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName)); + return ; + } QDomDocument xml_doc; bool ok = xml_doc.setContent(&file) ; - file.close(); + if(!ok) + { + error = RsCollectionErrorCode::XML_PARSING_ERROR; + return; + } + file.close(); + QDomNode root = xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - return ok; + if(root.isNull()) + { + error = RsCollectionErrorCode::INVALID_ROOT_NODE; + return; + } + + recursParseXml(xml_doc,root,0); + error = RsCollectionErrorCode::NO_ERROR; } - // check that the file is a valid rscollection file, and not a lol bomb or some shit like this -bool RsCollection::checkFile(const QString& fileName, bool showError) +// check that the file is a valid rscollection file, and not a lol bomb or some shit like this + +bool RsCollection::checkFile(const QString& fileName, RsCollectionErrorCode& error) { - QFile file(fileName); + QFile file(fileName); + error = RsCollectionErrorCode::NO_ERROR; - if (!file.open(QIODevice::ReadOnly)) - { - std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; - if (showError) { - showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName)); - } - return false; - } - if (file.reset()){ - std::cerr << "Checking this file for bomb elements and various wrong stuff" << std::endl; - char c ; + if (!file.open(QIODevice::ReadOnly)) + { + std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; + error = RsCollectionErrorCode::FILE_READ_ERROR; - std::vector bad_strings ; - bad_strings.push_back(std::string("= 0) - { - if (!file.atEnd()) - file.getChar(&c); - else - c=0; + std::vector bad_strings ; + bad_strings.push_back(std::string("= 0) + { + if (!file.atEnd()) + file.getChar(&c); + else + c=0; - if (n == max_size || file.atEnd()) - for(int i=0;i= 'A' && c <= 'Z') c += 'a' - 'A' ; + if(n == max_size) + --n ; - if(!file.atEnd()) - current[n] = c ; - else - current[n] = 0 ; + if(c >= 'A' && c <= 'Z') c += 'a' - 'A' ; - //std::cerr << "n==" << n <<" Checking string " << std::string(current,n+1) << " c = " << std::hex << (int)c << std::dec << std::endl; + if(!file.atEnd()) + current[n] = c ; + else + current[n] = 0 ; - for(uint i=0;i& file_entries, FileSearchFlags flags, QObject *parent = 0) ; RsCollection(const RsFileTree& ft); - virtual ~RsCollection() ; + RsCollection(const QString& filename,RsCollectionErrorCode& error_code); + + static QString errorString(RsCollectionErrorCode code); + + virtual ~RsCollection() ; void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ; void merge_in(const RsFileTree& tree) ; @@ -74,9 +86,6 @@ public: bool load(QWidget *parent); bool save(QWidget *parent) const ; #endif - // Loads file from disk. - bool load(const QString& fileName, bool showError = true); - // Save to disk bool save(const QString& fileName) const ; @@ -100,7 +109,7 @@ private slots: private: bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; - bool recursParseXml(QDomDocument& doc,const QDomElement& e,RsFileTree::DirIndex dd) ; + bool recursParseXml(QDomDocument& doc, const QDomNode &e, RsFileTree::DirIndex dd) ; // This function is used to populate a RsCollection from locally or remotly shared files. void recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags) ; @@ -118,7 +127,8 @@ private: #endif // check that the file is a valid rscollection file, and not a lol bomb or some shit like this - static bool checkFile(const QString &fileName, bool showError); + static bool checkFile(const QString &fileName, RsCollectionErrorCode &error); + // Auto Download recursively. void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; From 5071656209bd0dad327303d12413e274650e8bdf Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 24 Feb 2024 17:44:13 +0100 Subject: [PATCH 03/28] started adapting RsCollectionDialog to the new API of RsCollection --- .../src/gui/FileTransfer/SearchDialog.cpp | 18 +-- .../gui/FileTransfer/SharedFilesDialog.cpp | 18 +-- .../src/gui/FileTransfer/TransfersDialog.cpp | 30 ++--- retroshare-gui/src/gui/MainWindow.cpp | 10 +- .../src/gui/common/RsCollection.cpp | 82 ------------ retroshare-gui/src/gui/common/RsCollection.h | 6 +- .../src/gui/common/RsCollectionDialog.cpp | 126 +++++++++++++++--- .../src/gui/common/RsCollectionDialog.h | 15 ++- .../src/gui/common/RsCollectionModel.cpp | 0 .../src/gui/common/RsCollectionModel.h | 0 .../src/gui/common/RsUrlHandler.cpp | 9 +- 11 files changed, 148 insertions(+), 166 deletions(-) create mode 100644 retroshare-gui/src/gui/common/RsCollectionModel.cpp create mode 100644 retroshare-gui/src/gui/common/RsCollectionModel.h diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index ed2498545..a2be7bc07 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -30,7 +30,7 @@ #include "gui/RetroShareLink.h" #include "retroshare-gui/RsAutoUpdatePage.h" #include "gui/msgs/MessageComposer.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/FilesDefs.h" #include "gui/common/RsUrlHandler.h" #include "gui/settings/rsharesettings.h" @@ -542,12 +542,8 @@ void SearchDialog::collModif() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - }//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) - }//if (qinfo.exists()) + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } void SearchDialog::collView() @@ -574,12 +570,8 @@ void SearchDialog::collView() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath(), true); - }//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) - }//if (qinfo.exists()) + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); } void SearchDialog::collOpen() diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 4645841a9..2cd2437be 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -27,7 +27,7 @@ #include "gui/RetroShareLink.h" #include "gui/ShareManager.h" #include "gui/common/PeerDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/msgs/MessageComposer.h" #include "gui/gxschannels/GxsChannelDialog.h" #include "gui/gxsforums/GxsForumsDialog.h" @@ -759,12 +759,8 @@ void SharedFilesDialog::collModif() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } void SharedFilesDialog::collView() @@ -789,12 +785,8 @@ void SharedFilesDialog::collView() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath(), true); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); } void SharedFilesDialog::collOpen() diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index 8dca82e28..44c0260bd 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -24,7 +24,7 @@ #include "gui/SoundManager.h" #include "gui/RetroShareLink.h" #include "gui/common/FilesDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/RSTreeView.h" #include "gui/common/RsUrlHandler.h" #include "gui/FileTransfer/DetailsDialog.h" @@ -2466,21 +2466,17 @@ void TransfersDialog::collCreate() std::set::iterator it ; getDLSelectedItems(&items, NULL); + RsFileTree tree; + for (it = items.begin(); it != items.end(); ++it) { FileInfo info; if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; - DirDetails details; - details.name = info.fname; - details.hash = info.hash; - details.size = info.size; - details.type = DIR_TYPE_FILE; - - dirVec.push_back(details); + tree.addFile(tree.root(),info.fname,info.hash,info.size); } - RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); + RsCollectionDialog::openNewCollection(tree); } void TransfersDialog::collModif() @@ -2504,12 +2500,8 @@ void TransfersDialog::collModif() /* open collection */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } } @@ -2534,12 +2526,8 @@ void TransfersDialog::collView() /* open collection */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath(), true); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); } } diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index d69e2bb42..a35870bd1 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -119,7 +119,7 @@ #include "gui/statistics/StatisticsWindow.h" #include "gui/connect/ConnectFriendWizard.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "settings/rsettingswin.h" #include "settings/rsharesettings.h" #include "common/StatusDefs.h" @@ -1623,12 +1623,8 @@ void MainWindow::retroshareLinkActivated(const QUrl &url) void MainWindow::openRsCollection(const QString &filename) { QFileInfo qinfo(filename); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } void MainWindow::processLastArgs() diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 08474fb19..c1a21f9a1 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -615,89 +615,7 @@ bool RsCollection::save(QWidget *parent) const } -bool RsCollection::openNewColl(QWidget *parent, QString fileName) -{ - if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE - , QApplication::translate("RsCollectionFile", "Create collection file") - , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" - , fileName,0, QFileDialog::DontConfirmOverwrite)) - return false; - if (!fileName.endsWith("." + RsCollection::ExtensionString)) - fileName += "." + RsCollection::ExtensionString ; - - std::cerr << "Got file name: " << fileName.toStdString() << std::endl; - - QFile file(fileName) ; - - if(file.exists()) - { - if (!checkFile(fileName,true)) return false; - - QMessageBox mb; - mb.setText(tr("Save Collection File.")); - mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); - QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); - QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); - QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); - mb.setIcon(QMessageBox::Question); - mb.exec(); - - if (mb.clickedButton()==btnOwerWrite) { - //Nothing to do _xml_doc already up to date - } else if (mb.clickedButton()==btnMerge) { - //Open old file to merge it with _xml_doc - QDomDocument qddOldFile("RsCollection"); - if (qddOldFile.setContent(&file)) { - QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement(); - std::vector colOldFileInfos; - recursCollectColFileInfos(docOldElem,colOldFileInfos,QString(),false); - - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - for(uint32_t i = 0;i colFileInfos ; - - recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; - - RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos,true); - connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; - _saved=false; - rcd->exec() ; - delete rcd; - - return _saved; -} - -bool RsCollection::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) -{ - if (load(fileName, showError)) { - std::vector colFileInfos ; - - recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; - - RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos, true, readOnly); - connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; - _saved=false; - rcd->exec() ; - delete rcd; - - return _saved; - } - return false; -} #endif qulonglong RsCollection::size() diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 31fa777a3..32863be80 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -89,10 +89,8 @@ public: // Save to disk bool save(const QString& fileName) const ; - // Open new collection - bool openNewColl(QWidget *parent, QString fileName = ""); - // Open existing collection - bool openColl(const QString& fileName, bool readOnly = false, bool showError = true); + // returns the file tree + const RsFileTree& fileTree() const { return mFileTree; } // Download the content. void downloadFiles() const ; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 417af69bc..240bae85c 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -693,36 +693,35 @@ void RsCollectionDialog::changeFileName() std::cerr << "Got file name: " << fileName.toStdString() << std::endl; QFile file(fileName) ; + RsCollection::RsCollectionErrorCode err; - if(file.exists()) - { - RsCollection collFile; - if (!collFile.checkFile(fileName,true)) return; - + if(file.exists() && RsCollection::checkFile(fileName,err)) + { QMessageBox mb; mb.setText(tr("Save Collection File.")); mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); - QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); - QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); + QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); + QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); mb.setIcon(QMessageBox::Question); mb.exec(); if (mb.clickedButton()==btnOwerWrite) { //Nothing to do - } else if (mb.clickedButton()==btnMerge) { + } + else if(mb.clickedButton()==btnMerge) + { //Open old file to merge it with RsCollection - QDomDocument qddOldFile("RsCollection"); - if (qddOldFile.setContent(&file)) { - QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement(); - collFile.recursCollectColFileInfos(docOldElem,_newColFileInfos,QString(),false); - } - } else if (mb.clickedButton()==btnCancel) { + RsCollection qddOldFileCollection(fileName,err); + + if(err != RsCollection::RsCollectionErrorCode::NO_ERROR) + _collection.merge_in(qddOldFileCollection.fileTree()); + } + else if(mb.clickedButton()==btnCancel) return; - } else { + else return; - } } else {//if(file.exists()) //create a new empty file to check if name if good. @@ -1444,3 +1443,98 @@ void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *par } } } + +bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) +{ +#ifdef TODO + RsCollection::RsCollectionErrorCode err; + RsCollection col(fileName,err); + + if(err != RsCollection::RsCollectionErrorCode::NO_ERROR) + { + RsCollectionDialog rcd = new RsCollectionDialog(col, true, readOnly); + return rcd.exec() ; + } + + if(showError) + QMessageBox::information(nullptr,tr("Error openning RsCollection"),RsCollection::errorString(err)); + +#endif + return false; +} + +bool RsCollectionDialog::openNewCollection(const RsFileTree& tree,const QString& proposed_file_name) +{ +#ifdef TODO + QString fileName = proposed_file_name; + + if(!misc::getSaveFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE + , QApplication::translate("RsCollectionFile", "Create collection file") + , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" + , fileName,0, QFileDialog::DontConfirmOverwrite)) + return false; + + if (!fileName.endsWith("." + RsCollection::ExtensionString)) + fileName += "." + RsCollection::ExtensionString ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + QFile file(fileName) ; + + if(file.exists()) + { + RsCollection::RsCollectionErrorCode err; + if (!RsCollection::checkFile(fileName,err)) + { + QMessageBox::information(nullptr,tr("Error openning collection"),RsCollection::errorString(err)); + return false; + } + + QMessageBox mb; + mb.setText(tr("Save Collection File.")); + mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); + QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); + QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); + QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); + + if (mb.clickedButton()==btnOwerWrite) { + //Nothing to do _xml_doc already up to date + } else if (mb.clickedButton()==btnMerge) { + //Open old file to merge it with _xml_doc + QDomDocument qddOldFile("RsCollection"); + if (qddOldFile.setContent(&file)) { + QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement(); + std::vector colOldFileInfos; + recursCollectColFileInfos(docOldElem,colOldFileInfos,QString(),false); + + QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); + for(uint32_t i = 0;i colFileInfos ; + + recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; + + RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos,true); + connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; + _saved=false; + rcd->exec() ; + delete rcd; + +#endif + return true; +} + diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 43c7dbdd7..f4fd5749a 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -30,15 +30,20 @@ class RsCollectionDialog: public QDialog Q_OBJECT public: - RsCollectionDialog(const QString& filename - , const std::vector &colFileInfos - , const bool& creation - , const bool& readOnly = false) ; virtual ~RsCollectionDialog(); + // Open new collection + static bool openNewCollection(const RsFileTree &tree, const QString &proposed_file_name = QString()); + + // Open existing collection + static bool openExistingCollection(const QString& fileName, bool readOnly = false, bool showError = true); + protected: bool eventFilter(QObject *obj, QEvent *ev); + RsCollectionDialog(const QString& filename, const std::vector &colFileInfos, const bool& creation, + const bool& readOnly = false) ; + private slots: void directoryLoaded(QString dirLoaded); void updateSizes() ; @@ -88,4 +93,6 @@ private: QItemSelectionModel *_selectionProxy; bool _dirLoaded; QHash _listOfFilesAddedInDir; + + RsCollection _collection; }; diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h new file mode 100644 index 000000000..e69de29bb diff --git a/retroshare-gui/src/gui/common/RsUrlHandler.cpp b/retroshare-gui/src/gui/common/RsUrlHandler.cpp index 6ac6310ac..3d005aed6 100644 --- a/retroshare-gui/src/gui/common/RsUrlHandler.cpp +++ b/retroshare-gui/src/gui/common/RsUrlHandler.cpp @@ -28,12 +28,9 @@ bool RsUrlHandler::openUrl(const QUrl& url) { if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString)) { - RsCollection collection ; - if(collection.load(url.toLocalFile())) - { - collection.downloadFiles() ; - return true; - } + RsCollection::RsCollectionErrorCode err; + RsCollection(url.toLocalFile(),err).downloadFiles() ; + return true; } return QDesktopServices::openUrl(url) ; } From 5bc071b03c134dadeb2b9f7e27906d1efac3d5bf Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 24 Feb 2024 20:27:18 +0100 Subject: [PATCH 04/28] fixed compilation --- .../src/gui/FileTransfer/SearchDialog.cpp | 18 ++++++------- .../gui/FileTransfer/SharedFilesDialog.cpp | 19 +++++++++++++- retroshare-gui/src/gui/RemoteDirModel.cpp | 25 ------------------- retroshare-gui/src/gui/RemoteDirModel.h | 2 -- retroshare-gui/src/gui/common/RsCollection.h | 3 --- .../src/gui/common/RsCollectionDialog.cpp | 3 ++- 6 files changed, 28 insertions(+), 42 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index a2be7bc07..33646816a 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -497,25 +497,23 @@ void SearchDialog::collCreate() int selectedCount = selectedItems.size() ; QTreeWidgetItem * item ; - for (int i = 0; i < selectedCount; ++i) { + RsFileTree tree; + + for (int i = 0; i < selectedCount; ++i) + { item = selectedItems.at(i) ; - if (!item->text(SR_HASH_COL).isEmpty()) { + if (!item->text(SR_HASH_COL).isEmpty()) + { std::string name = item->text(SR_NAME_COL).toUtf8().constData(); RsFileHash hash( item->text(SR_HASH_COL).toStdString() ); uint64_t count = item->text(SR_SIZE_COL).toULongLong(); - DirDetails details; - details.name = name; - details.hash = hash; - details.size = count; - details.type = DIR_TYPE_FILE; - - dirVec.push_back(details); + tree.addFile(tree.root(),name,hash,count); } } - RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); + RsCollectionDialog::openNewCollection(tree); } void SearchDialog::collModif() diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 2cd2437be..7321486fe 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -733,8 +733,25 @@ void SharedFilesDialog::sendLinkTo() void SharedFilesDialog::collCreate() { +#ifdef TODO QModelIndexList lst = getSelected(); - model->createCollectionFile(this, lst); + + std::vector dirVec; + model->getDirDetailsFromSelect(lst, dirVec); + + FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; + + QString dir_name; + if(!RemoteMode) + { + if(!dirVec.empty()) + { + const DirDetails& details = dirVec[0]; + dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); + } + } + RsCollection(dirVec,f).openNewColl(parent,dir_name); +#endif } void SharedFilesDialog::collModif() diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp index 05e19857f..87f70c06c 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.cpp +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -1233,31 +1233,6 @@ bool RetroshareDirModel::requestDirDetails(void *ref, bool remote,DirDetails& d) return false ; } -void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndexList &list) -{ -/* if(RemoteMode) - { - std::cerr << "Cannot create a collection file from remote" << std::endl; - return ; - }*/ - - std::vector dirVec; - getDirDetailsFromSelect(list, dirVec); - - FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; - - QString dir_name; - if(!RemoteMode) - { - if(!dirVec.empty()) - { - const DirDetails& details = dirVec[0]; - dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); - } - } - RsCollection(dirVec,f).openNewColl(parent,dir_name); -} - void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool interactive) { if (!RemoteMode) diff --git a/retroshare-gui/src/gui/RemoteDirModel.h b/retroshare-gui/src/gui/RemoteDirModel.h index 83028dd48..b7811533e 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.h +++ b/retroshare-gui/src/gui/RemoteDirModel.h @@ -68,8 +68,6 @@ class RetroshareDirModel : public QAbstractItemModel /* Callback from GUI */ void downloadSelected(const QModelIndexList &list, bool interactive); - void createCollectionFile(QWidget *parent, const QModelIndexList &list); - void getDirDetailsFromSelect (const QModelIndexList &list, std::vector & dirVec); int getType ( const QModelIndex & index ) const ; diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 32863be80..ecc5aa6fc 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -101,9 +101,6 @@ public: static bool isCollectionFile(const QString& fileName); -private slots: - void saveColl(std::vector colFileInfos, const QString& fileName); - private: bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 240bae85c..c7a9ef7bb 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -1411,8 +1411,9 @@ void RsCollectionDialog::save() QTreeWidgetItem* root = getRootItem(); if (root) { saveChild(root); - +#ifdef TODO_COLLECTION emit saveColl(_newColFileInfos, _fileName); +#endif } close(); } From 97309f2f9fd876716aea91e09e4a444fa0ebaef8 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 24 Feb 2024 21:49:50 +0100 Subject: [PATCH 05/28] started implementing RsCollectionModel --- .../src/gui/common/RsCollection.cpp | 7 ++- retroshare-gui/src/gui/common/RsCollection.h | 4 +- .../src/gui/common/RsCollectionModel.cpp | 56 +++++++++++++++++ .../src/gui/common/RsCollectionModel.h | 62 +++++++++++++++++++ 4 files changed, 124 insertions(+), 5 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index c1a21f9a1..8f23a3d50 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -68,7 +68,7 @@ RsCollection::~RsCollection() void RsCollection::downloadFiles() const { -#ifdef TODO +#ifdef TODO_COLLECTION // print out the element names of all elements that are direct children // of the outermost element. QDomElement docElem = _xml_doc.documentElement(); @@ -83,7 +83,7 @@ void RsCollection::downloadFiles() const void RsCollection::autoDownloadFiles() const { -#ifdef TODO +#ifdef TODO_COLLECTION QDomElement docElem = _xml_doc.documentElement(); std::vector colFileInfos; @@ -322,13 +322,13 @@ void RsCollection::recursAddElements( d.appendChild(f) ; } } -#endif static void showErrorBox(const QString& fileName, const QString& error) { QMessageBox mb(QMessageBox::Warning, QObject::tr("Failed to process collection file"), QObject::tr("The collection file %1 could not be opened.\nReported error is: \n\n%2").arg(fileName).arg(error), QMessageBox::Ok); mb.exec(); } +#endif QString RsCollection::errorString(RsCollectionErrorCode code) { @@ -563,6 +563,7 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi n = n.nextSibling() ; } + return true; } bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const { diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index ecc5aa6fc..2295acacd 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -91,14 +91,14 @@ public: // returns the file tree const RsFileTree& fileTree() const { return mFileTree; } + // total size of files in the collection + qulonglong size(); // Download the content. void downloadFiles() const ; // Auto Download all the content. void autoDownloadFiles() const ; - qulonglong size(); - static bool isCollectionFile(const QString& fileName); private: diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index e69de29bb..bcc61d86f 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -0,0 +1,56 @@ +#include + +#include "RsCollectionModel.h" + +// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the +// architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and +// the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex) +// This way, index 0 is always the top dir. + +bool RsCollectionModel::convertIndexToInternalId(const EntryIndex& e,quintptr& ref) +{ + ref = (e.index << 1) || e.is_file; + return true; +} + +bool RsCollectionModel::convertInternalIdToIndex(quintptr ref, EntryIndex& e) +{ + e.is_file = (bool)(ref & 1); + e.index = ref >> 1; + return true; +} + +int RsCollectionModel::rowCount(const QModelIndex& parent) const +{ + if(!parent.isValid()) + return mCollection.fileTree().root(); + + EntryIndex i; + if(!convertInternalIdToIndex(parent.internalId(),i)) + return 0; + + if(i.is_file) + return 0; + else + return mCollection.fileTree().directoryData(i.index).subdirs.size(); +} + +int RsCollectionModel::columnCount(const QModelIndex&) const +{ + return 5; +} + +QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int) const +{ + switch(section) + { + case 0: return tr("File"); + case 1: return tr("Path"); + case 2: return tr("Size"); + case 3: return tr("Hash"); + case 4: return tr("Count"); + default: + return QVariant(); + } +} + diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index e69de29bb..22b4a4ddf 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -0,0 +1,62 @@ +#include + +#include "RsCollection.h" + +class RsCollectionModel: public QAbstractItemModel +{ + Q_OBJECT + + public: + enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2, FilterRole = Qt::UserRole+3 }; + + RsCollectionModel(bool mode, QObject *parent = 0); + virtual ~RsCollectionModel() ; + + + /* Callback from Core */ + void preMods(); + void postMods(); + + /* Callback from GUI */ + + void update() {} + void filterItems(const std::list& keywords, uint32_t& found) ; + + // Overloaded from QAbstractItemModel + virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override; + virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const override; + virtual QModelIndex parent ( const QModelIndex & index ) const override; + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const override; + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual QStringList mimeTypes () const override; + virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override; +#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) + virtual Qt::DropActions supportedDragActions() const override; +#endif + + protected: + struct EntryIndex { + bool is_file; // false=dir, true=file + uint64_t index; + }; + static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); + static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); + + // virtual QVariant displayRole(const DirDetails&,int) const = 0 ; + // virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const =0; + + // QVariant decorationRole(const DirDetails&,int) const ; + // QVariant filterRole(const DirDetails& details,int coln) const; + + bool mUpdating ; + + const RsCollection& mCollection; + + // std::set mFilteredPointers ; +}; From eb0ef1e39bc6a37369c16df2d14bf6d9def7eb64 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 25 Feb 2024 17:58:51 +0100 Subject: [PATCH 06/28] implemented RsCollectionModel --- .../src/gui/common/RsCollection.cpp | 33 +--- .../src/gui/common/RsCollectionModel.cpp | 146 +++++++++++++++++- .../src/gui/common/RsCollectionModel.h | 20 +-- 3 files changed, 157 insertions(+), 42 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 8f23a3d50..0313d4456 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -155,36 +155,21 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& } void RsCollection::merge_in(const RsFileTree& tree) { - RsFileTree::DirData dd; - tree.getDirectoryContent(tree.root(),dd); - - recursMergeTree(mFileTree.root(),tree,dd) ; + recursMergeTree(mFileTree.root(),tree,tree.directoryData(tree.root())) ; } void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) { for(uint32_t i=0;i= mCollection.fileTree().numDirs()) + return QModelIndex(); + + const auto& parentData(mCollection.fileTree().directoryData(i.index)); + + if(row < 0) + return QModelIndex(); + + if((size_t)row < parentData.subdirs.size()) + { + EntryIndex e; + e.is_file = false; + e.index = parentData.subdirs[row]; + + quintptr ref; + convertIndexToInternalId(e,ref); + return createIndex(row,column,ref); + } + + if((size_t)row < parentData.subdirs.size() + parentData.subfiles.size()) + { + EntryIndex e; + e.is_file = true; + e.index = parentData.subfiles[row - parentData.subdirs.size()]; + + quintptr ref; + convertIndexToInternalId(e,ref); + return createIndex(row,column,ref); + } + + return QModelIndex(); +} + +QModelIndex RsCollectionModel::parent(const QModelIndex & index) const +{ + EntryIndex i; + if(!convertInternalIdToIndex(index.internalId(),i)) + return QModelIndex(); + + EntryIndex p; + p.is_file = false; // all parents are directories + + if(i.is_file) + { + const auto it = mFileParents.find(i.index); + if(it == mFileParents.end()) + { + RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); + return QModelIndex(); + } + p.index = it->second; + } + else + { + const auto it = mDirParents.find(i.index); + if(it == mDirParents.end()) + { + RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); + return QModelIndex(); + } + p.index = it->second; + } + + quintptr ref; + convertIndexToInternalId(p,ref); + return createIndex(0,index.column(),ref); +} + +QVariant RsCollectionModel::data(const QModelIndex& index, int role) const +{ + EntryIndex i; + if(!convertInternalIdToIndex(index.internalId(),i)) + return QVariant(); + + switch(role) + { + case Qt::DisplayRole: return displayRole(i,index.column()); + //case Qt::SortRole: return SortRole(i,index.column()); + case Qt::DecorationRole: return decorationRole(i,index.column()); + default: + return QVariant(); + } +} + +QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const +{ + switch(col) + { + case 0: return (i.is_file)? + (QString::fromUtf8(mCollection.fileTree().fileData(i.index).name.c_str())) + : (QString::fromUtf8(mCollection.fileTree().directoryData(i.index).name.c_str())); + + case 1: if(i.is_file) + return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ; + + { + auto it = mDirSizes.find(i.index); + + if(it == mDirSizes.end()) + return QVariant(); + else + return QVariant((qulonglong)it->second); + } + + case 2: return (i.is_file)? + QString::fromStdString(mCollection.fileTree().fileData(i.index).hash.toStdString()) + :QVariant(); + + case 3: return (i.is_file)?((qulonglong)1):((qulonglong)(mCollection.fileTree().directoryData(i.index).subdirs.size())); + } + return QVariant(); +} +QVariant RsCollectionModel::sortRole(const EntryIndex& i,int col) const +{ + return QVariant(); +} +QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const +{ + return QVariant(); +} + + + + + + + + + diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index 22b4a4ddf..0ad770cc1 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -9,13 +9,12 @@ class RsCollectionModel: public QAbstractItemModel public: enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2, FilterRole = Qt::UserRole+3 }; - RsCollectionModel(bool mode, QObject *parent = 0); + RsCollectionModel(const RsCollection& col, QObject *parent = 0); virtual ~RsCollectionModel() ; - /* Callback from Core */ - void preMods(); - void postMods(); + void preMods(); // always call this before updating the RsCollection! + void postMods(); // always call this after updating the RsCollection! /* Callback from GUI */ @@ -48,15 +47,18 @@ class RsCollectionModel: public QAbstractItemModel static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); - // virtual QVariant displayRole(const DirDetails&,int) const = 0 ; - // virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const =0; - - // QVariant decorationRole(const DirDetails&,int) const ; - // QVariant filterRole(const DirDetails& details,int coln) const; + QVariant displayRole(const EntryIndex&,int col) const ; + QVariant sortRole(const EntryIndex&,int col) const ; + QVariant decorationRole(const EntryIndex&,int col) const ; + //QVariant filterRole(const DirDetails& details,int coln) const; bool mUpdating ; const RsCollection& mCollection; + std::map mFileParents; + std::map mDirParents; + std::map mDirSizes; + // std::set mFilteredPointers ; }; From eae4fe86aaff2335e40f9e137299326a25ffeebf Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 26 Feb 2024 22:10:32 +0100 Subject: [PATCH 07/28] added RsCollectionModel to RsCollectionDialog (unfiished) --- .../src/gui/common/RsCollection.cpp | 4 + retroshare-gui/src/gui/common/RsCollection.h | 2 + .../src/gui/common/RsCollectionDialog.cpp | 235 +++++++++--------- .../src/gui/common/RsCollectionDialog.h | 28 ++- .../src/gui/common/RsCollectionDialog.ui | 12 +- .../src/gui/common/RsCollectionModel.cpp | 62 ++++- .../src/gui/common/RsCollectionModel.h | 11 +- 7 files changed, 208 insertions(+), 146 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 0313d4456..bc76fff00 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -598,6 +598,10 @@ bool RsCollection::save(QWidget *parent) const #endif +qulonglong RsCollection::count() const +{ + return mFileTree.numFiles(); +} qulonglong RsCollection::size() { return mFileTree.totalFileSize(); diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 2295acacd..47fdee5d6 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -93,6 +93,8 @@ public: const RsFileTree& fileTree() const { return mFileTree; } // total size of files in the collection qulonglong size(); + // total number of files in the collection + qulonglong count() const; // Download the content. void downloadFiles() const ; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index c7a9ef7bb..52583c4f7 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -120,24 +120,31 @@ protected: /** * @brief RsCollectionDialog::RsCollectionDialog * @param collectionFileName: Filename of RSCollection saved - * @param colFileInfos: Vector of ColFileInfo to be add in intialization * @param creation: Open dialog as RsColl Creation or RsColl DownLoad * @param readOnly: Open dialog for RsColl as ReadOnly */ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName - , const std::vector& colFileInfos - , const bool& creation /* = false*/ - , const bool& readOnly) + , const bool& creation /* = false */ + , const bool& readOnly /* = false */) : _fileName(collectionFileName), _creationMode(creation) ,_readOnly(readOnly) { + RsCollection::RsCollectionErrorCode err_code; + mCollection = new RsCollection(collectionFileName,err_code); + + if(err_code != RsCollection::RsCollectionErrorCode::NO_ERROR) + { + QMessageBox::information(nullptr,tr("Could not load collection file"),tr("Could not load collection file")); + close(); + } + ui.setupUi(this) ; - uint32_t size = colFileInfos.size(); - for(uint32_t i=0;isetModel(mCollectionModel); + +#ifdef TO_REMOVE ui._fileEntriesTW->setColumnCount(COLUMN_COUNT) ; QTreeWidgetItem *headerItem = ui._fileEntriesTW->headerItem(); @@ -178,14 +189,15 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName headerItem->setText(COLUMN_SIZE, tr("Size")); headerItem->setText(COLUMN_HASH, tr("Hash")); headerItem->setText(COLUMN_FILEC, tr("File Count")); +#endif bool wrong_chars = !updateList(); // 2 - connect necessary signals/slots connect(ui._changeFile, SIGNAL(clicked()), this, SLOT(changeFileName())); - connect(ui._add_PB, SIGNAL(clicked()), this, SLOT(add())); - connect(ui._addRecur_PB, SIGNAL(clicked()), this, SLOT(addRecursive())); + connect(ui._add_PB, SIGNAL(clicked()), this, SLOT(addSelection())); + connect(ui._addRecur_PB, SIGNAL(clicked()), this, SLOT(addSelectionRecursive())); connect(ui._remove_PB, SIGNAL(clicked()), this, SLOT(remove())); connect(ui._makeDir_PB, SIGNAL(clicked()), this, SLOT(makeDir())); connect(ui._removeDuplicate_CB, SIGNAL(clicked(bool)), this, SLOT(updateRemoveDuplicate(bool))); @@ -193,7 +205,9 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName connect(ui._save_PB, SIGNAL(clicked()), this, SLOT(save())); connect(ui._download_PB, SIGNAL(clicked()), this, SLOT(download())); connect(ui._hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); - connect(ui._fileEntriesTW, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*,int))); +#ifdef TO_REMOVE + connect(ui._fileEntriesTW, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*,int))); +#endif // 3 Initialize List _dirModel = new QFileSystemModel(this); @@ -223,7 +237,9 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName ui._treeViewFrame->setVisible(_creationMode && !_readOnly); ui._download_PB->setVisible(!_creationMode && !_readOnly); - ui._fileEntriesTW->installEventFilter(this); +#ifdef TO_REMOVE + ui._fileEntriesTW->installEventFilter(this); +#endif ui._systemFileTW->installEventFilter(this); // 6 Add HashBox @@ -293,6 +309,7 @@ RsCollectionDialog::~RsCollectionDialog() */ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) { +#ifdef TODO_COLLECTION if (obj == ui._fileEntriesTW) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); @@ -350,6 +367,8 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) // pass the event on to the parent class return QDialog::eventFilter(obj, event); +#endif + return true; } /** @@ -411,6 +430,7 @@ void RsCollectionDialog::processSettings(bool bLoad) Settings->endGroup(); } +#ifdef TO_REMOVE /** * @brief RsCollectionDialog::getRootItem: Create the root Item if not existing * @return: the root item @@ -418,34 +438,8 @@ void RsCollectionDialog::processSettings(bool bLoad) QTreeWidgetItem* RsCollectionDialog::getRootItem() { return ui._fileEntriesTW->invisibleRootItem(); - -// (csoler) I removed this code because it does the job of the invisibleRootItem() method. -// -// QTreeWidgetItem* root= ui._fileEntriesTW->topLevelItem(0); -// if (!root) { -// root= new QTreeWidgetItem; -// root->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); -// root->setText(COLUMN_FILE, "/"); -// root->setToolTip(COLUMN_FILE,tr("This is the root directory.")); -// root->setText(COLUMN_FILEPATH, "/"); -// root->setText(COLUMN_HASH, ""); -// root->setData(COLUMN_HASH, ROLE_NAME, ""); -// root->setData(COLUMN_HASH, ROLE_PATH, ""); -// root->setData(COLUMN_HASH, ROLE_TYPE, DIR_TYPE_DIR); -// root->setText(COLUMN_SIZE, misc::friendlyUnit(0)); -// root->setToolTip(COLUMN_SIZE, tr("Real Size: Waiting child...")); -// root->setData(COLUMN_SIZE, ROLE_SIZE, 0); -// root->setData(COLUMN_SIZE, ROLE_SELSIZE, 0); -// root->setText(COLUMN_FILEC, "0"); -// root->setToolTip(COLUMN_FILEC, tr("Real File Count: Waiting child...")); -// root->setData(COLUMN_FILEC, ROLE_FILEC, 0); -// root->setData(COLUMN_FILEC, ROLE_SELFILEC, 0); -// ui._fileEntriesTW->addTopLevelItem(root); -// } -// root->setExpanded(true); -// -// return root; } +#endif /** * @brief RsCollectionDialog::updateList: Update list of item in RsCollection @@ -453,6 +447,7 @@ QTreeWidgetItem* RsCollectionDialog::getRootItem() */ bool RsCollectionDialog::updateList() { +#ifdef TODO_COLLECTION bool wrong_chars = false ; wrong_chars = addChild(getRootItem(), _newColFileInfos); @@ -466,8 +461,11 @@ bool RsCollectionDialog::updateList() updateSizes() ; return !wrong_chars; +#endif + return true; } +#ifdef TO_REMOVE /** * @brief RsCollectionDialog::addChild: Add Child Item in list * @param parent: Parent Item @@ -586,6 +584,7 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vectortopLevelItemCount();++i) - { - total_size += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_SIZE ,ROLE_SELSIZE ).toULongLong(); - total_count += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_FILEC,ROLE_SELFILEC).toULongLong(); - } - - ui._selectedFiles_TL->setText(QString::number(total_count)); - ui._totalSize_TL->setText(misc::friendlyUnit(total_size)); + ui._selectedFiles_TL->setText(QString::number(mCollection->count())); + ui._totalSize_TL->setText(misc::friendlyUnit(mCollection->size())); } /** @@ -716,16 +706,23 @@ void RsCollectionDialog::changeFileName() RsCollection qddOldFileCollection(fileName,err); if(err != RsCollection::RsCollectionErrorCode::NO_ERROR) - _collection.merge_in(qddOldFileCollection.fileTree()); + { + mCollectionModel->preMods(); + mCollection->merge_in(qddOldFileCollection.fileTree()); + mCollectionModel->postMods(); + } } else if(mb.clickedButton()==btnCancel) return; else return; - } else {//if(file.exists()) + } + else + { //create a new empty file to check if name if good. - if (!file.open(QFile::WriteOnly)) return; + if (!file.open(QFile::WriteOnly)) + return; file.remove(); } @@ -736,19 +733,40 @@ void RsCollectionDialog::changeFileName() /** * @brief RsCollectionDialog::add: */ -void RsCollectionDialog::add() +void RsCollectionDialog::addSelection() { - addRecursive(false); + addSelection(false); } /** * @brief RsCollectionDialog::addRecursive: */ -void RsCollectionDialog::addRecursive() +void RsCollectionDialog::addSelectionRecursive() { - addRecursive(true); + addSelection(true); } +static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive) +{ + QFileInfo fileInfo = path; + + if (fileInfo.isDir()) + { + auto di = tree.addDirectory(dir_index,fileInfo.fileName().toUtf8().constData()); + + QDir dirParent = fileInfo.absoluteFilePath(); + dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); + QFileInfoList childrenList = dirParent.entryInfoList(); + + for(QFileInfo f:childrenList) + recursBuildFileTree(f.absoluteFilePath(),tree,di,recursive); + } + else + { +#warning TODO: compute the hash + tree.addFile(dir_index,fileInfo.fileName().toUtf8().constData(),RsFileHash(),fileInfo.size()); + } +} /** * @brief RsCollectionDialog::addRecursive: Add Selected item to RSCollection * -Add File seperatly if parent folder not selected @@ -756,18 +774,25 @@ void RsCollectionDialog::addRecursive() * -Get root folder the selected one * @param recursive: If true, add all selected directory childrens */ -void RsCollectionDialog::addRecursive(bool recursive) +void RsCollectionDialog::addSelection(bool recursive) { QStringList fileToHash; QMap dirToAdd; int count=0;//to not scan all items on list .count() QModelIndexList milSelectionList = ui._systemFileTW->selectionModel()->selectedIndexes(); - foreach (QModelIndex index, milSelectionList) - { - if (index.column()==0){//Get only FileName - QString filePath = _dirModel->filePath(_tree_proxyModel->mapToSource(index)); + mCollectionModel->preMods(); + + foreach (QModelIndex index, milSelectionList) + if(index.column()==0) //Get only FileName + { + RsFileTree tree; + recursBuildFileTree(_dirModel->filePath(_tree_proxyModel->mapToSource(index)),tree,tree.root(),recursive); + + mCollection->merge_in(tree); + +#ifdef TO_REMOVE QFileInfo fileInfo = filePath; if (fileInfo.isDir()) { dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); @@ -786,9 +811,10 @@ void RsCollectionDialog::addRecursive(bool recursive) else _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),""); } +#endif } - } +#ifdef TO_REMOVE // Process Dirs QTreeWidgetItem *item = NULL; if (!ui._fileEntriesTW->selectedItems().empty()) @@ -833,6 +859,7 @@ void RsCollectionDialog::addRecursive(bool recursive) // Process Files once all done ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); +#endif } /** @@ -896,6 +923,7 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent */ void RsCollectionDialog::remove() { +#ifdef TODO_COLLECTION bool removeOnlyFile=false; QString listDir; // First, check if selection contains directories @@ -987,9 +1015,10 @@ void RsCollectionDialog::remove() } updateSizes() ; - +#endif } +#ifdef TODO_COLLECTION bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) { if (item){ @@ -1019,7 +1048,9 @@ bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) } return false; } +#endif +#ifdef TO_REMOVE /** Process each item to make a new RsCollection item */ void RsCollectionDialog::processItem(QMap &dirToAdd , int &index @@ -1063,12 +1094,14 @@ void RsCollectionDialog::processItem(QMap &dirToAdd } } } +#endif /** * @brief RsCollectionDialog::addDir: Add new empty dir to list */ void RsCollectionDialog::makeDir() { +#ifdef TODO_COLLECTION QString childName=""; bool ok, badChar, nameOK = false; // Ask for name @@ -1149,39 +1182,8 @@ void RsCollectionDialog::makeDir() _newColFileInfos.push_back(newChild); } - -// // Process all selected items -// int count = ui._fileEntriesTW->selectedItems().count(); -// int curs = 0; -// if (count == 0) curs = -1; -// -// for (; curs < count; ++curs) -// { -// QTreeWidgetItem *item = NULL; -// if (curs >= 0) { -// item= ui._fileEntriesTW->selectedItems().at(curs); -// } else { -// item = getRootItem(); -// } -// if (item) { -// while (item->parent() != NULL && item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { -// item = item->parent();//Only Dir as Parent -// } -// ColFileInfo newChild; -// newChild.name = childName; -// newChild.filename_has_wrong_characters = false; -// newChild.size = 0; -// newChild.type = DIR_TYPE_DIR; -// newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() -// + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); -// if (item == getRootItem()) newChild.path = ""; -// -// _newColFileInfos.push_back(newChild); -// } -// } - - updateList(); +#endif } /** @@ -1212,9 +1214,9 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) colFileInfo.path = _listOfFilesAddedInDir.value(hashedFile.filepath,""); _listOfFilesAddedInDir.remove(hashedFile.filepath); } - +#ifdef TODO_COLLECTION _newColFileInfos.push_back(colFileInfo); - +#endif } std::cerr << "RsCollectionDialog::fileHashingFinished message : " << message.toStdString() << std::endl; @@ -1222,6 +1224,7 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) updateList(); } +#ifdef TO_REMOVE void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col) { if (col != COLUMN_FILE) return; @@ -1254,6 +1257,7 @@ void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col) updateSizes() ; } +#endif /** * @brief RsCollectionDialog::updateRemoveDuplicate Remove all duplicate file when checked. @@ -1261,6 +1265,7 @@ void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col) */ void RsCollectionDialog::updateRemoveDuplicate(bool checked) { +#ifdef TODO_COLLECTION if (checked) { bool bRemoveAll = false; QTreeWidgetItemIterator it(ui._fileEntriesTW); @@ -1341,6 +1346,7 @@ void RsCollectionDialog::updateRemoveDuplicate(bool checked) } } } +#endif } /** @@ -1357,14 +1363,13 @@ void RsCollectionDialog::cancel() */ void RsCollectionDialog::download() { +#ifdef TODO_COLLECTION std::cerr << "Downloading!" << std::endl; QString dldir = ui.downloadFolder_LE->text(); std::cerr << "downloading all these files:" << std::endl; - QTreeWidgetItemIterator itemIterator(ui._fileEntriesTW); - QTreeWidgetItem *item; while ((item = *itemIterator) != NULL) { ++itemIterator; @@ -1399,6 +1404,7 @@ void RsCollectionDialog::download() } close(); +#endif } /** @@ -1406,18 +1412,20 @@ void RsCollectionDialog::download() */ void RsCollectionDialog::save() { + mCollection->save(_fileName); +#ifdef TO_REMOVE std::cerr << "Saving!" << std::endl; _newColFileInfos.clear(); QTreeWidgetItem* root = getRootItem(); if (root) { saveChild(root); -#ifdef TODO_COLLECTION emit saveColl(_newColFileInfos, _fileName); -#endif } close(); +#endif } +#ifdef TO_REMOVE /** * @brief RsCollectionDialog::saveChild: Save each child in _newColFileInfos * @param parent @@ -1444,29 +1452,16 @@ void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *par } } } +#endif bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) { -#ifdef TODO - RsCollection::RsCollectionErrorCode err; - RsCollection col(fileName,err); - - if(err != RsCollection::RsCollectionErrorCode::NO_ERROR) - { - RsCollectionDialog rcd = new RsCollectionDialog(col, true, readOnly); - return rcd.exec() ; - } - - if(showError) - QMessageBox::information(nullptr,tr("Error openning RsCollection"),RsCollection::errorString(err)); - -#endif - return false; + return RsCollectionDialog(fileName,readOnly,showError).exec(); } bool RsCollectionDialog::openNewCollection(const RsFileTree& tree,const QString& proposed_file_name) { -#ifdef TODO +#ifdef TODO_COLLECTION QString fileName = proposed_file_name; if(!misc::getSaveFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index f4fd5749a..192732338 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -20,6 +20,7 @@ #include "ui_RsCollectionDialog.h" #include "RsCollection.h" +#include "RsCollectionModel.h" #include #include @@ -41,26 +42,29 @@ public: protected: bool eventFilter(QObject *obj, QEvent *ev); - RsCollectionDialog(const QString& filename, const std::vector &colFileInfos, const bool& creation, - const bool& readOnly = false) ; + RsCollectionDialog(const QString& filename, const bool& creation, const bool& readOnly = false) ; private slots: void directoryLoaded(QString dirLoaded); void updateSizes() ; void changeFileName() ; - void add() ; - void addRecursive() ; + void addSelection() ; + void addSelectionRecursive() ; void remove() ; void chooseDestinationDirectory(); void setDestinationDirectory(); void openDestinationDirectoryMenu(); +#ifdef TO_REMOVE void processItem(QMap &dirToAdd , int &index , ColFileInfo &parent ) ; +#endif void makeDir() ; void fileHashingFinished(QList hashedFiles) ; - void itemChanged(QTreeWidgetItem* item,int col) ; +#ifdef TO_REMOVE + void itemChanged(QTreeWidgetItem* item,int col) ; +#endif void updateRemoveDuplicate(bool checked); void cancel() ; void download() ; @@ -71,22 +75,23 @@ signals: private: void processSettings(bool bLoad) ; - QTreeWidgetItem* getRootItem(); bool updateList(); - bool addChild(QTreeWidgetItem *parent, const std::vector &child); +#ifdef TO_REMOVE + QTreeWidgetItem* getRootItem(); + bool addChild(QTreeWidgetItem *parent, const std::vector &child); bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ; - void addRecursive(bool recursive) ; + void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL); +#endif + void addSelection(bool recursive) ; bool addAllChild(QFileInfo &fileInfoParent , QMap &dirToAdd , QStringList &fileToHash , int &count); - void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL); Ui::RsCollectionDialog ui; QString _fileName ; const bool _creationMode ; const bool _readOnly; - std::vector _newColFileInfos ; QFileSystemModel *_dirModel; QSortFilterProxyModel *_tree_proxyModel; @@ -94,5 +99,6 @@ private: bool _dirLoaded; QHash _listOfFilesAddedInDir; - RsCollection _collection; + RsCollectionModel *mCollectionModel; + RsCollection *mCollection; }; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index d8693ef0a..7d4de185b 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -6,7 +6,7 @@ 0 0 - 600 + 671 400 @@ -17,7 +17,7 @@ Collection - + :/images/mimetypes/rscollection-16.png:/images/mimetypes/rscollection-16.png @@ -382,7 +382,7 @@ - + QAbstractItemView::NoEditTriggers @@ -398,11 +398,6 @@ true - - - 1 - - @@ -517,7 +512,6 @@ - diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index c9e2f86c9..0bc0b779c 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -2,6 +2,10 @@ #include "RsCollectionModel.h" +RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) + : QAbstractItemModel(parent),mCollection(col) +{} + // Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the // architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and // the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex) @@ -35,6 +39,21 @@ int RsCollectionModel::rowCount(const QModelIndex& parent) const return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size(); } +bool RsCollectionModel::hasChildren(const QModelIndex & parent) const +{ + if(!parent.isValid()) + return mCollection.fileTree().root(); + + EntryIndex i; + if(!convertInternalIdToIndex(parent.internalId(),i)) + return 0; + + if(i.is_file) + return false; + else + return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0; +} + int RsCollectionModel::columnCount(const QModelIndex&) const { return 4; @@ -180,8 +199,47 @@ QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const return QVariant(); } - - +void RsCollectionModel::preMods() +{ + mUpdating = true; + emit layoutAboutToBeChanged(); +} +void RsCollectionModel::postMods() +{ + // update all the local structures + + mDirParents.clear(); + mFileParents.clear(); + mDirSizes.clear(); + + uint64_t s; + recursUpdateLocalStructures(mCollection.fileTree().root(),s); + + mUpdating = false; + emit layoutChanged(); +} + +void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size) +{ + total_size = 0; + + const auto& dd(mCollection.fileTree().directoryData(dir_index)); + + for(uint32_t i=0;i& keywords, uint32_t& found) ; // Overloaded from QAbstractItemModel - virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override; virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const override; virtual QModelIndex parent ( const QModelIndex & index ) const override; @@ -31,15 +30,17 @@ class RsCollectionModel: public QAbstractItemModel virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; +#ifdef TODO + virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override; virtual QStringList mimeTypes () const override; virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override; #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) virtual Qt::DropActions supportedDragActions() const override; +#endif #endif - protected: + private: struct EntryIndex { bool is_file; // false=dir, true=file uint64_t index; @@ -47,6 +48,8 @@ class RsCollectionModel: public QAbstractItemModel static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); + void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size); + QVariant displayRole(const EntryIndex&,int col) const ; QVariant sortRole(const EntryIndex&,int col) const ; QVariant decorationRole(const EntryIndex&,int col) const ; From 885eb640dc381f73ea0cfa15954dc90978b695a6 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 27 Feb 2024 22:10:49 +0100 Subject: [PATCH 08/28] starting fixing RsCollection with the new model --- .../gui/FileTransfer/SharedFilesDialog.cpp | 5 ++- .../src/gui/common/RsCollection.cpp | 37 +++++++++---------- retroshare-gui/src/gui/common/RsCollection.h | 4 +- .../src/gui/common/RsCollectionDialog.cpp | 2 +- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 7321486fe..8c7e460c2 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -733,7 +733,7 @@ void SharedFilesDialog::sendLinkTo() void SharedFilesDialog::collCreate() { -#ifdef TODO +#ifdef TODO_COLLECTION QModelIndexList lst = getSelected(); std::vector dirVec; @@ -831,6 +831,8 @@ void SharedFilesDialog::collOpen() if (qinfo.exists()) { if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(),true); +#ifdef TO_REMOVE RsCollection::RsCollectionErrorCode err; RsCollection collection(qinfo.absoluteFilePath(),err); @@ -839,6 +841,7 @@ void SharedFilesDialog::collOpen() collection.downloadFiles(); return; } +#endif } } } diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index bc76fff00..e7e329604 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -38,19 +38,17 @@ const QString RsCollection::ExtensionString = QString("rscollection") ; RsCollection::RsCollection(QObject *parent) - : QObject(parent) + : QObject(parent), mFileTree(new RsFileTree) { -// _root = _xml_doc.createElement("RsCollection"); -// _xml_doc.appendChild(_root); } RsCollection::RsCollection(const RsFileTree& ft) - : mFileTree(ft) { + mFileTree = std::unique_ptr(new RsFileTree(ft)); } RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) - : QObject(parent) + : QObject(parent), mFileTree(new RsFileTree) { if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) { @@ -59,7 +57,7 @@ RsCollection::RsCollection(const std::vector& file_infos,FileSearchF } for(uint32_t i = 0;iroot(),file_infos[i],flags) ; } RsCollection::~RsCollection() @@ -142,7 +140,7 @@ static QString purifyFileName(const QString& input,bool& bad) void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) { - mFileTree.addFile(mFileTree.root(),fname.toStdString(),hash,size); + mFileTree->addFile(mFileTree->root(),fname.toStdString(),hash,size); #ifdef TO_REMOVE ColFileInfo info ; info.type = DIR_TYPE_FILE ; @@ -155,7 +153,7 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& } void RsCollection::merge_in(const RsFileTree& tree) { - recursMergeTree(mFileTree.root(),tree,tree.directoryData(tree.root())) ; + recursMergeTree(mFileTree->root(),tree,tree.directoryData(tree.root())) ; } void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) @@ -163,13 +161,13 @@ void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& for(uint32_t i=0;iaddFile(parent,fd.name,fd.hash,fd.size); } for(uint32_t i=0;iaddDirectory(parent,ld.name); recursMergeTree(new_dir_index,tree,ld); } } @@ -234,10 +232,10 @@ void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vectoraddFile(parent,dd.name,dd.hash,dd.size); else if (dd.type == DIR_TYPE_DIR) { - RsFileTree::DirIndex new_dir_index = mFileTree.addDirectory(parent,dd.name); + RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,dd.name); for(uint32_t i=0;idirectoryData(mFileTree->root())); if(!recursExportToXml(xml_doc,root,root_data)) return false; @@ -504,7 +503,7 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi std::string name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected).toUtf8().constData() ; uint64_t size = ee.attribute(QString("size")).toULongLong() ; - mFileTree.addFile(parent,name,hash,size); + mFileTree->addFile(parent,name,hash,size); #ifdef TO_REMOVE mFileTree.addFile(parent,) ColFileInfo newChild ; @@ -522,7 +521,7 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi bool bad_chars_detected = false ; std::string cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected).toUtf8().constData() ; - RsFileTree::DirIndex new_dir_index = mFileTree.addDirectory(parent,cleanDirName); + RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,cleanDirName); recursParseXml(doc,ee,new_dir_index); #ifdef TO_REMOVE @@ -554,7 +553,7 @@ bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFi { QDomElement f = doc.createElement("File") ; - const RsFileTree::FileData& fd(mFileTree.fileData(dd.subfiles[i])); + const RsFileTree::FileData& fd(mFileTree->fileData(dd.subfiles[i])); f.setAttribute(QString("name"),QString::fromUtf8(fd.name.c_str())) ; f.setAttribute(QString("sha1"),QString::fromStdString(fd.hash.toStdString())) ; @@ -565,7 +564,7 @@ bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFi for(uint32_t i=0;idirectoryData(dd.subdirs[i])); QDomElement d = doc.createElement("Directory") ; d.setAttribute(QString("name"),QString::fromUtf8(di.name.c_str())) ; @@ -600,11 +599,11 @@ bool RsCollection::save(QWidget *parent) const qulonglong RsCollection::count() const { - return mFileTree.numFiles(); + return mFileTree->numFiles(); } qulonglong RsCollection::size() { - return mFileTree.totalFileSize(); + return mFileTree->totalFileSize(); #ifdef TO_REMOVE QDomElement docElem = _xml_doc.documentElement(); diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 47fdee5d6..745a4c764 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -90,7 +90,7 @@ public: bool save(const QString& fileName) const ; // returns the file tree - const RsFileTree& fileTree() const { return mFileTree; } + const RsFileTree& fileTree() const { return *mFileTree; } // total size of files in the collection qulonglong size(); // total number of files in the collection @@ -129,7 +129,7 @@ private: // Auto Download recursively. void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; - RsFileTree mFileTree; + std::unique_ptr mFileTree; #ifdef TO_REMOVE QDomDocument _xml_doc ; QString _fileName ; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 52583c4f7..c6f22ceb7 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -1456,7 +1456,7 @@ void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *par bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) { - return RsCollectionDialog(fileName,readOnly,showError).exec(); + return RsCollectionDialog(fileName,false,readOnly).exec(); } bool RsCollectionDialog::openNewCollection(const RsFileTree& tree,const QString& proposed_file_name) From 2ed72a146b047921e79963c1fd24b40ae4cbb672 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 28 Feb 2024 21:56:38 +0100 Subject: [PATCH 09/28] fixed basic functionality of RsCollectionModel --- .../src/gui/common/RsCollectionDialog.cpp | 5 +- .../src/gui/common/RsCollectionDialog.h | 2 +- .../src/gui/common/RsCollectionModel.cpp | 163 ++++++++++++++---- .../src/gui/common/RsCollectionModel.h | 15 +- 4 files changed, 141 insertions(+), 44 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index c6f22ceb7..775b70e06 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -307,9 +307,9 @@ RsCollectionDialog::~RsCollectionDialog() * @param event: event occured * @return If we don't have to process event in parent. */ +#ifdef TODO_COLLECTION bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) { -#ifdef TODO_COLLECTION if (obj == ui._fileEntriesTW) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); @@ -367,9 +367,8 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) // pass the event on to the parent class return QDialog::eventFilter(obj, event); -#endif - return true; } +#endif /** * @brief RsCollectionDialog::processSettings diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 192732338..82a28ee5c 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -40,7 +40,7 @@ public: static bool openExistingCollection(const QString& fileName, bool readOnly = false, bool showError = true); protected: - bool eventFilter(QObject *obj, QEvent *ev); + //bool eventFilter(QObject *obj, QEvent *ev); RsCollectionDialog(const QString& filename, const bool& creation, const bool& readOnly = false) ; diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 0bc0b779c..c0485360d 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -2,10 +2,28 @@ #include "RsCollectionModel.h" +// #define DEBUG_COLLECTION_MODEL 1 + +static const int COLLECTION_MODEL_NB_COLUMN = 4; + RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) : QAbstractItemModel(parent),mCollection(col) -{} +{ + postMods(); +} +#ifdef DEBUG_COLLECTION_MODEL +static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIndex& i) +{ + return o << ((i.is_file)?("File"):"Dir") << " with index " << (int)i.index ; +} +static std::ostream& operator<<(std::ostream& o,const QModelIndex& i) +{ + return o << "QModelIndex (row " << i.row() << ", of ref " << i.internalId() << ")" ; +} +#endif + +// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the // Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the // architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and // the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex) @@ -13,7 +31,7 @@ RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) bool RsCollectionModel::convertIndexToInternalId(const EntryIndex& e,quintptr& ref) { - ref = (e.index << 1) || e.is_file; + ref = (e.index << 1) | e.is_file; return true; } @@ -26,56 +44,95 @@ bool RsCollectionModel::convertInternalIdToIndex(quintptr ref, EntryIndex& e) int RsCollectionModel::rowCount(const QModelIndex& parent) const { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Asking rowCount of " << parent << std::endl; +#endif + + if(parent.column() >= COLLECTION_MODEL_NB_COLUMN) + return 0; + if(!parent.isValid()) - return mCollection.fileTree().root(); + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " root! returning " << mCollection.fileTree().directoryData(0).subdirs.size() + + mCollection.fileTree().directoryData(0).subfiles.size() << std::endl; +#endif + + return mCollection.fileTree().directoryData(0).subdirs.size() + + mCollection.fileTree().directoryData(0).subfiles.size(); + } EntryIndex i; if(!convertInternalIdToIndex(parent.internalId(),i)) return 0; if(i.is_file) + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " file: returning 0" << std::endl; +#endif return 0; + } else + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " dir: returning " << mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() + << std::endl; +#endif return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size(); + } } bool RsCollectionModel::hasChildren(const QModelIndex & parent) const { if(!parent.isValid()) - return mCollection.fileTree().root(); + return true; EntryIndex i; if(!convertInternalIdToIndex(parent.internalId(),i)) - return 0; + return false; if(i.is_file) return false; + else if(mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0) + return true; else - return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0; + return false; } int RsCollectionModel::columnCount(const QModelIndex&) const { - return 4; + return COLLECTION_MODEL_NB_COLUMN; } -QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int) const +QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int role) const { - switch(section) - { - case 0: return tr("File"); - case 1: return tr("Size"); - case 2: return tr("Hash"); - case 3: return tr("Count"); - default: - return QVariant(); - } + if(role == Qt::DisplayRole) + switch(section) + { + case 0: return tr("File"); + case 1: return tr("Size"); + case 2: return tr("Hash"); + case 3: return tr("Count"); + default: + return QVariant(); + } + return QVariant(); } QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & parent) const { + if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) + return QModelIndex(); + EntryIndex i; - if(!convertInternalIdToIndex(parent.internalId(),i)) + + if(!parent.isValid()) // root + { + i.is_file = false; + i.index = 0; + } + else if(!convertInternalIdToIndex(parent.internalId(),i)) return QModelIndex(); if(i.is_file || i.index >= mCollection.fileTree().numDirs()) @@ -83,9 +140,6 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa const auto& parentData(mCollection.fileTree().directoryData(i.index)); - if(row < 0) - return QModelIndex(); - if((size_t)row < parentData.subdirs.size()) { EntryIndex e; @@ -94,6 +148,10 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa quintptr ref; convertIndexToInternalId(e,ref); + +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl; +#endif return createIndex(row,column,ref); } @@ -105,6 +163,9 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa quintptr ref; convertIndexToInternalId(e,ref); +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl; +#endif return createIndex(row,column,ref); } @@ -113,12 +174,16 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa QModelIndex RsCollectionModel::parent(const QModelIndex & index) const { + if(!index.isValid()) + return QModelIndex(); + EntryIndex i; - if(!convertInternalIdToIndex(index.internalId(),i)) + if(!convertInternalIdToIndex(index.internalId(),i) || i.index==0) return QModelIndex(); EntryIndex p; p.is_file = false; // all parents are directories + int row; if(i.is_file) { @@ -128,7 +193,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); return QModelIndex(); } - p.index = it->second; + p.index = it->second.parent_index; + row = it->second.parent_row; } else { @@ -138,12 +204,14 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); return QModelIndex(); } - p.index = it->second; + p.index = it->second.parent_index; + row = it->second.parent_row; } quintptr ref; convertIndexToInternalId(p,ref); - return createIndex(0,index.column(),ref); + + return createIndex(row,0,ref); } QVariant RsCollectionModel::data(const QModelIndex& index, int role) const @@ -152,6 +220,9 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const if(!convertInternalIdToIndex(index.internalId(),i)) return QVariant(); +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Asking data of " << i << std::endl; +#endif switch(role) { case Qt::DisplayRole: return displayRole(i,index.column()); @@ -212,32 +283,54 @@ void RsCollectionModel::postMods() mFileParents.clear(); mDirSizes.clear(); +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Updating from tree: " << std::endl; +#endif uint64_t s; - recursUpdateLocalStructures(mCollection.fileTree().root(),s); + recursUpdateLocalStructures(mCollection.fileTree().root(),s,0); mUpdating = false; emit layoutChanged(); } -void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size) +void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size,int depth) { total_size = 0; const auto& dd(mCollection.fileTree().directoryData(dir_index)); - for(uint32_t i=0;i& keywords, uint32_t& found) ; // Overloaded from QAbstractItemModel @@ -40,15 +40,15 @@ class RsCollectionModel: public QAbstractItemModel #endif #endif - private: struct EntryIndex { bool is_file; // false=dir, true=file uint64_t index; }; + private: static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); - void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size); + void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index, uint64_t& total_size, int depth); QVariant displayRole(const EntryIndex&,int col) const ; QVariant sortRole(const EntryIndex&,int col) const ; @@ -59,8 +59,13 @@ class RsCollectionModel: public QAbstractItemModel const RsCollection& mCollection; - std::map mFileParents; - std::map mDirParents; + struct ParentInfo { + RsFileTree::DirIndex parent_index; // index of the parent + RsFileTree::DirIndex parent_row; // row of that child, in this parent + }; + + std::map mFileParents; + std::map mDirParents; std::map mDirSizes; // std::set mFilteredPointers ; From 31c390aa27f1697445752384b37ba53346b0b4df Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 29 Feb 2024 22:07:52 +0100 Subject: [PATCH 10/28] simplified usage of RsCollectionDialog in shared files (removed duplicate functionality) --- .../gui/FileTransfer/SharedFilesDialog.cpp | 12 +-- .../src/gui/common/RsCollectionDialog.cpp | 87 +++++++++++++------ .../src/gui/common/RsCollectionDialog.h | 21 +++-- .../src/gui/common/RsUrlHandler.cpp | 9 +- 4 files changed, 86 insertions(+), 43 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 8c7e460c2..f4e4cfbb3 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -777,7 +777,7 @@ void SharedFilesDialog::collModif() QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) - RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); + RsCollectionDialog::editExistingCollection(qinfo.absoluteFilePath()); } void SharedFilesDialog::collView() @@ -1168,12 +1168,14 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point ) collViewAct->setEnabled(bIsRsColl); collOpenAct->setEnabled(true); - QMenu collectionMenu(tr("Collection"), this); + QMenu collectionMenu(tr("Retroshare Collection"), this); collectionMenu.setIcon(QIcon(IMAGE_LIBRARY)); collectionMenu.addAction(collCreateAct); - collectionMenu.addAction(collModifAct); - collectionMenu.addAction(collViewAct); - collectionMenu.addAction(collOpenAct); + + if(bIsRsColl) + collectionMenu.addAction(collModifAct); + //collectionMenu.addAction(collViewAct); + //collectionMenu.addAction(collOpenAct); switch (type) { case DIR_TYPE_DIR : diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 775b70e06..09f8159b7 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -123,10 +123,8 @@ protected: * @param creation: Open dialog as RsColl Creation or RsColl DownLoad * @param readOnly: Open dialog for RsColl as ReadOnly */ -RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName - , const bool& creation /* = false */ - , const bool& readOnly /* = false */) - : _fileName(collectionFileName), _creationMode(creation) ,_readOnly(readOnly) +RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsCollectionDialogMode mode) + : _fileName(collectionFileName), _mode(mode) { RsCollection::RsCollectionErrorCode err_code; mCollection = new RsCollection(collectionFileName,err_code); @@ -154,26 +152,27 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/collections.png")); - if(creation) - { - ui.headerFrame->setHeaderText(tr("Collection Editor")); - ui.downloadFolder_LE->hide(); - ui.downloadFolder_LB->hide(); - ui.destinationDir_TB->hide(); - } - else + if(_mode == DOWNLOAD) { ui.headerFrame->setHeaderText(tr("Download files")); ui.downloadFolder_LE->show(); ui.downloadFolder_LB->show(); - ui.label_filename->hide(); + ui.label_filename->hide(); ui._filename_TL->hide(); ui.downloadFolder_LE->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str())) ; QObject::connect(ui.downloadFolder_LE,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(openDestinationDirectoryMenu())); QObject::connect(ui.destinationDir_TB,SIGNAL(pressed()), this, SLOT(openDestinationDirectoryMenu())); - } + } + else + { + ui.headerFrame->setHeaderText(tr("Collection Editor")); + ui.downloadFolder_LE->hide(); + ui.downloadFolder_LB->hide(); + ui.destinationDir_TB->hide(); + } + // 1 - add all elements to the list. @@ -230,12 +229,12 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName processSettings(true); // 5 Activate button follow creationMode - ui._changeFile->setVisible(_creationMode && !_readOnly); - ui._makeDir_PB->setVisible(_creationMode && !_readOnly); - ui._removeDuplicate_CB->setVisible(_creationMode && !_readOnly); - ui._save_PB->setVisible(_creationMode && !_readOnly); - ui._treeViewFrame->setVisible(_creationMode && !_readOnly); - ui._download_PB->setVisible(!_creationMode && !_readOnly); + ui._changeFile->setVisible(_mode == EDIT); + ui._makeDir_PB->setVisible(_mode == EDIT); + ui._removeDuplicate_CB->setVisible(_mode == EDIT); + ui._save_PB->setVisible(_mode == EDIT); + ui._treeViewFrame->setVisible(_mode == EDIT); + ui._download_PB->setVisible(_mode == DOWNLOAD); #ifdef TO_REMOVE ui._fileEntriesTW->installEventFilter(this); @@ -376,12 +375,12 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) */ void RsCollectionDialog::processSettings(bool bLoad) { - Settings->beginGroup("RsCollectionDialog"); + Settings->beginGroup("RsCollectionDialogV2"); if (bLoad) { // load settings - if(_creationMode && !_readOnly){ + if(_mode == EDIT){ // Load windows geometrie restoreGeometry(Settings->value("WindowGeometrie_CM").toByteArray()); // Load splitters state @@ -403,7 +402,7 @@ void RsCollectionDialog::processSettings(bool bLoad) ui._fileEntriesTW->header()->restoreState(Settings->value("FileEntriesHeader").toByteArray()); } } else { - if(_creationMode && !_readOnly){ + if(_mode == EDIT){ // Save windows geometrie Settings->setValue("WindowGeometrie_CM",saveGeometry()); // Save splitters state @@ -1412,6 +1411,7 @@ void RsCollectionDialog::download() void RsCollectionDialog::save() { mCollection->save(_fileName); + close(); #ifdef TO_REMOVE std::cerr << "Saving!" << std::endl; _newColFileInfos.clear(); @@ -1453,13 +1453,48 @@ void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *par } #endif -bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) +bool RsCollectionDialog::editExistingCollection(const QString& fileName, bool showError /* = true*/) { - return RsCollectionDialog(fileName,false,readOnly).exec(); + return RsCollectionDialog(fileName,EDIT).exec(); } -bool RsCollectionDialog::openNewCollection(const RsFileTree& tree,const QString& proposed_file_name) +bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool showError /* = true*/) { + return RsCollectionDialog(fileName,DOWNLOAD).exec(); +} + +bool RsCollectionDialog::openNewCollection(const RsFileTree& tree) +{ + RsCollection collection(tree); + QString fileName; + + if(!misc::getSaveFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE + , QApplication::translate("RsCollectionFile", "Create collection file") + , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" + , fileName,0, QFileDialog::DontConfirmOverwrite)) + return false; + + if (!fileName.endsWith("." + RsCollection::ExtensionString)) + fileName += "." + RsCollection::ExtensionString ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + QMessageBox mb; + mb.setText(tr("Save Collection File.")); + mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); + QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); + QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); + + if (mb.clickedButton()==btnCancel) + return false; + + if(!collection.save(fileName)) + return false; + + return RsCollectionDialog(fileName,EDIT).exec(); + #ifdef TODO_COLLECTION QString fileName = proposed_file_name; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 82a28ee5c..71c261cb4 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -34,15 +34,24 @@ public: virtual ~RsCollectionDialog(); // Open new collection - static bool openNewCollection(const RsFileTree &tree, const QString &proposed_file_name = QString()); + static bool openNewCollection(const RsFileTree &tree = RsFileTree()); - // Open existing collection - static bool openExistingCollection(const QString& fileName, bool readOnly = false, bool showError = true); + // Edit existing collection + static bool editExistingCollection(const QString& fileName, bool showError = true); + + // Open existing collection for download + static bool openExistingCollection(const QString& fileName, bool showError = true); protected: //bool eventFilter(QObject *obj, QEvent *ev); - RsCollectionDialog(const QString& filename, const bool& creation, const bool& readOnly = false) ; + enum RsCollectionDialogMode { + UNKNOWN = 0x00, + EDIT = 0x01, + DOWNLOAD = 0x02, + }; + + RsCollectionDialog(const QString& filename, RsCollectionDialogMode mode) ; private slots: void directoryLoaded(QString dirLoaded); @@ -90,8 +99,8 @@ private: Ui::RsCollectionDialog ui; QString _fileName ; - const bool _creationMode ; - const bool _readOnly; + + RsCollectionDialogMode _mode; QFileSystemModel *_dirModel; QSortFilterProxyModel *_tree_proxyModel; diff --git a/retroshare-gui/src/gui/common/RsUrlHandler.cpp b/retroshare-gui/src/gui/common/RsUrlHandler.cpp index 3d005aed6..94ec79753 100644 --- a/retroshare-gui/src/gui/common/RsUrlHandler.cpp +++ b/retroshare-gui/src/gui/common/RsUrlHandler.cpp @@ -21,16 +21,13 @@ #include #include #include -#include "RsCollection.h" +#include "RsCollectionDialog.h" #include "RsUrlHandler.h" bool RsUrlHandler::openUrl(const QUrl& url) { if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString)) - { - RsCollection::RsCollectionErrorCode err; - RsCollection(url.toLocalFile(),err).downloadFiles() ; - return true; - } + return RsCollectionDialog::openExistingCollection(url.toLocalFile()); + return QDesktopServices::openUrl(url) ; } From e106959fbd0b506ba1ca771b1a2ad4025c779210 Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 1 Mar 2024 23:00:17 +0100 Subject: [PATCH 11/28] fixed creating new collection --- .../src/gui/FileTransfer/SharedFilesDialog.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index f4e4cfbb3..a26f13728 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -733,15 +733,16 @@ void SharedFilesDialog::sendLinkTo() void SharedFilesDialog::collCreate() { -#ifdef TODO_COLLECTION QModelIndexList lst = getSelected(); std::vector dirVec; model->getDirDetailsFromSelect(lst, dirVec); + auto RemoteMode = isRemote(); FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; QString dir_name; + if(!RemoteMode) { if(!dirVec.empty()) @@ -750,8 +751,15 @@ void SharedFilesDialog::collCreate() dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); } } - RsCollection(dirVec,f).openNewColl(parent,dir_name); -#endif + + RsFileTree tree; + + for(uint32_t i=0;i Date: Mon, 4 Mar 2024 23:00:25 +0100 Subject: [PATCH 12/28] fixed update of tree when changed --- build_scripts/OBS | 2 +- libbitdht | 2 +- libretroshare | 2 +- retroshare-gui/src/gui/common/RsCollectionDialog.cpp | 3 +++ retroshare-webui | 2 +- supportlibs/libsam3 | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/build_scripts/OBS b/build_scripts/OBS index 353596b0e..9dd9d7f94 160000 --- a/build_scripts/OBS +++ b/build_scripts/OBS @@ -1 +1 @@ -Subproject commit 353596b0ee5ea76611eb663b90bf3ab1c9f34ad7 +Subproject commit 9dd9d7f94a600e8c8478887a4f7784fdc3294034 diff --git a/libbitdht b/libbitdht index 2ddc86fb5..659423769 160000 --- a/libbitdht +++ b/libbitdht @@ -1 +1 @@ -Subproject commit 2ddc86fb575a61170f4c06a00152e3e7dc74c8f4 +Subproject commit 659423769541169457c41f71c8a038e2d64ba079 diff --git a/libretroshare b/libretroshare index ac1c5f301..7e526a423 160000 --- a/libretroshare +++ b/libretroshare @@ -1 +1 @@ -Subproject commit ac1c5f3019ff17c695758dabec0ee8e540d401e0 +Subproject commit 7e526a4232285e1c2789315c1f382f54d868df8d diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 09f8159b7..b1a5e405a 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -171,6 +171,8 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl ui.downloadFolder_LE->hide(); ui.downloadFolder_LB->hide(); ui.destinationDir_TB->hide(); + ui.label_filename->show(); + ui._filename_TL->show(); } @@ -858,6 +860,7 @@ void RsCollectionDialog::addSelection(bool recursive) // Process Files once all done ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); #endif + mCollectionModel->postMods(); } /** diff --git a/retroshare-webui b/retroshare-webui index ba0de17f4..542a8c07b 160000 --- a/retroshare-webui +++ b/retroshare-webui @@ -1 +1 @@ -Subproject commit ba0de17f41914f1be6754db5bc5b4507b0deaafd +Subproject commit 542a8c07bd02f9bb9082f7aba5aaaed54e643fc1 diff --git a/supportlibs/libsam3 b/supportlibs/libsam3 index 2226ef0a2..8623304b6 160000 --- a/supportlibs/libsam3 +++ b/supportlibs/libsam3 @@ -1 +1 @@ -Subproject commit 2226ef0a20a001ec0942be6abe5e909c15447d8e +Subproject commit 8623304b62294dafbe477573f321a464fef721dd From f375912bc577f03be865b11e7aec1183835167a6 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 7 Mar 2024 22:15:12 +0100 Subject: [PATCH 13/28] added checkable items in RsCollectionModel --- .../src/gui/common/RsCollectionModel.cpp | 128 ++++++++++++++---- .../src/gui/common/RsCollectionModel.h | 29 +++- 2 files changed, 125 insertions(+), 32 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index c0485360d..87fe1fb53 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -4,6 +4,10 @@ // #define DEBUG_COLLECTION_MODEL 1 +static const int COLLECTION_MODEL_FILENAME = 0; +static const int COLLECTION_MODEL_SIZE = 1; +static const int COLLECTION_MODEL_HASH = 2; +static const int COLLECTION_MODEL_COUNT = 3; static const int COLLECTION_MODEL_NB_COLUMN = 4; RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) @@ -172,6 +176,14 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa return QModelIndex(); } +Qt::ItemFlags RsCollectionModel::flags ( const QModelIndex & index ) const +{ + if(index.isValid() && index.column() == COLLECTION_MODEL_FILENAME) + return QAbstractItemModel::flags(index) | Qt::ItemIsUserTristate; + + return QAbstractItemModel::flags(index) & ~Qt::ItemIsUserTristate; +} + QModelIndex RsCollectionModel::parent(const QModelIndex & index) const { if(!index.isValid()) @@ -187,8 +199,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const if(i.is_file) { - const auto it = mFileParents.find(i.index); - if(it == mFileParents.end()) + const auto it = mFileInfos.find(i.index); + if(it == mFileInfos.end()) { RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); return QModelIndex(); @@ -198,8 +210,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const } else { - const auto it = mDirParents.find(i.index); - if(it == mDirParents.end()) + const auto it = mDirInfos.find(i.index); + if(it == mDirInfos.end()) { RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); return QModelIndex(); @@ -228,11 +240,61 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const case Qt::DisplayRole: return displayRole(i,index.column()); //case Qt::SortRole: return SortRole(i,index.column()); case Qt::DecorationRole: return decorationRole(i,index.column()); + case Qt::CheckStateRole: return checkStateRole(i,index.column()); default: return QVariant(); } } +bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,int role) +{ + if(!index.isValid()) + return false; + + if (role==Qt::CheckStateRole) + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl; +#endif + return true; + } + else + return setData(index,value,role); +} + +QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const +{ + if(col == COLLECTION_MODEL_FILENAME) + { + if(i.is_file) + { + auto it = mFileInfos.find(i.index); + if(it == mFileInfos.end()) + return QVariant(); + + if(it->second.is_checked) + return QVariant(Qt::Checked); + else + return QVariant(Qt::Unchecked); + } + else + { + auto it = mDirInfos.find(i.index); + if(it == mDirInfos.end()) + return QVariant(); + + switch(it->second.check_state) + { + case SELECTED: return QVariant(Qt::Checked); + case PARTIALLY_SELECTED: return QVariant(Qt::PartiallyChecked); + default: + case UNSELECTED: return QVariant(Qt::Unchecked); + } + } + } + else + return QVariant(); +} QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const { switch(col) @@ -245,12 +307,12 @@ QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ; { - auto it = mDirSizes.find(i.index); + auto it = mDirInfos.find(i.index); - if(it == mDirSizes.end()) + if(it == mDirInfos.end()) return QVariant(); else - return QVariant((qulonglong)it->second); + return QVariant((qulonglong)it->second.total_size); } case 2: return (i.is_file)? @@ -279,9 +341,8 @@ void RsCollectionModel::postMods() { // update all the local structures - mDirParents.clear(); - mFileParents.clear(); - mDirSizes.clear(); + mDirInfos.clear(); + mFileInfos.clear(); #ifdef DEBUG_COLLECTION_MODEL std::cerr << "Updating from tree: " << std::endl; @@ -296,9 +357,29 @@ void RsCollectionModel::postMods() void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size,int depth) { total_size = 0; + bool all_checked = true; + bool all_unchecked = false; const auto& dd(mCollection.fileTree().directoryData(dir_index)); + for(uint32_t i=0;i= QT_VERSION_CHECK (5, 0, 0) @@ -53,20 +54,34 @@ class RsCollectionModel: public QAbstractItemModel QVariant displayRole(const EntryIndex&,int col) const ; QVariant sortRole(const EntryIndex&,int col) const ; QVariant decorationRole(const EntryIndex&,int col) const ; + QVariant checkStateRole(const EntryIndex& i,int col) const; //QVariant filterRole(const DirDetails& details,int coln) const; bool mUpdating ; const RsCollection& mCollection; - struct ParentInfo { - RsFileTree::DirIndex parent_index; // index of the parent - RsFileTree::DirIndex parent_row; // row of that child, in this parent + enum DirCheckState: uint8_t { + UNSELECTED = 0x00, + PARTIALLY_SELECTED = 0x01, + SELECTED = 0x02, }; - std::map mFileParents; - std::map mDirParents; - std::map mDirSizes; + struct ModelDirInfo { + RsFileTree::DirIndex parent_index; // index of the parent + RsFileTree::DirIndex parent_row; // row of that child, in this parent + DirCheckState check_state; + uint64_t total_size; + }; + + struct ModelFileInfo { + RsFileTree::DirIndex parent_index; // index of the parent + RsFileTree::DirIndex parent_row; // row of that child, in this parent + bool is_checked; + }; + + std::map mFileInfos; + std::map mDirInfos; // std::set mFilteredPointers ; }; From 67ff37a0d43783d04f03365fb78ac8195f9ea590 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 9 Mar 2024 00:03:16 +0100 Subject: [PATCH 14/28] using vectors instead of maps for mCollectionModel data. --- .../src/gui/common/RsCollectionModel.cpp | 160 +++++++++++++----- .../src/gui/common/RsCollectionModel.h | 4 +- 2 files changed, 120 insertions(+), 44 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 87fe1fb53..91cea236e 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -16,7 +16,6 @@ RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) postMods(); } -#ifdef DEBUG_COLLECTION_MODEL static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIndex& i) { return o << ((i.is_file)?("File"):"Dir") << " with index " << (int)i.index ; @@ -25,6 +24,7 @@ static std::ostream& operator<<(std::ostream& o,const QModelIndex& i) { return o << "QModelIndex (row " << i.row() << ", of ref " << i.internalId() << ")" ; } +#ifdef DEBUG_COLLECTION_MODEL #endif // Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the @@ -179,9 +179,19 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa Qt::ItemFlags RsCollectionModel::flags ( const QModelIndex & index ) const { if(index.isValid() && index.column() == COLLECTION_MODEL_FILENAME) - return QAbstractItemModel::flags(index) | Qt::ItemIsUserTristate; + { + EntryIndex e; - return QAbstractItemModel::flags(index) & ~Qt::ItemIsUserTristate; + if(!convertInternalIdToIndex(index.internalId(),e)) + return QAbstractItemModel::flags(index) ; + + if(e.is_file) + return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable; + else + return QAbstractItemModel::flags(index) | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable; + } + + return QAbstractItemModel::flags(index) ; } QModelIndex RsCollectionModel::parent(const QModelIndex & index) const @@ -199,25 +209,13 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const if(i.is_file) { - const auto it = mFileInfos.find(i.index); - if(it == mFileInfos.end()) - { - RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); - return QModelIndex(); - } - p.index = it->second.parent_index; - row = it->second.parent_row; + p.index = mFileInfos[i.index].parent_index; + row = mFileInfos[i.index].parent_row; } else { - const auto it = mDirInfos.find(i.index); - if(it == mDirInfos.end()) - { - RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); - return QModelIndex(); - } - p.index = it->second.parent_index; - row = it->second.parent_row; + p.index = mDirInfos[i.index].parent_index; + row = mDirInfos[i.index].parent_row; } quintptr ref; @@ -237,8 +235,7 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const #endif switch(role) { - case Qt::DisplayRole: return displayRole(i,index.column()); - //case Qt::SortRole: return SortRole(i,index.column()); + case Qt::DisplayRole: return displayRole(i,index.column()); case Qt::DecorationRole: return decorationRole(i,index.column()); case Qt::CheckStateRole: return checkStateRole(i,index.column()); default: @@ -251,15 +248,94 @@ bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,i if(!index.isValid()) return false; - if (role==Qt::CheckStateRole) + EntryIndex e; + + if(role==Qt::CheckStateRole && convertInternalIdToIndex(index.internalId(), e)) { -#ifdef DEBUG_COLLECTION_MODEL +//#ifdef DEBUG_COLLECTION_MODEL std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl; -#endif +//#endif + RsFileTree::DirIndex dir_index ; + + if(e.is_file) + { + mFileInfos[e.index].is_checked = value.toBool(); + dir_index = mFileInfos[e.index].parent_index; + } + else + { + std::function recursSetCheckFlag = [&](RsFileTree::DirIndex i,bool s) -> void + { + mDirInfos[i].check_state = (s)?SELECTED:UNSELECTED; + auto& dir_data(mCollection.fileTree().directoryData(i)); + + for(uint32_t i=0;isecond.is_checked) + std::cerr<< "entry is file, checkstate = " << (int)mFileInfos[i.index].is_checked << std::endl; + if(mFileInfos[i.index].is_checked) return QVariant(Qt::Checked); else return QVariant(Qt::Unchecked); } else { - auto it = mDirInfos.find(i.index); - if(it == mDirInfos.end()) - return QVariant(); + std::cerr<< "entry is dir, checkstate = " << (int)mDirInfos[i.index].check_state << std::endl; - switch(it->second.check_state) + switch(mDirInfos[i.index].check_state) { - case SELECTED: return QVariant(Qt::Checked); - case PARTIALLY_SELECTED: return QVariant(Qt::PartiallyChecked); + case SELECTED: return QVariant::fromValue((int)Qt::Checked); + case PARTIALLY_SELECTED: return QVariant::fromValue((int)Qt::PartiallyChecked); default: - case UNSELECTED: return QVariant(Qt::Unchecked); + case UNSELECTED: return QVariant::fromValue((int)Qt::Unchecked); } } } @@ -307,12 +378,12 @@ QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ; { - auto it = mDirInfos.find(i.index); +// auto it = mDirInfos[i.index]; - if(it == mDirInfos.end()) - return QVariant(); - else - return QVariant((qulonglong)it->second.total_size); +// if(it == mDirInfos.end()) +// return QVariant(); +// else + return QVariant((qulonglong)mDirInfos[i.index].total_size); } case 2: return (i.is_file)? @@ -344,6 +415,11 @@ void RsCollectionModel::postMods() mDirInfos.clear(); mFileInfos.clear(); + mDirInfos.resize(mCollection.fileTree().numDirs()); + mFileInfos.resize(mCollection.fileTree().numFiles()); + + mDirInfos[0].parent_index = 0; + #ifdef DEBUG_COLLECTION_MODEL std::cerr << "Updating from tree: " << std::endl; #endif diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index 459eb102d..7d6dc2a11 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -80,8 +80,8 @@ class RsCollectionModel: public QAbstractItemModel bool is_checked; }; - std::map mFileInfos; - std::map mDirInfos; + std::vector mFileInfos; + std::vector mDirInfos; // std::set mFilteredPointers ; }; From 9ba4ac6362d11b69d49728f91186100bf9b60005 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 9 Mar 2024 18:31:01 +0100 Subject: [PATCH 15/28] fixed a few bugs in file counting --- .../src/gui/common/RsCollectionDialog.cpp | 16 +--- .../src/gui/common/RsCollectionModel.cpp | 92 ++++++++++++------- .../src/gui/common/RsCollectionModel.h | 13 ++- 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index b1a5e405a..71e1c2c75 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -181,16 +181,8 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl mCollectionModel = new RsCollectionModel(*mCollection); ui._fileEntriesTW->setModel(mCollectionModel); -#ifdef TO_REMOVE - ui._fileEntriesTW->setColumnCount(COLUMN_COUNT) ; - - QTreeWidgetItem *headerItem = ui._fileEntriesTW->headerItem(); - headerItem->setText(COLUMN_FILE, tr("File")); - headerItem->setText(COLUMN_FILEPATH, tr("File Path")); - headerItem->setText(COLUMN_SIZE, tr("Size")); - headerItem->setText(COLUMN_HASH, tr("Hash")); - headerItem->setText(COLUMN_FILEC, tr("File Count")); -#endif + connect(mCollectionModel,SIGNAL(sizesChanged()),this,SLOT(updateSizes())); + updateSizes(); // forced because it's only called when the collection is changed, or when the model is created. bool wrong_chars = !updateList(); @@ -638,8 +630,8 @@ void RsCollectionDialog::directoryLoaded(QString dirLoaded) */ void RsCollectionDialog::updateSizes() { - ui._selectedFiles_TL->setText(QString::number(mCollection->count())); - ui._totalSize_TL->setText(misc::friendlyUnit(mCollection->size())); + ui._selectedFiles_TL->setText(QString::number(mCollectionModel->totalSelected())); + ui._totalSize_TL->setText(misc::friendlyUnit(mCollectionModel->totalSize())); } /** diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 91cea236e..bdf6c7abe 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -264,16 +264,31 @@ bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,i } else { - std::function recursSetCheckFlag = [&](RsFileTree::DirIndex i,bool s) -> void + std::function recursSetCheckFlag = [&](RsFileTree::DirIndex index,bool s) -> void { - mDirInfos[i].check_state = (s)?SELECTED:UNSELECTED; - auto& dir_data(mCollection.fileTree().directoryData(i)); + mDirInfos[index].check_state = (s)?SELECTED:UNSELECTED; + auto& dir_data(mCollection.fileTree().directoryData(index)); + + mDirInfos[index].total_size = 0; + mDirInfos[index].total_count = 0; for(uint32_t i=0;i Date: Sun, 10 Mar 2024 23:41:10 +0100 Subject: [PATCH 16/28] added some debug info in RsCollectionModel --- .../src/gui/common/RsCollectionModel.cpp | 106 +++++++++++++----- .../src/gui/common/RsCollectionModel.h | 2 + 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index bdf6c7abe..d7d352c8a 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -129,20 +129,20 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) return QModelIndex(); - EntryIndex i; + EntryIndex parent_index; if(!parent.isValid()) // root { - i.is_file = false; - i.index = 0; + parent_index.is_file = false; + parent_index.index = 0; } - else if(!convertInternalIdToIndex(parent.internalId(),i)) + else if(!convertInternalIdToIndex(parent.internalId(),parent_index)) return QModelIndex(); - if(i.is_file || i.index >= mCollection.fileTree().numDirs()) + if(parent_index.is_file || parent_index.index >= mCollection.fileTree().numDirs()) return QModelIndex(); - const auto& parentData(mCollection.fileTree().directoryData(i.index)); + const auto& parentData(mCollection.fileTree().directoryData(parent_index.index)); if((size_t)row < parentData.subdirs.size()) { @@ -450,6 +450,8 @@ void RsCollectionModel::postMods() mUpdating = false; emit layoutChanged(); emit sizesChanged(); + + debugDump(); } void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,int depth) @@ -461,27 +463,6 @@ void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_ind const auto& dd(mCollection.fileTree().directoryData(dir_index)); - for(uint32_t i=0;i recursDump = [&](RsFileTree::DirIndex indx,int depth) { + const auto& dir_data(mCollection.fileTree().directoryData(indx)); + + for(int i=0;i recursDump2 = [&](QModelIndex indx,int depth) { + + for(int i=0;i Date: Mon, 11 Mar 2024 13:37:09 +0100 Subject: [PATCH 17/28] fixed a few bugs in counting and model parenting --- retroshare-gui/src/gui/common/RsCollectionModel.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index d7d352c8a..f05e25231 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -22,7 +22,7 @@ static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIn } static std::ostream& operator<<(std::ostream& o,const QModelIndex& i) { - return o << "QModelIndex (row " << i.row() << ", of ref " << i.internalId() << ")" ; + return o << "QModelIndex (row " << i.row() << ", ref " << i.internalId() << ")" ; } #ifdef DEBUG_COLLECTION_MODEL #endif @@ -200,7 +200,7 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const return QModelIndex(); EntryIndex i; - if(!convertInternalIdToIndex(index.internalId(),i) || i.index==0) + if(index.internalId()==0 || !convertInternalIdToIndex(index.internalId(),i)) return QModelIndex(); EntryIndex p; @@ -276,7 +276,7 @@ bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,i { recursSetCheckFlag(dir_data.subdirs[i],s); mDirInfos[index].total_size += mDirInfos[dir_data.subdirs[i]].total_size ; - ++mDirInfos[index].total_count; + mDirInfos[index].total_count+= mDirInfos[dir_data.subdirs[i]].total_count; } for(uint32_t i=0;i Date: Tue, 12 Mar 2024 21:39:05 +0100 Subject: [PATCH 18/28] added auto-update of files being hashed --- .../src/gui/common/RsCollection.cpp | 375 ++++++++++-------- retroshare-gui/src/gui/common/RsCollection.h | 3 + .../src/gui/common/RsCollectionDialog.cpp | 64 ++- .../src/gui/common/RsCollectionDialog.h | 7 +- .../src/gui/common/RsCollectionModel.cpp | 7 +- 5 files changed, 266 insertions(+), 190 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index e7e329604..21079c114 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -45,19 +45,25 @@ RsCollection::RsCollection(QObject *parent) RsCollection::RsCollection(const RsFileTree& ft) { mFileTree = std::unique_ptr(new RsFileTree(ft)); + + for(uint64_t i=0;inumFiles();++i) + mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); } RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) : QObject(parent), mFileTree(new RsFileTree) { - if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) - { - std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; - return ; - } + if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) + { + std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; + return ; + } - for(uint32_t i = 0;iroot(),file_infos[i],flags) ; + + for(uint64_t i=0;inumFiles();++i) + mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); } RsCollection::~RsCollection() @@ -67,88 +73,88 @@ RsCollection::~RsCollection() void RsCollection::downloadFiles() const { #ifdef TODO_COLLECTION - // print out the element names of all elements that are direct children - // of the outermost element. - QDomElement docElem = _xml_doc.documentElement(); + // print out the element names of all elements that are direct children + // of the outermost element. + QDomElement docElem = _xml_doc.documentElement(); - std::vector colFileInfos ; + std::vector colFileInfos ; - recursCollectColFileInfos(docElem,colFileInfos,QString(),false) ; + recursCollectColFileInfos(docElem,colFileInfos,QString(),false) ; - RsCollectionDialog(_fileName, colFileInfos, false).exec() ; + RsCollectionDialog(_fileName, colFileInfos, false).exec() ; #endif } void RsCollection::autoDownloadFiles() const { #ifdef TODO_COLLECTION - QDomElement docElem = _xml_doc.documentElement(); + QDomElement docElem = _xml_doc.documentElement(); - std::vector colFileInfos; + std::vector colFileInfos; - recursCollectColFileInfos(docElem,colFileInfos,QString(),false); + recursCollectColFileInfos(docElem,colFileInfos,QString(),false); - QString dlDir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()); + QString dlDir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()); - foreach(ColFileInfo colFileInfo, colFileInfos) - { - autoDownloadFiles(colFileInfo, dlDir); - } + foreach(ColFileInfo colFileInfo, colFileInfos) + { + autoDownloadFiles(colFileInfo, dlDir); + } #endif } void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const { - if (!colFileInfo.filename_has_wrong_characters) - { - QString cleanPath = dlDir + colFileInfo.path ; - std::cout << "making directory " << cleanPath.toStdString() << std::endl; + if (!colFileInfo.filename_has_wrong_characters) + { + QString cleanPath = dlDir + colFileInfo.path ; + std::cout << "making directory " << cleanPath.toStdString() << std::endl; - if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) - std::cerr << "Unable to make path: " + cleanPath.toStdString() << std::endl; + if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) + std::cerr << "Unable to make path: " + cleanPath.toStdString() << std::endl; - if (colFileInfo.type==DIR_TYPE_FILE) - rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), - RsFileHash(colFileInfo.hash.toStdString()), - colFileInfo.size, - cleanPath.toUtf8().constData(), - RS_FILE_REQ_ANONYMOUS_ROUTING, - std::list()); - } - foreach(ColFileInfo colFileInfoChild, colFileInfo.children) - { - autoDownloadFiles(colFileInfoChild, dlDir); - } + if (colFileInfo.type==DIR_TYPE_FILE) + rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), + RsFileHash(colFileInfo.hash.toStdString()), + colFileInfo.size, + cleanPath.toUtf8().constData(), + RS_FILE_REQ_ANONYMOUS_ROUTING, + std::list()); + } + foreach(ColFileInfo colFileInfoChild, colFileInfo.children) + { + autoDownloadFiles(colFileInfoChild, dlDir); + } } static QString purifyFileName(const QString& input,bool& bad) { - static const QString bad_chars = "/\\\"*:?<>|" ; - bad = false ; - QString output = input ; + static const QString bad_chars = "/\\\"*:?<>|" ; + bad = false ; + QString output = input ; - for(int i=0;iaddFile(mFileTree->root(),fname.toStdString(),hash,size); #ifdef TO_REMOVE - ColFileInfo info ; - info.type = DIR_TYPE_FILE ; - info.name = fname ; - info.size = size ; - info.hash = QString::fromStdString(hash.toStdString()) ; + ColFileInfo info ; + info.type = DIR_TYPE_FILE ; + info.name = fname ; + info.size = size ; + info.hash = QString::fromStdString(hash.toStdString()) ; - recursAddElements(_xml_doc,info,_root) ; + recursAddElements(_xml_doc,info,_root) ; #endif } void RsCollection::merge_in(const RsFileTree& tree) @@ -175,56 +181,56 @@ void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& #ifdef TO_REMOVE void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const { - QDomNode n = e.firstChild() ; + QDomNode n = e.firstChild() ; #ifdef COLLECTION_DEBUG - std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; + std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; #endif - while(!n.isNull()) - { - QDomElement ee = n.toElement(); // try to convert the node to an element. + while(!n.isNull()) + { + QDomElement ee = n.toElement(); // try to convert the node to an element. #ifdef COLLECTION_DEBUG - std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl; + std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl; #endif - if(ee.tagName() == QString("File")) - { - ColFileInfo newChild ; - newChild.hash = ee.attribute(QString("sha1")) ; - bool bad_chars_detected = false ; - newChild.name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected) ; - newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newChild.size = ee.attribute(QString("size")).toULongLong() ; - newChild.path = current_path ; - newChild.type = DIR_TYPE_FILE ; + if(ee.tagName() == QString("File")) + { + ColFileInfo newChild ; + newChild.hash = ee.attribute(QString("sha1")) ; + bool bad_chars_detected = false ; + newChild.name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected) ; + newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; + newChild.size = ee.attribute(QString("size")).toULongLong() ; + newChild.path = current_path ; + newChild.type = DIR_TYPE_FILE ; - colFileInfos.push_back(newChild) ; - } - else if(ee.tagName() == QString("Directory")) - { - ColFileInfo newParent ; - bool bad_chars_detected = false ; - QString cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected) ; - newParent.name=cleanDirName; - newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newParent.size = 0; - newParent.path = current_path ; - newParent.type = DIR_TYPE_DIR ; + colFileInfos.push_back(newChild) ; + } + else if(ee.tagName() == QString("Directory")) + { + ColFileInfo newParent ; + bool bad_chars_detected = false ; + QString cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected) ; + newParent.name=cleanDirName; + newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; + newParent.size = 0; + newParent.path = current_path ; + newParent.type = DIR_TYPE_DIR ; - recursCollectColFileInfos(ee,newParent.children,current_path + "/" + cleanDirName, bad_chars_in_parent || bad_chars_detected) ; - uint32_t size = newParent.children.size(); - for(uint32_t i=0;iaddFile(parent,dd.name,dd.hash,dd.size); else if (dd.type == DIR_TYPE_DIR) - { + { RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,dd.name); for(uint32_t i=0;iRequestDirDetails(dd.children[i].ref, subDirDetails, flags)) - continue; + continue; recursAddElements(new_dir_index,subDirDetails,flags) ; - } - } + } + } } #ifdef TO_REMOVE void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const { - if (colFileInfo.type == DIR_TYPE_FILE) - { - QDomElement f = doc.createElement("File") ; + if (colFileInfo.type == DIR_TYPE_FILE) + { + QDomElement f = doc.createElement("File") ; - f.setAttribute(QString("name"),colFileInfo.name) ; - f.setAttribute(QString("sha1"),colFileInfo.hash) ; - f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ; + f.setAttribute(QString("name"),colFileInfo.name) ; + f.setAttribute(QString("sha1"),colFileInfo.hash) ; + f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ; - e.appendChild(f) ; - } - else if (colFileInfo.type == DIR_TYPE_DIR) - { - QDomElement d = doc.createElement("Directory") ; + e.appendChild(f) ; + } + else if (colFileInfo.type == DIR_TYPE_DIR) + { + QDomElement d = doc.createElement("Directory") ; - d.setAttribute(QString("name"),colFileInfo.name) ; + d.setAttribute(QString("name"),colFileInfo.name) ; - for (std::vector::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it) - recursAddElements(doc,(*it),d) ; + for (std::vector::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it) + recursAddElements(doc,(*it),d) ; - e.appendChild(d) ; - } + e.appendChild(d) ; + } } void RsCollection::recursAddElements( QDomDocument& doc, const RsFileTree& ft, uint32_t index, QDomElement& e ) const { - std::vector subdirs; - std::vector subfiles ; - std::string name; - if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return; + std::vector subdirs; + std::vector subfiles ; + std::string name; + if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return; - QDomElement d = doc.createElement("Directory") ; - d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ; - e.appendChild(d) ; + QDomElement d = doc.createElement("Directory") ; + d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ; + e.appendChild(d) ; - for (uint32_t i=0;inumFiles();++i) + mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); + return true; } bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const @@ -581,16 +591,16 @@ bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFi #ifdef TO_REMOVE bool RsCollection::save(QWidget *parent) const { - QString fileName; - if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) - return false; + QString fileName; + if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return false; - if (!fileName.endsWith("." + RsCollection::ExtensionString)) - fileName += "." + RsCollection::ExtensionString ; + if (!fileName.endsWith("." + RsCollection::ExtensionString)) + fileName += "." + RsCollection::ExtensionString ; - std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; - return save(fileName); + return save(fileName); } @@ -606,38 +616,59 @@ qulonglong RsCollection::size() return mFileTree->totalFileSize(); #ifdef TO_REMOVE - QDomElement docElem = _xml_doc.documentElement(); + QDomElement docElem = _xml_doc.documentElement(); - std::vector colFileInfos; - recursCollectColFileInfos(docElem, colFileInfos, QString(),false); + std::vector colFileInfos; + recursCollectColFileInfos(docElem, colFileInfos, QString(),false); - uint64_t size = 0; + uint64_t size = 0; - for (uint32_t i = 0; i < colFileInfos.size(); ++i) { - size += colFileInfos[i].size; - } + for (uint32_t i = 0; i < colFileInfos.size(); ++i) { + size += colFileInfos[i].size; + } - return size; + return size; #endif } bool RsCollection::isCollectionFile(const QString &fileName) { - QString ext = QFileInfo(fileName).suffix().toLower(); + QString ext = QFileInfo(fileName).suffix().toLower(); - return (ext == RsCollection::ExtensionString); + return (ext == RsCollection::ExtensionString); } +void RsCollection::updateHashes(const std::map& old_to_new_hashes) +{ + for(auto it:old_to_new_hashes) + { + auto fit = mHashes.find(it.first); + + if(fit == mHashes.end()) + { + RsErr() << "Could not find hash " << it.first << " in RsCollection list of hashes. This is a bug." ; + return ; + } + const auto& fd(mFileTree->fileData(fit->second)); + + if(fd.hash != it.first) + { + RsErr() << "Mismatch hash for file " << fd.name << " (found " << fd.hash << " instead of " << it.first << ") in RsCollection list of hashes. This is a bug." ; + return ; + } + mFileTree->updateFile(fit->second,fd.name,it.second,fd.size); + } +} #ifdef TO_REMOVE void RsCollection::saveColl(std::vector colFileInfos, const QString &fileName) { - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - while (root.childNodes().count()>0) root.removeChild(root.firstChild()); - for(uint32_t i = 0;i0) root.removeChild(root.firstChild()); + for(uint32_t i = 0;i& old_to_new_hashes); private: bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; @@ -130,6 +131,8 @@ private: void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; std::unique_ptr mFileTree; + std::map mHashes; // used to efficiently update files being hashed + #ifdef TO_REMOVE QDomDocument _xml_doc ; QString _fileName ; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 71e1c2c75..d6ec70f22 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -23,6 +23,7 @@ #include "RsCollection.h" #include "util/misc.h" +#include "util/rsdir.h" #include #include @@ -738,7 +739,7 @@ void RsCollectionDialog::addSelectionRecursive() addSelection(true); } -static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive) +static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive,QSet& paths_to_hash) { QFileInfo fileInfo = path; @@ -746,17 +747,28 @@ static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree: { auto di = tree.addDirectory(dir_index,fileInfo.fileName().toUtf8().constData()); - QDir dirParent = fileInfo.absoluteFilePath(); - dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); - QFileInfoList childrenList = dirParent.entryInfoList(); + if(recursive) + { + QDir dirParent = fileInfo.absoluteFilePath(); + dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); + QFileInfoList childrenList = dirParent.entryInfoList(); - for(QFileInfo f:childrenList) - recursBuildFileTree(f.absoluteFilePath(),tree,di,recursive); + for(QFileInfo f:childrenList) + recursBuildFileTree(f.absoluteFilePath(),tree,di,recursive,paths_to_hash); + } } else { -#warning TODO: compute the hash - tree.addFile(dir_index,fileInfo.fileName().toUtf8().constData(),RsFileHash(),fileInfo.size()); + // Here we use a temporary hash that serves two purposes: + // 1 - identify the file in the RsFileTree of the collection so that we can update its hash when calculated + // 2 - mark the file as being processed + // The hash s is computed to be the hash of the path of the file. The collection must take care of multiple instances. + + Sha1CheckSum s = RsDirUtil::sha1sum((uint8_t*)(fileInfo.filePath().toUtf8().constData()),fileInfo.filePath().toUtf8().size()); + + tree.addFile(dir_index,fileInfo.fileName().toUtf8().constData(),s,fileInfo.size()); + + paths_to_hash.insert(fileInfo.filePath().toUtf8().constData()); } } /** @@ -768,7 +780,6 @@ static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree: */ void RsCollectionDialog::addSelection(bool recursive) { - QStringList fileToHash; QMap dirToAdd; int count=0;//to not scan all items on list .count() @@ -776,11 +787,13 @@ void RsCollectionDialog::addSelection(bool recursive) mCollectionModel->preMods(); + QSet paths_to_hash; // sha1sum of the paths to hash + foreach (QModelIndex index, milSelectionList) if(index.column()==0) //Get only FileName { RsFileTree tree; - recursBuildFileTree(_dirModel->filePath(_tree_proxyModel->mapToSource(index)),tree,tree.root(),recursive); + recursBuildFileTree(_dirModel->filePath(_tree_proxyModel->mapToSource(index)),tree,tree.root(),recursive,paths_to_hash); mCollection->merge_in(tree); @@ -852,9 +865,18 @@ void RsCollectionDialog::addSelection(bool recursive) // Process Files once all done ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); #endif +// std::map paths_and_hashes; +// for(auto path:paths_to_hash) +// paths_and_hashes.insert(std::make_pair(RsDirUtil::sha1sum((uint8_t*)path.toUtf8().constData(),path.toUtf8().size()),path)); + +// mCollectionModel->addFilesToHash(paths_and_hashes); + mCollectionModel->postMods(); + + ui._hashBox->addAttachments(QStringList(paths_to_hash.begin(),paths_to_hash.end()),RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); } +#ifdef TO_REMOVE /** * @brief RsCollectionDialog::addAllChild: Add children to RsCollection * @param fileInfoParent: Parent's QFileInfo to scan @@ -910,6 +932,7 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent } return true; } +#endif /** * @brief RsCollectionDialog::remove: Remove selected Items in RSCollection @@ -1186,6 +1209,7 @@ void RsCollectionDialog::makeDir() */ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) { +#ifdef TO_REMOVE std::cerr << "RsCollectionDialog::fileHashingFinished() started." << std::endl; QString message; @@ -1211,8 +1235,26 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) _newColFileInfos.push_back(colFileInfo); #endif } +#endif + // build a map of old-hash to new-hash for the hashed files, so that it can be passed to the mCollection for update - std::cerr << "RsCollectionDialog::fileHashingFinished message : " << message.toStdString() << std::endl; + std::map old_to_new_hashes; + + for(auto f:hashedFiles) + { + auto it = mFilesBeingHashed.find(f.filepath); + + if(it == mFilesBeingHashed.end()) + { + RsErr() << "Could not find hash-ID correspondence for path " << f.filepath.toUtf8().constData() << ". This is a bug." << std::endl; + continue; + } + old_to_new_hashes.insert(std::make_pair(it->second,f.hash)); + mFilesBeingHashed.erase(it); + } + mCollectionModel->preMods(); + mCollection->updateHashes(old_to_new_hashes); + mCollectionModel->postMods(); updateList(); } diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 71c261cb4..9ba3ac857 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -18,6 +18,7 @@ * * *******************************************************************************/ +#include #include "ui_RsCollectionDialog.h" #include "RsCollection.h" #include "RsCollectionModel.h" @@ -90,12 +91,12 @@ private: bool addChild(QTreeWidgetItem *parent, const std::vector &child); bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ; void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL); -#endif - void addSelection(bool recursive) ; bool addAllChild(QFileInfo &fileInfoParent , QMap &dirToAdd , QStringList &fileToHash , int &count); +#endif + void addSelection(bool recursive) ; Ui::RsCollectionDialog ui; QString _fileName ; @@ -110,4 +111,6 @@ private: RsCollectionModel *mCollectionModel; RsCollection *mCollection; + + std::map mFilesBeingHashed; // map of file path vs. temporary ID used for the file while hashing }; diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index f05e25231..6e8352339 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -252,9 +252,9 @@ bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,i if(role==Qt::CheckStateRole && convertInternalIdToIndex(index.internalId(), e)) { -//#ifdef DEBUG_COLLECTION_MODEL +#ifdef DEBUG_COLLECTION_MODEL std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl; -//#endif +#endif RsFileTree::DirIndex dir_index ; if(e.is_file) @@ -370,7 +370,6 @@ QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const { if(i.is_file) { - std::cerr<< "entry is file, checkstate = " << (int)mFileInfos[i.index].is_checked << std::endl; if(mFileInfos[i.index].is_checked) return QVariant(Qt::Checked); else @@ -378,8 +377,6 @@ QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const } else { - std::cerr<< "entry is dir, checkstate = " << (int)mDirInfos[i.index].check_state << std::endl; - switch(mDirInfos[i.index].check_state) { case SELECTED: return QVariant::fromValue((int)Qt::Checked); From 06971162890cf5e8569e7225f789ba70cdefbd07 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 13 Mar 2024 22:20:21 +0100 Subject: [PATCH 19/28] added green color for files being hashed --- .../src/gui/common/RsCollection.cpp | 6 ++- .../src/gui/common/RsCollectionDialog.cpp | 30 ++++++++++----- .../src/gui/common/RsCollectionModel.cpp | 37 ++++++++++++++++--- .../src/gui/common/RsCollectionModel.h | 5 +++ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 21079c114..6b83a4bef 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -146,7 +146,7 @@ static QString purifyFileName(const QString& input,bool& bad) void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) { - mFileTree->addFile(mFileTree->root(),fname.toStdString(),hash,size); + mHashes[hash]= mFileTree->addFile(mFileTree->root(),fname.toStdString(),hash,size); #ifdef TO_REMOVE ColFileInfo info ; info.type = DIR_TYPE_FILE ; @@ -167,7 +167,7 @@ void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& for(uint32_t i=0;iaddFile(parent,fd.name,fd.hash,fd.size); + mHashes[fd.hash] = mFileTree->addFile(parent,fd.name,fd.hash,fd.size); } for(uint32_t i=0;i colFileInfos, const QString } #endif + + diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index d6ec70f22..c38498df0 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -739,7 +739,7 @@ void RsCollectionDialog::addSelectionRecursive() addSelection(true); } -static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive,QSet& paths_to_hash) +static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive,std::map& paths_to_hash) { QFileInfo fileInfo = path; @@ -768,7 +768,7 @@ static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree: tree.addFile(dir_index,fileInfo.fileName().toUtf8().constData(),s,fileInfo.size()); - paths_to_hash.insert(fileInfo.filePath().toUtf8().constData()); + paths_to_hash.insert(std::make_pair(fileInfo.filePath(),s)); } } /** @@ -787,7 +787,7 @@ void RsCollectionDialog::addSelection(bool recursive) mCollectionModel->preMods(); - QSet paths_to_hash; // sha1sum of the paths to hash + std::map paths_to_hash; // sha1sum of the paths to hash. foreach (QModelIndex index, milSelectionList) if(index.column()==0) //Get only FileName @@ -865,15 +865,24 @@ void RsCollectionDialog::addSelection(bool recursive) // Process Files once all done ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); #endif -// std::map paths_and_hashes; -// for(auto path:paths_to_hash) -// paths_and_hashes.insert(std::make_pair(RsDirUtil::sha1sum((uint8_t*)path.toUtf8().constData(),path.toUtf8().size()),path)); -// mCollectionModel->addFilesToHash(paths_and_hashes); + mFilesBeingHashed.insert(paths_to_hash.begin(),paths_to_hash.end()); + QStringList paths; + std::list hashes; + + for(auto it:paths_to_hash) + { + paths.push_back(it.first); + hashes.push_back(it.second); + + std::cerr << "Setting file has being hased: ID=" << it.second << " - " << it.first.toUtf8().constData() << std::endl; + } + + mCollectionModel->notifyFilesBeingHashed(hashes); mCollectionModel->postMods(); - ui._hashBox->addAttachments(QStringList(paths_to_hash.begin(),paths_to_hash.end()),RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); + ui._hashBox->addAttachments(paths,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); } #ifdef TO_REMOVE @@ -1238,6 +1247,7 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) #endif // build a map of old-hash to new-hash for the hashed files, so that it can be passed to the mCollection for update + mCollectionModel->preMods(); std::map old_to_new_hashes; for(auto f:hashedFiles) @@ -1249,10 +1259,12 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) RsErr() << "Could not find hash-ID correspondence for path " << f.filepath.toUtf8().constData() << ". This is a bug." << std::endl; continue; } + std::cerr << "Will update old hash " << it->second << " to new hash " << f.hash << std::endl; + old_to_new_hashes.insert(std::make_pair(it->second,f.hash)); mFilesBeingHashed.erase(it); + mCollectionModel->fileHashingFinished(it->second); } - mCollectionModel->preMods(); mCollection->updateHashes(old_to_new_hashes); mCollectionModel->postMods(); diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 6e8352339..870fb88b3 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -1,4 +1,5 @@ #include +#include #include "RsCollectionModel.h" @@ -238,6 +239,7 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const case Qt::DisplayRole: return displayRole(i,index.column()); case Qt::DecorationRole: return decorationRole(i,index.column()); case Qt::CheckStateRole: return checkStateRole(i,index.column()); + case Qt::TextColorRole: return textColorRole(i,index.column()); default: return QVariant(); } @@ -364,6 +366,13 @@ bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,i return QAbstractItemModel::setData(index,value,role); } +QVariant RsCollectionModel::textColorRole(const EntryIndex& i,int col) const +{ + if(i.is_file && mFilesBeingHashed.find(mCollection.fileTree().fileData(i.index).hash) != mFilesBeingHashed.end()) + return QVariant(QBrush(QColor::fromRgbF(0.1,0.9,0.2))); + else + return QVariant(); +} QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const { if(col == COLLECTION_MODEL_FILENAME) @@ -393,18 +402,25 @@ QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const { switch(col) { - case COLLECTION_MODEL_FILENAME: return (i.is_file)? - (QString::fromUtf8(mCollection.fileTree().fileData(i.index).name.c_str())) - : (QString::fromUtf8(mCollection.fileTree().directoryData(i.index).name.c_str())); + case COLLECTION_MODEL_FILENAME: if(i.is_file) + return QString::fromUtf8(mCollection.fileTree().fileData(i.index).name.c_str()); + else + return QString::fromUtf8(mCollection.fileTree().directoryData(i.index).name.c_str()); case COLLECTION_MODEL_SIZE: if(i.is_file) return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ; else return QVariant((qulonglong)mDirInfos[i.index].total_size); - case COLLECTION_MODEL_HASH: return (i.is_file)? - QString::fromStdString(mCollection.fileTree().fileData(i.index).hash.toStdString()) - :QVariant(); + case COLLECTION_MODEL_HASH: if(i.is_file) + { + if(mFilesBeingHashed.find(mCollection.fileTree().fileData(i.index).hash)!=mFilesBeingHashed.end()) + return tr("[File is being hashed]"); + else + return QString::fromStdString(mCollection.fileTree().fileData(i.index).hash.toStdString()); + } + else + return QVariant(); case COLLECTION_MODEL_COUNT: if(i.is_file) return (qulonglong)mFileInfos[i.index].is_checked; @@ -422,6 +438,15 @@ QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const return QVariant(); } +void RsCollectionModel::notifyFilesBeingHashed(const std::list& files) +{ + mFilesBeingHashed.insert(files.begin(),files.end()); +} +void RsCollectionModel::fileHashingFinished(const RsFileHash& hash) +{ + mFilesBeingHashed.erase(hash); +} + void RsCollectionModel::preMods() { mUpdating = true; diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index d41b64dd4..3bcc54ded 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -48,6 +48,8 @@ class RsCollectionModel: public QAbstractItemModel uint64_t totalSize() const { return mDirInfos[0].total_size; } uint64_t totalSelected() const { return mDirInfos[0].total_count; } + void notifyFilesBeingHashed(const std::list& files); + void fileHashingFinished(const RsFileHash& hash); signals: void sizesChanged(); // tells that the total size of the top level dir has changed (due to selection) @@ -61,6 +63,7 @@ class RsCollectionModel: public QAbstractItemModel QVariant sortRole(const EntryIndex&,int col) const ; QVariant decorationRole(const EntryIndex&,int col) const ; QVariant checkStateRole(const EntryIndex& i,int col) const; + QVariant textColorRole(const EntryIndex& i,int col) const; //QVariant filterRole(const DirDetails& details,int coln) const; void debugDump(); @@ -96,5 +99,7 @@ class RsCollectionModel: public QAbstractItemModel std::vector mFileInfos; std::vector mDirInfos; + std::set mFilesBeingHashed; + // std::set mFilteredPointers ; }; From 094c80e0460906a524095600bca1503f55fc3f7a Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 13 Mar 2024 22:28:39 +0100 Subject: [PATCH 20/28] disable save button when files are being hashed --- retroshare-gui/src/gui/common/RsCollectionDialog.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index c38498df0..6ed6a84e3 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -883,6 +883,12 @@ void RsCollectionDialog::addSelection(bool recursive) mCollectionModel->postMods(); ui._hashBox->addAttachments(paths,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); + + if(!mFilesBeingHashed.empty()) + { + ui._save_PB->setToolTip(tr("Please wait for all files to be properly processed before saving.")); + ui._save_PB->setEnabled(false); + } } #ifdef TO_REMOVE @@ -1268,6 +1274,11 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) mCollection->updateHashes(old_to_new_hashes); mCollectionModel->postMods(); + if(mFilesBeingHashed.empty()) + { + ui._save_PB->setToolTip(tr("")); + ui._save_PB->setEnabled(true); + } updateList(); } From 27f0962654de921bc17fd5fe9c5ae3c3531cad4d Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 14 Mar 2024 22:12:57 +0100 Subject: [PATCH 21/28] fixed download from RsCollection dialog --- .../src/gui/common/RsCollection.cpp | 9 ++-- .../src/gui/common/RsCollectionDialog.cpp | 44 ++++++++++++++++++- .../src/gui/common/RsCollectionModel.cpp | 7 +++ .../src/gui/common/RsCollectionModel.h | 1 + 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 6b83a4bef..644d94fc0 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -238,7 +238,7 @@ void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vectoraddFile(parent,dd.name,dd.hash,dd.size); + mHashes[dd.hash] = mFileTree->addFile(parent,dd.name,dd.hash,dd.size); else if (dd.type == DIR_TYPE_DIR) { RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,dd.name); @@ -488,6 +488,7 @@ bool RsCollection::save(const QString& fileName) const bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFileTree::DirIndex parent) { + mHashes.clear(); QDomNode n = e.firstChild() ; #ifdef COLLECTION_DEBUG std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; @@ -509,7 +510,7 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi std::string name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected).toUtf8().constData() ; uint64_t size = ee.attribute(QString("size")).toULongLong() ; - mFileTree->addFile(parent,name,hash,size); + mHashes[hash] = mFileTree->addFile(parent,name,hash,size); #ifdef TO_REMOVE mFileTree.addFile(parent,) ColFileInfo newChild ; @@ -551,10 +552,6 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi n = n.nextSibling() ; } - mHashes.clear(); - for(uint64_t i=0;inumFiles();++i) - mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); - return true; } bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 6ed6a84e3..8b52d6ed7 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -1421,13 +1421,55 @@ void RsCollectionDialog::cancel() */ void RsCollectionDialog::download() { -#ifdef TODO_COLLECTION std::cerr << "Downloading!" << std::endl; QString dldir = ui.downloadFolder_LE->text(); std::cerr << "downloading all these files:" << std::endl; + std::function recursDL = [&](RsFileTree::DirIndex index,const std::string& path) + { + const auto& dirdata(mCollection->fileTree().directoryData(index)); + RsCollectionModel::EntryIndex e; + + for(uint32_t i=0;iisChecked(e)) + continue; + + const auto& sdd = mCollection->fileTree().directoryData(e.index); + std::string subpath = RsDirUtil::makePath(path,sdd.name); + + std::cerr << "Creating subdir " << sdd.name << " to directory " << path << std::endl; + + if(!QDir(QApplication::applicationDirPath()).mkpath(QString::fromUtf8(subpath.c_str()))) + QMessageBox::warning(NULL,tr("Unable to make path"),tr("Unable to make path:")+"
"+QString::fromUtf8(subpath.c_str())) ; + + recursDL(dirdata.subdirs[i],subpath); + } + for(uint32_t i=0;iisChecked(e)) + continue; + + std::string subpath = RsDirUtil::makePath(path,dirdata.name); + const auto& f(mCollection->fileTree().fileData(dirdata.subfiles[i])); + + std::cerr << "Requesting file " << f.name << " to directory " << path << std::endl; + + rsFiles->FileRequest(f.name,f.hash,f.size,path,RS_FILE_REQ_ANONYMOUS_ROUTING,std::list()); + } + }; + + recursDL(mCollection->fileTree().root(),dldir.toUtf8().constData()); + close(); +#ifdef TO_REMOVE while ((item = *itemIterator) != NULL) { ++itemIterator; diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 870fb88b3..8aa83f080 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -438,6 +438,13 @@ QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const return QVariant(); } +bool RsCollectionModel::isChecked(EntryIndex i) +{ + if(i.is_file) + return mFileInfos[i.index].is_checked; + else + return mDirInfos[i.index].check_state != DirCheckState::UNSELECTED; +} void RsCollectionModel::notifyFilesBeingHashed(const std::list& files) { mFilesBeingHashed.insert(files.begin(),files.end()); diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index 3bcc54ded..f34b0d39e 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -50,6 +50,7 @@ class RsCollectionModel: public QAbstractItemModel void notifyFilesBeingHashed(const std::list& files); void fileHashingFinished(const RsFileHash& hash); + bool isChecked(EntryIndex); signals: void sizesChanged(); // tells that the total size of the top level dir has changed (due to selection) From a36f7221e7ed37013faf5890478aa686a23d8946 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 14 Mar 2024 22:44:49 +0100 Subject: [PATCH 22/28] added new folder capability in collection --- .../src/gui/common/RsCollection.cpp | 8 +++--- retroshare-gui/src/gui/common/RsCollection.h | 4 +-- .../src/gui/common/RsCollectionDialog.cpp | 26 +++++++++++++++++++ .../src/gui/common/RsCollectionDialog.ui | 12 ++++----- .../src/gui/common/RsCollectionModel.cpp | 9 +++++++ .../src/gui/common/RsCollectionModel.h | 2 ++ 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 644d94fc0..e86817d06 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -144,9 +144,9 @@ static QString purifyFileName(const QString& input,bool& bad) return output ; } -void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) +void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index) { - mHashes[hash]= mFileTree->addFile(mFileTree->root(),fname.toStdString(),hash,size); + mHashes[hash]= mFileTree->addFile(parent_index,fname.toStdString(),hash,size); #ifdef TO_REMOVE ColFileInfo info ; info.type = DIR_TYPE_FILE ; @@ -157,9 +157,9 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& recursAddElements(_xml_doc,info,_root) ; #endif } -void RsCollection::merge_in(const RsFileTree& tree) +void RsCollection::merge_in(const RsFileTree& tree, RsFileTree::DirIndex parent_index) { - recursMergeTree(mFileTree->root(),tree,tree.directoryData(tree.root())) ; + recursMergeTree(mFileTree->root(),tree,tree.directoryData(parent_index)) ; } void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index bc9ff2a28..5e3180c8c 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -77,8 +77,8 @@ public: virtual ~RsCollection() ; - void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ; - void merge_in(const RsFileTree& tree) ; + void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index=0) ; + void merge_in(const RsFileTree& tree,RsFileTree::DirIndex parent_index=0) ; static const QString ExtensionString ; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 8b52d6ed7..1e5998427 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -1132,6 +1132,32 @@ void RsCollectionDialog::processItem(QMap &dirToAdd */ void RsCollectionDialog::makeDir() { + QModelIndexList selected_indices = ui._fileEntriesTW->selectionModel()->selectedIndexes(); + + if(selected_indices.size() > 1) + { + QMessageBox::information(nullptr,tr("Too many places selected"),tr("Please select at most one directory where to create the new folder")); + return; + } + + QModelIndex place_index; + + if(!selected_indices.empty()) + place_index = selected_indices.first(); + + RsCollectionModel::EntryIndex e = mCollectionModel->getIndex(place_index); + + if(e.is_file) + { + QMessageBox::information(nullptr,tr("Selected place cannot be a file"),tr("Please select at most one directory where to create the new folder")); + return; + } + QString childName = QInputDialog::getText(this, tr("New Directory"), tr("Enter the new directory's name"), QLineEdit::Normal); + + mCollectionModel->preMods(); + mCollection->merge_in(*RsFileTree::fromDirectory(childName.toUtf8().constData()),e.index); + mCollectionModel->postMods(); + #ifdef TODO_COLLECTION QString childName=""; bool ok, badChar, nameOK = false; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index 7d4de185b..96fe8b399 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -6,8 +6,8 @@ 0 0 - 671 - 400 + 761 + 434
@@ -283,7 +283,7 @@ - :/images/feedback_arrow.png:/images/feedback_arrow.png + :/images/start.png:/images/start.png @@ -309,7 +309,7 @@ - :/images/update.png:/images/update.png + :/images/startall.png:/images/startall.png @@ -334,8 +334,8 @@ - - :/images/deletemail24.png:/images/deletemail24.png + + :/images/delete.png:/images/delete.png diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 8aa83f080..16a2e473d 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -438,6 +438,15 @@ QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const return QVariant(); } +RsCollectionModel::EntryIndex RsCollectionModel::getIndex(const QModelIndex& i) const +{ + EntryIndex res; + res.is_file = false; + res.index = 0; + + convertInternalIdToIndex(i.internalId(),res); + return res; +} bool RsCollectionModel::isChecked(EntryIndex i) { if(i.is_file) diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.h b/retroshare-gui/src/gui/common/RsCollectionModel.h index f34b0d39e..705c3fc3b 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.h +++ b/retroshare-gui/src/gui/common/RsCollectionModel.h @@ -51,6 +51,8 @@ class RsCollectionModel: public QAbstractItemModel void notifyFilesBeingHashed(const std::list& files); void fileHashingFinished(const RsFileHash& hash); bool isChecked(EntryIndex); + + EntryIndex getIndex(const QModelIndex& i) const; signals: void sizesChanged(); // tells that the total size of the top level dir has changed (due to selection) From 2ebd7617fc4a8d061c1202abb5ad59cae2523ee9 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 19 Mar 2024 23:22:46 +0100 Subject: [PATCH 23/28] added proper remove for files/dirs --- .../src/gui/common/RsCollection.cpp | 12 ++++++++++ retroshare-gui/src/gui/common/RsCollection.h | 5 ++++ .../src/gui/common/RsCollectionDialog.cpp | 23 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index e86817d06..2624dd246 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -670,4 +670,16 @@ void RsCollection::saveColl(std::vector colFileInfos, const QString } #endif +bool RsCollection::removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index) +{ + mFileTree->removeFile(index_to_remove,parent_index); +} +bool RsCollection::removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index) +{ + mFileTree->removeDirectory(index_to_remove,parent_index); +} +void RsCollection::cleanup() +{ + mFileTree = RsFileTree::fromTreeCleaned(*mFileTree); +} diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 5e3180c8c..7a01fc4b6 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -80,6 +80,11 @@ public: void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index=0) ; void merge_in(const RsFileTree& tree,RsFileTree::DirIndex parent_index=0) ; + bool removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index); + bool removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index); + + void cleanup(); // cleans up the collection, which may contain unreferenced files/dirs after lazy editing. + static const QString ExtensionString ; #ifdef TO_REMOVE diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 1e5998427..5269cb988 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -954,6 +954,27 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent */ void RsCollectionDialog::remove() { + QMap dirToRemove; + int count=0;//to not scan all items on list .count() + + QModelIndexList milSelectionList = ui._fileEntriesTW->selectionModel()->selectedIndexes(); + + mCollectionModel->preMods(); + + foreach (QModelIndex index, milSelectionList) + if(index.column()==0) //Get only FileName + { + auto indx = mCollectionModel->getIndex(index); + auto parent_indx = mCollectionModel->getIndex(index.parent()); + + if(indx.is_file) + mCollection->removeFile(indx.index,parent_indx.index); + else + mCollection->removeDirectory(indx.index,parent_indx.index); + } + + mCollectionModel->postMods(); + #ifdef TODO_COLLECTION bool removeOnlyFile=false; QString listDir; @@ -1538,6 +1559,8 @@ void RsCollectionDialog::download() */ void RsCollectionDialog::save() { + mCollectionModel->preMods(); + mCollection->cleanup(); mCollection->save(_fileName); close(); #ifdef TO_REMOVE From a02d2e63e2ed7f2e3d0c56fd5a6e14fd2c71ed9b Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 20 Mar 2024 21:00:42 +0100 Subject: [PATCH 24/28] fixed updating save filename, removal of files/dirs, and cleaning before save --- retroshare-gui/src/gui/common/RsCollection.cpp | 4 ++++ .../src/gui/common/RsCollectionDialog.cpp | 14 ++++++++++---- .../src/gui/common/RsCollectionDialog.ui | 7 ++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 2624dd246..01d6f7dc1 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -681,5 +681,9 @@ bool RsCollection::removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTr void RsCollection::cleanup() { + RsDbg() << "Cleaning up RsCollection with " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files." ; + mFileTree = RsFileTree::fromTreeCleaned(*mFileTree); + + RsDbg() << "Simplified to " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files."; } diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 5269cb988..ba4d5a118 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -125,7 +125,7 @@ protected: * @param readOnly: Open dialog for RsColl as ReadOnly */ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsCollectionDialogMode mode) - : _fileName(collectionFileName), _mode(mode) + : _mode(mode) { RsCollection::RsCollectionErrorCode err_code; mCollection = new RsCollection(collectionFileName,err_code); @@ -137,6 +137,7 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl } ui.setupUi(this) ; + ui._filename_TL->setText(collectionFileName); // uint32_t size = colFileInfos.size(); // for(uint32_t i=0;isetHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/collections.png")); @@ -719,7 +720,7 @@ void RsCollectionDialog::changeFileName() file.remove(); } - _fileName = fileName; + ui._filename_TL->setText(fileName); updateList(); } @@ -1559,9 +1560,14 @@ void RsCollectionDialog::download() */ void RsCollectionDialog::save() { + if(ui._filename_TL->text().isNull()) + changeFileName(); + if(ui._filename_TL->text().isNull()) + return; + mCollectionModel->preMods(); mCollection->cleanup(); - mCollection->save(_fileName); + mCollection->save(ui._filename_TL->text()); close(); #ifdef TO_REMOVE std::cerr << "Saving!" << std::endl; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index 96fe8b399..8871536a2 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -157,7 +157,7 @@ - + 21 @@ -170,6 +170,10 @@ ... + + + :/icons/browsable_blue_128.png:/icons/browsable_blue_128.png + @@ -512,6 +516,7 @@ + From 8366cbca597180c3223f3d98660c5f45435d3c03 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 28 Mar 2024 21:26:09 +0100 Subject: [PATCH 25/28] removed dead code, and added check for incorrect file names when saving --- .../gui/FileTransfer/SharedFilesDialog.cpp | 10 - .../src/gui/common/RsCollection.cpp | 215 ---- .../src/gui/common/RsCollectionDialog.cpp | 980 +----------------- .../src/gui/common/RsCollectionDialog.h | 22 - .../src/gui/common/RsCollectionDialog.ui | 20 - 5 files changed, 44 insertions(+), 1203 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index a26f13728..8ce8ac3d4 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -840,16 +840,6 @@ void SharedFilesDialog::collOpen() if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(),true); -#ifdef TO_REMOVE - RsCollection::RsCollectionErrorCode err; - RsCollection collection(qinfo.absoluteFilePath(),err); - - if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) - { - collection.downloadFiles(); - return; - } -#endif } } } diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index cbc763024..8f1853cc9 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -147,15 +147,6 @@ static QString purifyFileName(const QString& input,bool& bad) void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index) { mHashes[hash]= mFileTree->addFile(parent_index,fname.toStdString(),hash,size); -#ifdef TO_REMOVE - ColFileInfo info ; - info.type = DIR_TYPE_FILE ; - info.name = fname ; - info.size = size ; - info.hash = QString::fromStdString(hash.toStdString()) ; - - recursAddElements(_xml_doc,info,_root) ; -#endif } void RsCollection::merge_in(const RsFileTree& tree, RsFileTree::DirIndex parent_index) { @@ -178,63 +169,6 @@ void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& } } -#ifdef TO_REMOVE -void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const -{ - QDomNode n = e.firstChild() ; -#ifdef COLLECTION_DEBUG - std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; -#endif - - while(!n.isNull()) - { - QDomElement ee = n.toElement(); // try to convert the node to an element. - -#ifdef COLLECTION_DEBUG - std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl; -#endif - - if(ee.tagName() == QString("File")) - { - ColFileInfo newChild ; - newChild.hash = ee.attribute(QString("sha1")) ; - bool bad_chars_detected = false ; - newChild.name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected) ; - newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newChild.size = ee.attribute(QString("size")).toULongLong() ; - newChild.path = current_path ; - newChild.type = DIR_TYPE_FILE ; - - colFileInfos.push_back(newChild) ; - } - else if(ee.tagName() == QString("Directory")) - { - ColFileInfo newParent ; - bool bad_chars_detected = false ; - QString cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected) ; - newParent.name=cleanDirName; - newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newParent.size = 0; - newParent.path = current_path ; - newParent.type = DIR_TYPE_DIR ; - - recursCollectColFileInfos(ee,newParent.children,current_path + "/" + cleanDirName, bad_chars_in_parent || bad_chars_detected) ; - uint32_t size = newParent.children.size(); - for(uint32_t i=0;i::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it) - recursAddElements(doc,(*it),d) ; - - e.appendChild(d) ; - } -} - -void RsCollection::recursAddElements( - QDomDocument& doc, const RsFileTree& ft, uint32_t index, - QDomElement& e ) const -{ - std::vector subdirs; - std::vector subfiles ; - std::string name; - if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return; - - QDomElement d = doc.createElement("Directory") ; - d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ; - e.appendChild(d) ; - - for (uint32_t i=0;iaddFile(parent,name,hash,size); -#ifdef TO_REMOVE - mFileTree.addFile(parent,) - ColFileInfo newChild ; - bool bad_chars_detected = false ; - newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newChild.size = ee.attribute(QString("size")).toULongLong() ; - newChild.path = current_path ; - newChild.type = DIR_TYPE_FILE ; - - colFileInfos.push_back(newChild) ; -#endif } else if(ee.tagName() == QString("Directory")) { @@ -533,23 +382,6 @@ bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFi RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,cleanDirName); recursParseXml(doc,ee,new_dir_index); -#ifdef TO_REMOVE - newParent.name=cleanDirName; - newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ; - newParent.size = 0; - newParent.path = current_path ; - newParent.type = DIR_TYPE_DIR ; - - recursCollectColFileInfos(ee,newParent.children,current_path + "/" + cleanDirName, bad_chars_in_parent || bad_chars_detected) ; - uint32_t size = newParent.children.size(); - for(uint32_t i=0;inumFiles(); @@ -613,21 +426,6 @@ qulonglong RsCollection::count() const qulonglong RsCollection::size() { return mFileTree->totalFileSize(); - -#ifdef TO_REMOVE - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos; - recursCollectColFileInfos(docElem, colFileInfos, QString(),false); - - uint64_t size = 0; - - for (uint32_t i = 0; i < colFileInfos.size(); ++i) { - size += colFileInfos[i].size; - } - - return size; -#endif } bool RsCollection::isCollectionFile(const QString &fileName) @@ -658,19 +456,6 @@ void RsCollection::updateHashes(const std::map& old_to_ne mFileTree->updateFile(fit->second,fd.name,it.second,fd.size); } } -#ifdef TO_REMOVE -void RsCollection::saveColl(std::vector colFileInfos, const QString &fileName) -{ - - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - while (root.childNodes().count()>0) root.removeChild(root.firstChild()); - for(uint32_t i = 0;i)), this, SLOT(fileHashingFinished(QList))); -#ifdef TO_REMOVE - connect(ui._fileEntriesTW, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*,int))); -#endif // 3 Initialize List _dirModel = new QFileSystemModel(this); @@ -227,14 +221,10 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl // 5 Activate button follow creationMode ui._changeFile->setVisible(_mode == EDIT); ui._makeDir_PB->setVisible(_mode == EDIT); - ui._removeDuplicate_CB->setVisible(_mode == EDIT); ui._save_PB->setVisible(_mode == EDIT); ui._treeViewFrame->setVisible(_mode == EDIT); ui._download_PB->setVisible(_mode == DOWNLOAD); -#ifdef TO_REMOVE - ui._fileEntriesTW->installEventFilter(this); -#endif ui._systemFileTW->installEventFilter(this); // 6 Add HashBox @@ -242,9 +232,6 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl ui._hashBox->setDropWidget(this); ui._hashBox->setAutoHide(true); ui._hashBox->setDefaultTransferRequestFlags(RS_FILE_REQ_ANONYMOUS_ROUTING) ; - - if(wrong_chars) - QMessageBox::warning(NULL,tr("Bad filenames have been cleaned"),tr("Some filenames or directory names contained forbidden characters.\nCharacters \",|,/,\\,<,>,*,? will be replaced by '_'.\n Concerned files are listed in red.")) ; } void RsCollectionDialog::openDestinationDirectoryMenu() @@ -296,75 +283,6 @@ RsCollectionDialog::~RsCollectionDialog() processSettings(false); } -/** - * @brief RsCollectionDialog::eventFilter: Proccess event in object - * @param obj: object where event occured - * @param event: event occured - * @return If we don't have to process event in parent. - */ -#ifdef TODO_COLLECTION -bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == ui._fileEntriesTW) { - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && (keyEvent->key() == Qt::Key_Space)) { - // Space pressed - - // get state of current item - QTreeWidgetItem *item = ui._fileEntriesTW->currentItem(); - if (item) { - Qt::CheckState checkState = (item->checkState(COLUMN_FILE) == Qt::Checked) ? Qt::Unchecked : Qt::Checked; - - // set state of all selected items - QList selectedItems = ui._fileEntriesTW->selectedItems(); - QList::iterator it; - for (it = selectedItems.begin(); it != selectedItems.end(); ++it) { - if ((*it)->checkState(COLUMN_FILE) != checkState) - (*it)->setCheckState(COLUMN_FILE, checkState); - } - } - - return true; // eat event - } - - if (keyEvent && (keyEvent->key() == Qt::Key_Delete)) { - // Delete pressed - remove(); - return true; // eat event - } - - if (keyEvent && (keyEvent->key() == Qt::Key_Plus)) { - // Plus pressed - makeDir(); - return true; // eat event - } - - } - } - - if (obj == ui._systemFileTW) { - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && ((keyEvent->key() == Qt::Key_Enter) - || keyEvent->key() == Qt::Key_Return)) { - // Enter pressed - if (keyEvent->modifiers() == Qt::ShiftModifier) - addRecursive(); - else if(keyEvent->modifiers() == Qt::NoModifier) { - add(); - } - - return true; // eat event - } - } - } - - // pass the event on to the parent class - return QDialog::eventFilter(obj, event); -} -#endif - /** * @brief RsCollectionDialog::processSettings * @param bLoad: Load or Save dialog's settings @@ -424,162 +342,6 @@ void RsCollectionDialog::processSettings(bool bLoad) Settings->endGroup(); } -#ifdef TO_REMOVE -/** - * @brief RsCollectionDialog::getRootItem: Create the root Item if not existing - * @return: the root item - */ -QTreeWidgetItem* RsCollectionDialog::getRootItem() -{ - return ui._fileEntriesTW->invisibleRootItem(); -} -#endif - -/** - * @brief RsCollectionDialog::updateList: Update list of item in RsCollection - * @return If at least one item have a Wrong Char - */ -bool RsCollectionDialog::updateList() -{ -#ifdef TODO_COLLECTION - bool wrong_chars = false ; - wrong_chars = addChild(getRootItem(), _newColFileInfos); - - _newColFileInfos.clear(); - - ui._filename_TL->setText(_fileName) ; - for (int column = 0; column < ui._fileEntriesTW->columnCount(); ++column) { - ui._fileEntriesTW->resizeColumnToContents(column); - } - - updateSizes() ; - - return !wrong_chars; -#endif - return true; -} - -#ifdef TO_REMOVE -/** - * @brief RsCollectionDialog::addChild: Add Child Item in list - * @param parent: Parent Item - * @param child: Child ColFileInfo item to add - * @param total_size: Saved total size of children to save in parent - * @param total_files: Saved total file of children to save in parent - * @return If at least one item have a Wrong Char - */ -bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector& child) -{ - bool wrong_chars = false ; - - uint32_t childCount = child.size(); - for(uint32_t i=0; i founds; - QList parentsFounds; - parentsFounds = ui._fileEntriesTW->findItems(colFileInfo.path , Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - if (colFileInfo.type == DIR_TYPE_DIR){ - founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - } else { - founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - if (ui._removeDuplicate_CB->isChecked()) { - founds << ui._fileEntriesTW->findItems(colFileInfo.hash, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH); - } - } - if (founds.empty()) { - QTreeWidgetItem *item = new QTreeWidgetItem; - - //item->setFlags(Qt::ItemIsUserCheckable | item->flags()); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); - item->setCheckState(COLUMN_FILE, Qt::Checked); - item->setText(COLUMN_FILE, colFileInfo.name); - item->setText(COLUMN_FILEPATH, colFileInfo.path + "/" + colFileInfo.name); - item->setText(COLUMN_HASH, colFileInfo.hash); - item->setData(COLUMN_HASH, ROLE_NAME, colFileInfo.name); - item->setData(COLUMN_HASH, ROLE_PATH, colFileInfo.path); - item->setData(COLUMN_HASH, ROLE_TYPE, colFileInfo.type); - QFont font = item->font(COLUMN_FILE); - if (colFileInfo.type==DIR_TYPE_DIR) { - item->setToolTip(COLUMN_FILE,tr("This is a directory. Double-click to expand it.")); - font.setBold(true); - //Size calculated after for added child after init - item->setText(COLUMN_SIZE, misc::friendlyUnit(0)); - item->setToolTip(COLUMN_SIZE,tr("Real Size: Waiting child...")); - item->setData(COLUMN_SIZE, ROLE_SIZE, 0); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, 0); - - item->setText(COLUMN_FILEC, ""); - item->setToolTip(COLUMN_FILEC, tr("Real File Count: Waiting child...")); - item->setData(COLUMN_FILEC, ROLE_FILEC, 0); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, 0); - } else { - font.setBold(false); - item->setText(COLUMN_SIZE, misc::friendlyUnit(colFileInfo.size)); - item->setToolTip(COLUMN_SIZE, tr("Real Size=%1").arg(misc::friendlyUnit(colFileInfo.size))); - item->setData(COLUMN_SIZE, ROLE_SIZE, colFileInfo.size); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, colFileInfo.size); - - item->setText(COLUMN_FILEC, "1"); - item->setToolTip(COLUMN_FILEC, tr("Real File Count=%1").arg(1)); - item->setData(COLUMN_FILEC, ROLE_FILEC, 1); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, 1); - } - item->setFont(COLUMN_FILE, font); - item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); - - if (colFileInfo.filename_has_wrong_characters) - { - //TODO (Phenom): Add qproperty for these text colors in stylesheets - wrong_chars = true ; - item->setData(COLUMN_FILE, Qt::ForegroundRole, QColor(255,80,120)) ; - } - - if (parentsFounds.empty()) { - parent->addChild(item); - } else { - parentsFounds.at(0)->addChild(item); - } - - if (colFileInfo.type == DIR_TYPE_FILE) { - //update parents size only for file children - QTreeWidgetItem *itemParent = item->parent(); - if (itemParent) { - while (itemParent) { - qulonglong parentSize = itemParent->data(COLUMN_SIZE, ROLE_SIZE).toULongLong() + colFileInfo.size; - itemParent->setData(COLUMN_SIZE, ROLE_SIZE, parentSize); - itemParent->setToolTip(COLUMN_SIZE, tr("Real Size=%1").arg(misc::friendlyUnit(parentSize))); - qulonglong parentSelSize = itemParent->data(COLUMN_SIZE, ROLE_SELSIZE).toULongLong() + colFileInfo.size; - itemParent->setData(COLUMN_SIZE, ROLE_SELSIZE, parentSelSize); - itemParent->setText(COLUMN_SIZE, misc::friendlyUnit(parentSelSize)); - - qulonglong parentFileCount = itemParent->data(COLUMN_FILEC, ROLE_FILEC).toULongLong() + 1; - itemParent->setData(COLUMN_FILEC, ROLE_FILEC, parentFileCount); - itemParent->setToolTip(COLUMN_FILEC, tr("Real File Count=%1").arg(parentFileCount)); - qulonglong parentSelFileCount = itemParent->data(COLUMN_FILEC, ROLE_SELFILEC).toULongLong() + 1; - itemParent->setData(COLUMN_FILEC, ROLE_SELFILEC, parentSelFileCount); - itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentSelFileCount)); - - itemParent = itemParent->parent(); - } - } - } - - founds.push_back(item); - } - - if (!founds.empty()) { - - if (colFileInfo.type == DIR_TYPE_DIR) { - wrong_chars |= addChild(founds.at(0), colFileInfo.children); - } - } - } - return wrong_chars; -} -#endif - /** * @brief RsCollectionDialog::directoryLoaded: called when ui._treeView have load an directory as QFileSystemModel don't load all in one time * @param dirLoaded: Name of directory just loaded @@ -642,21 +404,21 @@ void RsCollectionDialog::updateSizes() * @param bad * @return */ -static QString purifyFileName(const QString& input, bool& bad) +static bool checkFileName(const std::string& input, std::string& corrected) { - static const QString bad_chars = "/\\\"*:?<>|" ; - bad = false ; - QString output = input ; + static const std::string bad_chars ( "/\\\"*:?<>|" ); + bool ok = true ; + corrected = input ; - for(int i=0;isetText(fileName); - - updateList(); } /** @@ -782,8 +542,6 @@ static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree: void RsCollectionDialog::addSelection(bool recursive) { QMap dirToAdd; - int count=0;//to not scan all items on list .count() - QModelIndexList milSelectionList = ui._systemFileTW->selectionModel()->selectedIndexes(); mCollectionModel->preMods(); @@ -797,76 +555,8 @@ void RsCollectionDialog::addSelection(bool recursive) recursBuildFileTree(_dirModel->filePath(_tree_proxyModel->mapToSource(index)),tree,tree.root(),recursive,paths_to_hash); mCollection->merge_in(tree); - -#ifdef TO_REMOVE - QFileInfo fileInfo = filePath; - if (fileInfo.isDir()) { - dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - ++count; - if (recursive) { - if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return; - } else { - continue; - } - } - if (fileInfo.isFile()){ - fileToHash.append(fileInfo.absoluteFilePath()); - ++count; - if (dirToAdd.contains(fileInfo.absolutePath())) - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - else - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),""); - } -#endif } -#ifdef TO_REMOVE - // Process Dirs - QTreeWidgetItem *item = NULL; - if (!ui._fileEntriesTW->selectedItems().empty()) - item= ui._fileEntriesTW->selectedItems().at(0); - if (item) { - while (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { - item = item->parent();//Only Dir as Parent - } - } - - int index = 0; - while (index < dirToAdd.count()) - { - ColFileInfo root; - if (item && (item != getRootItem())) { - root.name = ""; - root.path = item->text(COLUMN_FILEPATH); - } else { - root.name = ""; - root.path = ""; - } - //QMap is ordered, so we get parent before child - //Iterator is moved inside this function - processItem(dirToAdd, index, root); - } - - //Update liste before attach files to be sure when file is hashed, parent directory exists. - updateList(); - - for (QHash::Iterator it = _listOfFilesAddedInDir.begin(); it != _listOfFilesAddedInDir.end() ; ++it) - { - QString path = it.value(); - //it.value() = "";//Don't reset value, could be an older attachment not terminated. - if (dirToAdd.contains(path)){ - it.value() = dirToAdd.value(path); - } else if(item) { - if (item->data(COLUMN_HASH, ROLE_NAME) != "") { - it.value() = item->text(COLUMN_FILEPATH); - } - } - } - - // Process Files once all done - ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); -#endif - mFilesBeingHashed.insert(paths_to_hash.begin(),paths_to_hash.end()); QStringList paths; @@ -892,64 +582,6 @@ void RsCollectionDialog::addSelection(bool recursive) } } -#ifdef TO_REMOVE -/** - * @brief RsCollectionDialog::addAllChild: Add children to RsCollection - * @param fileInfoParent: Parent's QFileInfo to scan - * @param dirToAdd: QMap where directories are added - * @param fileToHash: QStringList where files are added - * @return false if too many items is selected and aborted - */ -bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent - , QMap &dirToAdd - , QStringList &fileToHash - , int &count) -{ - //Save count only first time to not scan all items on list .count() - if (count == 0) count = (dirToAdd.count() + fileToHash.count()); - QDir dirParent = fileInfoParent.absoluteFilePath(); - dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); - QFileInfoList childrenList = dirParent.entryInfoList(); - foreach (QFileInfo fileInfo, childrenList) - { - if (count == MAX_FILE_ADDED_BEFORE_ASK) - { - QMessageBox msgBox; - msgBox.setText(tr("Warning, selection contains more than %1 items.").arg(MAX_FILE_ADDED_BEFORE_ASK)); - msgBox.setInformativeText("Do you want to continue?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - return false; - break; - break; - default: - // should never be reached - break; - } - } - if (fileInfo.isDir()) { - dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - ++count; - if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return false; - } - if (fileInfo.isFile()){ - fileToHash.append(fileInfo.absoluteFilePath()); - ++count; - if (dirToAdd.contains(fileInfo.absolutePath())) - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - else - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),""); - } - } - return true; -} -#endif - /** * @brief RsCollectionDialog::remove: Remove selected Items in RSCollection */ @@ -975,180 +607,8 @@ void RsCollectionDialog::remove() } mCollectionModel->postMods(); - -#ifdef TODO_COLLECTION - bool removeOnlyFile=false; - QString listDir; - // First, check if selection contains directories - for (int curs = 0; curs < ui._fileEntriesTW->selectedItems().count(); ++curs) - {// Have to call ui._fileEntriesTW->selectedItems().count() each time as selected could change - QTreeWidgetItem *item = NULL; - item= ui._fileEntriesTW->selectedItems().at(curs); - - //Uncheck child directory item if parent is checked - if (item != getRootItem()){ - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() == DIR_TYPE_DIR) { - QString path = item->data(COLUMN_HASH, ROLE_PATH).toString(); - if (listDir.contains(path) && !path.isEmpty()) { - item->setSelected(false); - } else { - listDir += item->data(COLUMN_HASH, ROLE_NAME).toString() +"
"; - } - } - } - } - - //If directories, ask to remove them or not - if (!listDir.isEmpty()){ - QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, "", ""); - msgBox->setText("Warning, selection contains directories."); - //msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit - QGridLayout* layout = qobject_cast(msgBox->layout()); - if (layout) { - int newRow = 1; - for (int row = layout->count()-1; row >= 0; --row) { - for (int col = layout->columnCount()-1; col >= 0; --col) { - QLayoutItem *item = layout->itemAtPosition(row, col); - if (item) { - int index = layout->indexOf(item->widget()); - int r=0, c=0, rSpan=0, cSpan=0; - layout->getItemPosition(index, &r, &c, &rSpan, &cSpan); - if (r>0) { - layout->removeItem(item); - layout->addItem(item, r+3, c, rSpan, cSpan); - } else if (rSpan>1) { - newRow = rSpan + 1; - } - } - } - } - QLabel *label = new QLabel(tr("Do you want to remove them and all their children, too?")); - layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - QTextEdit *edit = new QTextEdit(listDir); - edit->setReadOnly(true); - edit->setWordWrapMode(QTextOption::NoWrap); - layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - } - - msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - msgBox->setDefaultButton(QMessageBox::Yes); - int ret = msgBox->exec(); - switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - removeOnlyFile = true; - break; - case QMessageBox::Cancel: { - delete msgBox; - return; - } - break; - default: - // should never be reached - break; - } - delete msgBox; - } - - //Remove wanted items - int leftItem = 0; - // Have to call ui._fileEntriesTW->selectedItems().count() each time as selected change - while (ui._fileEntriesTW->selectedItems().count() > leftItem) { - QTreeWidgetItem *item = ui._fileEntriesTW->selectedItems().at(leftItem); - - if (item != getRootItem()){ - if (!removeItem(item, removeOnlyFile)) { - ++leftItem; - } - } else { - //Get Root change index - ++leftItem; - } - } - - updateSizes() ; -#endif } -#ifdef TODO_COLLECTION -bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) -{ - if (item){ - if ((item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) || !removeOnlyFile) { - int leftItem = 0; - while (item->childCount() > leftItem) { - if (!removeItem(item->child(0), removeOnlyFile)) { - ++leftItem; - } - } - if (leftItem == 0) { - //First uncheck item to update parent informations - item->setCheckState(COLUMN_FILE,Qt::Unchecked); - QTreeWidgetItem *parent = item->parent(); - if (parent) { - parent->removeChild(item); - } else { - getRootItem()->removeChild(item); - } - return true; - } else { - if (!removeOnlyFile) { - std::cerr << "(EE) RsCollectionDialog::removeItem This could never happen." << std::endl; - } - } - } - } - return false; -} -#endif - -#ifdef TO_REMOVE -/** Process each item to make a new RsCollection item */ -void RsCollectionDialog::processItem(QMap &dirToAdd - , int &index - , ColFileInfo &parent - ) -{ - ColFileInfo newChild; - int count = dirToAdd.count(); - if (index < count) { - QString key=dirToAdd.keys().at(index); - bool bad_chars_detected = false; - QFileInfo fileInfo=key; - QString cleanDirName = purifyFileName(fileInfo.fileName(),bad_chars_detected); - newChild.name = cleanDirName; - newChild.filename_has_wrong_characters = bad_chars_detected; - newChild.size = fileInfo.isDir()? 0: fileInfo.size(); - newChild.type = fileInfo.isDir()? DIR_TYPE_DIR: DIR_TYPE_FILE ; - if (parent.name != "") { - newChild.path = parent.path + "/" + parent.name; - } else { - newChild.path = parent.path; - } - dirToAdd[key] = newChild.path + "/" + newChild.name; - //Move to next item - ++index; - if (index < count){ - QString newKey = dirToAdd.keys().at(index); - while ((dirToAdd.value(newKey) == key) - && (index < count)) { - processItem(dirToAdd, index, newChild); - if (index < count)newKey = dirToAdd.keys().at(index); - } - } - - //Save parent when child are processed - if (parent.name != "") { - parent.children.push_back(newChild); - parent.size += newChild.size; - } else { - _newColFileInfos.push_back(newChild); - } - } -} -#endif - /** * @brief RsCollectionDialog::addDir: Add new empty dir to list */ @@ -1179,90 +639,6 @@ void RsCollectionDialog::makeDir() mCollectionModel->preMods(); mCollection->merge_in(*RsFileTree::fromDirectory(childName.toUtf8().constData()),e.index); mCollectionModel->postMods(); - -#ifdef TODO_COLLECTION - QString childName=""; - bool ok, badChar, nameOK = false; - // Ask for name - while (!nameOK) - { - childName = QInputDialog::getText(this, tr("New Directory") - , tr("Enter the new directory's name") - , QLineEdit::Normal, childName, &ok); - if (ok && !childName.isEmpty()) - { - childName = purifyFileName(childName, badChar); - nameOK = !badChar; - if (badChar) - { - QMessageBox msgBox; - msgBox.setText("The name contains bad characters."); - msgBox.setInformativeText("Do you want to use the corrected one?\n" + childName); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Retry | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Ok: - nameOK = true; - break; - case QMessageBox::Retry: - break; - case QMessageBox::Cancel: - return; - break; - default: - // should never be reached - break; - } - } - } else {//if (ok && !childName.isEmpty()) - return; - } - - } - - - QList selected = ui._fileEntriesTW->selectedItems(); - - if(selected.empty()) - { - QTreeWidgetItem *item = getRootItem(); - - ColFileInfo newChild; - newChild.name = childName; - newChild.filename_has_wrong_characters = false; - newChild.size = 0; - newChild.type = DIR_TYPE_DIR; - newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() - + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); - if (item == getRootItem()) newChild.path = ""; - - _newColFileInfos.push_back(newChild); - } - else - for(auto it(selected.begin());it!=selected.end();++it) - { - QTreeWidgetItem *item = *it; - - while(item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) - item = item->parent();//Only Dir as Parent - - ColFileInfo newChild; - newChild.name = childName; - newChild.filename_has_wrong_characters = false; - newChild.size = 0; - newChild.type = DIR_TYPE_DIR; - - if (item == getRootItem()) - newChild.path = ""; - else - newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); - - _newColFileInfos.push_back(newChild); - } - - updateList(); -#endif } /** @@ -1272,33 +648,6 @@ void RsCollectionDialog::makeDir() */ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) { -#ifdef TO_REMOVE - std::cerr << "RsCollectionDialog::fileHashingFinished() started." << std::endl; - - QString message; - - QList::iterator it; - for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) { - HashedFile& hashedFile = *it; - - ColFileInfo colFileInfo; - colFileInfo.name=hashedFile.filename; - colFileInfo.path=""; - colFileInfo.size=hashedFile.size; - colFileInfo.hash=QString::fromStdString(hashedFile.hash.toStdString()); - colFileInfo.filename_has_wrong_characters=false; - colFileInfo.type=DIR_TYPE_FILE; - - if(_listOfFilesAddedInDir.value(hashedFile.filepath,"")!="") { - //File Added in directory, find its parent - colFileInfo.path = _listOfFilesAddedInDir.value(hashedFile.filepath,""); - _listOfFilesAddedInDir.remove(hashedFile.filepath); - } -#ifdef TODO_COLLECTION - _newColFileInfos.push_back(colFileInfo); -#endif - } -#endif // build a map of old-hash to new-hash for the hashed files, so that it can be passed to the mCollection for update mCollectionModel->preMods(); @@ -1327,132 +676,6 @@ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) ui._save_PB->setToolTip(tr("")); ui._save_PB->setEnabled(true); } - updateList(); -} - -#ifdef TO_REMOVE -void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col) -{ - if (col != COLUMN_FILE) return; - - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_FILE) return; - - //In COLUMN_FILE, normaly, only checkState could change... - qulonglong size = item->data(COLUMN_SIZE, ROLE_SIZE).toULongLong(); - bool unchecked = (item->checkState(COLUMN_FILE) == Qt::Unchecked); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, unchecked?0:size); - item->setText(COLUMN_SIZE, misc::friendlyUnit(unchecked?0:size)); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, unchecked?0:1); - item->setText(COLUMN_FILEC, QString("%1").arg(unchecked?0:1)); - - //update parents size - QTreeWidgetItem *itemParent = item->parent(); - while (itemParent) { - //When unchecked only remove selected size - qulonglong parentSize = itemParent->data(COLUMN_SIZE, ROLE_SELSIZE).toULongLong() + (unchecked?0-size:size); - itemParent->setData(COLUMN_SIZE, ROLE_SELSIZE, parentSize); - itemParent->setText(COLUMN_SIZE, misc::friendlyUnit(parentSize)); - - qulonglong parentFileCount = itemParent->data(COLUMN_FILEC, ROLE_SELFILEC).toULongLong() + (unchecked?0-1:1); - itemParent->setData(COLUMN_FILEC, ROLE_SELFILEC, parentFileCount); - itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentFileCount)); - - itemParent = itemParent->parent(); - } - - updateSizes() ; - -} -#endif - -/** - * @brief RsCollectionDialog::updateRemoveDuplicate Remove all duplicate file when checked. - * @param checked - */ -void RsCollectionDialog::updateRemoveDuplicate(bool checked) -{ -#ifdef TODO_COLLECTION - if (checked) { - bool bRemoveAll = false; - QTreeWidgetItemIterator it(ui._fileEntriesTW); - QTreeWidgetItem *item; - while ((item = *it) != NULL) { - ++it; - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { - QList founds; - founds << ui._fileEntriesTW->findItems(item->text(COLUMN_HASH), Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH); - if (founds.count() > 1) { - bool bRemove = false; - if (!bRemoveAll) { - QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, "", ""); - msgBox->setText("Warning, duplicate file found."); - //msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit - msgBox->setStandardButtons(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - msgBox->setDefaultButton(QMessageBox::Yes); - - QGridLayout* layout = qobject_cast(msgBox->layout()); - if (layout) { - int newRow = 1; - for (int row = layout->count()-1; row >= 0; --row) { - for (int col = layout->columnCount()-1; col >= 0; --col) { - QLayoutItem *item = layout->itemAtPosition(row, col); - if (item) { - int index = layout->indexOf(item->widget()); - int r=0, c=0, rSpan=0, cSpan=0; - layout->getItemPosition(index, &r, &c, &rSpan, &cSpan); - if (r>0) { - layout->removeItem(item); - layout->addItem(item, r+3, c, rSpan, cSpan); - } else if (rSpan>1) { - newRow = rSpan + 1; - } - } - } - } - QLabel *label = new QLabel(tr("Do you want to remove this file from the list?")); - layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - QTextEdit *edit = new QTextEdit(item->text(COLUMN_FILEPATH)); - edit->setReadOnly(true); - edit->setWordWrapMode(QTextOption::NoWrap); - layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - } - - int ret = msgBox->exec(); - switch (ret) { - case QMessageBox::YesToAll: { - bRemoveAll = true; - } - break; - case QMessageBox::Yes: { - bRemove = true; - } - break; - case QMessageBox::No: - break; - case QMessageBox::Cancel: { - delete msgBox; - ui._removeDuplicate_CB->setChecked(false); - return; - } - break; - default: - // should never be reached - break; - } - delete msgBox; - } - - if (bRemove || bRemoveAll) { - //First uncheck item to update parent informations - item->setCheckState(COLUMN_FILE,Qt::Unchecked); - item->parent()->removeChild(item); - } - - } - } - } - } -#endif } /** @@ -1470,6 +693,8 @@ void RsCollectionDialog::cancel() void RsCollectionDialog::download() { std::cerr << "Downloading!" << std::endl; + bool auto_correct = false; + bool auto_skip = false; QString dldir = ui.downloadFolder_LE->text(); @@ -1509,50 +734,44 @@ void RsCollectionDialog::download() std::string subpath = RsDirUtil::makePath(path,dirdata.name); const auto& f(mCollection->fileTree().fileData(dirdata.subfiles[i])); - std::cerr << "Requesting file " << f.name << " to directory " << path << std::endl; + std::string corrected_name; - rsFiles->FileRequest(f.name,f.hash,f.size,path,RS_FILE_REQ_ANONYMOUS_ROUTING,std::list()); + if(!checkFileName(f.name,corrected_name) && !auto_correct) + { + if(auto_skip) + continue; + + QMessageBox mb; + mb.setText(tr("Incompatible filename.")); + mb.setInformativeText(tr("This filename is not usable on your system.")+"\n"+tr("Retroshare can replace every problematic chars by '_'.") + +"\n"+tr("What do you want to do?")); + QAbstractButton *btnCorrect = mb.addButton(tr("Correct filename"), QMessageBox::ResetRole); + QAbstractButton *btnCorrectAll = mb.addButton(tr("Correct all"), QMessageBox::YesRole); + QAbstractButton *btnSkip = mb.addButton(tr("Skip this file"), QMessageBox::ApplyRole); + QAbstractButton *btnSkipAll = mb.addButton(tr("Skip all"), QMessageBox::AcceptRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); + + if(mb.clickedButton() == btnSkipAll) + { + auto_skip = true; + continue; + } + if(mb.clickedButton() == btnSkip) + continue; + + if(mb.clickedButton() == btnCorrectAll) + auto_correct = true; + } + + std::cerr << "Requesting file " << corrected_name << " to directory " << path << std::endl; + + rsFiles->FileRequest(corrected_name,f.hash,f.size,path,RS_FILE_REQ_ANONYMOUS_ROUTING,std::list()); } }; recursDL(mCollection->fileTree().root(),dldir.toUtf8().constData()); close(); -#ifdef TO_REMOVE - while ((item = *itemIterator) != NULL) { - ++itemIterator; - - if (item->checkState(COLUMN_FILE) == Qt::Checked) { - std::cerr << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() - << " " << item->text(COLUMN_HASH).toStdString() - << " " << item->text(COLUMN_SIZE).toStdString() - << " " << item->data(COLUMN_HASH,ROLE_PATH).toString().toStdString() << std::endl; - ColFileInfo colFileInfo; - colFileInfo.hash = item->text(COLUMN_HASH); - colFileInfo.name = item->data(COLUMN_HASH,ROLE_NAME).toString(); - colFileInfo.path = item->data(COLUMN_HASH,ROLE_PATH).toString(); - colFileInfo.type = item->data(COLUMN_HASH,ROLE_TYPE).toUInt(); - colFileInfo.size = item->data(COLUMN_SIZE,ROLE_SELSIZE).toULongLong(); - - QString cleanPath = dldir + colFileInfo.path ; - std::cerr << "making directory " << cleanPath.toStdString() << std::endl; - - if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) - QMessageBox::warning(NULL,QObject::tr("Unable to make path"),QObject::tr("Unable to make path:")+"
"+cleanPath) ; - - if (colFileInfo.type==DIR_TYPE_FILE) - rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), - RsFileHash(colFileInfo.hash.toStdString()), - colFileInfo.size, - cleanPath.toUtf8().constData(), - RS_FILE_REQ_ANONYMOUS_ROUTING, - std::list()); - } else {//if (item->checkState(COLUMN_FILE) == Qt::Checked) - std::cerr<<"Skipping file : " << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() << std::endl; - } - } - - close(); -#endif } /** @@ -1569,47 +788,8 @@ void RsCollectionDialog::save() mCollection->cleanup(); mCollection->save(ui._filename_TL->text()); close(); -#ifdef TO_REMOVE - std::cerr << "Saving!" << std::endl; - _newColFileInfos.clear(); - QTreeWidgetItem* root = getRootItem(); - if (root) { - saveChild(root); - emit saveColl(_newColFileInfos, _fileName); - } - close(); -#endif } -#ifdef TO_REMOVE -/** - * @brief RsCollectionDialog::saveChild: Save each child in _newColFileInfos - * @param parent - */ -void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo) -{ - ColFileInfo parent; - if (!parentInfo) parentInfo = &parent; - - parentInfo->checked = (parentItem->checkState(COLUMN_FILE)==Qt::Checked); - parentInfo->hash = parentItem->text(COLUMN_HASH); - parentInfo->name = parentItem->data(COLUMN_HASH,ROLE_NAME).toString(); - parentInfo->path = parentItem->data(COLUMN_HASH,ROLE_PATH).toString(); - parentInfo->type = parentItem->data(COLUMN_HASH,ROLE_TYPE).toUInt(); - parentInfo->size = parentItem->data(COLUMN_SIZE,ROLE_SELSIZE).toULongLong(); - - for (int i=0; ichildCount(); ++i) { - ColFileInfo child; - saveChild(parentItem->child(i), &child); - if (parentInfo->name != "") { - parentInfo->children.push_back(child); - } else { - _newColFileInfos.push_back(child); - } - } -} -#endif - bool RsCollectionDialog::editExistingCollection(const QString& fileName, bool showError /* = true*/) { return RsCollectionDialog(fileName,EDIT).exec(); @@ -1651,77 +831,5 @@ bool RsCollectionDialog::openNewCollection(const RsFileTree& tree) return false; return RsCollectionDialog(fileName,EDIT).exec(); - -#ifdef TODO_COLLECTION - QString fileName = proposed_file_name; - - if(!misc::getSaveFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE - , QApplication::translate("RsCollectionFile", "Create collection file") - , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" - , fileName,0, QFileDialog::DontConfirmOverwrite)) - return false; - - if (!fileName.endsWith("." + RsCollection::ExtensionString)) - fileName += "." + RsCollection::ExtensionString ; - - std::cerr << "Got file name: " << fileName.toStdString() << std::endl; - - QFile file(fileName) ; - - if(file.exists()) - { - RsCollection::RsCollectionErrorCode err; - if (!RsCollection::checkFile(fileName,err)) - { - QMessageBox::information(nullptr,tr("Error openning collection"),RsCollection::errorString(err)); - return false; - } - - QMessageBox mb; - mb.setText(tr("Save Collection File.")); - mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); - QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); - QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); - QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); - mb.setIcon(QMessageBox::Question); - mb.exec(); - - if (mb.clickedButton()==btnOwerWrite) { - //Nothing to do _xml_doc already up to date - } else if (mb.clickedButton()==btnMerge) { - //Open old file to merge it with _xml_doc - QDomDocument qddOldFile("RsCollection"); - if (qddOldFile.setContent(&file)) { - QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement(); - std::vector colOldFileInfos; - recursCollectColFileInfos(docOldElem,colOldFileInfos,QString(),false); - - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - for(uint32_t i = 0;i colFileInfos ; - - recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; - - RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos,true); - connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; - _saved=false; - rcd->exec() ; - delete rcd; - -#endif - return true; } diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 9ba3ac857..4b4fe5ffd 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -64,18 +64,8 @@ private slots: void chooseDestinationDirectory(); void setDestinationDirectory(); void openDestinationDirectoryMenu(); -#ifdef TO_REMOVE - void processItem(QMap &dirToAdd - , int &index - , ColFileInfo &parent - ) ; -#endif void makeDir() ; void fileHashingFinished(QList hashedFiles) ; -#ifdef TO_REMOVE - void itemChanged(QTreeWidgetItem* item,int col) ; -#endif - void updateRemoveDuplicate(bool checked); void cancel() ; void download() ; void save() ; @@ -85,21 +75,9 @@ signals: private: void processSettings(bool bLoad) ; - bool updateList(); -#ifdef TO_REMOVE - QTreeWidgetItem* getRootItem(); - bool addChild(QTreeWidgetItem *parent, const std::vector &child); - bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ; - void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL); - bool addAllChild(QFileInfo &fileInfoParent - , QMap &dirToAdd - , QStringList &fileToHash - , int &count); -#endif void addSelection(bool recursive) ; Ui::RsCollectionDialog ui; - QString _fileName ; RsCollectionDialogMode _mode; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index 8871536a2..6f3bee40d 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -410,26 +410,6 @@ - - - - Remove Duplicate - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - From 0551f4f819c9092221492ddd39880f0c05e62b93 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 28 Mar 2024 22:14:46 +0100 Subject: [PATCH 26/28] fixed compilation after removal of RsCollection::downloadFiles --- .../src/gui/FileTransfer/SearchDialog.cpp | 4 +- .../gui/FileTransfer/SharedFilesDialog.cpp | 2 +- .../src/gui/FileTransfer/TransfersDialog.cpp | 8 +-- retroshare-gui/src/gui/RemoteDirModel.cpp | 4 +- retroshare-gui/src/gui/RetroShareLink.cpp | 11 ++-- .../src/gui/common/RsCollection.cpp | 59 +++++-------------- retroshare-gui/src/gui/common/RsCollection.h | 36 ++--------- .../src/gui/common/RsCollectionDialog.cpp | 17 ++++++ .../src/gui/common/RsCollectionDialog.h | 7 ++- 9 files changed, 56 insertions(+), 92 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index 387b3427a..8c4b3f31d 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -598,7 +598,7 @@ void SearchDialog::collOpen() RsCollection::RsCollectionErrorCode err; qinfo.setFile(QString::fromUtf8(path.c_str())); if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) - RsCollection(qinfo.absoluteFilePath(),err).downloadFiles(); + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); } } } @@ -613,7 +613,7 @@ void SearchDialog::collOpen() RsCollection collection(fileName, err); if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) - collection.downloadFiles(); + RsCollectionDialog::downloadFiles(collection); else QMessageBox::information(nullptr,tr("Error open RsCollection file"),RsCollection::errorString(err)); } diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 8ce8ac3d4..b1dd7fcff 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -855,7 +855,7 @@ void SharedFilesDialog::collOpen() RsCollection collection(fileName,err); if(err == RsCollection::RsCollectionErrorCode::NO_ERROR) - collection.downloadFiles(); + RsCollectionDialog::downloadFiles(collection); } void LocalSharedFilesDialog::playselectedfiles() diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index 44c0260bd..d3ffc698d 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -1975,7 +1975,7 @@ void TransfersDialog::pasteLink() for(auto &it : links) col.merge_in(it.name(),it.size(),RsFileHash(it.hash().toStdString())) ; - col.downloadFiles(); + RsCollectionDialog::downloadFiles(col); } void TransfersDialog::getDLSelectedItems(std::set *ids, std::set *rows) @@ -2555,7 +2555,7 @@ void TransfersDialog::collOpen() if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { RsCollection::RsCollectionErrorCode code; - RsCollection(qinfo.absoluteFilePath(),code).downloadFiles(); + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),code)); return; } } @@ -2572,7 +2572,7 @@ void TransfersDialog::collOpen() RsCollection collection(fileName,code); if(code == RsCollection::RsCollectionErrorCode::NO_ERROR) - collection.downloadFiles(); + RsCollectionDialog::downloadFiles(collection); else QMessageBox::information(nullptr,tr("Error openning collection file"),RsCollection::errorString(code)); } @@ -2597,7 +2597,7 @@ void TransfersDialog::collAutoOpen(const QString &fileHash) RsCollection::RsCollectionErrorCode err; if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) - RsCollection(qinfo.absoluteFilePath(),err).autoDownloadFiles(); + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); } } } diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp index 87f70c06c..962001a76 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.cpp +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -24,7 +24,7 @@ #include "gui/common/FilesDefs.h" #include "gui/common/GroupDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsUrlHandler.h" #include "gui/gxs/GxsIdDetails.h" #include "retroshare/rsfiles.h" @@ -1253,7 +1253,7 @@ void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool inter FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; if(interactive) - RsCollection(dirVec,f).downloadFiles() ; + RsCollectionDialog::downloadFiles(RsCollection(dirVec,f)) ; else /* Fire off requests */ for (int i = 0, n = dirVec.size(); i < n; ++i) { diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index f87c72760..4271c40ef 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -25,7 +25,7 @@ #include "HomePage.h" #include "chat/ChatDialog.h" #include "common/PeerDefs.h" -#include "common/RsCollection.h" +#include "common/RsCollectionDialog.h" #include "common/RsUrlHandler.h" #include "connect/ConfCertDialog.h" #include "connect/ConnectFriendWizard.h" @@ -1724,10 +1724,9 @@ static void processList(const QStringList &list, const QString &textSingular, co case TYPE_FILE_TREE: { - auto ft = RsFileTree::fromRadix64( - link.radix().toStdString() ); - RsCollection(*ft).downloadFiles(); - break; + auto ft = RsFileTree::fromRadix64(link.radix().toStdString() ); + RsCollectionDialog::downloadFiles(RsCollection(*ft)); + break; } case TYPE_CHAT_ROOM: @@ -1778,7 +1777,7 @@ static void processList(const QStringList &list, const QString &textSingular, co // were single file links found? if (fileLinkFound) - col.downloadFiles(); + RsCollectionDialog::downloadFiles(col); int countProcessed = 0; int countError = 0; diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index 8f1853cc9..673099a50 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -37,11 +37,10 @@ const QString RsCollection::ExtensionString = QString("rscollection") ; -RsCollection::RsCollection(QObject *parent) - : QObject(parent), mFileTree(new RsFileTree) +RsCollection::RsCollection() { + mFileTree = std::unique_ptr(new RsFileTree()); } - RsCollection::RsCollection(const RsFileTree& ft) { mFileTree = std::unique_ptr(new RsFileTree(ft)); @@ -50,8 +49,8 @@ RsCollection::RsCollection(const RsFileTree& ft) mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); } -RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) - : QObject(parent), mFileTree(new RsFileTree) +RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags) + : mFileTree(new RsFileTree) { if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) { @@ -70,39 +69,6 @@ RsCollection::~RsCollection() { } -void RsCollection::downloadFiles() const -{ -#ifdef TODO_COLLECTION - // print out the element names of all elements that are direct children - // of the outermost element. - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos ; - - recursCollectColFileInfos(docElem,colFileInfos,QString(),false) ; - - RsCollectionDialog(_fileName, colFileInfos, false).exec() ; -#endif -} - -void RsCollection::autoDownloadFiles() const -{ -#ifdef TODO_COLLECTION - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos; - - recursCollectColFileInfos(docElem,colFileInfos,QString(),false); - - QString dlDir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()); - - foreach(ColFileInfo colFileInfo, colFileInfos) - { - autoDownloadFiles(colFileInfo, dlDir); - } -#endif -} - void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const { if (!colFileInfo.filename_has_wrong_characters) @@ -197,15 +163,20 @@ QString RsCollection::errorString(RsCollectionErrorCode code) switch(code) { default: [[fallthrough]] ; - case RsCollectionErrorCode::UNKNOWN_ERROR: return tr("Unknown error"); - case RsCollectionErrorCode::NO_ERROR: return tr("No error"); - case RsCollectionErrorCode::FILE_READ_ERROR: return tr("Error while openning file"); - case RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS: return tr("Collection file contains potentially harmful code"); - case RsCollectionErrorCode::INVALID_ROOT_NODE: return tr("Invalid root node. RsCollection node was expected."); - case RsCollectionErrorCode::XML_PARSING_ERROR: return tr("XML parsing error in collection file"); + case RsCollectionErrorCode::UNKNOWN_ERROR: return QObject::tr("Unknown error"); + case RsCollectionErrorCode::NO_ERROR: return QObject::tr("No error"); + case RsCollectionErrorCode::FILE_READ_ERROR: return QObject::tr("Error while openning file"); + case RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS: return QObject::tr("Collection file contains potentially harmful code"); + case RsCollectionErrorCode::INVALID_ROOT_NODE: return QObject::tr("Invalid root node. RsCollection node was expected."); + case RsCollectionErrorCode::XML_PARSING_ERROR: return QObject::tr("XML parsing error in collection file"); } } +RsCollection::RsCollection(const RsCollection& col) + : mFileTree(new RsFileTree(*col.mFileTree)),mHashes(col.mHashes) +{ +} + RsCollection::RsCollection(const QString& fileName, RsCollectionErrorCode& error) : mFileTree(new RsFileTree) { diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 7a01fc4b6..7be48804a 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -26,7 +26,6 @@ #pragma once -#include #include #include #include @@ -53,10 +52,8 @@ public: }; Q_DECLARE_METATYPE(ColFileInfo) -class RsCollection : public QObject +class RsCollection { - Q_OBJECT - public: enum class RsCollectionErrorCode:uint8_t { NO_ERROR = 0x00, @@ -67,9 +64,9 @@ public: XML_PARSING_ERROR = 0x05, }; - RsCollection(QObject *parent = 0) ; - // create from list of files and directories - RsCollection(const std::vector& file_entries, FileSearchFlags flags, QObject *parent = 0) ; + RsCollection(); + RsCollection(const RsCollection&); + RsCollection(const std::vector& file_entries, FileSearchFlags flags) ; RsCollection(const RsFileTree& ft); RsCollection(const QString& filename,RsCollectionErrorCode& error_code); @@ -87,10 +84,6 @@ public: static const QString ExtensionString ; -#ifdef TO_REMOVE - bool load(QWidget *parent); - bool save(QWidget *parent) const ; -#endif // Save to disk bool save(const QString& fileName) const ; @@ -101,11 +94,6 @@ public: // total number of files in the collection qulonglong count() const; - // Download the content. - void downloadFiles() const ; - // Auto Download all the content. - void autoDownloadFiles() const ; - static bool isCollectionFile(const QString& fileName); void updateHashes(const std::map& old_to_new_hashes); @@ -120,15 +108,6 @@ private: // This function is used to merge an existing RsFileTree into the RsCollection void recursMergeTree(RsFileTree::DirIndex parent, const RsFileTree& tree, const RsFileTree::DirData &dd); -#ifdef TO_REMOVE - void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const; - void recursAddElements( - QDomDocument& doc, const RsFileTree& ft, uint32_t index, - QDomElement& e ) const; - - void recursCollectColFileInfos(const QDomElement&,std::vector& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ; -#endif - // check that the file is a valid rscollection file, and not a lol bomb or some shit like this static bool checkFile(const QString &fileName, RsCollectionErrorCode &error); @@ -138,13 +117,6 @@ private: std::unique_ptr mFileTree; std::map mHashes; // used to efficiently update files being hashed -#ifdef TO_REMOVE - QDomDocument _xml_doc ; - QString _fileName ; - bool _saved; - QDomElement _root ; -#endif - friend class RsCollectionDialog ; }; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 16f265a03..258c80649 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -136,6 +136,17 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsColl close(); } + init(collectionFileName); +} + +RsCollectionDialog::RsCollectionDialog(const RsCollection& coll, RsCollectionDialogMode mode) + : _mode(mode) +{ + mCollection = new RsCollection(coll); + init(QString()); +} +void RsCollectionDialog::init(const QString& collectionFileName) +{ ui.setupUi(this) ; ui._filename_TL->setText(collectionFileName); @@ -800,6 +811,12 @@ bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool sh return RsCollectionDialog(fileName,DOWNLOAD).exec(); } +bool RsCollectionDialog::downloadFiles(const RsCollection &collection) +{ + return RsCollectionDialog(collection,DOWNLOAD).exec(); +} + + bool RsCollectionDialog::openNewCollection(const RsFileTree& tree) { RsCollection collection(tree); diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 4b4fe5ffd..3c1f5c29a 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -43,8 +43,12 @@ public: // Open existing collection for download static bool openExistingCollection(const QString& fileName, bool showError = true); + // Open existing collection for download + static bool downloadFiles(const RsCollection& collection); protected: - //bool eventFilter(QObject *obj, QEvent *ev); + static QString errorString(RsCollection::RsCollectionErrorCode code); + + void init(const QString& collectionFileName); enum RsCollectionDialogMode { UNKNOWN = 0x00, @@ -53,6 +57,7 @@ protected: }; RsCollectionDialog(const QString& filename, RsCollectionDialogMode mode) ; + RsCollectionDialog(const RsCollection& coll, RsCollectionDialogMode mode) ; private slots: void directoryLoaded(QString dirLoaded); From 3f9d49921d19708f8862e77b75081134b0d5d026 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 30 Mar 2024 18:37:20 +0100 Subject: [PATCH 27/28] fixed bug asking for overwriting a non existant file --- .../src/gui/common/RsCollectionDialog.cpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 258c80649..66a6c6d8c 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -756,10 +756,10 @@ void RsCollectionDialog::download() mb.setText(tr("Incompatible filename.")); mb.setInformativeText(tr("This filename is not usable on your system.")+"\n"+tr("Retroshare can replace every problematic chars by '_'.") +"\n"+tr("What do you want to do?")); - QAbstractButton *btnCorrect = mb.addButton(tr("Correct filename"), QMessageBox::ResetRole); - QAbstractButton *btnCorrectAll = mb.addButton(tr("Correct all"), QMessageBox::YesRole); - QAbstractButton *btnSkip = mb.addButton(tr("Skip this file"), QMessageBox::ApplyRole); - QAbstractButton *btnSkipAll = mb.addButton(tr("Skip all"), QMessageBox::AcceptRole); + QAbstractButton *btnCorrect = mb.addButton(tr("Correct filename"), QMessageBox::YesRole); + QAbstractButton *btnCorrectAll = mb.addButton(tr("Correct all"), QMessageBox::AcceptRole); + QAbstractButton *btnSkip = mb.addButton(tr("Skip this file"), QMessageBox::NoRole); + QAbstractButton *btnSkipAll = mb.addButton(tr("Skip all"), QMessageBox::RejectRole); mb.setIcon(QMessageBox::Question); mb.exec(); @@ -833,16 +833,19 @@ bool RsCollectionDialog::openNewCollection(const RsFileTree& tree) std::cerr << "Got file name: " << fileName.toStdString() << std::endl; - QMessageBox mb; - mb.setText(tr("Save Collection File.")); - mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); - QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); - QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); - mb.setIcon(QMessageBox::Question); - mb.exec(); + if(QFile(fileName).exists()) + { + QMessageBox mb; + mb.setText(tr("Save Collection File.")); + mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); + QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); + QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); - if (mb.clickedButton()==btnCancel) - return false; + if (mb.clickedButton()==btnCancel) + return false; + } if(!collection.save(fileName)) return false; From 0b75abaa0436d8d2467cdd437ef6a0fa58f52abc Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 1 Apr 2024 18:25:49 +0200 Subject: [PATCH 28/28] minor fixes to rscollection PR --- .../src/gui/common/RsCollectionDialog.ui | 19 +++++++++++++++++++ .../src/gui/common/RsCollectionModel.cpp | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index 6f3bee40d..5ceadb647 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -430,6 +430,12 @@ + + + 0 + 0 + + Qt::CustomContextMenu @@ -441,6 +447,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp index 16a2e473d..8c7fa9283 100644 --- a/retroshare-gui/src/gui/common/RsCollectionModel.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -489,7 +489,7 @@ void RsCollectionModel::postMods() emit layoutChanged(); emit sizesChanged(); - debugDump(); +// debugDump(); } void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,int depth)