Merge pull request #1065 from csoler/v0.6-Links2

V0.6 links2
This commit is contained in:
csoler 2017-10-23 22:14:06 +02:00 committed by GitHub
commit 06f489ec61
30 changed files with 991 additions and 446 deletions

View File

@ -35,6 +35,8 @@
//#define DEBUG_DIRECTORY_STORAGE 1
typedef FileListIO::read_error read_error;
/******************************************************************************************************************/
/* Internal File Hierarchy Storage */
/******************************************************************************************************************/
@ -1041,22 +1043,6 @@ bool InternalFileHierarchyStorage::save(const std::string& fname)
}
}
class read_error
{
public:
read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag)
{
std::ostringstream s ;
s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl;
err_string = s.str();
}
read_error(const std::string& s) : err_string(s) {}
const std::string& what() const { return err_string ; }
private:
std::string err_string ;
};
bool InternalFileHierarchyStorage::load(const std::string& fname)
{
unsigned char *buffer = NULL ;

View File

@ -0,0 +1,298 @@
#include <iomanip>
#include <util/radix64.h>
#include <util/rsdir.h>
#include "file_sharing_defaults.h"
#include "filelist_io.h"
#include "file_tree.h"
std::string FileTreeImpl::toRadix64() const
{
unsigned char *buff = NULL ;
uint32_t size = 0 ;
serialise(buff,size) ;
std::string res ;
Radix64::encode(buff,size,res) ;
free(buff) ;
return res ;
}
FileTree *FileTree::create(const std::string& radix64_string)
{
FileTreeImpl *ft = new FileTreeImpl ;
std::vector<uint8_t> mem = Radix64::decode(radix64_string);
ft->deserialise(mem.data(),mem.size()) ;
return ft ;
}
void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const DirDetails& dd,bool remote,bool remove_top_dirs)
{
if(ft.mDirs.size() <= index)
ft.mDirs.resize(index+1) ;
if(remove_top_dirs)
ft.mDirs[index].name = RsDirUtil::getTopDir(dd.name) ;
else
ft.mDirs[index].name = dd.name ;
ft.mDirs[index].subfiles.clear();
ft.mDirs[index].subdirs.clear();
DirDetails dd2 ;
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
for(uint32_t i=0;i<dd.children.size();++i)
if(rsFiles->RequestDirDetails(dd.children[i].ref,dd2,flags))
{
if(dd.children[i].type == DIR_TYPE_FILE)
{
FileTree::FileData f ;
f.name = dd2.name ;
f.size = dd2.count ;
f.hash = dd2.hash ;
ft.mDirs[index].subfiles.push_back(ft.mFiles.size()) ;
ft.mFiles.push_back(f) ;
ft.mTotalFiles++ ;
ft.mTotalSize += f.size ;
}
else if(dd.children[i].type == DIR_TYPE_DIR)
{
ft.mDirs[index].subdirs.push_back(ft.mDirs.size());
recurs_buildFileTree(ft,ft.mDirs.size(),dd2,remote,remove_top_dirs) ;
}
else
std::cerr << "(EE) Unsupported DirDetails type." << std::endl;
}
else
std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl;
}
bool FileTreeImpl::getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const
{
if(index >= mDirs.size())
return false ;
name = mDirs[index].name;
subdirs = mDirs[index].subdirs ;
subfiles.clear() ;
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
subfiles.push_back(mFiles[mDirs[index].subfiles[i]]);
return true ;
}
FileTree *FileTree::create(const DirDetails& dd, bool remote,bool remove_top_dirs)
{
FileTreeImpl *ft = new FileTreeImpl ;
FileTreeImpl::recurs_buildFileTree(*ft,0,dd,remote,remove_top_dirs) ;
return ft ;
}
typedef FileListIO::read_error read_error ;
bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
{
uint32_t buffer_offset = 0 ;
mTotalFiles = 0;
mTotalSize = 0;
try
{
// Read some header
uint32_t version,n_dirs,n_files ;
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,version)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION) ;
if(version != (uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001) throw std::runtime_error("Wrong version number") ;
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_files)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_dirs)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
// Write all file/dir entries
mFiles.resize(n_files) ;
mDirs.resize(n_dirs) ;
unsigned char *node_section_data = NULL ;
uint32_t node_section_size = 0 ;
for(uint32_t i=0;i<mFiles.size() && buffer_offset < buffer_size;++i) // only the 2nd condition really is needed. The first one ensures that the loop wont go forever.
{
uint32_t node_section_offset = 0 ;
#ifdef DEBUG_DIRECTORY_STORAGE
std::cerr << "reading node " << i << ", offset " << buffer_offset << " : " << RsUtil::BinToHex(&buffer[buffer_offset],std::min((int)buffer_size - (int)buffer_offset,100)) << "..." << std::endl;
#endif
if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,node_section_data,node_section_size))
{
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,mFiles[i].name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,mFiles[i].size )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ) ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,mFiles[i].hash )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH) ;
mTotalFiles++ ;
mTotalSize += mFiles[i].size ;
}
else
throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY) ;
}
for(uint32_t i=0;i<mDirs.size() && buffer_offset < buffer_size;++i)
{
uint32_t node_section_offset = 0 ;
if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,node_section_data,node_section_size))
{
DirData& de(mDirs[i]) ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME,de.name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ;
uint32_t n_subdirs = 0 ;
uint32_t n_subfiles = 0 ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
for(uint32_t j=0;j<n_subdirs;++j)
{
uint32_t di = 0 ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,di)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
de.subdirs.push_back(di) ;
}
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
for(uint32_t j=0;j<n_subfiles;++j)
{
uint32_t fi = 0 ;
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,fi)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
de.subfiles.push_back(fi) ;
}
}
else
throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY) ;
}
free(node_section_data) ;
return true ;
}
catch(read_error& e)
{
#ifdef DEBUG_DIRECTORY_STORAGE
std::cerr << "Error while reading: " << e.what() << std::endl;
#endif
return false;
}
return true ;
}
bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
{
buffer = 0 ;
uint32_t buffer_offset = 0 ;
unsigned char *tmp_section_data = (unsigned char*)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ;
if(!tmp_section_data)
return false;
uint32_t tmp_section_size = FL_BASE_TMP_SECTION_SIZE ;
try
{
// Write some header
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001)) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mFiles.size())) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mDirs.size())) throw std::runtime_error("Write error") ;
// Write all file/dir entries
for(uint32_t i=0;i<mFiles.size();++i)
{
const FileData& fe(mFiles[i]) ;
uint32_t file_section_offset = 0 ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,fe.name )) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,fe.size )) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,fe.hash )) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,tmp_section_data,file_section_offset)) throw std::runtime_error("Write error") ;
}
for(uint32_t i=0;i<mDirs.size();++i)
{
const DirData& de(mDirs[i]) ;
uint32_t dir_section_offset = 0 ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,de.name )) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs.size())) throw std::runtime_error("Write error") ;
for(uint32_t j=0;j<de.subdirs.size();++j)
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs[j])) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subfiles.size())) throw std::runtime_error("Write error") ;
for(uint32_t j=0;j<de.subfiles.size();++j)
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subfiles[j])) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,tmp_section_data,dir_section_offset)) throw std::runtime_error("Write error") ;
}
free(tmp_section_data) ;
buffer_size = buffer_offset;
return true ;
}
catch(std::exception& e)
{
std::cerr << "Error while writing: " << e.what() << std::endl;
if(buffer != NULL)
free(buffer) ;
if(tmp_section_data != NULL)
free(tmp_section_data) ;
return false;
}
}
void FileTreeImpl::print() const
{
std::cerr << "File hierarchy: name=" << mDirs[0].name << " size=" << mTotalSize << std::endl;
recurs_print(0," ") ;
}
void FileTreeImpl::recurs_print(uint32_t index,const std::string& indent) const
{
if(index >= mDirs.size())
{
std::cerr << "(EE) inconsistent FileTree structure" << std::endl;
return;
}
std::cerr << indent << mDirs[index].name << std::endl;
for(uint32_t i=0;i<mDirs[index].subdirs.size();++i)
recurs_print(mDirs[index].subdirs[i],indent+" ") ;
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
{
const FileData& fd(mFiles[mDirs[index].subfiles[i]]) ;
std::cerr << indent << " " << fd.hash << " " << std::setprecision(8) << fd.size << " " << fd.name << std::endl;
}
}

View File

@ -0,0 +1,33 @@
#include "retroshare/rsfiles.h"
class FileTreeImpl: public FileTree
{
public:
FileTreeImpl()
{
mTotalFiles = 0 ;
mTotalSize = 0 ;
}
virtual std::string toRadix64() const ;
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const ;
virtual void print() const ;
bool serialise(unsigned char *& data,uint32_t& data_size) const ;
bool deserialise(unsigned char* data, uint32_t data_size) ;
protected:
void recurs_print(uint32_t index,const std::string& indent) const;
static void recurs_buildFileTree(FileTreeImpl& ft, uint32_t index, const DirDetails& dd, bool remote, bool remove_top_dirs);
struct DirData {
std::string name;
std::vector<uint32_t> subdirs ;
std::vector<uint32_t> subfiles ;
};
std::vector<FileData> mFiles ;
std::vector<DirData> mDirs ;
friend class FileTree ;
};

View File

@ -22,12 +22,22 @@
* Please report all bugs and problems to "retroshare.project@gmail.com".
*
*/
#include <sstream>
#include "retroshare/rsids.h"
#include "pqi/authssl.h"
#include "util/rsdir.h"
#include "util/rsprint.h"
#include "serialiser/rsbaseserial.h"
#include "filelist_io.h"
FileListIO::read_error::read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag)
{
std::ostringstream s ;
s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl;
err_string = s.str();
}
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint32_t & val) { return setRawUInt32(buff,size,&offset,val) ; }
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint64_t & val) { return setRawUInt64(buff,size,&offset,val) ; }
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const std::string & val) { return setRawString(buff,size,&offset,val) ; }

