cli,shared: Add remove, show and list for tags
This commit is contained in:
parent
e8d217e191
commit
4c5643e342
@ -3,14 +3,39 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "tagmanager.h"
|
#include "tagmanager.h"
|
||||||
|
|
||||||
|
bool CommandTag::ensureAbsolutePaths(const QVector<QString> &paths, QVector<QString> &absolutePaths)
|
||||||
|
{
|
||||||
|
for(const QString &path : paths)
|
||||||
|
{
|
||||||
|
QFileInfo info{path};
|
||||||
|
if(!info.exists())
|
||||||
|
{
|
||||||
|
Logger::error() << "Can't add tag for file " + info.absoluteFilePath() + " because it does not exist"
|
||||||
|
<< Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QString absolutePath = info.absoluteFilePath();
|
||||||
|
if(!this->dbService->fileExistsInDatabase(absolutePath))
|
||||||
|
{
|
||||||
|
Logger::error() << "Only files that have been indexed can be tagged. File not in index: " + absolutePath
|
||||||
|
<< Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
absolutePaths.append(absolutePath);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int CommandTag::handle(QStringList arguments)
|
int CommandTag::handle(QStringList arguments)
|
||||||
{
|
{
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addPositionalArgument("add", "Adds a tag to a file",
|
parser.addPositionalArgument("add", "Adds a tag to a file",
|
||||||
"add [tag] [paths...]. Adds the tag to the specified paths");
|
"add [tag] [paths...]. Adds the tag to the specified paths");
|
||||||
parser.addPositionalArgument("remove", "Removes a file associated to tag", "remove [tag] [file]");
|
parser.addPositionalArgument("remove", "Removes a path associated to a tag", "remove [tag] [path]");
|
||||||
parser.addPositionalArgument("delete", "Deletes a tag", "delete [tag]");
|
parser.addPositionalArgument("delete", "Deletes a tag", "delete [tag]");
|
||||||
parser.addPositionalArgument("list", "Lists paths associated with a tag, or all tags", "list [tag]");
|
parser.addPositionalArgument("list", "Lists paths associated with a tag, or all tags", "list [tag]");
|
||||||
|
parser.addPositionalArgument("show", "Lists tags associated with a path", "show [path]");
|
||||||
|
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
||||||
parser.parse(arguments);
|
parser.parse(arguments);
|
||||||
@ -21,9 +46,8 @@ int CommandTag::handle(QStringList arguments)
|
|||||||
parser.showHelp(EXIT_FAILURE);
|
parser.showHelp(EXIT_FAILURE);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
TagManager tagManager{*this->dbService};
|
||||||
QString cmd = args[0];
|
QString cmd = args[0];
|
||||||
qDebug() << cmd;
|
|
||||||
if(cmd == "add")
|
if(cmd == "add")
|
||||||
{
|
{
|
||||||
if(args.length() < 3)
|
if(args.length() < 3)
|
||||||
@ -33,28 +57,14 @@ int CommandTag::handle(QStringList arguments)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
QString tag = args[1];
|
QString tag = args[1];
|
||||||
auto paths = args.mid(2).toVector();
|
QVector<QString> paths = args.mid(2).toVector();
|
||||||
for(int i = 0; i < paths.size(); i++)
|
|
||||||
{
|
|
||||||
QFileInfo info{paths[i]};
|
|
||||||
if(!info.exists())
|
|
||||||
{
|
|
||||||
Logger::error() << "Can't add tag for file " + info.absoluteFilePath() + " because it does not exist"
|
|
||||||
<< Qt::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
QString absolutePath = info.absoluteFilePath();
|
|
||||||
if(!this->dbService->fileExistsInDatabase(absolutePath))
|
|
||||||
{
|
|
||||||
Logger::error() << "Only files that have been indexed can be tagged. File not in index: " + absolutePath
|
|
||||||
<< Qt::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
paths[i] = absolutePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagManager tagManager{*this->dbService};
|
QVector<QString> absolutePaths;
|
||||||
bool result = tagManager.addPathsToTag(tag, paths);
|
if(!ensureAbsolutePaths(paths, absolutePaths))
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
bool result = tagManager.addPathsToTag(tag, absolutePaths);
|
||||||
if(!result)
|
if(!result)
|
||||||
{
|
{
|
||||||
Logger::error() << "Failed to assign tags" << Qt::endl;
|
Logger::error() << "Failed to assign tags" << Qt::endl;
|
||||||
@ -62,6 +72,82 @@ int CommandTag::handle(QStringList arguments)
|
|||||||
}
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
if(cmd == "list")
|
||||||
|
{
|
||||||
|
|
||||||
return 0;
|
QString tag;
|
||||||
|
if(args.length() >= 2)
|
||||||
|
{
|
||||||
|
tag = args[1];
|
||||||
|
}
|
||||||
|
QVector<QString> entries;
|
||||||
|
if(tag.isEmpty())
|
||||||
|
{
|
||||||
|
entries = tagManager.getTags();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entries = tagManager.getPaths(tag);
|
||||||
|
}
|
||||||
|
for(const QString &entry : entries)
|
||||||
|
{
|
||||||
|
Logger::info() << entry << Qt::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cmd == "remove")
|
||||||
|
{
|
||||||
|
if(args.length() < 3)
|
||||||
|
{
|
||||||
|
Logger::error() << "Not enough arguments provided. 'remove' requires a tag followed by at least one path"
|
||||||
|
<< Qt::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
QString tag = args[1];
|
||||||
|
QVector<QString> paths = args.mid(2).toVector();
|
||||||
|
|
||||||
|
QVector<QString> absolutePaths;
|
||||||
|
if(!ensureAbsolutePaths(paths, absolutePaths))
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tagManager.removePathsForTag(tag, absolutePaths))
|
||||||
|
{
|
||||||
|
Logger::error() << "Failed to remove path assignments" << Qt::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cmd == "delete")
|
||||||
|
{
|
||||||
|
if(args.length() != 2)
|
||||||
|
{
|
||||||
|
Logger::error() << "The 'delete' command requires the tag to delete" << Qt::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if(!tagManager.deleteTag(args[1]))
|
||||||
|
{
|
||||||
|
Logger::error() << "Failed to delete tag" << Qt::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cmd == "show")
|
||||||
|
{
|
||||||
|
if(args.length() != 2)
|
||||||
|
{
|
||||||
|
Logger::error() << "The 'show' command requires a path to show the assigned tags" << Qt::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
QString path = args[1];
|
||||||
|
QVector<QString> absolutePaths;
|
||||||
|
if(!ensureAbsolutePaths({path}, absolutePaths))
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
QVector<QString> tags = tagManager.getTags(absolutePaths.at(0));
|
||||||
|
for(const QString &entry : tags)
|
||||||
|
{
|
||||||
|
Logger::info() << entry << Qt::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
class CommandTag : public Command
|
class CommandTag : public Command
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
bool ensureAbsolutePaths(const QVector<QString> &paths, QVector<QString> &absolutePaths);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Command::Command;
|
using Command::Command;
|
||||||
|
|
||||||
|
@ -142,6 +142,27 @@ QVector<QString> SqliteDbService::getTagsForPath(QString path)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<QString> SqliteDbService::getPathsForTag(QString tag)
|
||||||
|
{
|
||||||
|
QVector<QString> result;
|
||||||
|
auto query = QSqlQuery(dbFactory->forCurrentThread());
|
||||||
|
query.prepare(
|
||||||
|
"SELECT file.path FROM tag INNER JOIN filetag ON tag.id = filetag.tagid INNER JOIN file ON filetag.fileid "
|
||||||
|
"= file.id WHERE tag.name = ?");
|
||||||
|
query.addBindValue(tag.toLower());
|
||||||
|
query.setForwardOnly(true);
|
||||||
|
if(!query.exec())
|
||||||
|
{
|
||||||
|
throw LooqsGeneralException("Error while trying to retrieve paths from database: " + query.lastError().text());
|
||||||
|
}
|
||||||
|
while(query.next())
|
||||||
|
{
|
||||||
|
QString path = query.value(0).toString();
|
||||||
|
result.append(path);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool SqliteDbService::setTags(QString path, const QSet<QString> &tags)
|
bool SqliteDbService::setTags(QString path, const QSet<QString> &tags)
|
||||||
{
|
{
|
||||||
QSqlDatabase db = dbFactory->forCurrentThread();
|
QSqlDatabase db = dbFactory->forCurrentThread();
|
||||||
@ -379,3 +400,68 @@ bool SqliteDbService::addTag(QString tag, const QVector<QString> &paths)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SqliteDbService::removePathsForTag(QString tag, const QVector<QString> &paths)
|
||||||
|
{
|
||||||
|
QSqlDatabase db = dbFactory->forCurrentThread();
|
||||||
|
QSqlQuery tagQuery(db);
|
||||||
|
QSqlQuery fileTagQuery(db);
|
||||||
|
|
||||||
|
tag = tag.toLower();
|
||||||
|
|
||||||
|
fileTagQuery.prepare(
|
||||||
|
"DELETE FROM filetag WHERE fileid = (SELECT id FROM file WHERE path = ?) AND tagid = (SELECT id "
|
||||||
|
"FROM tag WHERE name = ?)");
|
||||||
|
|
||||||
|
fileTagQuery.bindValue(1, tag);
|
||||||
|
for(const QString &path : paths)
|
||||||
|
{
|
||||||
|
fileTagQuery.bindValue(0, path);
|
||||||
|
if(!fileTagQuery.exec())
|
||||||
|
{
|
||||||
|
Logger::error() << "An error occured while trying to remove paths from tag assignment" << Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteDbService::deleteTag(QString tag)
|
||||||
|
{
|
||||||
|
QSqlDatabase db = dbFactory->forCurrentThread();
|
||||||
|
if(!db.transaction())
|
||||||
|
{
|
||||||
|
Logger::error() << "Failed to open transaction while trying to delete tag " << tag << " : " << db.lastError()
|
||||||
|
<< Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = tag.toLower();
|
||||||
|
QSqlQuery assignmentDeleteQuery(db);
|
||||||
|
assignmentDeleteQuery.prepare("DELETE FROM filetag WHERE tagid = (SELECT id FROM tag WHERE name = ?)");
|
||||||
|
assignmentDeleteQuery.addBindValue(tag);
|
||||||
|
if(!assignmentDeleteQuery.exec())
|
||||||
|
{
|
||||||
|
db.rollback();
|
||||||
|
Logger::error() << "Error while trying to delete tag: " << db.lastError() << Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery deleteTagQuery(db);
|
||||||
|
deleteTagQuery.prepare("DELETE FROM tag WHERE name = ?");
|
||||||
|
deleteTagQuery.addBindValue(tag);
|
||||||
|
if(!deleteTagQuery.exec())
|
||||||
|
{
|
||||||
|
db.rollback();
|
||||||
|
Logger::error() << "Error while trying to delete tag: " << db.lastError() << Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!db.commit())
|
||||||
|
{
|
||||||
|
db.rollback();
|
||||||
|
Logger::error() << "Error while trying to delete tag: " << db.lastError() << Qt::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -34,7 +34,10 @@ class SqliteDbService
|
|||||||
bool addTag(QString tag, const QVector<QString> &paths);
|
bool addTag(QString tag, const QVector<QString> &paths);
|
||||||
QVector<QString> getTags();
|
QVector<QString> getTags();
|
||||||
QVector<QString> getTagsForPath(QString path);
|
QVector<QString> getTagsForPath(QString path);
|
||||||
|
QVector<QString> getPathsForTag(QString path);
|
||||||
bool setTags(QString path, const QSet<QString> &tags);
|
bool setTags(QString path, const QSet<QString> &tags);
|
||||||
|
bool removePathsForTag(QString tag, const QVector<QString> &paths);
|
||||||
|
bool deleteTag(QString tag);
|
||||||
|
|
||||||
QVector<SearchResult> search(const LooqsQuery &query);
|
QVector<SearchResult> search(const LooqsQuery &query);
|
||||||
|
|
||||||
|
@ -28,6 +28,31 @@ bool TagManager::removeTagsForPath(QString path, const QSet<QString> &tags)
|
|||||||
return this->dbService->setTags(path, newTags);
|
return this->dbService->setTags(path, newTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TagManager::removePathsForTag(QString tag, const QVector<QString> &paths)
|
||||||
|
{
|
||||||
|
return this->dbService->removePathsForTag(tag, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TagManager::deleteTag(QString tag)
|
||||||
|
{
|
||||||
|
return this->dbService->deleteTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> TagManager::getTags(QString path)
|
||||||
|
{
|
||||||
|
return this->dbService->getTagsForPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> TagManager::getTags()
|
||||||
|
{
|
||||||
|
return this->dbService->getTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> TagManager::getPaths(QString tag)
|
||||||
|
{
|
||||||
|
return this->dbService->getPathsForTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
bool TagManager::addTagsToPath(QString path, QString tagstring, QChar delim)
|
bool TagManager::addTagsToPath(QString path, QString tagstring, QChar delim)
|
||||||
{
|
{
|
||||||
auto splitted = tagstring.split(delim);
|
auto splitted = tagstring.split(delim);
|
||||||
|
@ -17,9 +17,11 @@ class TagManager
|
|||||||
bool addPathsToTag(QString tag, const QVector<QString> &paths);
|
bool addPathsToTag(QString tag, const QVector<QString> &paths);
|
||||||
bool removeTagsForPath(QString path, const QSet<QString> &tags);
|
bool removeTagsForPath(QString path, const QSet<QString> &tags);
|
||||||
|
|
||||||
|
bool removePathsForTag(QString tag, const QVector<QString> &paths);
|
||||||
bool deleteTag(QString tag);
|
bool deleteTag(QString tag);
|
||||||
|
|
||||||
QVector<QString> getTags(QString path);
|
QVector<QString> getTags(QString path);
|
||||||
|
QVector<QString> getTags();
|
||||||
QVector<QString> getPaths(QString tag);
|
QVector<QString> getPaths(QString tag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user