File: DiscoverBackendsFactory.cpp

package info (click to toggle)
plasma-discover 6.5.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,288 kB
  • sloc: cpp: 30,576; xml: 2,710; python: 311; sh: 5; makefile: 5
file content (142 lines) | stat: -rw-r--r-- 4,838 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
 *
 *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 */

#include "DiscoverBackendsFactory.h"
#include "libdiscover_debug.h"
#include "resources/AbstractResourcesBackend.h"
#include "resources/ResourcesModel.h"
#include "utils.h"
#include <KConfigGroup>
#include <KDesktopFile>
#include <KLocalizedString>
#include <KSharedConfig>
#include <QCommandLineParser>
#include <QDir>
#include <QDirIterator>
#include <QPluginLoader>
#include <QStandardPaths>

using namespace Qt::StringLiterals;

Q_GLOBAL_STATIC(QStringList, s_requestedBackends)
static bool s_isFeedback = false;

void DiscoverBackendsFactory::setRequestedBackends(const QStringList &backends)
{
    *s_requestedBackends = backends;
}

bool DiscoverBackendsFactory::hasRequestedBackends()
{
    return !s_requestedBackends->isEmpty();
}

DiscoverBackendsFactory::DiscoverBackendsFactory()
{
}

QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::backend(const QString &name) const
{
    if (QDir::isAbsolutePath(name) && QStandardPaths::isTestModeEnabled()) {
        return backendForFile(name, QFileInfo(name).fileName());
    } else {
        return backendForFile(name, name);
    }
}

QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::backendForFile(const QString &libname, const QString &name) const
{
    QPluginLoader *loader = new QPluginLoader(QLatin1String("discover/") + libname, QCoreApplication::instance());

    if (const auto iid = loader->metaData().value("IID"_L1).toString(); iid != QLatin1StringView(DISCOVER_PLUGIN_IID)) {
        qCWarning(LIBDISCOVER_LOG) << "Plugin" << libname << "doesn't have the right IID" << iid << "expected" << DISCOVER_PLUGIN_IID;
        return {};
    }

    // qCDebug(LIBDISCOVER_LOG) << "trying to load plugin:" << loader->fileName();
    AbstractResourcesBackendFactory *f = qobject_cast<AbstractResourcesBackendFactory *>(loader->instance());
    if (!f) {
        qCWarning(LIBDISCOVER_LOG) << "error loading" << libname << loader->errorString() << loader->metaData();
        return {};
    }
    auto instances = f->newInstance(QCoreApplication::instance(), name);
    if (instances.isEmpty()) {
        qCWarning(LIBDISCOVER_LOG) << "Couldn't find the backend: " << libname << "among" << allBackendNames(false, true);
        return instances;
    }

    return instances;
}

QStringList DiscoverBackendsFactory::allBackendNames(bool whitelist, bool allowDummy) const
{
    if (whitelist) {
        QStringList whitelistNames = *s_requestedBackends;
        if (s_isFeedback || !whitelistNames.isEmpty())
            return whitelistNames;
    }

    QStringList pluginNames;
    const auto libraryPaths = QCoreApplication::libraryPaths();
    qDebug() << "libs" << libraryPaths;
    for (const QString &dir : libraryPaths) {
        QDirIterator it(dir + QStringLiteral("/discover"), QDir::Files);
        while (it.hasNext()) {
            it.next();
            if (QLibrary::isLibrary(it.fileName()) && (allowDummy || it.fileName() != QLatin1String("dummy-backend.so"))) {
                pluginNames += it.fileInfo().baseName();
            }
        }
    }

    pluginNames.removeDuplicates(); // will happen when discover is installed twice on the system
    return pluginNames;
}

QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::allBackends() const
{
    QStringList names = allBackendNames();
    auto ret = kTransform<QVector<AbstractResourcesBackend *>>(names, [this](const QString &name) {
        return backend(name);
    });
    ret.removeAll(nullptr);

    if (ret.isEmpty()) {
        qCWarning(LIBDISCOVER_LOG) << "Didn't find any Discover backend!";
    }
    return ret;
}

int DiscoverBackendsFactory::backendsCount() const
{
    return allBackendNames().count();
}

void DiscoverBackendsFactory::setupCommandLine(QCommandLineParser *parser)
{
    parser->addOption(QCommandLineOption(QStringLiteral("backends"),
                                         i18n("List all the backends we'll want to have loaded, separated by comma ','."),
                                         QStringLiteral("names")));
}

void DiscoverBackendsFactory::processCommandLine(QCommandLineParser *parser, bool test)
{
    if (parser->isSet(QStringLiteral("feedback"))) {
        s_isFeedback = true;
        s_requestedBackends->clear();
        return;
    }

    QStringList backends = test //
        ? QStringList{QStringLiteral("dummy-backend")} //
        : parser->value(QStringLiteral("backends")).split(QLatin1Char(','), Qt::SkipEmptyParts);
    for (auto &backend : backends) {
        if (!backend.endsWith(QLatin1String("-backend"))) {
            backend.append(QLatin1String("-backend"));
        }
    }
    *s_requestedBackends = backends;
}