View File

@ -36,6 +36,7 @@
// WARNING: the encoding is system-dependent, so this should *not* be used to exchange data between computers.
static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_STORAGE_VERSION_0001 = 0x00000001 ;
static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 = 0x00010001 ;
static const uint8_t FILE_LIST_IO_TAG_UNKNOWN = 0x00 ;
static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION = 0x01 ;
@ -65,6 +66,7 @@ static const uint8_t FILE_LIST_IO_TAG_RAW_NUMBER = 0x62 ;
static const uint32_t SECTION_HEADER_MAX_SIZE = 6 ; // section tag (1 byte) + size (max = 5 bytes)
class FileListIO
{
public:
@ -93,6 +95,18 @@ public:
return deserialise(buff,buff_size,offset,val);
}
class read_error
{
public:
read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag);
read_error(const std::string& s) : err_string(s) {}
const std::string& what() const { return err_string ; }
private:
std::string err_string ;
};
static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ;
static bool readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) ;

View File

@ -47,6 +47,7 @@ file_lists {
file_sharing/directory_updater.h \
file_sharing/rsfilelistitems.h \
file_sharing/dir_hierarchy.h \
file_sharing/file_tree.h \
file_sharing/file_sharing_defaults.h
SOURCES *= file_sharing/p3filelists.cc \
@ -55,6 +56,7 @@ file_lists {
file_sharing/directory_storage.cc \
file_sharing/directory_updater.cc \
file_sharing/dir_hierarchy.cc \
file_sharing/file_tree.cc \
file_sharing/rsfilelistitems.cc
}

View File

@ -134,6 +134,38 @@ struct SharedDirStats
uint64_t total_shared_size ;
};
// This class represents a tree of directories and files, only with their names size and hash. It is used to create collection links in the GUI
// and to transmit directory information between services. This class is independent from the existing FileHierarchy classes used in storage because
// we need a very copact serialization and storage size since we create links with it. Besides, we cannot afford to risk the leak of other local information
// by using the orignal classes.
class FileTree
{
public:
virtual ~FileTree() {}
static FileTree *create(const DirDetails& dd, bool remote, bool remove_top_dirs = true) ;
static FileTree *create(const std::string& radix64_string) ;
virtual std::string toRadix64() const =0 ;
// These methods allow the user to browse the hierarchy
struct FileData {
std::string name ;
uint64_t size ;
RsFileHash hash ;
};
virtual uint32_t root() const { return 0;}
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const = 0;
virtual void print() const=0;
uint32_t mTotalFiles ;
uint64_t mTotalSize ;
};
class RsFiles
{
public:

View File

@ -30,7 +30,7 @@
#include "gui/RetroShareLink.h"
#include "retroshare-gui/RsAutoUpdatePage.h"
#include "gui/msgs/MessageComposer.h"
#include "gui/common/RsCollectionFile.h"
#include "gui/common/RsCollection.h"
#include "gui/common/FilesDefs.h"
#include "gui/common/RsUrlHandler.h"
#include "gui/settings/rsharesettings.h"
@ -345,7 +345,7 @@ void SearchDialog::searchResultWidgetCustomPopupMenu( QPoint /*point*/ )
QList<QTreeWidgetItem*> item =ui.searchResultWidget->selectedItems() ;
if (item.at(0)->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool()) {
contextMnu.addAction(QIcon(IMAGE_OPENFOLDER), tr("Open Folder"), this, SLOT(openFolderSearch())) ;
if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollectionFile::ExtensionString)) {
if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollection::ExtensionString)) {
add_CollActions = true ;
}//if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollectionFile::ExtensionString))
}//if (item.at(0)->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool())
@ -448,7 +448,7 @@ void SearchDialog::collCreate()
}//if (!item->text(SR_HASH_COL).isEmpty())
}//for (int i = 0; i < numdls; ++i)
RsCollectionFile(dirVec).openNewColl(this);
RsCollection(dirVec).openNewColl(this);
}
void SearchDialog::collModif()
@ -476,8 +476,8 @@ void SearchDialog::collModif()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
@ -508,8 +508,8 @@ void SearchDialog::collView()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
@ -540,8 +540,8 @@ void SearchDialog::collOpen()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return;
@ -552,7 +552,7 @@ void SearchDialog::collOpen()
}
}
RsCollectionFile collection;
RsCollection collection;
if (collection.load(this)) {
collection.downloadFiles();
}//if (collection.load(this))

View File

@ -33,13 +33,15 @@
#include "SharedFilesDialog.h"
#include "gui/notifyqt.h"
#include "gui/MainWindow.h"
#include "gui/RemoteDirModel.h"
#include "gui/RetroShareLink.h"
#include "gui/ShareManager.h"
#include "gui/common/PeerDefs.h"
#include "gui/common/RsCollectionFile.h"
#include "gui/common/RsCollection.h"
#include "gui/msgs/MessageComposer.h"
#include "gui/settings/AddFileAssociationDialog.h"
#include "gui/gxschannels/GxsChannelDialog.h"
#include "gui/settings/rsharesettings.h"
#include "util/QtVersion.h"
#include "util/RsAction.h"
@ -61,6 +63,7 @@
#define IMAGE_OPENFOLDER ":/images/folderopen.png"
#define IMAGE_OPENFILE ":/images/fileopen.png"
#define IMAGE_LIBRARY ":/images/library.png"
#define IMAGE_CHANNEL ":/images/channels32.png"
#define IMAGE_COLLCREATE ":/images/library_add.png"
#define IMAGE_COLLMODIF ":/images/library_edit.png"
#define IMAGE_COLLVIEW ":/images/library_view.png"
@ -154,9 +157,6 @@ SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareD
connect(notify, SIGNAL(filesPreModChanged(bool)), this, SLOT(preModDirectories(bool)));
connect(notify, SIGNAL(filesPostModChanged(bool)), this, SLOT(postModDirectories(bool)));
//== connect(ui.localButton, SIGNAL(toggled(bool)), this, SLOT(showFrame(bool)));
//== connect(ui.remoteButton, SIGNAL(toggled(bool)), this, SLOT(showFrameRemote(bool)));
//== connect(ui.splittedButton, SIGNAL(toggled(bool)), this, SLOT(showFrameSplitted(bool)));
connect(ui.viewType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(changeCurrentViewModel(int)));
connect( ui.dirTreeView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( spawnCustomPopupMenu( QPoint ) ) );
@ -499,36 +499,24 @@ void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
QMenu contextMnu( this ) ;
//bool bIsRsColl = currentFile.endsWith(RsCollectionFile::ExtensionString);
collCreateAct->setEnabled(true);
//collModifAct->setEnabled(bIsRsColl);
//collViewAct->setEnabled(bIsRsColl);
collOpenAct->setEnabled(true);
QMenu collectionMenu(tr("Collection"), this);
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
collectionMenu.addAction(collCreateAct);
//collectionMenu.addAction(collModifAct);
//collectionMenu.addAction(collViewAct);
collectionMenu.addAction(collOpenAct);
QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), &contextMnu ) ;
connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ;
contextMnu.addAction( downloadAct) ;
if ( type == DIR_TYPE_FILE ) {
//QAction *copyremotelinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Link" ), &contextMnu ) ;
//connect( copyremotelinkAct , SIGNAL( triggered() ), this, SLOT( copyLink() ) ) ;
//QAction *sendremotelinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Link" ), &contextMnu ) ;
//connect( sendremotelinkAct , SIGNAL( triggered() ), this, SLOT( sendremoteLinkTo( ) ) ) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction( copylinkAct) ;
contextMnu.addAction( sendlinkAct) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(recommendFilesToMsg())) ;
}//if (type == DIR_TYPE_FILE)
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addMenu(&collectionMenu) ;
@ -542,7 +530,7 @@ QModelIndexList SharedFilesDialog::getSelected()
QModelIndexList proxyList ;
for (QModelIndexList::iterator index = list.begin(); index != list.end(); ++index ) {
proxyList.append(proxyModel->mapToSource(*index)) ;
}//for (QModelIndexList::iterator index
}
return proxyList ;
}
@ -567,15 +555,13 @@ void RemoteSharedFilesDialog::downloadRemoteSelected()
model -> downloadSelected(lst) ;
}
void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<RetroShareLink>& urls,bool& has_unhashed_files)
{
std::vector<DirDetails> dirVec;
model->getDirDetailsFromSelect(lst, dirVec);
QList<RetroShareLink> urls ;
bool has_unhashed_files = false;
has_unhashed_files = false;
for (int i = 0, n = dirVec.size(); i < n; ++i)
{
@ -583,28 +569,19 @@ void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
if (details.type == DIR_TYPE_DIR)
{
for(uint32_t j=0;j<details.children.size();++j)
{
const DirStub& dirStub = details.children[j];
FileTree *ft = FileTree::create(details,remote) ;
DirDetails details;
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
std::cerr << "Created collection file tree:" << std::endl;
ft->print();
// do not recursive copy sub dirs.
if (!rsFiles->RequestDirDetails(dirStub.ref, details, flags) || details.type != DIR_TYPE_FILE)
continue;
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
if(details.hash.isNull())
{
has_unhashed_files = true;
continue;
}
RetroShareLink link = RetroShareLink::createCollection(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ;
RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.toStdString().c_str());
if (link.valid()) {
if(link.valid())
urls.push_back(link) ;
}
}
delete ft ;
}
else
{
@ -619,10 +596,18 @@ void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
}
}
}
}
void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
{
QList<RetroShareLink> urls ;
bool has_unhashed_files = false;
copyLinks(lst,remote,urls,has_unhashed_files) ;
RSLinkClipboard::copyLinks(urls) ;
if(has_unhashed_files)
QMessageBox::warning(NULL,tr("Some files have been omitted"),tr("Some files have been omitted because their hash is not available yet.")) ;
QMessageBox::warning(NULL,tr("Some files have been omitted"),tr("Some files have been omitted because they have not been indexed yet.")) ;
}
void SharedFilesDialog::copyLink()
@ -692,11 +677,11 @@ void SharedFilesDialog::collModif()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
}
}
}
void SharedFilesDialog::collView()
@ -722,11 +707,11 @@ void SharedFilesDialog::collView()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
}
}
}
void SharedFilesDialog::collOpen()
@ -752,8 +737,8 @@ void SharedFilesDialog::collOpen()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return;
@ -763,10 +748,10 @@ void SharedFilesDialog::collOpen()
}
}
RsCollectionFile collection;
RsCollection collection;
if (collection.load(this)) {
collection.downloadFiles();
}//if (collection.load(this))
}
}
void LocalSharedFilesDialog::playselectedfiles()
@ -995,7 +980,7 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
QMenu contextMnu(this) ;
bool bIsRsColl = currentFile.endsWith(RsCollectionFile::ExtensionString);
bool bIsRsColl = currentFile.endsWith(RsCollection::ExtensionString);
collCreateAct->setEnabled(true);
collModifAct->setEnabled(bIsRsColl);
collViewAct->setEnabled(bIsRsColl);
@ -1011,6 +996,7 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
switch (type) {
case DIR_TYPE_DIR :
contextMnu.addAction(openfolderAct) ;
contextMnu.addAction(copylinkAct) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addMenu(&collectionMenu) ;
break ;
@ -1023,16 +1009,53 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addMenu(&collectionMenu) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(recommendFilesToMsg())) ;
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
break ;
default :
return ;
}//switch (type)
}
GxsChannelDialog *channelDialog = dynamic_cast<GxsChannelDialog*>(MainWindow::getPage(MainWindow::Channels));
if(channelDialog != NULL)
{
QMenu shareChannelMenu(tr("Share on channel...")) ;
shareChannelMenu.setIcon(QIcon(IMAGE_CHANNEL));
std::list<RsGroupMetaData> grp_metas ;
channelDialog->getGroupList(grp_metas) ;
for(auto it(grp_metas.begin());it!=grp_metas.end();++it)
if(IS_GROUP_PUBLISHER((*it).mSubscribeFlags))
shareChannelMenu.addAction(QString::fromUtf8((*it).mGroupName.c_str()), this, SLOT(shareOnChannel()))->setData(QString::fromStdString((*it).mGroupId.toStdString())) ;
contextMnu.addMenu(&shareChannelMenu) ;
contextMnu.exec(QCursor::pos()) ; // added here because the shareChannelMenu QMenu object is deleted afterwards
}
else
contextMnu.exec(QCursor::pos()) ;
}
void LocalSharedFilesDialog::shareOnChannel()
{
RsGxsGroupId groupId(qobject_cast<QAction*>(sender())->data().toString().toStdString());
GxsChannelDialog *channelDialog = dynamic_cast<GxsChannelDialog*>(MainWindow::getPage(MainWindow::Channels));
if(channelDialog == NULL)
return ;
std::list<DirDetails> files_info ;
QList<RetroShareLink> file_links_list ;
bool has_unhashed_files ;
copyLinks(getSelected(),false,file_links_list,has_unhashed_files) ;
channelDialog->shareOnChannel(groupId,file_links_list) ;
}
//============================================================================
QAction*

View File

@ -24,6 +24,7 @@
#include <set>
#include "RsAutoUpdatePage.h"
#include "gui/RetroShareLink.h"
#include "ui_SharedFilesDialog.h"
class RetroshareDirModel;
@ -68,10 +69,6 @@ private slots:
void collView();
void collOpen();
//== void showFrame(bool show);
//== void showFrameRemote(bool show);
//== void showFrameSplitted(bool show);
void recommendFilesToMsg();
void indicatorChanged(int index);
@ -103,6 +100,7 @@ protected:
//QMenu* contextMnu2;
void copyLinks(const QModelIndexList& lst, bool remote, QList<RetroShareLink>& urls, bool& has_unhashed_files);
void copyLink (const QModelIndexList& lst, bool remote);
void FilterItems();
@ -161,6 +159,7 @@ class LocalSharedFilesDialog : public SharedFilesDialog
void runCommandForFile();
void tryToAddNewAssotiation();
void forceCheck();
void shareOnChannel();
QAction* fileAssotiationAction(const QString fileName);

View File

@ -31,7 +31,7 @@
#include <QStandardItemModel>
#include <gui/common/FilesDefs.h>
#include <gui/common/RsCollectionFile.h>
#include <gui/common/RsCollection.h>
#include <gui/common/RsUrlHandler.h>
#include <gui/common/RSTreeView.h>
@ -50,7 +50,7 @@
#include "xprogressbar.h"
#include <gui/settings/rsharesettings.h>
#include "util/misc.h"
#include <gui/common/RsCollectionFile.h>
#include <gui/common/RsCollection.h>
#include "TransferUserNotify.h"
#include "util/QtVersion.h"
#include "util/RsFile.h"
@ -653,6 +653,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
QMenu contextMnu( this );
if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE)) add_PasteLink=true;
if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE_TREE)) add_PasteLink=true;
if(!items.empty())
{
@ -666,8 +667,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
//Look only for first column == File List
//Get Info for current item
if (rsFiles->FileDetails(fileHash
, RS_FILE_HINTS_DOWNLOAD, info)) {
if (rsFiles->FileDetails(fileHash, RS_FILE_HINTS_DOWNLOAD, info)) {
/*const uint32_t FT_STATE_FAILED = 0x0000;
*const uint32_t FT_STATE_OKAY = 0x0001;
*const uint32_t FT_STATE_WAITING = 0x0002;
@ -677,22 +677,21 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
*const uint32_t FT_STATE_PAUSED = 0x0006;
*const uint32_t FT_STATE_CHECKING_HASH = 0x0007;
*/
if (info.downloadStatus == FT_STATE_WAITING) {
if (info.downloadStatus == FT_STATE_WAITING)
atLeastOne_Waiting = true ;
}//if (info.downloadStatus == FT_STATE_WAITING)
if (info.downloadStatus == FT_STATE_DOWNLOADING) {
if (info.downloadStatus == FT_STATE_DOWNLOADING)
atLeastOne_Downloading=true ;
}//if (info.downloadStatus == FT_STATE_DOWNLOADING)
if (info.downloadStatus == FT_STATE_COMPLETE) {
atLeastOne_Complete = true ;
add_OpenFileOption = single ;
}//if (info.downloadStatus == FT_STATE_COMPLETE)
if (info.downloadStatus == FT_STATE_QUEUED) {
}
if (info.downloadStatus == FT_STATE_QUEUED)
atLeastOne_Queued = true ;
}//if(info.downloadStatus == FT_STATE_QUEUED)
if (info.downloadStatus == FT_STATE_PAUSED) {
if (info.downloadStatus == FT_STATE_PAUSED)
atLeastOne_Paused = true ;
}//if (info.downloadStatus == FT_STATE_PAUSED)
size_t pos = info.fname.find_last_of('.') ;
if (pos != std::string::npos) {
@ -700,23 +699,23 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
if (misc::isPreviewable(info.fname.substr(pos + 1).c_str())) {
add_PreviewOption = (info.downloadStatus != FT_STATE_COMPLETE) ;
add_PlayOption = !add_PreviewOption ;
}// if (misc::isPreviewable(info.fname.substr(pos + 1).c_str()))
}
// Check if the file is a collection
if (RsCollectionFile::ExtensionString == info.fname.substr(pos + 1).c_str()) {
if (RsCollection::ExtensionString == info.fname.substr(pos + 1).c_str()) {
add_CollActions = (info.downloadStatus == FT_STATE_COMPLETE);
}//if (RsCollectionFile::ExtensionString == info
}// if(pos != std::string::npos)
}
}
}// if FileDetails
}// for items iterate
}// if (!items.empty())
}
}
}
if (atLeastOne_Waiting || atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Paused) {
contextMnu.addMenu( &prioritySpeedMenu) ;
}
if (atLeastOne_Queued) {
contextMnu.addMenu( &priorityQueueMenu) ;
}//if (atLeastOne_Queued)
}
if ( (!items.empty())
&& (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting || atLeastOne_Paused)) {
@ -724,7 +723,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
if (single) {
contextMnu.addAction( renameFileAct) ;
}//if (single)
}
QMenu *directoryMenu = contextMnu.addMenu(QIcon(IMAGE_OPENFOLDER), tr("Set destination directory")) ;
directoryMenu->addAction(specifyDestinationDirectoryAct) ;
@ -745,27 +744,24 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
act->setData(QString::fromUtf8( (*it).filename.c_str() ) ) ;
connect(act, SIGNAL(triggered()), this, SLOT(setDestinationDirectory())) ;
directoryMenu->addAction( act) ;
}//for (std::list<SharedDirInfo>::const_iterator it
}//if ( (!items.empty()) &&
}
}
if (atLeastOne_Paused) {
if (atLeastOne_Paused)
contextMnu.addAction(resumeAct) ;
}//if (atLeastOne_Paused)
if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting) {
if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting)
contextMnu.addAction(pauseAct) ;
}//if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting)
if (!atLeastOne_Complete && !items.empty()) {
contextMnu.addAction(forceCheckAct) ;
contextMnu.addAction(cancelAct) ;
}//if (!atLeastOne_Complete && !items.empty())
if (add_PlayOption) {
}
if (add_PlayOption)
contextMnu.addAction(playAct) ;
}//if (add_PlayOption)
if (atLeastOne_Paused || atLeastOne_Downloading || atLeastOne_Complete || add_PlayOption) {
contextMnu.addSeparator() ;//------------------------------------------------
}//if (atLeastOne_Paused ||
if (atLeastOne_Paused || atLeastOne_Downloading || atLeastOne_Complete || add_PlayOption)
contextMnu.addSeparator() ;
if (single) {
if (add_OpenFileOption) contextMnu.addAction( openFileAct) ;
@ -773,20 +769,20 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
contextMnu.addAction( openFolderAct) ;
contextMnu.addAction( detailsFileAct) ;
contextMnu.addSeparator() ;//--------------------------------------------
}//if (single)
}
contextMnu.addAction( clearCompletedAct) ;
contextMnu.addSeparator() ;//------------------------------------------------
contextMnu.addSeparator() ;
if (add_CopyLink) {
contextMnu.addAction( copyLinkAct) ;
}//if (add_CopyLink)
}
if (add_PasteLink) {
contextMnu.addAction( pasteLinkAct) ;
}//if (add_PasteLink)
}
if (add_CopyLink || add_PasteLink) {
contextMnu.addSeparator() ;//--------------------------------------------
}//if (add_CopyLink || add_PasteLink)
contextMnu.addSeparator() ;
}
if (DLLFilterModel->rowCount()>0 ) {
contextMnu.addAction( expandAllDLAct ) ;
@ -1644,7 +1640,27 @@ void TransfersDialog::updateDetailsDialog()
void TransfersDialog::pasteLink()
{
RSLinkClipboard::process(RetroShareLink::TYPE_FILE);
QList<RetroShareLink> links ;
// We want to capture and process all links at once here, because we're possibly pasting a large collection of files. So we first
// merge all links into a single RsCollection and then process it.
RsCollection col ;
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE_TREE);
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
{
FileTree *ft = FileTree::create((*it).radix().toStdString()) ;
col.merge_in(*ft) ;
}
links.clear();
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE);
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
col.merge_in((*it).name(),(*it).size(),RsFileHash((*it).hash().toStdString())) ;
col.downloadFiles();
}
void TransfersDialog::getDLSelectedItems(std::set<RsFileHash> *ids, std::set<int> *rows)
@ -2155,7 +2171,7 @@ void TransfersDialog::collCreate()
dirVec.push_back(details);
}//for (it = items.begin();
RsCollectionFile(dirVec).openNewColl(this);
RsCollection(dirVec).openNewColl(this);
}
void TransfersDialog::collModif()
@ -2180,12 +2196,12 @@ void TransfersDialog::collModif()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
}//if (info.downloadStatus == FT_STATE_COMPLETE)
}
}
}
}
void TransfersDialog::collView()
@ -2210,12 +2226,12 @@ void TransfersDialog::collView()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
}//if (info.downloadStatus == FT_STATE_COMPLETE)
}
}
}
}
void TransfersDialog::collOpen()
@ -2240,8 +2256,8 @@ void TransfersDialog::collOpen()
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return;
@ -2252,95 +2268,24 @@ void TransfersDialog::collOpen()
}
}
RsCollectionFile collection;
RsCollection collection;
if (collection.load(this)) {
collection.downloadFiles();
}//if (collection.load(this))
}
void TransfersDialog::setShowDLSizeColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_SIZE)) != show) {
ui.downloadList->setColumnHidden(COLUMN_SIZE, !show);
}
}
void TransfersDialog::setShowDLCompleteColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_COMPLETED)) != show) {
ui.downloadList->setColumnHidden(COLUMN_COMPLETED, !show);
}
}
void TransfersDialog::setShowDLDLSpeedColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_DLSPEED)) != show) {
ui.downloadList->setColumnHidden(COLUMN_DLSPEED, !show);
}
}
void TransfersDialog::setShowDLProgressColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_PROGRESS)) != show) {
ui.downloadList->setColumnHidden(COLUMN_PROGRESS, !show);
}
}
void TransfersDialog::setShowDLSourcesColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_SOURCES)) != show) {
ui.downloadList->setColumnHidden(COLUMN_SOURCES, !show);
}
}
void TransfersDialog::setShowDLStatusColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_STATUS)) != show) {
ui.downloadList->setColumnHidden(COLUMN_STATUS, !show);
}
}
void TransfersDialog::setShowDLPriorityColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_PRIORITY)) != show) {
ui.downloadList->setColumnHidden(COLUMN_PRIORITY, !show);
}
}
void TransfersDialog::setShowDLRemainingColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_REMAINING)) != show) {
ui.downloadList->setColumnHidden(COLUMN_REMAINING, !show);
}
}
void TransfersDialog::setShowDLDownloadTimeColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_DOWNLOADTIME)) != show) {
ui.downloadList->setColumnHidden(COLUMN_DOWNLOADTIME, !show);
}
}
void TransfersDialog::setShowDLIDColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_ID)) != show) {
ui.downloadList->setColumnHidden(COLUMN_ID, !show);
}
}
void TransfersDialog::setShowDLLastDLColumn(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_LASTDL)) != show) {
ui.downloadList->setColumnHidden(COLUMN_LASTDL, !show);
}
}
void TransfersDialog::setShowDLPath(bool show)
{
if ( (!ui.downloadList->isColumnHidden(COLUMN_PATH)) != show) {
ui.downloadList->setColumnHidden(COLUMN_PATH, !show);
}
}
void TransfersDialog::setShowDLSizeColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SIZE, !show); }
void TransfersDialog::setShowDLCompleteColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_COMPLETED, !show); }
void TransfersDialog::setShowDLDLSpeedColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_DLSPEED, !show); }
void TransfersDialog::setShowDLProgressColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PROGRESS, !show); }
void TransfersDialog::setShowDLSourcesColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SOURCES, !show); }
void TransfersDialog::setShowDLStatusColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_STATUS, !show); }
void TransfersDialog::setShowDLPriorityColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PRIORITY, !show); }
void TransfersDialog::setShowDLRemainingColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_REMAINING, !show); }
void TransfersDialog::setShowDLDownloadTimeColumn(bool show) { ui.downloadList->setColumnHidden(COLUMN_DOWNLOADTIME, !show); }
void TransfersDialog::setShowDLIDColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_ID, !show); }
void TransfersDialog::setShowDLLastDLColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_LASTDL, !show); }
void TransfersDialog::setShowDLPath (bool show) { ui.downloadList->setColumnHidden(COLUMN_PATH, !show); }
void TransfersDialog::expandAllDL()
{

View File

@ -103,7 +103,7 @@
#include "gui/statistics/StatisticsWindow.h"
#include "gui/connect/ConnectFriendWizard.h"
#include "gui/common/RsCollectionFile.h"
#include "gui/common/RsCollection.h"
#include "settings/rsettingswin.h"
#include "settings/rsharesettings.h"
#include "settings/WebuiPage.h"
@ -1031,7 +1031,7 @@ void MainWindow::newRsCollection()
{
std::vector <DirDetails> dirVec;
RsCollectionFile(dirVec).openNewColl(this);
RsCollection(dirVec).openNewColl(this);
}
/** Shows Share Manager */
@ -1459,8 +1459,8 @@ void MainWindow::openRsCollection(const QString &filename)
{
QFileInfo qinfo(filename);
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
RsCollectionFile collection;
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}
}

