Commit 4b4f6a3f authored by Harald Sitter's avatar Harald Sitter 💎

refactor about-distro to more generically support textual dumps

Summary:
this previously relied on manually replicating strings and whatnot, it was
very awkward to read and the load functions were also getting a bit long.

introducing the new entry system:
generic table entries are now represented by a more generic Entry object
comprised of the entry label (e.g. 'Plasma Version:') and its value
(e.g. '5.17.0'). from those entries the UI is then constructed (i.e.
large parts of the UI are now no longer in the designer file but rather
constructed manually).
all visible entries are further more collected in a global list of entries
from which we'll generate the clipboard dump.
localization switching is now carried out through KLocalized String instead
of having string copies floating about. depending on context we'll either
resolve the localized or original string.

this should also make it easier to change the data set in the future, be
it adding or removing new data

RTL languages have a broken clipboard but it looks that was the case before
as well and I utterly failed to bend it into shape with bidirectional
control characters :(

Test Plan:
# LANGUAGE=en
- all entires shown
- copy to clipboard dumps all entries as before

# LANGUAGE=de
- as above
- copy to as english dumps in english rather than german

# LANGUAGE=he
- as above
- copy in hebrew seems incorrectly order (probably because bidi algorithm falls over from both the RTL label being in the same line as the LTR numbers)

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D26667
parent 8fe51fbe
This diff is collapsed.
This diff is collapsed.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of
the license or (at your option) at any later version that is
accepted by the membership of KDE e.V. (or its successor
approved by the membership of KDE e.V.), which shall act as a
proxy as defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
MIT License Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "BitEntry.h"
BitEntry::BitEntry()
: Entry(ki18n("OS Type:"), bitString())
{
}
QString BitEntry::bitString()
{
const int bits = QT_POINTER_SIZE == 8 ? 64 : 32;
return i18nc("@label %1 is the CPU bit width (e.g. 32 or 64)",
"%1-bit", QString::number(bits));
}
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef BITENTRY_H
#define BITENTRY_H
#include "Entry.h"
#include <QString>
class BitEntry : public Entry
{
public:
BitEntry();
static QString bitString();
};
#endif // BITENTRY_H
......@@ -4,6 +4,13 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(kcm_SRCS
main.cpp
Module.cpp
Entry.cpp
PlasmaEntry.cpp
KernelEntry.cpp
SectionLabel.cpp
BitEntry.cpp
MemoryEntry.cpp
CPUEntry.cpp
)
ki18n_wrap_ui(kcm_SRCS Module.ui)
......
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "CPUEntry.h"
#include <QMap>
#include <solid/device.h>
#include <solid/processor.h>
CPUEntry::CPUEntry()
: Entry(KLocalizedString(), QString())
{
const QList<Solid::Device> list = Solid::Device::listFromType(Solid::DeviceInterface::Processor);
label = ki18np("Processor:", "Processors:").subs(list.count());
// Format processor string
// Group by processor name
QMap<QString, int> processorMap;
for (const Solid::Device &device : list) {
const QString name = device.product();
auto it = processorMap.find(name);
if (it == processorMap.end()) {
processorMap.insert(name, 1);
} else {
++it.value();
}
}
// Create a formatted list of grouped processors
QStringList names;
names.reserve(processorMap.count());
for (auto it = processorMap.constBegin(); it != processorMap.constEnd(); ++it) {
const int count = it.value();
QString name = it.key();
name.replace(QStringLiteral("(TM)"), QChar(8482));
name.replace(QStringLiteral("(R)"), QChar(174));
name = name.simplified();
names.append(QStringLiteral("%1 × %2").arg(count).arg(name));
}
value = names.join(QLatin1String(", "));
}
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef CPUENTRY_H
#define CPUENTRY_H
#include "Entry.h"
class CPUEntry : public Entry
{
public:
CPUEntry();
};
#endif // CPUENTRY_H
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "Entry.h"
Entry::Entry(const KLocalizedString &label_, const QString &value_)
: label(label_)
, value(value_)
{
Q_ASSERT(label.isEmpty() || localizedLabel(Language::English).endsWith(':'));
}
Entry::~Entry() = default;
// When false this entry is garbage (e.g. incomplete data) and shouldn't be rendered.
bool Entry::isValid() const
{
return !label.toString().isEmpty() && !value.isEmpty();
}
// Returns textual representation of entry.
QString Entry::diagnosticLine(Language language) const
{
// FIXME: This isn't really working for right-to-left
// The answer probably is in uncide control characters, but
// didn't work when tried.
// Essentially what needs to happen is that the label should be RTL
// that is to say the colon should be on the left, BUT englishy words
// within that should be LTR, everything besides the label should be LTR
// because we do not localize the values I don't think?
return localizedLabel(language) + ' ' + value + '\n';
}
QString Entry::localizedLabel(Language language) const
{
switch (language) {
case Language::System:
return label.toString();
case Language::English:
// https://bugs.kde.org/show_bug.cgi?id=416247
return label.toString(QStringList { QStringLiteral("en_US") });
}
Q_UNREACHABLE();
return QStringLiteral("Unknown Label Language %1 (bug in KInfocenter!):").arg(
QString::number(static_cast<int>(language)));
}
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef ENTRY_H
#define ENTRY_H
#include <QString>
#include <KLocalizedString>
// Generic dumpable info entry.
// This encapsulates a table entry so that it may be put into the UI
// and also serialized into textual form for copy to clipboard.
// All entries that are meant to be serializable should derive from this!
// This class may either be subclassed or used as-is if label/value are trivial
// to obtain.
class Entry
{
public:
enum class Language {
System,
English
};
Entry(const KLocalizedString &label_, const QString &value_);
virtual ~Entry();
// When false this entry is garbage (e.g. incomplete data) and shouldn't be rendered.
bool isValid() const;
// Returns textual representation of entry.
QString diagnosticLine(Language language = Language::System) const;
// Descriptive label
KLocalizedString label;
// Value of the entry (e.g. the version of plasma)
QString value;
private:
QString localizedLabel(Language language) const;
};
#endif // ENTRY_H
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "KernelEntry.h"
#include <sys/utsname.h>
KernelEntry::KernelEntry()
: Entry(ki18n("Kernel Version:"), kernelVersion())
{
}
QString KernelEntry::kernelVersion()
{
struct utsname utsName;
if (uname(&utsName) == 0) {
return QString::fromLatin1(utsName.release);
}
return QString();
}
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef KERNELENTRY_H
#define KERNELENTRY_H
#include "Entry.h"
class KernelEntry : public Entry
{
public:
KernelEntry();
static QString kernelVersion();
};
#endif // KERNELENTRY_H
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "MemoryEntry.h"
#include <KFormat>
#ifdef Q_OS_LINUX
#include <sys/sysinfo.h>
#elif defined(Q_OS_FREEBSD)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
MemoryEntry::MemoryEntry() : Entry(ki18n("Memory:"), text())
{
}
qlonglong MemoryEntry::calculateTotalRam()
{
qlonglong ret = -1;
#ifdef Q_OS_LINUX
struct sysinfo info;
if (sysinfo(&info) == 0)
// manpage "sizes are given as multiples of mem_unit bytes"
ret = qlonglong(info.totalram) * info.mem_unit;
#elif defined(Q_OS_FREEBSD)
/* Stuff for sysctl */
size_t len;
unsigned long memory;
len = sizeof(memory);
sysctlbyname("hw.physmem", &memory, &len, NULL, 0);
ret = memory;
#endif
return ret;
}
QString MemoryEntry::text()
{
const qlonglong totalRam = calculateTotalRam();
if (totalRam > 0) {
return i18nc("@label %1 is the formatted amount of system memory (e.g. 7,7 GiB)",
"%1 of RAM", KFormat().formatByteSize(totalRam));
}
return i18nc("Unknown amount of RAM", "Unknown");
}
/*
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef MEMORYENTRY_H
#define MEMORYENTRY_H
#include "Entry.h"
class MemoryEntry : public Entry
{
public:
MemoryEntry();
static qlonglong calculateTotalRam();
static QString text();
};
#endif // MEMORYENTRY_H
This diff is collapsed.
/*
Copyright (C) 2012 Harald Sitter <apachelogger@ubuntu.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
SPDX-FileCopyrightText: 2012-2020 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef MODULE_H
......@@ -27,7 +12,7 @@ namespace Ui {
class Module;
}
class QLabel;
class Entry;
class Module : public KCModule
{
......@@ -62,25 +47,24 @@ public:
void defaults() override;
private:
void loadSoftware();
void loadHardware();
// Load os-release data into UI.
void loadOSData();
// Load generic entries into UI.
void loadEntries();
/**
* Copies the software and hardware information to clipboard.
*/
// Copy data dump to clipboard
void copyToClipboard();
// Same as copyToClipboard but in en_US when the system language
// is something else
void copyToClipboardInEnglish();
QVector<QPair<QLabel*, QLabel*> > labelsForClipboard;
QString englishTextForClipboard;
/**
* UI
*/
Ui::Module *ui = nullptr;
/** \returns Version of plasmashell or an empty string when none was found */
QString plasmaVersion() const;
/*** Description entries for dumping into textual form. Already excludes invalids. */
std::vector<const Entry *> m_entries;
};
#endif // MODULE_H
......@@ -46,7 +46,7 @@
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="infoGrid">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
......@@ -137,189 +137,6 @@
</item>
</layout>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Software</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="plasma">
<property name="text">
<string>KDE Plasma Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="plasmaLabel">
<property name="text">
<string notr="true">{KDEVersion}</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="frameworksLabelKey">
<property name="text">
<string>KDE Frameworks Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="frameworksLabel">
<property name="text">
<string notr="true">{FrameworksVersion}</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="qt">
<property name="text">
<string>Qt Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="qtLabel">
<property name="text">
<string notr="true">{QtVersion}</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="kernel">
<property name="text">
<string>Kernel Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="kernelLabel">
<property name="text">
<string notr="true">{KernelName}</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="bitsKey">
<property name="text">
<string>OS Type:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="bitsLabel">
<property name="text">
<string notr="true">{QtArchitecutre}</string>
</property>
</widget>
</item>
<item row="8" column="1">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Hardware</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="processor">
<property name="text">
<string notr="true">Processor:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="processorLabel">
<property name="text">
<string notr="true">{PrcoessorName}</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="memory">
<property name="text">
<string>Memory:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="memoryLabel">
<property name="text">
<string notr="true">{MemoryAmount}</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
......@@ -367,18 +184,18 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonCopyInfoInEnglish">
<property name="toolTip">
<string>Copy software and hardware information to clipboard in English</string>
</property>
<property name="text">
<string>Copy to Clipboard in English</string>