File: PackageKitDependencies.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 (207 lines) | stat: -rw-r--r-- 5,698 bytes parent folder | download | duplicates (2)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 *   SPDX-FileCopyrightText: 2024 ivan tkachenko <me@ratijas.tk>
 *   SPDX-FileCopyrightText: 2024 Harald Sitter <sitter@kde.org>
 *
 *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 */

#include "PackageKitDependencies.h"
#include "PackageKitMessages.h"
#include "libdiscover_backend_packagekit_debug.h"

#include <QDebug>

#include <PackageKit/Daemon>
#include <PackageKit/Transaction>

#include <variant>

using namespace Qt::StringLiterals;

PackageKitDependency::PackageKitDependency(PackageKit::Transaction::Info info, const QString &packageId, const QString &summary)
    : m_info(info)
    , m_infoString(PackageKitMessages::info(info))
    , m_packageId(packageId)
    , m_summary(summary)
{
}

bool PackageKitDependency::operator==(const PackageKitDependency &other) const
{
    // Skip derived fields.
    return m_info == other.m_info && m_packageId == other.m_packageId && m_summary == other.m_summary;
}

PackageKit::Transaction::Info PackageKitDependency::info() const
{
    return m_info;
}

QString PackageKitDependency::infoString() const
{
    return m_infoString;
}

QString PackageKitDependency::packageId() const
{
    return m_packageId;
}

QString PackageKitDependency::packageName() const
{
    return PackageKit::Transaction::packageName(m_packageId);
}

QString PackageKitDependency::summary() const
{
    return m_summary;
}

PackageKitDependencies::PackageKitDependencies(QObject *parent)
    : QObject(parent)
{
}

PackageKitDependencies::~PackageKitDependencies()
{
    cancel(false);
}

QString PackageKitDependencies::packageId() const
{
    return m_packageId;
}

void PackageKitDependencies::setPackageId(const QString &packageId)
{
    if (m_packageId != packageId) {
        m_packageId = packageId;
        cancel(true);
        Q_EMIT packageIdChanged();
    }
}

bool PackageKitDependencies::hasFetchedDependencies()
{
    return m_state.has_value() && std::holds_alternative<Data>(*m_state);
}

QList<PackageKitDependency> PackageKitDependencies::dependencies()
{
    if (!m_state.has_value()) {
        return {};
    }
    if (auto list = std::get_if<Data>(&m_state.value())) {
        return *list;
    }
    // the job is still running
    return {};
}

void PackageKitDependencies::start()
{
    Q_ASSERT(!m_state.has_value()); // cancel must have been called before!
    Job job{new PackageKitFetchDependenciesJob(m_packageId)};
    connect(job, &PackageKitFetchDependenciesJob::finished, this, &PackageKitDependencies::onJobFinished);
    m_state = job;
}

void PackageKitDependencies::refresh()
{
    cancel(true);
    start();
}

void PackageKitDependencies::onJobFinished(QList<PackageKitDependency> dependencies)
{
    Q_ASSERT(m_state.has_value());
    Q_ASSERT(std::holds_alternative<Job>(m_state.value()));

    if (auto job = std::get<Job>(m_state.value())) {
        // Should not emit twice, but better be on the safe side
        disconnect(job, &PackageKitFetchDependenciesJob::finished, this, &PackageKitDependencies::onJobFinished);
    }

    m_state = dependencies;
    Q_EMIT dependenciesChanged();
}

void PackageKitDependencies::cancel(bool notify)
{
    if (m_state.has_value()) {
        if (auto jobPtr = std::get_if<Job>(&m_state.value())) {
            if (auto job = *jobPtr) {
                disconnect(job, &PackageKitFetchDependenciesJob::finished, this, &PackageKitDependencies::onJobFinished);
                job->cancel();
            }
            notify = false;
        }
        m_state.reset();
        // first reset, only then notify and only if variant held Data before (i.e. not a Job)
        if (notify) {
            Q_EMIT dependenciesChanged();
        }
    }
}

PackageKitFetchDependenciesJob::PackageKitFetchDependenciesJob(const QString &packageId)
{
    if (packageId.isEmpty()) {
        onTransactionFinished();
        return;
    }

    m_transaction = PackageKit::Daemon::dependsOn(packageId);
    if (!m_transaction) {
        onTransactionFinished();
        return;
    }

    m_transaction->setParent(this);
    connect(m_transaction, &QObject::destroyed, this, &QObject::deleteLater);

    connect(m_transaction, &PackageKit::Transaction::errorCode, this, &PackageKitFetchDependenciesJob::onTransactionErrorCode);
    connect(m_transaction, &PackageKit::Transaction::package, this, &PackageKitFetchDependenciesJob::onTransactionPackage);
    connect(m_transaction, &PackageKit::Transaction::finished, this, &PackageKitFetchDependenciesJob::onTransactionFinished);
}

PackageKitFetchDependenciesJob::~PackageKitFetchDependenciesJob()
{
    cancel();
}

void PackageKitFetchDependenciesJob::cancel()
{
    if (m_transaction) {
        m_transaction->cancel();
    }
    deleteLater();
}

void PackageKitFetchDependenciesJob::onTransactionErrorCode(PackageKit::Transaction::Error error, const QString &details)
{
    qCWarning(LIBDISCOVER_BACKEND_PACKAGEKIT_LOG) << "PackageKitFetchDependenciesJob: Transaction error:" << m_transaction << error << details;
}

void PackageKitFetchDependenciesJob::onTransactionPackage(PackageKit::Transaction::Info info, const QString &packageId, const QString &summary)
{
    m_dependencies.append(PackageKitDependency(info, packageId, summary));
}

void PackageKitFetchDependenciesJob::onTransactionFinished()
{
    std::sort(m_dependencies.begin(), m_dependencies.end(), [](const PackageKitDependency &a, const PackageKitDependency &b) {
        return a.info() < b.info() || (a.info() == b.info() && a.packageName() < b.packageName());
    });

    Q_EMIT finished(m_dependencies);

    deleteLater();
}

void PackageKitDependencies::setDirty()
{
    cancel(true);
}

#include "moc_PackageKitDependencies.cpp"