View File

@ -26,7 +26,7 @@
#include <QTimer>
#include <retroshare-gui/RsAutoUpdatePage.h>
#include <gui/common/RsCollectionFile.h>
#include <gui/common/RsCollection.h>
#include <gui/common/RsUrlHandler.h>
#include <gui/common/FilesDefs.h>
#include <gui/common/GroupDefs.h>
@ -1065,7 +1065,7 @@ void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndex
std::vector <DirDetails> dirVec;
getDirDetailsFromSelect(list, dirVec);
RsCollectionFile(dirVec).openNewColl(parent);
RsCollection(dirVec).openNewColl(parent);
}
void RetroshareDirModel::downloadSelected(const QModelIndexList &list)

View File

@ -43,7 +43,7 @@
#include "msgs/MessageComposer.h"
#include "util/misc.h"
#include "common/PeerDefs.h"
#include "common/RsCollectionFile.h"
#include "common/RsCollection.h"
#include <gui/common/RsUrlHandler.h>
#include "gui/connect/ConnectFriendWizard.h"
#include "gui/connect/ConfCertDialog.h"
@ -58,6 +58,7 @@
//#define DEBUG_RSLINK 1
#define HOST_FILE "file"
#define HOST_COLLECTION "collection"
#define HOST_EXTRAFILE "extra"
#define HOST_PERSON "person"
#define HOST_FORUM "forum"
@ -68,13 +69,18 @@
#define HOST_CERTIFICATE "certificate"
#define HOST_PUBLIC_MSG "public_msg"
#define HOST_IDENTITY "identity"
#define HOST_REGEXP "file|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg|identity"
#define HOST_REGEXP "file|collection|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg|identity"
#define FILE_NAME "name"
#define FILE_SIZE "size"
#define FILE_HASH "hash"
#define FILE_SOURCE "src"
#define COLLECTION_NAME "name"
#define COLLECTION_SIZE "size"
#define COLLECTION_DATA "radix"
#define COLLECTION_COUNT "files"
#define PERSON_NAME "name"
#define PERSON_HASH "hash"
@ -328,6 +334,20 @@ void RetroShareLink::fromUrl(const QUrl& url)
return;
}
if (url.host() == HOST_COLLECTION) {
bool ok;
_type = TYPE_FILE_TREE;
_radix = decodedQueryItemValue(urlQuery, COLLECTION_DATA);
_name = decodedQueryItemValue(urlQuery, COLLECTION_NAME);
_size = urlQuery.queryItemValue(COLLECTION_SIZE).toULongLong(&ok);
_count = urlQuery.queryItemValue(COLLECTION_COUNT).toULongLong(&ok);
#ifdef DEBUG_RSLINK
std::cerr << "Got a certificate link!!" << std::endl;
#endif
check() ;
return;
}
if (url.host() == HOST_CERTIFICATE) {
_type = TYPE_CERTIFICATE;
_radix = decodedQueryItemValue(urlQuery, CERTIFICATE_RADIX);
@ -400,6 +420,21 @@ RetroShareLink RetroShareLink::createFile(const QString& name, uint64_t size, co
return link;
}
RetroShareLink RetroShareLink::createCollection(const QString& name, uint64_t size, uint32_t count, const QString& radix_data)
{
RetroShareLink link;
link.clear();
link._name = name;
link._count = count;
link._size = size;
link._radix = radix_data ;
link._type = TYPE_FILE_TREE;
link.check();
return link;
}
RetroShareLink RetroShareLink::createPublicMsgInvite(time_t time_stamp,const QString& issuer_pgp_id,const QString& hash)
{
RetroShareLink link;
@ -608,6 +643,8 @@ void RetroShareLink::check()
if(!checkSSLId(_SSLid))
_valid = false; // no break! We also test file stuff below.
/* fallthrough */
case TYPE_FILE_TREE:
case TYPE_FILE:
if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files?
_valid = false;
@ -615,7 +652,7 @@ void RetroShareLink::check()
if(!checkName(_name))
_valid = false;
if(!checkHash(_hash))
if(!checkRadix64(_radix))
_valid = false;
break;
@ -717,6 +754,8 @@ QString RetroShareLink::title() const
rsPeers->getGPGDetails(RsPgpId(_GPGid.toStdString()), detail) ;
return QObject::tr("Click to send a private message to %1 (%2).").arg(QString::fromUtf8(detail.name.c_str())).arg(_GPGid) ;
}
case TYPE_FILE_TREE:
return QObject::tr("Click to browse/download this file collection");
case TYPE_EXTRAFILE:
return QObject::tr("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size()));
case TYPE_FILE:
@ -860,6 +899,15 @@ QString RetroShareLink::toString() const
break;
case TYPE_FILE_TREE:
url.setScheme(RSLINK_SCHEME);
url.setHost(HOST_COLLECTION) ;
urlQuery.addQueryItem(COLLECTION_NAME, encodeItem(_name));
urlQuery.addQueryItem(COLLECTION_SIZE, QString::number(_size));
urlQuery.addQueryItem(COLLECTION_DATA, encodeItem(_radix));
urlQuery.addQueryItem(COLLECTION_COUNT, QString::number(_count));
break;
case TYPE_CERTIFICATE:
url.setScheme(RSLINK_SCHEME);
url.setHost(HOST_CERTIFICATE) ;
@ -882,9 +930,15 @@ QString RetroShareLink::niceName() const
if (type() == TYPE_PERSON)
return PeerDefs::rsid(name().toUtf8().constData(), RsPgpId(hash().toStdString()));
if(type() == TYPE_FILE_TREE)
return QObject::tr("%1 (%2 files, %3)").arg(_name).arg(_count).arg(misc::friendlyUnit(_size));
if(type() == TYPE_IDENTITY)
return QObject::tr("Identity link (name=%1, ID=%2)").arg(_name).arg(_hash) ;
if(type() == TYPE_FILE_TREE)
return QObject::tr("File directory (Total %s) Click to browse/download this file collection").arg(misc::friendlyUnit(_size));
if(type() == TYPE_PUBLIC_MSG) {
RsPeerDetails detail;
rsPeers->getGPGDetails(RsPgpId(_GPGid.toStdString()), detail) ;
@ -926,10 +980,10 @@ QString RetroShareLink::toHtmlSize() const
{
QString size = QString("(%1)").arg(misc::friendlyUnit(_size));
if (type() == TYPE_FILE && RsCollectionFile::isCollectionFile(name())) {
if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) {
FileInfo finfo;
if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) {
RsCollectionFile collection;
RsCollection collection;
if (collection.load(QString::fromUtf8(finfo.path.c_str()), false)) {
size += QString(" [%1]").arg(misc::friendlyUnit(collection.size()));
}
@ -1095,6 +1149,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
case TYPE_SEARCH:
case TYPE_MESSAGE:
case TYPE_IDENTITY:
case TYPE_FILE_TREE:
case TYPE_CERTIFICATE:
case TYPE_PUBLIC_MSG:
case TYPE_PRIVATE_CHAT:
@ -1336,6 +1391,16 @@ static void processList(const QStringList &list, const QString &textSingular, co
}
break;
case TYPE_FILE_TREE:
{
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
RsCollection(*ft).downloadFiles() ;
delete ft;
}
break;
case TYPE_PERSON:
{
#ifdef DEBUG_RSLINK
@ -1347,34 +1412,6 @@ static void processList(const QStringList &list, const QString &textSingular, co
PGPKeyDialog::showIt(detail.gpg_id,PGPKeyDialog::PageDetails) ;
else
personNotFound.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
// needNotifySuccess = true;
// RsPeerDetails detail;
// if (rsPeers->getGPGDetails(RsPgpId(link.hash().toStdString()), detail))
// {
// if (RsPgpId(detail.gpg_id) == rsPeers->getGPGOwnId()) {
// // it's me, do nothing
// break;
// }
//
// if (detail.accept_connection) {
// // peer connection is already accepted
// personExist.append(PeerDefs::rsid(detail));
// break;
// }
//
// if (rsPeers->addFriend(RsPeerId(), RsPgpId(link.hash().toStdString()))) {
// ConfCertDialog::loadAll();
// personAdded.append(PeerDefs::rsid(detail));
// break;
// }
//
// personFailed.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
// break;
// }
//
// personNotFound.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
}
break;
@ -1679,17 +1716,17 @@ void RSLinkClipboard::copyLinks(const QList<RetroShareLink>& links)
QApplication::clipboard()->setText(res) ;
}
void RSLinkClipboard::pasteLinks(QList<RetroShareLink> &links)
void RSLinkClipboard::pasteLinks(QList<RetroShareLink> &links,RetroShareLink::enumType type)
{
return parseClipboard(links);
return parseClipboard(links,type);
}
void RSLinkClipboard::parseClipboard(QList<RetroShareLink> &links)
void RSLinkClipboard::parseClipboard(QList<RetroShareLink> &links,RetroShareLink::enumType type)
{
// parse clipboard for links.
//
QString text = QApplication::clipboard()->text() ;
parseText(text, links);
parseText(text, links,type);
}
QString RSLinkClipboard::toString()
@ -1734,26 +1771,18 @@ bool RSLinkClipboard::empty(RetroShareLink::enumType type /* = RetroShareLink::T
return true;
}
/*static*/ int RSLinkClipboard::process(RetroShareLink::enumType type /* = RetroShareLink::TYPE_UNKNOWN*/, uint flag /* = RSLINK_PROCESS_NOTIFY_ALL*/)
int RSLinkClipboard::process(RetroShareLink::enumType type /* = RetroShareLink::TYPE_UNKNOWN*/, uint flag /* = RSLINK_PROCESS_NOTIFY_ALL*/)
{
QList<RetroShareLink> links;
pasteLinks(links);
pasteLinks(links,type);
QList<RetroShareLink> linksToProcess;
for (int i = 0; i < links.size(); ++i) {
if (links[i].valid() && (type == RetroShareLink::TYPE_UNKNOWN || links[i].type() == type)) {
linksToProcess.append(links[i]);
}
}
if (linksToProcess.isEmpty()) {
if (links.isEmpty())
return 0;
}
return RetroShareLink::process(linksToProcess, flag);
return RetroShareLink::process(links, flag);
}
void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links)
void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links,RetroShareLink::enumType type )
{
links.clear();
@ -1768,7 +1797,7 @@ void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links)
QString url(text.mid(pos, rx.matchedLength()));
RetroShareLink link(url);
if(link.valid())
if(link.valid() && (type == RetroShareLink::TYPE_UNKNOWN || type == link.type()))
{
// check that the link is not already in the list:
bool already = false ;

View File

@ -69,7 +69,8 @@ class RetroShareLink
TYPE_PRIVATE_CHAT = 0x09,
TYPE_PUBLIC_MSG = 0x0a,
TYPE_POSTED = 0x0b,
TYPE_IDENTITY = 0x0c
TYPE_IDENTITY = 0x0c,
TYPE_FILE_TREE = 0x0d
};
public:
@ -80,6 +81,7 @@ class RetroShareLink
static RetroShareLink createIdentity(const RsGxsId& gxs_id,const QString& name,const QString& radix_data) ;
static RetroShareLink createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id);
static RetroShareLink createFile(const QString& name, uint64_t size, const QString& hash);
static RetroShareLink createCollection(const QString& name, uint64_t size,uint32_t count,const QString& radix_data);
static RetroShareLink createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ;
static RetroShareLink createPerson(const RsPgpId &id);
static RetroShareLink createCertificate(const RsPeerId &ssl_id) ;
@ -167,6 +169,7 @@ class RetroShareLink
QString _encrypted_chat_info ; // encrypted data string for the recipient of a chat invite
time_t _time_stamp ; // time stamp at which the link will expire.
QString _radix_group_data;
uint32_t _count ;
unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...)
};
@ -189,7 +192,7 @@ class RSLinkClipboard
// Get the liste of pasted links, either from the internal RS links, or by default
// from the clipboard.
//
static void pasteLinks(QList<RetroShareLink> &links) ;
static void pasteLinks(QList<RetroShareLink> &links,RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
// Produces a list of links with no html structure.
static QString toString() ;
@ -212,10 +215,10 @@ class RSLinkClipboard
//
static int process(RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN, uint flag = RSLINK_PROCESS_NOTIFY_ALL);
static void parseText(QString text, QList<RetroShareLink> &links) ;
static void parseText(QString text, QList<RetroShareLink> &links, RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
private:
static void parseClipboard(QList<RetroShareLink> &links) ;
static void parseClipboard(QList<RetroShareLink> &links, RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
};
#endif

View File

@ -23,7 +23,7 @@
#include <QFileInfo>
#include "FilesDefs.h"
#include "RsCollectionFile.h"
#include "RsCollection.h"
static QString getInfoFromFilename(const QString& filename, bool anyForUnknown, bool image)
{
@ -54,7 +54,7 @@ static QString getInfoFromFilename(const QString& filename, bool anyForUnknown,
return image ? ":/images/FileTypeDocument.png" : QApplication::translate("FilesDefs", "Document");
} else if (ext == "pdf") {
return image ? ":/images/mimetypes/pdf.png" : QApplication::translate("FilesDefs", "Document");
} else if (ext == RsCollectionFile::ExtensionString) {
} else if (ext == RsCollection::ExtensionString) {
return image ? ":/images/mimetypes/rscollection-16.png" : QApplication::translate("FilesDefs", "RetroShare collection file");
} else if (ext == "sub" || ext == "srt") {
return image ? ":/images/FileTypeAny.png" : QApplication::translate("FilesDefs", "Subtitles");

View File

@ -24,7 +24,7 @@
#include <stdexcept>
#include <retroshare/rsfiles.h>
#include "RsCollectionFile.h"
#include "RsCollection.h"
#include "RsCollectionDialog.h"
#include "util/misc.h"
@ -36,28 +36,41 @@
#include <QMessageBox>
#include <QIcon>
const QString RsCollectionFile::ExtensionString = QString("rscollection") ;
// #define COLLECTION_DEBUG 1
RsCollectionFile::RsCollectionFile(QObject *parent)
const QString RsCollection::ExtensionString = QString("rscollection") ;
RsCollection::RsCollection(QObject *parent)
: QObject(parent), _xml_doc("RsCollection")
{
_root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(_root);
}
RsCollectionFile::RsCollectionFile(const std::vector<DirDetails>& file_infos, QObject *parent)
RsCollection::RsCollection(const FileTree& fr)
: _xml_doc("RsCollection")
{
_root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(_root);
recursAddElements(_xml_doc,fr,0,_root) ;
}
RsCollection::RsCollection(const std::vector<DirDetails>& file_infos, QObject *parent)
: QObject(parent), _xml_doc("RsCollection")
{
QDomElement root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(root);
_root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(_root);
for(uint32_t i = 0;i<file_infos.size();++i)
recursAddElements(_xml_doc,file_infos[i],root) ;
recursAddElements(_xml_doc,file_infos[i],_root) ;
}
RsCollectionFile::~RsCollectionFile()
RsCollection::~RsCollection()
{
}
void RsCollectionFile::downloadFiles() const
void RsCollection::downloadFiles() const
{
// print out the element names of all elements that are direct children
// of the outermost element.
@ -87,17 +100,35 @@ static QString purifyFileName(const QString& input,bool& bad)
return output ;
}
void RsCollectionFile::recursCollectColFileInfos(const QDomElement& e,std::vector<ColFileInfo>& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const
void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash)
{
ColFileInfo info ;
info.type = DIR_TYPE_FILE ;
info.name = fname ;
info.size = size ;
info.hash = QString::fromStdString(hash.toStdString()) ;
recursAddElements(_xml_doc,info,_root) ;
}
void RsCollection::merge_in(const FileTree& tree)
{
recursAddElements(_xml_doc,tree,0,_root) ;
}
void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector<ColFileInfo>& 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"))
{
@ -139,7 +170,7 @@ void RsCollectionFile::recursCollectColFileInfos(const QDomElement& e,std::vecto
}
void RsCollectionFile::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e) const
void RsCollection::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e) const
{
if (details.type == DIR_TYPE_FILE)
{
@ -175,7 +206,7 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const DirDetails& det
}
}
void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const
void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const
{
if (colFileInfo.type == DIR_TYPE_FILE)
{
@ -186,7 +217,7 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& co
f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ;
e.appendChild(f) ;
}
}
else if (colFileInfo.type == DIR_TYPE_DIR)
{
QDomElement d = doc.createElement("Directory") ;
@ -194,21 +225,47 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& co
d.setAttribute(QString("name"),colFileInfo.name) ;
for (std::vector<ColFileInfo>::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it)
{
recursAddElements(doc,(*it),d) ;
}
e.appendChild(d) ;
}
}
void RsCollection::recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const
{
std::vector<uint32_t> subdirs ;
std::vector<FileTree::FileData> subfiles ;
std::string name;
if(!ft.getDirectoryContent(index,name,subdirs,subfiles))
return ;
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ;
e.appendChild(d) ;
for (uint32_t i=0;i<subdirs.size();++i)
recursAddElements(doc,ft,subdirs[i],d) ;
for(uint32_t i=0;i<subfiles.size();++i)
{
QDomElement f = doc.createElement("File") ;
f.setAttribute(QString("name"),QString::fromUtf8(subfiles[i].name.c_str())) ;
f.setAttribute(QString("sha1"),QString::fromStdString(subfiles[i].hash.toStdString())) ;
f.setAttribute(QString("size"),QString::number(subfiles[i].size)) ;
d.appendChild(f) ;
}
}
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();
}
bool RsCollectionFile::load(const QString& fileName, bool showError /* = true*/)
bool RsCollection::load(const QString& fileName, bool showError /* = true*/)
{
if (!checkFile(fileName,showError)) return false;
@ -235,10 +292,10 @@ bool RsCollectionFile::load(const QString& fileName, bool showError /* = true*/)
}
return ok;
}
}
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this
bool RsCollectionFile::checkFile(const QString& fileName, bool showError)
bool RsCollection::checkFile(const QString& fileName, bool showError)
{
QFile file(fileName);
@ -305,11 +362,10 @@ bool RsCollectionFile::checkFile(const QString& fileName, bool showError)
}
return false;
}
bool RsCollectionFile::load(QWidget *parent)
bool RsCollection::load(QWidget *parent)
{
QString fileName;
if (!misc::getOpenFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")", fileName))
if (!misc::getOpenFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
return false;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
@ -317,7 +373,7 @@ bool RsCollectionFile::load(QWidget *parent)
return load(fileName, true);
}
bool RsCollectionFile::save(const QString& fileName) const
bool RsCollection::save(const QString& fileName) const
{
QFile file(fileName);
@ -337,14 +393,14 @@ bool RsCollectionFile::save(const QString& fileName) const
return true;
}
bool RsCollectionFile::save(QWidget *parent) const
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") + " (*." + RsCollectionFile::ExtensionString + ")", 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("." + RsCollectionFile::ExtensionString))
fileName += "." + RsCollectionFile::ExtensionString ;
if (!fileName.endsWith("." + RsCollection::ExtensionString))
fileName += "." + RsCollection::ExtensionString ;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
@ -352,17 +408,17 @@ bool RsCollectionFile::save(QWidget *parent) const
}
bool RsCollectionFile::openNewColl(QWidget *parent)
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") + " (*." + RsCollectionFile::ExtensionString + ")"
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")"
, fileName,0, QFileDialog::DontConfirmOverwrite))
return false;
if (!fileName.endsWith("." + RsCollectionFile::ExtensionString))
fileName += "." + RsCollectionFile::ExtensionString ;
if (!fileName.endsWith("." + RsCollection::ExtensionString))
fileName += "." + RsCollection::ExtensionString ;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
@ -419,7 +475,7 @@ bool RsCollectionFile::openNewColl(QWidget *parent)
return _saved;
}
bool RsCollectionFile::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/)
bool RsCollection::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/)
{
if (load(fileName, showError)) {
std::vector<ColFileInfo> colFileInfos ;
@ -433,11 +489,11 @@ bool RsCollectionFile::openColl(const QString& fileName, bool readOnly /* = fals
delete rcd;
return _saved;
}//if (load(fileName, showError))
}
return false;
}
qulonglong RsCollectionFile::size()
qulonglong RsCollection::size()
{
QDomElement docElem = _xml_doc.documentElement();
@ -453,14 +509,14 @@ qulonglong RsCollectionFile::size()
return size;
}
bool RsCollectionFile::isCollectionFile(const QString &fileName)
bool RsCollection::isCollectionFile(const QString &fileName)
{
QString ext = QFileInfo(fileName).suffix().toLower();
return (ext == RsCollectionFile::ExtensionString);
return (ext == RsCollection::ExtensionString);
}
void RsCollectionFile::saveColl(std::vector<ColFileInfo> colFileInfos, const QString &fileName)
void RsCollection::saveColl(std::vector<ColFileInfo> colFileInfos, const QString &fileName)
{
QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement();

View File

@ -56,21 +56,23 @@ public:
};
Q_DECLARE_METATYPE(ColFileInfo)
class RsCollectionFile : public QObject
class RsCollection : public QObject
{
Q_OBJECT
public:
RsCollectionFile(QObject *parent = 0) ;
RsCollection(QObject *parent = 0) ;
// create from list of files and directories
RsCollectionFile(const std::vector<DirDetails>& file_entries, QObject *parent = 0) ;
virtual ~RsCollectionFile() ;
RsCollection(const std::vector<DirDetails>& file_entries, QObject *parent = 0) ;
RsCollection(const FileTree& fr);
virtual ~RsCollection() ;
void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ;
void merge_in(const FileTree& tree) ;
static const QString ExtensionString ;
// Loads file from disk.
bool load(QWidget *parent);
bool load(const QString& fileName, bool showError = true);
@ -94,10 +96,12 @@ public:
private slots:
void saveColl(std::vector<ColFileInfo> colFileInfos, const QString& fileName);
private:
private:
void recursAddElements(QDomDocument&,const DirDetails&,QDomElement&) const ;
void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const;
void recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const;
void recursCollectColFileInfos(const QDomElement&,std::vector<ColFileInfo>& 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
static bool checkFile(const QString &fileName, bool showError);
@ -105,6 +109,7 @@ private slots:
QDomDocument _xml_doc ;
QString _fileName ;
bool _saved;
QDomElement _root ;
friend class RsCollectionDialog ;
};

View File

@ -23,13 +23,14 @@
#include <QCheckBox>
#include <QMessageBox>
#include <QMenu>
#include <QTextEdit>
#include <QDir>
#include <QKeyEvent>
#include <QDateTime>
#include <QInputDialog>
#include "RsCollectionDialog.h"
#include "RsCollectionFile.h"
#include "RsCollection.h"
#include "util/misc.h"
#define COLUMN_FILE 0
#define COLUMN_FILEPATH 1
@ -50,6 +51,7 @@
#define MAX_FILE_ADDED_BEFORE_ASK 500 //Number of file added in Recursive mode before asking to continue
#define IMAGE_SEARCH ":/icons/svg/magnifying-glass.svg"
/**
* @brief The FSMSortFilterProxyModel class sort directory before file.
@ -138,7 +140,23 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
ui.headerFrame->setHeaderImage(QPixmap(":/images/library64.png"));
if(creation)
{
ui.headerFrame->setHeaderText(tr("Collection Editor"));
ui.downloadFolder_LE->hide();
ui.downloadFolder_LB->hide();
}
else
{
ui.headerFrame->setHeaderText(tr("Download files"));
ui.downloadFolder_LE->show();
ui.downloadFolder_LB->show();
ui.downloadFolder_LE->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str())) ;
QObject::connect(ui.downloadFolder_LE,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(openDestinationDirectoryMenu(QPoint)));
}
// 1 - add all elements to the list.
@ -209,6 +227,46 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
QMessageBox::warning(NULL,tr("Bad filenames have been cleaned"),tr("Some filenames or directory names contained forbidden characters.\nCharacters <b>\",|,/,\\,&lt;,&gt;,*,?</b> will be replaced by '_'.\n Concerned files are listed in red.")) ;
}
void RsCollectionDialog::openDestinationDirectoryMenu(QPoint)
{
QMenu contextMnu( this );
// pop a menu with existing entries and also a custom entry
// Now get the list of existing directories.
std::list< SharedDirInfo> dirs ;
rsFiles->getSharedDirectories( dirs) ;
for (std::list<SharedDirInfo>::const_iterator it(dirs.begin());it!=dirs.end();++it){
// Check for existence of directory name
QFile directory( QString::fromUtf8((*it).filename.c_str())) ;
if (!directory.exists()) continue ;
if (!(directory.permissions() & QFile::WriteOwner)) continue ;
contextMnu.addAction(QString::fromUtf8((*it).filename.c_str()), this, SLOT(setDestinationDirectory()))->setData(QString::fromUtf8( (*it).filename.c_str() ) ) ;
}
contextMnu.addAction( QIcon(IMAGE_SEARCH),tr("Specify..."),this,SLOT(chooseDestinationDirectory()));
contextMnu.exec(QCursor::pos()) ;
}
void RsCollectionDialog::setDestinationDirectory()
{
QString dest_dir(qobject_cast<QAction*>(sender())->data().toString()) ;
ui.downloadFolder_LE->setText(dest_dir) ;
}
void RsCollectionDialog::chooseDestinationDirectory()
{
QString dest_dir = QFileDialog::getExistingDirectory(this,tr("Choose directory")) ;
if(dest_dir.isNull())
return ;
ui.downloadFolder_LE->setText(dest_dir) ;
}
/**
* @brief RsCollectionDialog::~RsCollectionDialog
*/
@ -243,26 +301,26 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
for (it = selectedItems.begin(); it != selectedItems.end(); ++it) {
if ((*it)->checkState(COLUMN_FILE) != checkState)
(*it)->setCheckState(COLUMN_FILE, checkState);
}//for (it
}//if (item)
}
}
return true; // eat event
}//if (keyEvent && keyEvent->key() == Qt::Key_Space)
}
if (keyEvent && (keyEvent->key() == Qt::Key_Delete)) {
// Delete pressed
remove();
return true; // eat event
}//if (keyEvent && keyEvent->key() == Qt::Key_Delete)
}
if (keyEvent && (keyEvent->key() == Qt::Key_Plus)) {
// Plus pressed
makeDir();
return true; // eat event
}//if (keyEvent && keyEvent->key() == Qt::Key_Plus)
}
}//if (event->type() == QEvent::KeyPress)
}//if (obj == ui._fileEntriesTW)
}
}
if (obj == ui._systemFileTW) {
if (event->type() == QEvent::KeyPress) {
@ -277,9 +335,9 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
}
return true; // eat event
}//if (keyEvent && keyEvent->key() == Qt::Key_Enter...
}//if (event->type() == QEvent::KeyPress)
}//if (obj == ui._systemFileTW)
}
}
}
// pass the event on to the parent class
return QDialog::eventFilter(obj, event);
@ -452,7 +510,7 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
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);
}//if (colFileInfo.type==DIR_TYPE_DIR
}
item->setFont(COLUMN_FILE, font);
if (colFileInfo.filename_has_wrong_characters)
@ -487,12 +545,12 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentSelFileCount));
itemParent = itemParent->parent();
}//while (itemParent)
}//if (itemParent)
}//if (colFileInfo.type==DIR_TYPE_FILE)
}
}
}
founds.push_back(item);
}//(founds.empty())
}
if (!founds.empty()) {
@ -591,12 +649,12 @@ void RsCollectionDialog::changeFileName()
QString fileName;
if(!misc::getSaveFileName(this, RshareSettings::LASTDIR_EXTRAFILE
, QApplication::translate("RsCollectionFile", "Create collection file")
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")"
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")"
, fileName,0, QFileDialog::DontConfirmOverwrite))
return;
if (!fileName.endsWith("." + RsCollectionFile::ExtensionString))
fileName += "." + RsCollectionFile::ExtensionString ;
if (!fileName.endsWith("." + RsCollection::ExtensionString))
fileName += "." + RsCollection::ExtensionString ;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
@ -604,7 +662,7 @@ void RsCollectionDialog::changeFileName()
if(file.exists())
{
RsCollectionFile collFile;
RsCollection collFile;
if (!collFile.checkFile(fileName,true)) return;
QMessageBox mb;
@ -624,7 +682,7 @@ void RsCollectionDialog::changeFileName()
if (qddOldFile.setContent(&file)) {
QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement();
collFile.recursCollectColFileInfos(docOldElem,_newColFileInfos,QString(),false);
}//(qddOldFile.setContent(&file))
}
} else if (mb.clickedButton()==btnCancel) {
return;
@ -636,7 +694,7 @@ void RsCollectionDialog::changeFileName()
//create a new empty file to check if name if good.
if (!file.open(QFile::WriteOnly)) return;
file.remove();
}//if(file.exists())
}
_fileName = fileName;
@ -686,7 +744,7 @@ void RsCollectionDialog::addRecursive(bool recursive)
} else {
continue;
}
}//if (fileInfo.isDir())
}
if (fileInfo.isFile()){
fileToHash.append(fileInfo.absoluteFilePath());
++count;
@ -694,9 +752,9 @@ void RsCollectionDialog::addRecursive(bool recursive)
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
else
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),"");
}//if (fileInfo.isFile())
}//if (index.column()==0)
}//foreach (QModelIndex index, milSelectionList)
}
}
}
// Process Dirs
QTreeWidgetItem *item = NULL;
@ -705,8 +763,8 @@ void RsCollectionDialog::addRecursive(bool recursive)
if (item) {
while (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) {
item = item->parent();//Only Dir as Parent
}//while
}//if (item)
}
}
int index = 0;
while (index < dirToAdd.count())
@ -722,7 +780,7 @@ void RsCollectionDialog::addRecursive(bool recursive)
//QMap is ordered, so we get parent before child
//Iterator is moved inside this function
processItem(dirToAdd, index, root);
}//while (index < dirToAdd.count())
}
//Update liste before attach files to be sure when file is hashed, parent directory exists.
updateList();
@ -736,9 +794,9 @@ void RsCollectionDialog::addRecursive(bool recursive)
} else if(item) {
if (item->data(COLUMN_HASH, ROLE_NAME) != "") {
it.value() = item->text(COLUMN_FILEPATH);
}//if (item->data(COLUMN_HASH, ROLE_NAME) != "")
}//if (dirToAdd.contains(path))
}//for (QHash<QString,QString>::Iterator it
}
}
}
// Process Files once all done
ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/);
@ -781,13 +839,13 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent
default:
// should never be reached
break;
}//switch (ret)
}
}
if (fileInfo.isDir()) {
dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
++count;
if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return false;
}//if (fileInfo.isDir())
}
if (fileInfo.isFile()){
fileToHash.append(fileInfo.absoluteFilePath());
++count;
@ -795,8 +853,8 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
else
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),"");
}//if (fileInfo.isFile())
}//foreach (QFileInfo fileInfo, dirParent.entryInfoList())
}
}
return true;
}
@ -821,10 +879,10 @@ void RsCollectionDialog::remove()
item->setSelected(false);
} else {
listDir += item->data(COLUMN_HASH, ROLE_NAME).toString() +"<br>";
}//if (listDir.contains(item->data(COLUMN_HASH, ROLE_PATH).toString()))
}//if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() == DIR_TYPE_DIR)
}//if (item != getRootItem())
}//for (int curs = 0; curs < count; ++curs)
}
}
}
}
//If directories, ask to remove them or not
if (!listDir.isEmpty()){
@ -870,14 +928,14 @@ void RsCollectionDialog::remove()
case QMessageBox::Cancel: {
delete msgBox;
return;
}//case QMessageBox::Cancel:
}
break;
default:
// should never be reached
break;
}//switch (ret)
}
delete msgBox;
}//if (!listDir.isEmpty())
}
//Remove wanted items
int leftItem = 0;
@ -966,7 +1024,7 @@ void RsCollectionDialog::processItem(QMap<QString, QString> &dirToAdd
} else {
_newColFileInfos.push_back(newChild);
}
}//(index < count)
}
}
/**
@ -1006,13 +1064,13 @@ void RsCollectionDialog::makeDir()
default:
// should never be reached
break;
}//switch (ret)
}//if (badChar)
}
}
} else {//if (ok && !childName.isEmpty())
return;
}//if (ok && !childName.isEmpty())
}
}//while (!nameOK)
}
// Process all selected items
int count = ui._fileEntriesTW->selectedItems().count();
@ -1040,8 +1098,8 @@ void RsCollectionDialog::makeDir()
if (item == getRootItem()) newChild.path = "";
_newColFileInfos.push_back(newChild);
}//if (item)
}//for (; curs < count; ++curs)
}
}
updateList();
@ -1074,7 +1132,7 @@ void RsCollectionDialog::fileHashingFinished(QList<HashedFile> hashedFiles)
//File Added in directory, find its parent
colFileInfo.path = _listOfFilesAddedInDir.value(hashedFile.filepath,"");
_listOfFilesAddedInDir.remove(hashedFile.filepath);
}//if (_listOfFilesAddedInDir.value(hashedFile.filepath,"")!="")
}
_newColFileInfos.push_back(colFileInfo);
@ -1112,7 +1170,7 @@ void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col)
itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentFileCount));
itemParent = itemParent->parent();
}//while (itemParent)
}
updateSizes() ;
@ -1222,7 +1280,7 @@ void RsCollectionDialog::download()
{
std::cerr << "Downloading!" << std::endl;
QString dldir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()) ;
QString dldir = ui.downloadFolder_LE->text();
std::cerr << "downloading all these files:" << std::endl;
@ -1258,8 +1316,8 @@ void RsCollectionDialog::download()
std::list<RsPeerId>());
} else {//if (item->checkState(COLUMN_FILE) == Qt::Checked)
std::cerr<<"Skipping file : " << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() << std::endl;
}//if (item->checkState(COLUMN_FILE) == Qt::Checked)
}//while ((item = *itemIterator) != NULL)
}
}
close();
}

View File

@ -22,7 +22,7 @@
****************************************************************/
#include "ui_RsCollectionDialog.h"
#include "RsCollectionFile.h"
#include "RsCollection.h"
#include <QFileSystemModel>
#include <QSortFilterProxyModel>
@ -49,6 +49,9 @@ private slots:
void add() ;
void addRecursive() ;
void remove() ;
void chooseDestinationDirectory();
void setDestinationDirectory();
void openDestinationDirectoryMenu(QPoint pt);
void processItem(QMap<QString, QString> &dirToAdd
, int &index
, ColFileInfo &parent

View File

@ -6,10 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
<width>693</width>
<height>525</height>
<width>969</width>
<height>778</height>
</rect>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="windowTitle">
<string>Collection</string>
</property>
@ -67,19 +70,7 @@
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="_frameInfo">
<property name="sizePolicy">
@ -403,7 +394,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="_removeDuplicate_CB">
<property name="text">
@ -424,6 +415,26 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="downloadFolder_LB">
<property name="text">
<string>Destination:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="downloadFolder_LE">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="toolTip">
<string>Right click to change download directory</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="_cancel_PB">
<property name="text">

View File

@ -22,14 +22,14 @@
#include <stdexcept>
#include <QDesktopServices>
#include <QUrl>
#include "RsCollectionFile.h"
#include "RsCollection.h"
#include "RsUrlHandler.h"
bool RsUrlHandler::openUrl(const QUrl& url)
{
if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollectionFile::ExtensionString))
if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString))
{
RsCollectionFile collection ;
RsCollection collection ;
if(collection.load(url.toLocalFile()))
{
collection.downloadFiles() ;

View File

@ -121,6 +121,13 @@ GxsGroupFrameDialog::~GxsGroupFrameDialog()
delete(ui);
}
void GxsGroupFrameDialog::getGroupList(std::list<RsGroupMetaData>& group_list)
{
group_list = mCachedGroupMetas ;
if(group_list.empty())
requestGroupSummary();
}
void GxsGroupFrameDialog::initUi()
{
registerHelpButton(ui->helpButton, getHelpString(),pageName()) ;
@ -927,6 +934,8 @@ void GxsGroupFrameDialog::loadGroupSummary(const uint32_t &token)
RsUserdata *userdata = NULL;
loadGroupSummaryToken(token, groupInfo, userdata);
mCachedGroupMetas = groupInfo ;
insertGroupsData(groupInfo, userdata);
mStateHelper->setLoading(TOKEN_TYPE_GROUP_SUMMARY, false);

View File

@ -81,6 +81,8 @@ public:
virtual QString getHelpString() const =0;
virtual void getGroupList(std::list<RsGroupMetaData>& groups) ;
protected:
virtual void showEvent(QShowEvent *event);
virtual void updateDisplay(bool complete);
@ -197,6 +199,8 @@ private:
/** Qt Designer generated object */
Ui::GxsGroupFrameDialog *ui;
std::list<RsGroupMetaData> mCachedGroupMetas;
};
#endif

View File

@ -412,6 +412,11 @@ void CreateGxsChannelMsg::addExtraFile()
}
}
void CreateGxsChannelMsg::addHtmlText(const QString& text)
{
msgEdit->setHtml(text) ;
}
void CreateGxsChannelMsg::addAttachment(const std::string &path)
{
/* add a SubFileItem to the attachment section */

View File

@ -43,6 +43,7 @@ public:
/** Default Destructor */
~CreateGxsChannelMsg();
void addHtmlText(const QString& text) ;
void addAttachment(const std::string &path);
void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId,bool assume_file_ready = false);

