Commit 620be5cd authored by Harald Sitter's avatar Harald Sitter 🚔

[about-distro] pimpl OSRelease privates

Summary:
in preparation of moving it into library

- private members are now in private class
- private class is dptr'd into public class
- public class has getters for all keys
- public class has docs

Test Plan: test still passes

Reviewers: apol

Reviewed By: apol

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D19975
parent 43bfb812
......@@ -31,24 +31,24 @@ private Q_SLOTS:
void testParse()
{
auto r = OSRelease(QFINDTESTDATA("data/os-release"));
QCOMPARE(r.name, "Name");
QCOMPARE(r.version, "100.5");
QCOMPARE(r.id, "theid");
QCOMPARE(r.idLike, QStringList({"otherid", "otherotherid"}));
QCOMPARE(r.versionCodename, "versioncodename");
QCOMPARE(r.versionId, "500.1");
QCOMPARE(r.prettyName, "Pretty Name");
QCOMPARE(r.ansiColor, "1;34");
QCOMPARE(r.cpeName, "cpe:/o:foo:bar:100");
QCOMPARE(r.homeUrl, "https://url.home");
QCOMPARE(r.documentationUrl, "https://url.docs");
QCOMPARE(r.supportUrl, "https://url.support");
QCOMPARE(r.bugReportUrl, "https://url.bugs");
QCOMPARE(r.privacyPolicyUrl, "https://url.privacy");
QCOMPARE(r.buildId, "105.5");
QCOMPARE(r.variant, "Test Edition");
QCOMPARE(r.variantId, "test");
QCOMPARE(r.logo, "start-here-test");
QCOMPARE(r.name(), "Name");
QCOMPARE(r.version(), "100.5");
QCOMPARE(r.id(), "theid");
QCOMPARE(r.idLike(), QStringList({"otherid", "otherotherid"}));
QCOMPARE(r.versionCodename(), "versioncodename");
QCOMPARE(r.versionId(), "500.1");
QCOMPARE(r.prettyName(), "Pretty Name");
QCOMPARE(r.ansiColor(), "1;34");
QCOMPARE(r.cpeName(), "cpe:/o:foo:bar:100");
QCOMPARE(r.homeUrl(), "https://url.home");
QCOMPARE(r.documentationUrl(), "https://url.docs");
QCOMPARE(r.supportUrl(), "https://url.support");
QCOMPARE(r.bugReportUrl(), "https://url.bugs");
QCOMPARE(r.privacyPolicyUrl(), "https://url.privacy");
QCOMPARE(r.buildId(), "105.5");
QCOMPARE(r.variant(), "Test Edition");
QCOMPARE(r.variantId(), "test");
QCOMPARE(r.logo(), "start-here-test");
}
};
......
......@@ -150,7 +150,7 @@ void Module::loadSoftware()
OSRelease os;
QString logoPath = cg.readEntry("LogoPath", os.logo);
QString logoPath = cg.readEntry("LogoPath", os.logo());
if (logoPath.isEmpty()) {
logoPath = QStringLiteral("start-here-kde");
}
......@@ -160,10 +160,10 @@ void Module::loadSoftware()
// We allow overriding of the OS name for branding purposes.
// For example OS Ubuntu may be rebranded as Kubuntu. Also Kubuntu Active
// as a product brand is different from Kubuntu.
const QString distroName = cg.readEntry("Name", os.name);
const QString distroName = cg.readEntry("Name", os.name());
const QString osrVersion = cg.readEntry("UseOSReleaseVersion", false)
? os.version
: os.versionId;
? os.version()
: os.versionId();
const QString versionId = cg.readEntry("Version", osrVersion);
const QString distroNameVersion = QStringLiteral("%1 %2").arg(distroName, versionId);
ui->nameVersionLabel->setText(distroNameVersion);
......@@ -173,14 +173,14 @@ void Module::loadSoftware()
labelsForClipboard << qMakePair(dummyDistroDescriptionLabel, ui->nameVersionLabel);
englishTextForClipboard += QStringLiteral("Operating System: %1\n").arg(distroNameVersion);
const QString variant = cg.readEntry("Variant", os.variant);
const QString variant = cg.readEntry("Variant", os.variant());
if (variant.isEmpty()) {
ui->variantLabel->hide();
} else {
ui->variantLabel->setText(variant);
}
const QString url = cg.readEntry("Website", os.homeUrl);
const QString url = cg.readEntry("Website", os.homeUrl());
if (url.isEmpty()) {
ui->urlLabel->hide();
} else {
......
......@@ -25,7 +25,8 @@
#include <KShell>
static void setVar(QString *var, const QString &value)
// Sets a QString var
static void setVar(QString *var, const QString &value)
{
// Values may contain quotation marks, strip them as we have no use for them.
KShell::Errors error;
......@@ -36,6 +37,7 @@ static void setVar(QString *var, const QString &value)
*var = args.join(QLatin1Char(' '));
}
// Sets a QStringList var (i.e. splits a string value)
static void setVar(QStringList *var, const QString &value)
{
// Instead of passing the verbatim value we manually strip any initial quotes
......@@ -60,77 +62,207 @@ static void setVar(QStringList *var, const QString &value)
*var = args;
}
OSRelease::OSRelease(const QString &filePath)
class Q_DECL_HIDDEN OSRelease::Private
{
// Set default values for non-optional fields.
name = QStringLiteral("Linux");
id = QStringLiteral("linux");
prettyName = QStringLiteral("Linux");
public:
Private(const QString &filePath)
: name(QStringLiteral("Linux"))
, id(QStringLiteral("linux"))
, prettyName(QStringLiteral("Linux"))
{
// Default values for non-optional fields set above ^.
if (filePath.isEmpty()) {
return;
}
QHash<QString, QString *> stringHash = {
{ QStringLiteral("NAME"), &name },
{ QStringLiteral("VERSION"), &version },
{ QStringLiteral("ID"), &id },
// idLike is not a QString, special handling below!
{ QStringLiteral("VERSION_CODENAME"), &versionCodename },
{ QStringLiteral("VERSION_ID"), &versionId },
{ QStringLiteral("PRETTY_NAME"), &prettyName },
{ QStringLiteral("ANSI_COLOR"), &ansiColor },
{ QStringLiteral("CPE_NAME"), &cpeName },
{ QStringLiteral("HOME_URL"), &homeUrl },
{ QStringLiteral("DOCUMENTATION_URL"), &documentationUrl },
{ QStringLiteral("SUPPORT_URL"), &supportUrl },
{ QStringLiteral("BUG_REPORT_URL"), &bugReportUrl },
{ QStringLiteral("PRIVACY_POLICY_URL"), &privacyPolicyUrl },
{ QStringLiteral("BUILD_ID"), &buildId },
{ QStringLiteral("VARIANT"), &variant },
{ QStringLiteral("VARIANT_ID"), &variantId },
{ QStringLiteral("LOGO"), &logo }
};
QFile file(filePath);
// NOTE: The os-release specification defines default values for specific
// fields which means that even if we can not read the os-release file
// we have sort of expected default values to use.
// TODO: it might still be handy to indicate to the outside whether
// fallback values are being used or not.
file.open(QIODevice::ReadOnly | QIODevice::Text);
QString line;
QStringList comps;
while (!file.atEnd()) {
line = QString::fromLatin1(file.readLine());
if (line.startsWith(QLatin1Char('#'))) {
// Comment line
continue;
if (filePath.isEmpty()) {
return;
}
comps = line.split(QLatin1Char('='));
QHash<QString, QString *> stringHash = {
{ QStringLiteral("NAME"), &name },
{ QStringLiteral("VERSION"), &version },
{ QStringLiteral("ID"), &id },
// idLike is not a QString, special handling below!
{ QStringLiteral("VERSION_CODENAME"), &versionCodename },
{ QStringLiteral("VERSION_ID"), &versionId },
{ QStringLiteral("PRETTY_NAME"), &prettyName },
{ QStringLiteral("ANSI_COLOR"), &ansiColor },
{ QStringLiteral("CPE_NAME"), &cpeName },
{ QStringLiteral("HOME_URL"), &homeUrl },
{ QStringLiteral("DOCUMENTATION_URL"), &documentationUrl },
{ QStringLiteral("SUPPORT_URL"), &supportUrl },
{ QStringLiteral("BUG_REPORT_URL"), &bugReportUrl },
{ QStringLiteral("PRIVACY_POLICY_URL"), &privacyPolicyUrl },
{ QStringLiteral("BUILD_ID"), &buildId },
{ QStringLiteral("VARIANT"), &variant },
{ QStringLiteral("VARIANT_ID"), &variantId },
{ QStringLiteral("LOGO"), &logo }
};
if (comps.size() != 2) {
// Invalid line.
continue;
}
QFile file(filePath);
// NOTE: The os-release specification defines default values for specific
// fields which means that even if we can not read the os-release file
// we have sort of expected default values to use.
// TODO: it might still be handy to indicate to the outside whether
// fallback values are being used or not.
file.open(QIODevice::ReadOnly | QIODevice::Text);
QString line;
QStringList parts;
while (!file.atEnd()) {
// Trimmed to handle indented comment lines properly
line = QString::fromLatin1(file.readLine()).trimmed();
QString key = comps.at(0);
QString value = comps.at(1).trimmed();
if (line.startsWith(QLatin1Char('#'))) {
// Comment line
continue;
}
if (QString *var = stringHash.value(key, nullptr)) {
setVar(var, value);
}
parts = line.split(QLatin1Char('='));
// ID_LIKE is a list and parsed as such (rather than a QString).
if (key == QLatin1String("ID_LIKE")) {
setVar(&idLike, value);
}
if (parts.size() != 2 || line.contains(QChar('#'))) {
// Invalid line...
// For the purposes of simple parsing we'll not support >2 =
// or >1 # characters.
// The former makes splitting and the latter makes comment
// stripping difficult.
continue;
}
QString key = parts.at(0);
QString value = parts.at(1).trimmed();
if (QString *var = stringHash.value(key, nullptr)) {
setVar(var, value);
continue;
}
// ID_LIKE is a list and parsed as such (rather than a QString).
if (key == QLatin1String("ID_LIKE")) {
setVar(&idLike, value);
continue;
}
// os-release explicitly allows for vendor specific aditions. We have no
// interest in those right now.
}
}
QString name;
QString version;
QString id;
QStringList idLike;
QString versionCodename;
QString versionId;
QString prettyName;
QString ansiColor;
QString cpeName;
QString homeUrl;
QString documentationUrl;
QString supportUrl;
QString bugReportUrl;
QString privacyPolicyUrl;
QString buildId;
QString variant;
QString variantId;
QString logo;
};
OSRelease::OSRelease(const QString &filePath)
: d(new Private(filePath))
{
}
OSRelease::~OSRelease()
{
delete d;
}
QString OSRelease::name() const
{
return d->name;
}
QString OSRelease::version() const
{
return d->version;
}
QString OSRelease::id() const
{
return d->id;
}
QStringList OSRelease::idLike() const
{
return d->idLike;
}
QString OSRelease::versionCodename() const
{
return d->versionCodename;
}
QString OSRelease::versionId() const
{
return d->versionId;
}
QString OSRelease::prettyName() const
{
return d->prettyName;
}
QString OSRelease::ansiColor() const
{
return d->ansiColor;
}
QString OSRelease::cpeName() const
{
return d->cpeName;
}
QString OSRelease::homeUrl() const
{
return d->homeUrl;
}
QString OSRelease::documentationUrl() const
{
return d->documentationUrl;
}
QString OSRelease::supportUrl() const
{
return d->supportUrl;
}
QString OSRelease::bugReportUrl() const
{
return d->bugReportUrl;
}
QString OSRelease::privacyPolicyUrl() const
{
return d->privacyPolicyUrl;
}
QString OSRelease::buildId() const
{
return d->buildId;
}
QString OSRelease::variant() const
{
return d->variant;
}
QString OSRelease::variantId() const
{
return d->variantId;
}
QString OSRelease::logo() const
{
return d->logo;
}
QString OSRelease::defaultFilePath()
......
......@@ -24,33 +24,73 @@
#include <QString>
#include <QStringList>
/**
* @brief The OSRelease class parses /etc/os-release files
*
* https://www.freedesktop.org/software/systemd/man/os-release.html
*
* os-release is a free software standard for describing an operating system.
* This class parses and models os-release files.
*/
class OSRelease
{
public:
OSRelease(const QString &filePath = defaultFilePath());
/**
* Constructs a new OSRelease instance. Parsing happens in the constructor
* and the data is not cached across instances.
*
* @note For parsing simplicity neither trailing comments nor multiple '='
* characters are allowed.
*
* @param filePath The path to the os-release file. By default the first
* available file of the paths specified in the os-release manpage is
* parsed.
*/
explicit OSRelease(const QString &filePath = defaultFilePath());
~OSRelease();
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#NAME= */
QString name() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#VERSION= */
QString version() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#ID= */
QString id() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#ID_LIKE= */
QStringList idLike() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#VERSION_CODENAME= */
QString versionCodename() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#VERSION_ID= */
QString versionId() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#PRETTY_NAME= */
QString prettyName() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#ANSI_COLOR= */
QString ansiColor() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#CPE_NAME= */
QString cpeName() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#HOME_URL= */
QString homeUrl() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#HOME_URL= */
QString documentationUrl() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#HOME_URL= */
QString supportUrl() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#HOME_URL= */
QString bugReportUrl() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#HOME_URL= */
QString privacyPolicyUrl() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#BUILD_ID= */
QString buildId() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#VARIANT= */
QString variant() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#VARIANT_ID= */
QString variantId() const;
/** @see https://www.freedesktop.org/software/systemd/man/os-release.html#LOGO= */
QString logo() const;
private:
static QString defaultFilePath();
QString name;
QString version;
QString id;
QStringList idLike;
QString versionCodename;
QString versionId;
QString prettyName;
QString ansiColor;
QString cpeName;
// TODO: url struct or map?
QString homeUrl;
QString documentationUrl;
QString supportUrl;
QString bugReportUrl;
QString privacyPolicyUrl;
QString buildId;
QString variant;
QString variantId;
QString logo;
class Private;
Private *const d = nullptr;
};
#endif // OSRELEASE_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment