mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
commit
c5f91e3b6b
@ -199,25 +199,26 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_p
|
|||||||
std::set<std::string> subdirs ;
|
std::set<std::string> subdirs ;
|
||||||
|
|
||||||
for(;dirIt.isValid();dirIt.next())
|
for(;dirIt.isValid();dirIt.next())
|
||||||
{
|
if(filterFile(dirIt.file_name()))
|
||||||
switch(dirIt.file_type())
|
{
|
||||||
{
|
switch(dirIt.file_type())
|
||||||
case librs::util::FolderIterator::TYPE_FILE: subfiles[dirIt.file_name()].modtime = dirIt.file_modtime() ;
|
{
|
||||||
subfiles[dirIt.file_name()].size = dirIt.file_size();
|
case librs::util::FolderIterator::TYPE_FILE: subfiles[dirIt.file_name()].modtime = dirIt.file_modtime() ;
|
||||||
|
subfiles[dirIt.file_name()].size = dirIt.file_size();
|
||||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||||
std::cerr << " adding sub-file \"" << dirIt.file_name() << "\"" << std::endl;
|
std::cerr << " adding sub-file \"" << dirIt.file_name() << "\"" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case librs::util::FolderIterator::TYPE_DIR: subdirs.insert(dirIt.file_name());
|
case librs::util::FolderIterator::TYPE_DIR: subdirs.insert(dirIt.file_name());
|
||||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||||
std::cerr << " adding sub-dir \"" << dirIt.file_name() << "\"" << std::endl;
|
std::cerr << " adding sub-dir \"" << dirIt.file_name() << "\"" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << dirIt.file_name() << "\"" << std::endl;
|
std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << dirIt.file_name() << "\"" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update folder modificatoin time, which is the only way to detect e.g. removed or renamed files.
|
// update folder modificatoin time, which is the only way to detect e.g. removed or renamed files.
|
||||||
|
|
||||||
mSharedDirectories->setDirectoryLocalModTime(indx,dirIt.dir_modtime()) ;
|
mSharedDirectories->setDirectoryLocalModTime(indx,dirIt.dir_modtime()) ;
|
||||||
@ -232,16 +233,16 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_p
|
|||||||
// now go through list of subfiles and request the hash to hashcache
|
// now go through list of subfiles and request the hash to hashcache
|
||||||
|
|
||||||
for(DirectoryStorage::FileIterator dit(mSharedDirectories,indx);dit;++dit)
|
for(DirectoryStorage::FileIterator dit(mSharedDirectories,indx);dit;++dit)
|
||||||
{
|
{
|
||||||
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
||||||
|
|
||||||
RsFileHash hash ;
|
RsFileHash hash ;
|
||||||
|
|
||||||
// mSharedDirectories des two things: store H(F), and compute H(H(F)), which is used in FT. The later is always needed.
|
// mSharedDirectories does two things: store H(F), and compute H(H(F)), which is used in FT. The later is always needed.
|
||||||
|
|
||||||
if(mHashCache->requestHash(cumulated_path + "/" + dit.name(),dit.size(),dit.modtime(),hash,this,*dit))
|
if(mHashCache->requestHash(cumulated_path + "/" + dit.name(),dit.size(),dit.modtime(),hash,this,*dit))
|
||||||
mSharedDirectories->updateHash(*dit,hash,hash != dit.hash());
|
mSharedDirectories->updateHash(*dit,hash,hash != dit.hash());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||||
else
|
else
|
||||||
@ -259,6 +260,36 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LocalDirectoryUpdater::filterFile(const std::string& fname) const
|
||||||
|
{
|
||||||
|
if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES)
|
||||||
|
for(auto it(mIgnoredSuffixes.begin());it!=mIgnoredSuffixes.end();++it)
|
||||||
|
if(fname.size() >= (*it).size() && fname.substr( fname.size() - (*it).size()) == *it)
|
||||||
|
{
|
||||||
|
std::cerr << "(II) ignoring file " << fname << ", because it matches suffix \"" << *it << "\"" << std::endl;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES)
|
||||||
|
for(auto it(mIgnoredPrefixes.begin());it!=mIgnoredPrefixes.end();++it)
|
||||||
|
if(fname.size() >= (*it).size() && fname.substr( 0,(*it).size()) == *it)
|
||||||
|
{
|
||||||
|
std::cerr << "(II) ignoring file " << fname << ", because it matches prefix \"" << *it << "\"" << std::endl;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalDirectoryUpdater::togglePauseHashingProcess()
|
||||||
|
{
|
||||||
|
mHashCache->togglePauseHashingProcess() ;
|
||||||
|
}
|
||||||
|
bool LocalDirectoryUpdater::hashingProcessPaused()
|
||||||
|
{
|
||||||
|
return mHashCache->hashingProcessPaused();
|
||||||
|
}
|
||||||
|
|
||||||
bool LocalDirectoryUpdater::inDirectoryCheck() const
|
bool LocalDirectoryUpdater::inDirectoryCheck() const
|
||||||
{
|
{
|
||||||
return mHashCache->isRunning();
|
return mHashCache->isRunning();
|
||||||
@ -301,5 +332,19 @@ bool LocalDirectoryUpdater::followSymLinks() const
|
|||||||
return mFollowSymLinks ;
|
return mFollowSymLinks ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalDirectoryUpdater::setIgnoreLists(const std::list<std::string>& ignored_prefixes,const std::list<std::string>& ignored_suffixes,uint32_t ignore_flags)
|
||||||
|
{
|
||||||
|
mIgnoredPrefixes = ignored_prefixes ;
|
||||||
|
mIgnoredSuffixes = ignored_suffixes ;
|
||||||
|
mIgnoreFlags = ignore_flags;
|
||||||
|
}
|
||||||
|
bool LocalDirectoryUpdater::getIgnoreLists(std::list<std::string>& ignored_prefixes,std::list<std::string>& ignored_suffixes,uint32_t& ignore_flags) const
|
||||||
|
{
|
||||||
|
ignored_prefixes = mIgnoredPrefixes;
|
||||||
|
ignored_suffixes = mIgnoredSuffixes;
|
||||||
|
ignore_flags = mIgnoreFlags ;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ public:
|
|||||||
|
|
||||||
void forceUpdate();
|
void forceUpdate();
|
||||||
bool inDirectoryCheck() const ;
|
bool inDirectoryCheck() const ;
|
||||||
|
void togglePauseHashingProcess();
|
||||||
|
bool hashingProcessPaused();
|
||||||
|
|
||||||
void setHashSalt(const RsFileHash& hash) { mHashSalt = hash; }
|
void setHashSalt(const RsFileHash& hash) { mHashSalt = hash; }
|
||||||
const RsFileHash& hashSalt() const { return mHashSalt; }
|
const RsFileHash& hashSalt() const { return mHashSalt; }
|
||||||
@ -53,6 +55,9 @@ public:
|
|||||||
void setEnabled(bool b) ;
|
void setEnabled(bool b) ;
|
||||||
bool isEnabled() const ;
|
bool isEnabled() const ;
|
||||||
|
|
||||||
|
void setIgnoreLists(const std::list<std::string>& ignored_prefixes,const std::list<std::string>& ignored_suffixes,uint32_t ignore_flags) ;
|
||||||
|
bool getIgnoreLists(std::list<std::string>& ignored_prefixes,std::list<std::string>& ignored_suffixes,uint32_t& ignore_flags) const ;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void data_tick() ;
|
virtual void data_tick() ;
|
||||||
|
|
||||||
@ -63,6 +68,8 @@ protected:
|
|||||||
bool sweepSharedDirectories();
|
bool sweepSharedDirectories();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool filterFile(const std::string& fname) const ; // reponds true if the file passes the ignore lists test.
|
||||||
|
|
||||||
HashStorage *mHashCache ;
|
HashStorage *mHashCache ;
|
||||||
LocalDirectoryStorage *mSharedDirectories ;
|
LocalDirectoryStorage *mSharedDirectories ;
|
||||||
|
|
||||||
@ -77,5 +84,9 @@ private:
|
|||||||
bool mNeedsFullRecheck ;
|
bool mNeedsFullRecheck ;
|
||||||
bool mIsChecking ;
|
bool mIsChecking ;
|
||||||
bool mForceUpdate ;
|
bool mForceUpdate ;
|
||||||
|
|
||||||
|
uint32_t mIgnoreFlags ;
|
||||||
|
std::list<std::string> mIgnoredPrefixes ;
|
||||||
|
std::list<std::string> mIgnoredSuffixes ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,6 +39,9 @@ static const std::string WATCH_FILE_DURATION_SS = "WATCH_FILES_DELAY" ; // key
|
|||||||
static const std::string WATCH_FILE_ENABLED_SS = "WATCH_FILES_ENABLED"; // key to store ON/OFF flags for file whatch
|
static const std::string WATCH_FILE_ENABLED_SS = "WATCH_FILES_ENABLED"; // key to store ON/OFF flags for file whatch
|
||||||
static const std::string FOLLOW_SYMLINKS_SS = "FOLLOW_SYMLINKS"; // dereference symbolic links, or just ignore them.
|
static const std::string FOLLOW_SYMLINKS_SS = "FOLLOW_SYMLINKS"; // dereference symbolic links, or just ignore them.
|
||||||
static const std::string WATCH_HASH_SALT_SS = "WATCH_HASH_SALT"; // Salt that is used to hash directory names
|
static const std::string WATCH_HASH_SALT_SS = "WATCH_HASH_SALT"; // Salt that is used to hash directory names
|
||||||
|
static const std::string IGNORED_PREFIXES_SS = "IGNORED_PREFIXES"; // ignore file prefixes
|
||||||
|
static const std::string IGNORED_SUFFIXES_SS = "IGNORED_SUFFIXES"; // ignore file suffixes
|
||||||
|
static const std::string IGNORE_LIST_FLAGS_SS = "IGNORED_FLAGS"; // ignore file flags
|
||||||
|
|
||||||
static const std::string FILE_SHARING_DIR_NAME = "file_sharing" ; // hard-coded directory name to store friend file lists, hash cache, etc.
|
static const std::string FILE_SHARING_DIR_NAME = "file_sharing" ; // hard-coded directory name to store friend file lists, hash cache, etc.
|
||||||
static const std::string HASH_CACHE_FILE_NAME = "hash_cache.bin" ; // hard-coded directory name to store encrypted hash cache.
|
static const std::string HASH_CACHE_FILE_NAME = "hash_cache.bin" ; // hard-coded directory name to store encrypted hash cache.
|
||||||
|
@ -44,6 +44,7 @@ HashStorage::HashStorage(const std::string& save_file_name)
|
|||||||
mTotalSizeToHash = 0;
|
mTotalSizeToHash = 0;
|
||||||
mTotalFilesToHash = 0;
|
mTotalFilesToHash = 0;
|
||||||
mMaxStorageDurationDays = DEFAULT_HASH_STORAGE_DURATION_DAYS ;
|
mMaxStorageDurationDays = DEFAULT_HASH_STORAGE_DURATION_DAYS ;
|
||||||
|
mHashingProcessPaused = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mHashMtx) ;
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
@ -52,6 +53,18 @@ HashStorage::HashStorage(const std::string& save_file_name)
|
|||||||
try_load_import_old_hash_cache();
|
try_load_import_old_hash_cache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HashStorage::togglePauseHashingProcess()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
mHashingProcessPaused = !mHashingProcessPaused ;
|
||||||
|
}
|
||||||
|
bool HashStorage::hashingProcessPaused()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
return mHashingProcessPaused;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string friendlyUnit(uint64_t val)
|
static std::string friendlyUnit(uint64_t val)
|
||||||
{
|
{
|
||||||
const std::string units[5] = {"B","KB","MB","GB","TB"};
|
const std::string units[5] = {"B","KB","MB","GB","TB"};
|
||||||
@ -78,12 +91,14 @@ void HashStorage::data_tick()
|
|||||||
RsFileHash hash;
|
RsFileHash hash;
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
bool empty ;
|
bool empty ;
|
||||||
uint32_t st ;
|
uint32_t st ;
|
||||||
|
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mHashMtx) ;
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
|
||||||
if(mChanged && mLastSaveTime + MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE < time(NULL))
|
if(mChanged && mLastSaveTime + MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE < time(NULL))
|
||||||
{
|
{
|
||||||
locked_save();
|
locked_save();
|
||||||
@ -136,6 +151,19 @@ void HashStorage::data_tick()
|
|||||||
}
|
}
|
||||||
mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME;
|
mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME;
|
||||||
|
|
||||||
|
bool paused = false ;
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
paused = mHashingProcessPaused ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(paused) // we need to wait off mutex!!
|
||||||
|
{
|
||||||
|
usleep(MAX_INACTIVITY_SLEEP_TIME) ;
|
||||||
|
std::cerr << "Hashing process currently paused." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mHashMtx) ;
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
|
||||||
|
@ -84,6 +84,8 @@ public:
|
|||||||
uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; }
|
uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; }
|
||||||
void clear() { mFiles.clear(); mChanged=true; } // drop all known hashes. Not something to do, except if you want to rehash the entire database
|
void clear() { mFiles.clear(); mChanged=true; } // drop all known hashes. Not something to do, except if you want to rehash the entire database
|
||||||
bool empty() const { return mFiles.empty() ; }
|
bool empty() const { return mFiles.empty() ; }
|
||||||
|
void togglePauseHashingProcess() ;
|
||||||
|
bool hashingProcessPaused();
|
||||||
|
|
||||||
// Functions called by the thread
|
// Functions called by the thread
|
||||||
|
|
||||||
@ -112,6 +114,7 @@ private:
|
|||||||
std::map<std::string, HashStorageInfo> mFiles ; // stored as (full_path, hash_info)
|
std::map<std::string, HashStorageInfo> mFiles ; // stored as (full_path, hash_info)
|
||||||
std::string mFilePath ; // file where the hash database is stored
|
std::string mFilePath ; // file where the hash database is stored
|
||||||
bool mChanged ;
|
bool mChanged ;
|
||||||
|
bool mHashingProcessPaused ;
|
||||||
|
|
||||||
struct FileHashJob
|
struct FileHashJob
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,19 @@ p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers)
|
|||||||
addSerialType(new RsFileListsSerialiser()) ;
|
addSerialType(new RsFileListsSerialiser()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void p3FileDatabase::setIgnoreLists(const std::list<std::string>& ignored_prefixes,const std::list<std::string>& ignored_suffixes, uint32_t ignore_flags)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ;
|
||||||
|
|
||||||
|
IndicateConfigChanged();
|
||||||
|
}
|
||||||
|
bool p3FileDatabase::getIgnoreLists(std::list<std::string>& ignored_prefixes,std::list<std::string>& ignored_suffixes, uint32_t& ignore_flags)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
return mLocalDirWatcher->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ;
|
||||||
|
}
|
||||||
|
|
||||||
RsSerialiser *p3FileDatabase::setupSerialiser()
|
RsSerialiser *p3FileDatabase::setupSerialiser()
|
||||||
{
|
{
|
||||||
// This one is for saveList/loadList
|
// This one is for saveList/loadList
|
||||||
@ -345,6 +358,28 @@ cleanup = true;
|
|||||||
|
|
||||||
rskv->tlvkvs.pairs.push_back(kv);
|
rskv->tlvkvs.pairs.push_back(kv);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
std::list<std::string> prefix_list,suffix_list;
|
||||||
|
uint32_t flags ;
|
||||||
|
|
||||||
|
mLocalDirWatcher->getIgnoreLists(prefix_list,suffix_list,flags) ;
|
||||||
|
|
||||||
|
std::string prefix_string, suffix_string ;
|
||||||
|
|
||||||
|
for(auto it(prefix_list.begin());it!=prefix_list.end();++it) prefix_string += *it + ";" ;
|
||||||
|
for(auto it(suffix_list.begin());it!=suffix_list.end();++it) suffix_string += *it + ";" ;
|
||||||
|
|
||||||
|
RsTlvKeyValue kv;
|
||||||
|
|
||||||
|
kv.key = IGNORED_PREFIXES_SS; kv.value = prefix_string; rskv->tlvkvs.pairs.push_back(kv);
|
||||||
|
kv.key = IGNORED_SUFFIXES_SS; kv.value = suffix_string; rskv->tlvkvs.pairs.push_back(kv);
|
||||||
|
|
||||||
|
std::string s ;
|
||||||
|
rs_sprintf(s, "%lu", flags) ;
|
||||||
|
|
||||||
|
kv.key = IGNORE_LIST_FLAGS_SS; kv.value = s; rskv->tlvkvs.pairs.push_back(kv);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add KeyValue to saveList */
|
/* Add KeyValue to saveList */
|
||||||
sList.push_back(rskv);
|
sList.push_back(rskv);
|
||||||
|
|
||||||
@ -363,6 +398,8 @@ bool p3FileDatabase::loadList(std::list<RsItem *>& load)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::list<SharedDirInfo> dirList;
|
std::list<SharedDirInfo> dirList;
|
||||||
|
std::list<std::string> ignored_prefixes,ignored_suffixes ;
|
||||||
|
uint32_t ignore_flags ;
|
||||||
|
|
||||||
for(std::list<RsItem *>::iterator it = load.begin(); it != load.end(); ++it)
|
for(std::list<RsItem *>::iterator it = load.begin(); it != load.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -400,6 +437,37 @@ bool p3FileDatabase::loadList(std::list<RsItem *>& load)
|
|||||||
std::cerr << "Initing directory watcher with saved secret salt..." << std::endl;
|
std::cerr << "Initing directory watcher with saved secret salt..." << std::endl;
|
||||||
mLocalDirWatcher->setHashSalt(RsFileHash(kit->value)) ;
|
mLocalDirWatcher->setHashSalt(RsFileHash(kit->value)) ;
|
||||||
}
|
}
|
||||||
|
else if(kit->key == IGNORED_PREFIXES_SS)
|
||||||
|
{
|
||||||
|
std::string b ;
|
||||||
|
for(uint32_t i=0;i<kit->value.size();++i)
|
||||||
|
if(kit->value[i] == ';')
|
||||||
|
{
|
||||||
|
ignored_prefixes.push_back(b) ;
|
||||||
|
b.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
b.push_back(kit->value[i]) ;
|
||||||
|
}
|
||||||
|
else if(kit->key == IGNORED_SUFFIXES_SS)
|
||||||
|
{
|
||||||
|
std::string b ;
|
||||||
|
for(uint32_t i=0;i<kit->value.size();++i)
|
||||||
|
if(kit->value[i] == ';')
|
||||||
|
{
|
||||||
|
ignored_suffixes.push_back(b) ;
|
||||||
|
b.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
b.push_back(kit->value[i]) ;
|
||||||
|
}
|
||||||
|
else if(kit->key == IGNORE_LIST_FLAGS_SS)
|
||||||
|
{
|
||||||
|
int t=0 ;
|
||||||
|
if(sscanf(kit->value.c_str(),"%d",&t) == 1)
|
||||||
|
ignore_flags = (uint32_t)t ;
|
||||||
|
}
|
||||||
|
|
||||||
delete *it ;
|
delete *it ;
|
||||||
continue ;
|
continue ;
|
||||||
}
|
}
|
||||||
@ -427,6 +495,8 @@ bool p3FileDatabase::loadList(std::list<RsItem *>& load)
|
|||||||
|
|
||||||
/* set directories */
|
/* set directories */
|
||||||
mLocalSharedDirs->setSharedDirectoryList(dirList);
|
mLocalSharedDirs->setSharedDirectoryList(dirList);
|
||||||
|
mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ;
|
||||||
|
|
||||||
load.clear() ;
|
load.clear() ;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -908,6 +978,16 @@ void p3FileDatabase::forceDirectoryCheck() // Force re-sweep the di
|
|||||||
{
|
{
|
||||||
mLocalDirWatcher->forceUpdate();
|
mLocalDirWatcher->forceUpdate();
|
||||||
}
|
}
|
||||||
|
void p3FileDatabase::togglePauseHashingProcess()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
mLocalDirWatcher->togglePauseHashingProcess();
|
||||||
|
}
|
||||||
|
bool p3FileDatabase::hashingProcessPaused()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
return mLocalDirWatcher->hashingProcessPaused();
|
||||||
|
}
|
||||||
bool p3FileDatabase::inDirectoryCheck()
|
bool p3FileDatabase::inDirectoryCheck()
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mFLSMtx) ;
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
@ -127,6 +127,9 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
|||||||
void updateShareFlags(const SharedDirInfo& info) ;
|
void updateShareFlags(const SharedDirInfo& info) ;
|
||||||
bool convertSharedFilePath(const std::string& path,std::string& fullpath);
|
bool convertSharedFilePath(const std::string& path,std::string& fullpath);
|
||||||
|
|
||||||
|
void setIgnoreLists(const std::list<std::string>& ignored_prefixes,const std::list<std::string>& ignored_suffixes, uint32_t ignore_flags) ;
|
||||||
|
bool getIgnoreLists(std::list<std::string>& ignored_prefixes,std::list<std::string>& ignored_suffixes, uint32_t& ignore_flags) ;
|
||||||
|
|
||||||
// computes/gathers statistics about shared directories
|
// computes/gathers statistics about shared directories
|
||||||
|
|
||||||
int getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats);
|
int getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats);
|
||||||
@ -145,6 +148,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
|||||||
|
|
||||||
void forceDirectoryCheck(); // Force re-sweep the directories and see what's changed
|
void forceDirectoryCheck(); // Force re-sweep the directories and see what's changed
|
||||||
bool inDirectoryCheck();
|
bool inDirectoryCheck();
|
||||||
|
void togglePauseHashingProcess();
|
||||||
|
bool hashingProcessPaused();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -826,6 +826,16 @@ bool ftServer::removeSharedDirectory(std::string dir)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ftServer::getIgnoreLists(std::list<std::string>& ignored_prefixes, std::list<std::string>& ignored_suffixes,uint32_t& ignore_flags)
|
||||||
|
{
|
||||||
|
return mFileDatabase->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ;
|
||||||
|
}
|
||||||
|
void ftServer::setIgnoreLists(const std::list<std::string>& ignored_prefixes, const std::list<std::string>& ignored_suffixes, uint32_t ignore_flags)
|
||||||
|
{
|
||||||
|
mFileDatabase->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ;
|
||||||
|
}
|
||||||
|
|
||||||
bool ftServer::watchEnabled() { return mFileDatabase->watchEnabled() ; }
|
bool ftServer::watchEnabled() { return mFileDatabase->watchEnabled() ; }
|
||||||
int ftServer::watchPeriod() const { return mFileDatabase->watchPeriod()/60 ; }
|
int ftServer::watchPeriod() const { return mFileDatabase->watchPeriod()/60 ; }
|
||||||
bool ftServer::followSymLinks() const { return mFileDatabase->followSymLinks() ; }
|
bool ftServer::followSymLinks() const { return mFileDatabase->followSymLinks() ; }
|
||||||
@ -834,6 +844,9 @@ void ftServer::setWatchEnabled(bool b) { mFileDatabase->setWatchEnab
|
|||||||
void ftServer::setWatchPeriod(int minutes) { mFileDatabase->setWatchPeriod(minutes*60) ; }
|
void ftServer::setWatchPeriod(int minutes) { mFileDatabase->setWatchPeriod(minutes*60) ; }
|
||||||
void ftServer::setFollowSymLinks(bool b) { mFileDatabase->setFollowSymLinks(b) ; }
|
void ftServer::setFollowSymLinks(bool b) { mFileDatabase->setFollowSymLinks(b) ; }
|
||||||
|
|
||||||
|
void ftServer::togglePauseHashingProcess() { mFileDatabase->togglePauseHashingProcess() ; }
|
||||||
|
bool ftServer::hashingProcessPaused() { return mFileDatabase->hashingProcessPaused() ; }
|
||||||
|
|
||||||
bool ftServer::getShareDownloadDirectory()
|
bool ftServer::getShareDownloadDirectory()
|
||||||
{
|
{
|
||||||
std::list<SharedDirInfo> dirList;
|
std::list<SharedDirInfo> dirList;
|
||||||
|
@ -213,6 +213,9 @@ public:
|
|||||||
virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist !
|
virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist !
|
||||||
virtual bool removeSharedDirectory(std::string dir);
|
virtual bool removeSharedDirectory(std::string dir);
|
||||||
|
|
||||||
|
virtual bool getIgnoreLists(std::list<std::string>& ignored_prefixes, std::list<std::string>& ignored_suffixes, uint32_t& ignore_flags) ;
|
||||||
|
virtual void setIgnoreLists(const std::list<std::string>& ignored_prefixes, const std::list<std::string>& ignored_suffixes,uint32_t ignore_flags) ;
|
||||||
|
|
||||||
virtual bool getShareDownloadDirectory();
|
virtual bool getShareDownloadDirectory();
|
||||||
virtual bool shareDownloadDirectory(bool share);
|
virtual bool shareDownloadDirectory(bool share);
|
||||||
|
|
||||||
@ -222,6 +225,8 @@ public:
|
|||||||
virtual bool watchEnabled() ;
|
virtual bool watchEnabled() ;
|
||||||
virtual bool followSymLinks() const;
|
virtual bool followSymLinks() const;
|
||||||
virtual void setFollowSymLinks(bool b);
|
virtual void setFollowSymLinks(bool b);
|
||||||
|
virtual void togglePauseHashingProcess();
|
||||||
|
virtual bool hashingProcessPaused();
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/*************** Data Transfer Interface ***********************/
|
/*************** Data Transfer Interface ***********************/
|
||||||
|
@ -41,7 +41,7 @@ namespace RsRegularExpression { class Expression; }
|
|||||||
/* These are used mainly by ftController at the moment */
|
/* These are used mainly by ftController at the moment */
|
||||||
const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100;
|
const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100;
|
||||||
const uint32_t RS_FILE_CTRL_START = 0x00000200;
|
const uint32_t RS_FILE_CTRL_START = 0x00000200;
|
||||||
const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400;
|
const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400;
|
||||||
|
|
||||||
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ;
|
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ;
|
||||||
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ;
|
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ;
|
||||||
@ -60,6 +60,9 @@ const uint32_t RS_FILE_RATE_STREAM_VIDEO = 0x00000006;
|
|||||||
const uint32_t RS_FILE_PEER_ONLINE = 0x00001000;
|
const uint32_t RS_FILE_PEER_ONLINE = 0x00001000;
|
||||||
const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000;
|
const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000;
|
||||||
|
|
||||||
|
const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES = 0x0001 ;
|
||||||
|
const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES = 0x0002 ;
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
* Used To indicate where to search.
|
* Used To indicate where to search.
|
||||||
*
|
*
|
||||||
@ -251,12 +254,17 @@ class RsFiles
|
|||||||
virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist !
|
virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist !
|
||||||
virtual bool removeSharedDirectory(std::string dir) = 0;
|
virtual bool removeSharedDirectory(std::string dir) = 0;
|
||||||
|
|
||||||
|
virtual bool getIgnoreLists(std::list<std::string>& ignored_prefixes, std::list<std::string>& ignored_suffixes,uint32_t& flags) =0;
|
||||||
|
virtual void setIgnoreLists(const std::list<std::string>& ignored_prefixes, const std::list<std::string>& ignored_suffixes,uint32_t flags) =0;
|
||||||
|
|
||||||
virtual void setWatchPeriod(int minutes) =0;
|
virtual void setWatchPeriod(int minutes) =0;
|
||||||
virtual void setWatchEnabled(bool b) =0;
|
virtual void setWatchEnabled(bool b) =0;
|
||||||
virtual int watchPeriod() const =0;
|
virtual int watchPeriod() const =0;
|
||||||
virtual bool watchEnabled() =0;
|
virtual bool watchEnabled() =0;
|
||||||
virtual bool followSymLinks() const=0;
|
virtual bool followSymLinks() const=0;
|
||||||
virtual void setFollowSymLinks(bool b)=0 ;
|
virtual void setFollowSymLinks(bool b)=0 ;
|
||||||
|
virtual void togglePauseHashingProcess() =0; // pauses/resumes the hashing process.
|
||||||
|
virtual bool hashingProcessPaused() =0;
|
||||||
|
|
||||||
virtual bool getShareDownloadDirectory() = 0;
|
virtual bool getShareDownloadDirectory() = 0;
|
||||||
virtual bool shareDownloadDirectory(bool share) = 0;
|
virtual bool shareDownloadDirectory(bool share) = 0;
|
||||||
|
@ -54,6 +54,30 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags)
|
|||||||
QObject::connect(ui.autoCheckDirectoriesDelay_SB,SIGNAL(valueChanged(int)),this,SLOT(updateAutoScanDirectoriesPeriod())) ;
|
QObject::connect(ui.autoCheckDirectoriesDelay_SB,SIGNAL(valueChanged(int)),this,SLOT(updateAutoScanDirectoriesPeriod())) ;
|
||||||
QObject::connect(ui.shareDownloadDirectoryCB, SIGNAL(toggled(bool)), this,SLOT(updateShareDownloadDirectory())) ;
|
QObject::connect(ui.shareDownloadDirectoryCB, SIGNAL(toggled(bool)), this,SLOT(updateShareDownloadDirectory())) ;
|
||||||
QObject::connect(ui.followSymLinks_CB, SIGNAL(toggled(bool)), this,SLOT(updateFollowSymLinks())) ;
|
QObject::connect(ui.followSymLinks_CB, SIGNAL(toggled(bool)), this,SLOT(updateFollowSymLinks())) ;
|
||||||
|
|
||||||
|
QObject::connect(ui.prefixesIgnoreList_LE, SIGNAL(editingFinished()), this,SLOT(updateIgnoreLists())) ;
|
||||||
|
QObject::connect(ui.prefixesIgnoreList_CB, SIGNAL(toggled(bool)), this,SLOT(updateIgnoreLists())) ;
|
||||||
|
QObject::connect(ui.suffixesIgnoreList_LE, SIGNAL(editingFinished()), this,SLOT(updateIgnoreLists())) ;
|
||||||
|
QObject::connect(ui.suffixesIgnoreList_CB, SIGNAL(toggled(bool)), this,SLOT(updateIgnoreLists())) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferPage::updateIgnoreLists()
|
||||||
|
{
|
||||||
|
uint32_t flags = 0 ;
|
||||||
|
if(ui.prefixesIgnoreList_CB->isChecked()) flags |= RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES ;
|
||||||
|
if(ui.suffixesIgnoreList_CB->isChecked()) flags |= RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES ;
|
||||||
|
|
||||||
|
std::list<std::string> lp,ls ;
|
||||||
|
{ QStringList L = ui.prefixesIgnoreList_LE->text().split(';') ; for(QStringList::const_iterator it(L.begin());it!=L.end();++it) lp.push_back((*it).toStdString()) ; }
|
||||||
|
{ QStringList L = ui.suffixesIgnoreList_LE->text().split(';') ; for(QStringList::const_iterator it(L.begin());it!=L.end();++it) ls.push_back((*it).toStdString()) ; }
|
||||||
|
|
||||||
|
rsFiles->setIgnoreLists(lp,ls,flags) ;
|
||||||
|
|
||||||
|
std::cerr << "Setting ignore lists: " << std::endl;
|
||||||
|
|
||||||
|
std::cerr << " flags: " << flags << std::endl;
|
||||||
|
std::cerr << " prefixes: " ; for(auto it(lp.begin());it!=lp.end();++it) std::cerr << "\"" << *it << "\" " ; std::cerr << std::endl;
|
||||||
|
std::cerr << " suffixes: " ; for(auto it(ls.begin());it!=ls.end();++it) std::cerr << "\"" << *it << "\" " ; std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferPage::updateMaxTRUpRate(int b)
|
void TransferPage::updateMaxTRUpRate(int b)
|
||||||
@ -125,6 +149,32 @@ void TransferPage::load()
|
|||||||
case RS_FILE_PERM_DIRECT_DL_NO: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(1) ; break ;
|
case RS_FILE_PERM_DIRECT_DL_NO: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(1) ; break ;
|
||||||
default: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(2) ; break ;
|
default: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(2) ; break ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::string> suffixes, prefixes;
|
||||||
|
uint32_t ignore_flags ;
|
||||||
|
|
||||||
|
rsFiles->getIgnoreLists(prefixes,suffixes,ignore_flags) ;
|
||||||
|
|
||||||
|
QString ignore_prefixes_string,ignore_suffixes_string ;
|
||||||
|
|
||||||
|
for(auto it(prefixes.begin());it!=prefixes.end();)
|
||||||
|
{
|
||||||
|
ignore_prefixes_string += QString::fromStdString(*it) ;
|
||||||
|
|
||||||
|
if(++it != prefixes.end())
|
||||||
|
ignore_prefixes_string += ";" ;
|
||||||
|
}
|
||||||
|
for(auto it(suffixes.begin());it!=suffixes.end();)
|
||||||
|
{
|
||||||
|
ignore_suffixes_string += QString::fromStdString(*it) ;
|
||||||
|
|
||||||
|
if(++it != suffixes.end())
|
||||||
|
ignore_suffixes_string += ";" ;
|
||||||
|
}
|
||||||
|
whileBlocking(ui.prefixesIgnoreList_CB)->setChecked( ignore_flags & RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES ) ;
|
||||||
|
whileBlocking(ui.suffixesIgnoreList_CB)->setChecked( ignore_flags & RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES ) ;
|
||||||
|
whileBlocking(ui.prefixesIgnoreList_LE)->setText( ignore_prefixes_string );
|
||||||
|
whileBlocking(ui.suffixesIgnoreList_LE)->setText( ignore_suffixes_string );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferPage::updateDefaultStrategy(int i)
|
void TransferPage::updateDefaultStrategy(int i)
|
||||||
|
@ -50,6 +50,7 @@ class TransferPage: public ConfigPage
|
|||||||
void updateEncryptionPolicy(int);
|
void updateEncryptionPolicy(int);
|
||||||
void updateMaxUploadSlots(int);
|
void updateMaxUploadSlots(int);
|
||||||
void updateFilePermDirectDL(int);
|
void updateFilePermDirectDL(int);
|
||||||
|
void updateIgnoreLists();
|
||||||
|
|
||||||
void editDirectories() ;
|
void editDirectories() ;
|
||||||
void setIncomingDirectory();
|
void setIncomingDirectory();
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1126</width>
|
<width>1126</width>
|
||||||
<height>1099</height>
|
<height>1103</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="TransferPageVLayout">
|
<layout class="QVBoxLayout" name="TransferPageVLayout">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Shared Directories</string>
|
<string>Shared Directories</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="sharedGBoxVLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="shareDownloadHLayout">
|
<layout class="QHBoxLayout" name="shareDownloadHLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -88,6 +88,34 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="suffixesIgnoreList_CB">
|
||||||
|
<property name="text">
|
||||||
|
<string>ignore files with these suffixes:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="suffixesIgnoreList_LE"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="prefixesIgnoreList_CB">
|
||||||
|
<property name="text">
|
||||||
|
<string>ignore files with these prefixes:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="prefixesIgnoreList_LE"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMovie>
|
#include <QMovie>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
#include "retroshare/rsfiles.h"
|
||||||
#include "hashingstatus.h"
|
#include "hashingstatus.h"
|
||||||
#include "gui/common/ElidedLabel.h"
|
#include "gui/common/ElidedLabel.h"
|
||||||
#include "gui/notifyqt.h"
|
#include "gui/notifyqt.h"
|
||||||
@ -61,13 +63,14 @@ HashingStatus::~HashingStatus()
|
|||||||
|
|
||||||
void HashingStatus::updateHashingInfo(const QString& s)
|
void HashingStatus::updateHashingInfo(const QString& s)
|
||||||
{
|
{
|
||||||
if (s.isEmpty()) {
|
if (s.isEmpty())
|
||||||
|
{
|
||||||
statusHashing->hide() ;
|
statusHashing->hide() ;
|
||||||
hashloader->hide() ;
|
hashloader->hide() ;
|
||||||
|
|
||||||
movie->stop() ;
|
movie->stop() ;
|
||||||
} else {
|
} else {
|
||||||
hashloader->setToolTip(s) ;
|
setToolTip(s + "\n"+QObject::tr("Click to pause the hashing process"));
|
||||||
|
|
||||||
if (_compactMode) {
|
if (_compactMode) {
|
||||||
statusHashing->hide() ;
|
statusHashing->hide() ;
|
||||||
@ -80,3 +83,24 @@ void HashingStatus::updateHashingInfo(const QString& s)
|
|||||||
movie->start() ;
|
movie->start() ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HashingStatus::mousePressEvent(QMouseEvent *)
|
||||||
|
{
|
||||||
|
rsFiles->togglePauseHashingProcess() ;
|
||||||
|
|
||||||
|
if(rsFiles->hashingProcessPaused())
|
||||||
|
{
|
||||||
|
movie->stop() ;
|
||||||
|
hashloader->setPixmap(QPixmap(":/images/resume.png")) ;
|
||||||
|
|
||||||
|
mLastText = statusHashing->text();
|
||||||
|
statusHashing->setText(QObject::tr("[Hashing is paused]"));
|
||||||
|
setToolTip(QObject::tr("Click to resume the hashing process"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hashloader->setMovie(movie) ;
|
||||||
|
statusHashing->setText(mLastText);
|
||||||
|
movie->start() ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
~HashingStatus();
|
~HashingStatus();
|
||||||
|
|
||||||
void setCompactMode(bool compact) {_compactMode = compact; }
|
void setCompactMode(bool compact) {_compactMode = compact; }
|
||||||
|
void mousePressEvent(QMouseEvent *);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateHashingInfo(const QString&) ;
|
void updateHashingInfo(const QString&) ;
|
||||||
@ -42,6 +43,7 @@ public slots:
|
|||||||
private:
|
private:
|
||||||
ElidedLabel *statusHashing;
|
ElidedLabel *statusHashing;
|
||||||
QLabel *hashloader;
|
QLabel *hashloader;
|
||||||
|
QString mLastText ;
|
||||||
QMovie *movie;
|
QMovie *movie;
|
||||||
bool _compactMode;
|
bool _compactMode;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user