Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow symlinks in library #1204

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 76 additions & 102 deletions src/board/UBFeaturesController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<QUrl> &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<QString> scanRoots;
scanRoots << currentPath.toLocalFile();

scanFS(currentPath, currVirtualPath, scanRoots, processFeature);
}

void UBFeaturesComputingThread::scanFS(const QUrl& currentPath, const QString& currVirtualPath, QSet<QString>& 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<QPair<QUrl, UBFeature> > pScanningData, const QSet<QUrl> &pFavoriteSet)
{
for (int i = 0; i < pScanningData.count(); i++) {
for (const auto curPair : pScanningData)
{
if (abort) {
return;
}
QPair<QUrl, UBFeature> 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<QPair<QUrl, UBFeature> > pScanningData)
{
int noItems = 0;
for (int i = 0; i < pScanningData.count(); i++) {
QPair<QUrl, UBFeature> 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;
Expand Down Expand Up @@ -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);
Expand Down
45 changes: 22 additions & 23 deletions src/board/UBFeaturesController.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -80,9 +99,10 @@ class UBFeaturesComputingThread : public QThread
public slots:

private:
void scanFS(const QUrl & currentPath, const QString & currVirtualPath, const QSet<QUrl> &pFavoriteSet);
typedef std::function<void (const QFileInfo&, UBFeatureElementType, QString virtualPath)> FeatureProcessor;
void scanFS(const QUrl& currentPath, const QString & currVirtualPath, FeatureProcessor processFeature);
void scanFS(const QUrl& currentPath, const QString & currVirtualPath, QSet<QString>& scanRoots, FeatureProcessor processFeature);
void scanAll(QList<QPair<QUrl, UBFeature> > pScanningData, const QSet<QUrl> &pFavoriteSet);
int featuresCount(const QUrl &pPath);
int featuresCountAll(QList<QPair<QUrl, UBFeature> > pScanningData);

private:
Expand All @@ -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:
Expand Down Expand Up @@ -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 );
Expand Down
2 changes: 1 addition & 1 deletion src/frameworks/UBFileSystemUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down