View File

@ -27,6 +27,7 @@
#include "GxsChannelDialog.h"
#include "GxsChannelGroupDialog.h"
#include "GxsChannelPostsWidget.h"
#include "CreateGxsChannelMsg.h"
#include "GxsChannelUserNotify.h"
#include "gui/gxs/GxsGroupShareKey.h"
#include "gui/feeds/GxsChannelPostItem.h"
@ -76,6 +77,20 @@ UserNotify *GxsChannelDialog::getUserNotify(QObject *parent)
return new GxsChannelUserNotify(rsGxsChannels, parent);
}
void GxsChannelDialog::shareOnChannel(const RsGxsGroupId& channel_id,const QList<RetroShareLink>& file_links)
{
std::cerr << "Sharing file link on channel " << channel_id << ": Not yet implemented!" << std::endl;
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(channel_id) ;
QString txt ;
for(QList<RetroShareLink>::const_iterator it(file_links.begin());it!=file_links.end();++it)
txt += (*it).toHtml() + "\n" ;
msgDialog->addHtmlText(txt);
msgDialog->show();
}
QString GxsChannelDialog::text(TextType type)
{
switch (type) {

View File

@ -42,6 +42,8 @@ public:
virtual UserNotify *getUserNotify(QObject *parent);
void shareOnChannel(const RsGxsGroupId& channel_id, const QList<RetroShareLink>& file_link) ;
protected:
/* GxsGroupFrameDialog */
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_CHANNEL; }

View File

@ -476,7 +476,6 @@ HEADERS += rshare.h \
gui/common/ElidedLabel.h \
gui/common/vmessagebox.h \
gui/common/RsUrlHandler.h \
gui/common/RsCollectionFile.h \
gui/common/RsCollectionDialog.h \
gui/common/rwindow.h \
gui/common/html.h \
@ -565,7 +564,8 @@ HEADERS += rshare.h \
gui/GetStartedDialog.h \
gui/statistics/BWGraph.h \
util/RsSyntaxHighlighter.h \
util/imageutil.h
util/imageutil.h \
gui/common/RsCollection.h
# gui/ForumsDialog.h \
# gui/forums/ForumDetails.h \
@ -791,7 +791,6 @@ SOURCES += main.cpp \
gui/common/RSGraphWidget.cpp \
gui/common/ElidedLabel.cpp \
gui/common/vmessagebox.cpp \
gui/common/RsCollectionFile.cpp \
gui/common/RsCollectionDialog.cpp \
gui/common/RsUrlHandler.cpp \
gui/common/rwindow.cpp \
@ -925,7 +924,8 @@ SOURCES += main.cpp \
gui/statistics/RttStatistics.cpp \
gui/statistics/BWGraph.cpp \
util/RsSyntaxHighlighter.cpp \
util/imageutil.cpp
util/imageutil.cpp \
gui/common/RsCollection.cpp
# gui/ForumsDialog.cpp \
# gui/forums/ForumDetails.cpp \

View File

@ -227,6 +227,7 @@ bool RsHtml::canReplaceAnchor(QDomDocument &/*doc*/, QDomElement &/*element*/, c
switch (link.type()) {
case RetroShareLink::TYPE_UNKNOWN:
case RetroShareLink::TYPE_FILE:
case RetroShareLink::TYPE_FILE_TREE:
case RetroShareLink::TYPE_PERSON:
case RetroShareLink::TYPE_FORUM:
case RetroShareLink::TYPE_CHANNEL:
@ -257,6 +258,7 @@ void RsHtml::anchorStylesheetForImg(QDomDocument &/*doc*/, QDomElement &/*elemen
switch (link.type()) {
case RetroShareLink::TYPE_UNKNOWN:
case RetroShareLink::TYPE_FILE:
case RetroShareLink::TYPE_FILE_TREE:
case RetroShareLink::TYPE_PERSON:
case RetroShareLink::TYPE_FORUM:
case RetroShareLink::TYPE_CHANNEL: