diff --git a/src/engine/databasesanitizer.h b/src/engine/databasesanitizer.h --- a/src/engine/databasesanitizer.h +++ b/src/engine/databasesanitizer.h @@ -33,6 +33,16 @@ */ class BALOO_ENGINE_EXPORT DatabaseSanitizer { +public: + enum ItemAccessFilterFlags { + IgnoreNone = 0, + IgnoreAvailable = 1, + IgnoreUnavailable = 2, + IgnoreMounted = IgnoreAvailable << 4, + IgnoreUnmounted = IgnoreUnavailable << 4 + }; + Q_DECLARE_FLAGS(ItemAccessFilters, ItemAccessFilterFlags) + public: DatabaseSanitizer(const Database& db, Transaction::TransactionType type); DatabaseSanitizer(Database* db, Transaction::TransactionType type); @@ -49,8 +59,8 @@ * \p urlFilter Filter result urls. Default is null = Print everything. */ void printList(const QVector& deviceIds, - const bool missingOnly, - const QSharedPointer& urlFilter + const ItemAccessFilters accessFilter = IgnoreNone, + const QSharedPointer& urlFilter = nullptr ); /** * Print info about known devices to stdout @@ -60,12 +70,14 @@ * * \p missingOnly Only inaccessible items are printed. */ - void printDevices(const QVector& deviceIds, const bool missingOnly = false); + void printDevices(const QVector& deviceIds, const ItemAccessFilters accessFilter = IgnoreNone); private: DatabaseSanitizer(const DatabaseSanitizer& rhs) = delete; DatabaseSanitizerImpl* m_pimpl; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(DatabaseSanitizer::ItemAccessFilters) + } #endif // BALOODATABASESANITIZER_H diff --git a/src/engine/databasesanitizer.cpp b/src/engine/databasesanitizer.cpp --- a/src/engine/databasesanitizer.cpp +++ b/src/engine/databasesanitizer.cpp @@ -71,7 +71,7 @@ */ QVector createList( const QVector& deviceIds, - const bool purging, + const DatabaseSanitizer::ItemAccessFilters accessFilter, const QSharedPointer& urlFilter ) const { @@ -109,7 +109,7 @@ info.accessible = !url.isEmpty() && QFileInfo::exists(url); if ((!includeIds.isEmpty() && !includeIds.contains(info.deviceId)) || (!excludeIds.isEmpty() && excludeIds.contains(info.deviceId)) - || (purging && info.accessible) + || (info.accessible && (accessFilter & DatabaseSanitizer::IgnoreAvailable)) || (urlFilter && !urlFilter->match(info.url).hasMatch()) ) { continue; @@ -151,7 +151,8 @@ } } - QVector createDeviceList(const QVector& infos) + QVector createDeviceList(const QVector& infos, + const DatabaseSanitizer::ItemAccessFilters accessFilter = DatabaseSanitizer::IgnoreNone) { // Create a hash to sum-up indexed items QMultiHash usedDevices; @@ -163,8 +164,12 @@ const auto keys = usedDevices.uniqueKeys(); for (const auto& dev : keys) { auto devinfo = getDeviceInfo(dev); - devinfo.items = usedDevices.values(dev).count(); - result.append(devinfo); + if ((devinfo.mounted && !(accessFilter & DatabaseSanitizer::IgnoreMounted)) + || (!devinfo.mounted && !(accessFilter & DatabaseSanitizer::IgnoreUnmounted)) + ) { + devinfo.items = usedDevices.values(dev).count(); + result.append(devinfo); + } } return result; @@ -208,15 +213,15 @@ */ void DatabaseSanitizer::printList( const QVector& deviceIds, - const bool missingOnly, + const ItemAccessFilters accessFilter, const QSharedPointer& urlFilter) { - auto infos = m_pimpl->createList(deviceIds, missingOnly, urlFilter); + auto infos = m_pimpl->createList(deviceIds, accessFilter, urlFilter); const auto sep = QLatin1Char(' '); QTextStream out(stdout); QTextStream err(stderr); for (const auto& info: infos) { - if (!missingOnly) { + if (!(accessFilter & IgnoreAvailable)) { out << QStringLiteral("%1").arg(info.accessible ? "+" : "!") << sep; } else if (!info.accessible) { out << i18n("Missing:") << sep; @@ -233,17 +238,17 @@ } -void DatabaseSanitizer::printDevices(const QVector& deviceIds, const bool missingOnly) +void DatabaseSanitizer::printDevices(const QVector& deviceIds, const ItemAccessFilters accessFilter) { - auto infos = m_pimpl->createList(deviceIds, false, nullptr); - auto usedDevices = m_pimpl->createDeviceList(infos); + auto infos = m_pimpl->createList(deviceIds, accessFilter, nullptr); + auto usedDevices = m_pimpl->createDeviceList(infos, accessFilter); const auto sep = QLatin1Char(' '); QTextStream out(stdout); QTextStream err(stderr); int matchCount = 0; for (const auto& dev : usedDevices) { - if (missingOnly && dev.mounted) { + if ((accessFilter & IgnoreMounted) && dev.mounted) { continue; } matchCount++; diff --git a/src/tools/baloodb/main.cpp b/src/tools/baloodb/main.cpp --- a/src/tools/baloodb/main.cpp +++ b/src/tools/baloodb/main.cpp @@ -59,14 +59,18 @@ "\nOnly applies to \"%1\" command", QStringLiteral("prune")) }, QCommandLineOption{ - QStringList{QStringLiteral("m"), QStringLiteral("missing-only")}, + QStringList{QStringLiteral("m"), QStringLiteral("missing-only")}, i18n("List only inaccessible entries.\nOnly applies to \"%1\"", QStringLiteral("list")) + }, + QCommandLineOption{ + QStringList{QStringLiteral("u"), QStringLiteral("mounted-only")}, + i18n("Act only on item on mounted devices") } }; const auto commands = std::vector{ Command{ - QStringLiteral("list"), + QStringLiteral("list"), i18n("List database contents. Use a regular expression as argument to filter output"), QStringList{ QStringLiteral("pattern") @@ -78,16 +82,16 @@ }, /*TODO: Command{ - QStringLiteral("check"), + QStringLiteral("check"), i18n("Check database contents. " "Beware this may take very long to execute"), QStringList{}, QStringList{} }, */ /*TODO: Command{ - QStringLiteral("prune"), + QStringLiteral("prune"), i18n("Remove stale database entries"), QStringList{ QStringLiteral("pattern") @@ -99,10 +103,10 @@ }, */ Command{ - QStringLiteral("devices"), + QStringLiteral("devices"), i18n("List devices"), QStringList{}, - QStringList{QStringLiteral("missing-only")} + QStringList{QStringLiteral("missing-only"), QStringLiteral("mounted-only")} } }; @@ -114,24 +118,24 @@ } return names; } -const QStringList getOptions(const QString& name) +const QStringList getOptions(const QString& name) { for (const auto& c : commands) { if (c.name == name) { return c.options; } } return QStringList(); } -QString createDescription() +QString createDescription() { QStringList allowedcommands; for (const auto& c: commands) { auto options = getOptions(c.name); const QString optionStr = options.isEmpty() ? QString() : QStringLiteral(" [--%1]").arg(options.join(QLatin1Literal("] [--"))); - + QString argumentStr; if (!c.args.isEmpty() ) { argumentStr = QStringLiteral(" [%1]").arg(c.args.join(QStringLiteral("] ["))); @@ -141,11 +145,11 @@ .arg(c.name) .arg(optionStr) .arg(argumentStr); - + const QString str = QStringLiteral("%1 %2") .arg(commandStr, -48) .arg(c.description); - + allowedcommands.append(str); } const QString allCommandsStr = allowedcommands.join(QStringLiteral("\n ")); @@ -163,22 +167,22 @@ i18n("(c) 2018, Michael Heidelbach")); aboutData.addAuthor(i18n("Michael Heidelbach"), i18n("Maintainer"), QStringLiteral("ottwolt@gmail.com")); KAboutData::setApplicationData(aboutData); - + QCommandLineParser parser; parser.addOptions(options); - parser.addPositionalArgument(QStringLiteral("command"), - i18n("The command to execute"), + parser.addPositionalArgument(QStringLiteral("command"), + i18n("The command to execute"), allowedCommands().join(QStringLiteral("|")) ); - parser.addPositionalArgument(QStringLiteral("pattern"), + parser.addPositionalArgument(QStringLiteral("pattern"), i18nc("Command", "A regular expression applied to the URL of database items" "\nExample: %1" , "baloodb list '^/media/videos/series'" ) ); const QString warnExperiment = QStringLiteral( - "===\nPlease note: This is an experimental tool. Command line switches or their meaning may change.\n==="); - + "===\nPlease note: This is an experimental tool. Command line switches or their meaning may change.\n==="); + parser.setApplicationDescription(warnExperiment + createDescription()); parser.addVersionOption(); parser.addHelpOption(); @@ -188,29 +192,37 @@ qDebug() << "No command"; parser.showHelp(1); } - + auto args = parser.positionalArguments(); auto command = args.at(0); args.removeFirst(); - + if(!allowedCommands().contains(command)) { qDebug() << "Unknown command" << command; parser.showHelp(1); } - + const auto optNames = parser.optionNames(); const auto allowedOptions = getOptions(command); - + QVector deviceIds; for (const auto& dev : parser.values(QStringLiteral("device-id"))) { deviceIds.append(dev.toInt()); } - const bool missingOnly = parser.isSet(QStringLiteral("missing-only")); + const DatabaseSanitizer::ItemAccessFilters accessFilter = ( + parser.isSet(QStringLiteral("missing-only")) + ? DatabaseSanitizer::IgnoreAvailable + : DatabaseSanitizer::IgnoreNone + ) | ( + parser.isSet(QStringLiteral("mounted-only")) + ? DatabaseSanitizer::IgnoreUnmounted + : DatabaseSanitizer::IgnoreNone + ); const QString pattern = args.isEmpty() ? QString() : args.at(0); - const QSharedPointer urlFilter(pattern.isEmpty() - ? nullptr + const QSharedPointer urlFilter(pattern.isEmpty() + ? nullptr : new QRegularExpression{pattern}); auto db = globalDatabaseInstance(); @@ -225,20 +237,20 @@ } DatabaseSanitizer san(db, Transaction::ReadOnly); err << i18n("Listing database contents...") << endl; - san.printList(deviceIds, missingOnly, urlFilter); + san.printList(deviceIds, accessFilter, urlFilter); } else if (command == QStringLiteral("devices")) { if (!db->open(Database::ReadOnlyDatabase)) { err << i18n("Baloo Index could not be opened") << endl; return 1; } DatabaseSanitizer san(db, Transaction::ReadOnly); err << i18n("Listing database contents...") << endl; - san.printDevices(deviceIds, missingOnly); - + san.printDevices(deviceIds, accessFilter); + } else if (command == QStringLiteral("clean")) { /* TODO: add prune command */ parser.showHelp(1); - + } else if (command == QStringLiteral("check")) { parser.showHelp(1); /* TODO: After check methods are improved