File indexing completed on 2024-06-16 05:01:13

0001 /*
0002  *   Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
0003  *
0004  *   This program is free software; you can redistribute it and/or modify
0005  *   it under the terms of the GNU General Public License as published by
0006  *   the Free Software Foundation; either version 2 of the License, or
0007  *   (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *   GNU General Public License for more details.
0013  *
0014  *   You should have received a copy of the GNU General Public License
0015  *   along with this program; if not, write to the
0016  *   Free Software Foundation, Inc.,
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
0018  */
0019 
0020 #include <QCoreApplication>
0021 #include <QDebug>
0022 #include <QObject> // tr()
0023 #include <QModelIndex>
0024 #include <QTime>
0025 
0026 #include "common/resource.h"
0027 #include "common/storage.h"
0028 #include "common/resourceconfig.h"
0029 #include "common/log.h"
0030 #include "common/definitions.h"
0031 #include "common/store.h"
0032 #include "common/propertyparser.h"
0033 
0034 #include "sinksh_utils.h"
0035 #include "state.h"
0036 #include "syntaxtree.h"
0037 
0038 namespace SinkLiveQuery
0039 {
0040 
0041 Syntax::List syntax();
0042 
0043 bool livequery(const QStringList &args_, State &state)
0044 {
0045     if (args_.isEmpty()) {
0046         state.printError(syntax()[0].usage());
0047         return false;
0048     }
0049 
0050     auto options = SyntaxTree::parseOptions(args_);
0051 
0052     auto type = options.positionalArguments.isEmpty() ? QString{} : options.positionalArguments.first();
0053 
0054     Sink::Query query;
0055     query.setId("livequery");
0056     query.setFlags(Sink::Query::LiveQuery);
0057     if (!SinkshUtils::applyFilter(query, options)) {
0058         state.printError(syntax()[0].usage());
0059         return false;
0060     }
0061     if (options.options.contains("resource")) {
0062         for (const auto &f : options.options.value("resource")) {
0063             query.resourceFilter(f.toLatin1());
0064         }
0065     }
0066     if (options.options.contains("filter")) {
0067         for (const auto &f : options.options.value("filter")) {
0068             auto filter = f.split("=");
0069             const auto property = filter.value(0).toLatin1();
0070             query.filter(property, Sink::PropertyParser::parse(type.toLatin1(), property, filter.value(1)));
0071         }
0072     }
0073     if (options.options.contains("id")) {
0074         for (const auto &f : options.options.value("id")) {
0075             query.filter(f.toUtf8());
0076         }
0077     }
0078     // auto compact = options.options.contains("compact");
0079     if (!options.options.contains("showall")) {
0080         if (options.options.contains("show")) {
0081             auto list = options.options.value("show");
0082             std::transform(list.constBegin(), list.constEnd(), std::back_inserter(query.requestedProperties), [] (const QString &s) { return s.toLatin1(); });
0083         } else {
0084             query.requestedProperties = SinkshUtils::requestedProperties(type);
0085         }
0086     }
0087 
0088     QByteArrayList toPrint;
0089     QStringList tableLine;
0090 
0091     auto model = SinkshUtils::loadModel(query.type(), query);
0092     QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, state](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) {
0093         if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
0094             state.printLine(QObject::tr("Counted results %1").arg(model->rowCount(QModelIndex())));
0095         }
0096     });
0097     QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, state](const QModelIndex &index, int start, int end) {
0098         for (int i = start; i <= end; i++) {
0099             auto object = model->data(model->index(i, 0, index), Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>();
0100             state.printLine("Resource: " + object->resourceInstanceIdentifier(), 1);
0101             state.printLine("Identifier: " + object->identifier(), 1);
0102             state.stageTableLine(QStringList()
0103                     << QObject::tr("Property:")
0104                     << QObject::tr("Value:"));
0105 
0106             for (const auto &property : object->availableProperties()) {
0107                 state.stageTableLine(QStringList()
0108                         << property
0109                         << object->getProperty(property).toString());
0110             }
0111             state.flushTable();
0112         }
0113     });
0114 
0115     if (!model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()) {
0116         return true;
0117     }
0118 
0119     return false;
0120 }
0121 
0122 Syntax::List syntax()
0123 {
0124     Syntax list("livequery", QObject::tr("Run a livequery."), &SinkLiveQuery::livequery, Syntax::EventDriven);
0125 
0126     list.addPositionalArgument({"type", "The type to run the livequery on" });
0127     list.addParameter("resource", {"resource", "Filter the livequery to the given resource" });
0128     list.addFlag("compact", "Use a compact view (reduces the size of IDs)");
0129     list.addParameter("filter", {"property=$value", "Filter the results" });
0130     list.addParameter("id", {"id", "List only the content with the given ID" });
0131     list.addFlag("showall", "Show all properties");
0132     list.addParameter("show", {"property", "Only show the given property" });
0133 
0134     list.completer = &SinkshUtils::resourceOrTypeCompleter;
0135     return Syntax::List() << list;
0136 }
0137 
0138 REGISTER_SYNTAX(SinkLiveQuery)
0139 
0140 }