diff --git a/src/board/UBFeaturesController.cpp b/src/board/UBFeaturesController.cpp index c93d9e9ae..59e9a0e62 100644 --- a/src/board/UBFeaturesController.cpp +++ b/src/board/UBFeaturesController.cpp @@ -64,88 +64,116 @@ const QString UBFeaturesController::favoritePath = rootPath + "/Favorites"; const QString UBFeaturesController::webSearchPath = rootPath + "/Web search"; -void UBFeaturesComputingThread::scanFS(const QUrl & currentPath, const QString & currVirtualPath, const QSet &pFavoriteSet) +void UBFeaturesComputingThread::scanFS(const QUrl& currentPath, const QString& currVirtualPath, FeatureProcessor processFeature) { -// Q_ASSERT(QFileInfo(currentPath.toLocalFile()).exists()); -// if(QFileInfo(currentPath.toLocalFile()).exists()) -// return; + QSet scanRoots; + scanRoots << currentPath.toLocalFile(); + scanFS(currentPath, currVirtualPath, scanRoots, processFeature); +} + +void UBFeaturesComputingThread::scanFS(const QUrl& currentPath, const QString& currVirtualPath, QSet& scanRoots, FeatureProcessor processFeature) +{ QFileInfoList fileInfoList = UBFileSystemUtils::allElementsInDirectory(currentPath.toLocalFile()); - QFileInfoList::iterator fileInfo; - for ( fileInfo = fileInfoList.begin(); fileInfo != fileInfoList.end(); fileInfo += 1) { - if (abort) { + // new implementation taking care of symlinks + for (const auto& fileInfo : fileInfoList) + { + if (abort) + { return; } - QString fullFileName = fileInfo->absoluteFilePath(); - UBFeatureElementType featureType = UBFeaturesController::fileTypeFromUrl(fullFileName); - QString fileName = fileInfo->fileName(); - - QImage icon = UBFeaturesController::getIcon(fullFileName, featureType); - - if ( fullFileName.contains(".thumbnail.")) - continue; + if (fileInfo.isSymLink()) + { + const auto symLinkTarget = QFileInfo(fileInfo.symLinkTarget()); - UBFeature testFeature(currVirtualPath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType); + if (symLinkTarget.isDir()) + { + bool valid{true}; + // add trailing slash to make sure to compare full path segments afterwards + const auto target = symLinkTarget.canonicalFilePath() + "/"; + + // check target + for (const auto& root : scanRoots) + { + if (root.startsWith(target) || target.startsWith(root)) + { + qDebug() << "skipping" << fileInfo << "linking to" << target; + valid = false; + break; + } + } + + if (!valid) + { + continue; + } + + scanRoots << target; + } + } - emit sendFeature(testFeature); - emit featureSent(); - emit scanPath(fullFileName); + const auto fullFileName = fileInfo.canonicalFilePath(); + const auto featureType = UBFeaturesController::fileTypeFromUrl(fullFileName); - if ( pFavoriteSet.find(QUrl::fromLocalFile(fullFileName)) != pFavoriteSet.end()) { - //TODO send favoritePath from the controller or make favoritePath public and static - emit sendFeature(UBFeature( UBFeaturesController::favoritePath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType)); + if (featureType == UBFeatureElementType::FEATURE_INVALID || fullFileName.contains(".thumbnail.")) + { + continue; } - if (featureType == FEATURE_FOLDER) { - scanFS(QUrl::fromLocalFile(fullFileName), currVirtualPath + "/" + fileName, pFavoriteSet); + processFeature(fileInfo, featureType, currVirtualPath); + + if (featureType == UBFeatureElementType::FEATURE_FOLDER) + { + // scan recursive + scanFS(QUrl::fromLocalFile(fullFileName), currVirtualPath + "/" + fileInfo.fileName(), scanRoots, processFeature); } } } void UBFeaturesComputingThread::scanAll(QList > pScanningData, const QSet &pFavoriteSet) { - for (int i = 0; i < pScanningData.count(); i++) { + for (const auto curPair : pScanningData) + { if (abort) { return; } - QPair curPair = pScanningData.at(i); emit scanCategory(curPair.second.getDisplayName()); - scanFS(curPair.first, curPair.second.getFullVirtualPath(), pFavoriteSet); - } -} -int UBFeaturesComputingThread::featuresCount(const QUrl &pPath) -{ - int noItems = 0; + const auto currVirtualPath = curPair.second.getFullVirtualPath(); - QFileInfoList fileInfoList = UBFileSystemUtils::allElementsInDirectory(pPath.toLocalFile()); + scanFS(curPair.first, currVirtualPath, [this, &pFavoriteSet](const QFileInfo& fileInfo, UBFeatureElementType featureType, QString virtualPath){ + const auto fileName = fileInfo.fileName(); + const auto fullFileName = fileInfo.canonicalFilePath(); + QImage icon = UBFeaturesController::getIcon(fullFileName, featureType); - QFileInfoList::iterator fileInfo; - for ( fileInfo = fileInfoList.begin(); fileInfo != fileInfoList.end(); fileInfo += 1) { - QString fullFileName = fileInfo->absoluteFilePath(); - UBFeatureElementType featureType = UBFeaturesController::fileTypeFromUrl(fullFileName); + UBFeature testFeature{virtualPath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType}; - if (featureType != FEATURE_INVALID && !fullFileName.contains(".thumbnail.")) { - noItems++; - } + emit sendFeature(testFeature); + emit featureSent(); + emit scanPath(fullFileName); - if (featureType == FEATURE_FOLDER) { - noItems += featuresCount(QUrl::fromLocalFile(fullFileName)); - } + if (pFavoriteSet.contains(QUrl::fromLocalFile(fullFileName))) + { + emit sendFeature(UBFeature{UBFeaturesController::favoritePath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType}); + } + }); } - - return noItems; } int UBFeaturesComputingThread::featuresCountAll(QList > pScanningData) { int noItems = 0; - for (int i = 0; i < pScanningData.count(); i++) { - QPair curPair = pScanningData.at(i); - noItems += featuresCount(curPair.first); + + for (const auto curPair : pScanningData) + { + const auto currVirtualPath = curPair.second.getFullVirtualPath(); + + scanFS(curPair.first, currVirtualPath, [this, &noItems](const QFileInfo& fileInfo, UBFeatureElementType featureType, QString virtualPath){ + ++noItems; + }); } return noItems; @@ -468,60 +496,6 @@ void UBFeaturesController::scanFS() } } -void UBFeaturesController::fileSystemScan(const QUrl & currentPath, const QString & currVirtualPath) -{ - QFileInfoList fileInfoList = UBFileSystemUtils::allElementsInDirectory(currentPath.toLocalFile()); - - QFileInfoList::iterator fileInfo; - for ( fileInfo = fileInfoList.begin(); fileInfo != fileInfoList.end(); fileInfo += 1) { - QString fullFileName = fileInfo->absoluteFilePath(); - UBFeatureElementType featureType = fileTypeFromUrl(fullFileName); - QString fileName = fileInfo->fileName(); - - QImage icon = getIcon(fullFileName, featureType); - - if ( fullFileName.contains(".thumbnail.")) - continue; - - UBFeature testFeature(currVirtualPath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType); - - featuresList->append(testFeature); - - if ( favoriteSet->find( QUrl::fromLocalFile( fullFileName ) ) != favoriteSet->end() ) { - featuresList->append( UBFeature( favoritePath + "/" + fileName, icon, fileName, QUrl::fromLocalFile( fullFileName ), featureType ) ); - } - - if (featureType == FEATURE_FOLDER) { - fileSystemScan(QUrl::fromLocalFile(fullFileName), currVirtualPath + "/" + fileName); - } - } -} - -int UBFeaturesController::featuresCount(const QUrl &currPath) -{ - int noItems = 0; - - QFileInfoList fileInfoList = UBFileSystemUtils::allElementsInDirectory(currPath.toLocalFile()); - - QFileInfoList::iterator fileInfo; - for ( fileInfo = fileInfoList.begin(); fileInfo != fileInfoList.end(); fileInfo += 1) { - QString fullFileName = fileInfo->absoluteFilePath(); - UBFeatureElementType featureType = fileTypeFromUrl(fullFileName); - - if (featureType != FEATURE_INVALID && !fullFileName.contains(".thumbnail.")) { - noItems++; - } else { - continue; - } - - if (featureType == FEATURE_FOLDER) { - noItems += featuresCount(QUrl::fromLocalFile(fullFileName)); - } - } - - return noItems; -} - bool UBFeaturesController::isInFavoriteList(QUrl url) { return favoriteSet->contains(url); diff --git a/src/board/UBFeaturesController.h b/src/board/UBFeaturesController.h index 407b5aa6e..2216e03e8 100644 --- a/src/board/UBFeaturesController.h +++ b/src/board/UBFeaturesController.h @@ -57,6 +57,25 @@ class UBFeaturesListView; class UBFeature; +enum UBFeatureElementType +{ + FEATURE_CATEGORY, + FEATURE_VIRTUALFOLDER, + FEATURE_FOLDER, + FEATURE_INTERACTIVE, + FEATURE_INTERNAL, + FEATURE_ITEM, + FEATURE_AUDIO, + FEATURE_VIDEO, + FEATURE_IMAGE, + FEATURE_FLASH, + FEATURE_TRASH, + FEATURE_FAVORITE, + FEATURE_SEARCH, + FEATURE_DOCUMENT, + FEATURE_INVALID +}; + class UBFeaturesComputingThread : public QThread { Q_OBJECT @@ -80,9 +99,10 @@ class UBFeaturesComputingThread : public QThread public slots: private: - void scanFS(const QUrl & currentPath, const QString & currVirtualPath, const QSet &pFavoriteSet); + typedef std::function FeatureProcessor; + void scanFS(const QUrl& currentPath, const QString & currVirtualPath, FeatureProcessor processFeature); + void scanFS(const QUrl& currentPath, const QString & currVirtualPath, QSet& scanRoots, FeatureProcessor processFeature); void scanAll(QList > pScanningData, const QSet &pFavoriteSet); - int featuresCount(const QUrl &pPath); int featuresCountAll(QList > pScanningData); private: @@ -97,25 +117,6 @@ public slots: }; -enum UBFeatureElementType -{ - FEATURE_CATEGORY, - FEATURE_VIRTUALFOLDER, - FEATURE_FOLDER, - FEATURE_INTERACTIVE, - FEATURE_INTERNAL, - FEATURE_ITEM, - FEATURE_AUDIO, - FEATURE_VIDEO, - FEATURE_IMAGE, - FEATURE_FLASH, - FEATURE_TRASH, - FEATURE_FAVORITE, - FEATURE_SEARCH, - FEATURE_DOCUMENT, - FEATURE_INVALID -}; - class UBFeature { public: @@ -205,8 +206,6 @@ Q_OBJECT void importImage(const QByteArray& imageData, const UBFeature &destination, const QString &fileName = QString() ); QStringList getFileNamesInFolders(); - void fileSystemScan(const QUrl &currPath, const QString & currVirtualPath); - int featuresCount(const QUrl &currPath); static UBFeatureElementType fileTypeFromUrl( const QString &path ); static QString fileNameFromUrl( const QUrl &url ); diff --git a/src/frameworks/UBFileSystemUtils.cpp b/src/frameworks/UBFileSystemUtils.cpp index 9a5614133..a9a9f3f65 100644 --- a/src/frameworks/UBFileSystemUtils.cpp +++ b/src/frameworks/UBFileSystemUtils.cpp @@ -247,7 +247,7 @@ QStringList UBFileSystemUtils::allFiles(const QString& pDirPath, bool isRecursiv QFileInfoList UBFileSystemUtils::allElementsInDirectory(const QString& pDirPath) { QDir dir = QDir(pDirPath); - dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); + dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); dir.setSorting(QDir::DirsFirst); return QFileInfoList(dir.entryInfoList());