core: use hyprutils and std again

This commit is contained in:
outfoxxed 2024-10-15 03:17:31 -07:00
parent 6738e7db72
commit 5d6473bd79
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
10 changed files with 166 additions and 163 deletions

View file

@ -6,10 +6,13 @@ string(STRIP ${VER_RAW} VER)
project(hsi VERSION ${VER} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.5 REQUIRED COMPONENTS Widgets Quick QuickControls2)
set(CMAKE_CXX_STANDARD 20)
find_package(PkgConfig REQUIRED)
pkg_check_modules(hyprutils REQUIRED IMPORTED_TARGET hyprutils)
qt_standard_project_setup(REQUIRES 6.5)

24
flake.lock generated
View file

@ -1,5 +1,28 @@
{
"nodes": {
"hyprutils": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1727300645,
"narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprutils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1728492678,
@ -18,6 +41,7 @@
},
"root": {
"inputs": {
"hyprutils": "hyprutils",
"nixpkgs": "nixpkgs",
"systems": "systems"
}

View file

@ -4,6 +4,12 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
systems.url = "github:nix-systems/default-linux";
hyprutils = {
url = "github:hyprwm/hyprutils";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
};
};
outputs = {

View file

@ -5,6 +5,8 @@
kdePackages,
pciutils,
qt6,
pkg-config,
hyprutils,
version ? "0",
}: let
inherit (lib.sources) cleanSource cleanSourceWith;
@ -24,6 +26,7 @@ in
nativeBuildInputs = [
cmake
pkg-config
qt6.wrapQtAppsHook
];
@ -32,6 +35,7 @@ in
qt6.qtbase
qt6.qtsvg
qt6.qtwayland
hyprutils
];
preFixup = ''

View file

@ -14,6 +14,7 @@ in {
default = self.overlays.hyprsysteminfo;
hyprsysteminfo = lib.composeManyExtensions [
inputs.hyprutils.overlays.default
(final: prev: {
hyprsysteminfo = final.callPackage ./. {
version = "${version}+date=${date}_${self.shortRev or "dirty"}";

View file

@ -11,4 +11,4 @@ qt_add_qml_module(hyprsysteminfo
QML_FILES main.qml
)
target_link_libraries(hyprsysteminfo PRIVATE Qt6::Widgets Qt6::QuickControls2)
target_link_libraries(hyprsysteminfo PRIVATE Qt6::Widgets Qt6::QuickControls2 PkgConfig::hyprutils)

View file

@ -2,51 +2,53 @@
#include "util/Utils.hpp"
#include <qclipboard.h>
#include <array>
#include <qcontainerfwd.h>
#include <qfiledevice.h>
#include <qimage.h>
#include <qobject.h>
#include <qscreen.h>
#include <qfile.h>
#include <qstringliteral.h>
#include <string>
#include <format>
#include <qguiapplication.h>
#include <qtenvironmentvariables.h>
#include <qwindowdefs.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <hyprutils/string/VarList.hpp>
#include <hyprutils/string/String.hpp>
using namespace Hyprutils::String;
CSystemInternals::CSystemInternals(QObject* parent) : QObject(parent) {
// gather data from os-release
{
QFile osInfo("/etc/os-release");
if (osInfo.open(QIODevice::ReadOnly | QIODevice::Text)) {
auto stream = QTextStream(&osInfo);
if (auto data = readFile("/etc/os-release")) {
CVarList lines(data.value(), 0, '\n');
while (!stream.atEnd()) {
auto line = stream.readLine();
auto split = line.split('=');
if (split.length() != 2)
continue;
for (auto& line : lines) {
CVarList param(line, 2, '=');
const auto& key = split.at(0);
auto value = split.at(1);
const auto& key = param[0];
auto value = param[1];
if (value.length() >= 2 && value.at(0) == '\"')
value = value.sliced(1).chopped(1);
if (value.length() >= 2 && value.at(0) == '\"')
value = value.substr(1, value.length() - 2);
if (key == "PRETTY_NAME") {
systemName = value;
continue;
}
if (key == "PRETTY_NAME") {
systemName = QString::fromLocal8Bit(value);
continue;
}
if (key == "HOME_URL") {
systemURL = value;
continue;
}
if (key == "HOME_URL") {
systemURL = QString::fromLocal8Bit(value);
continue;
}
if (key == "LOGO") {
systemLogoName = value;
continue;
}
if (key == "LOGO") {
systemLogoName = QString::fromLocal8Bit(value);
continue;
}
}
}
@ -60,34 +62,25 @@ CSystemInternals::CSystemInternals(QObject* parent) : QObject(parent) {
// get hyprland info
if (getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
hlSystemVersion = execAndGet("hyprctl", {"version"});
auto tagIndex = hlSystemVersion.indexOf("Tag: ");
auto DATA = hlSystemVersion.toStdString();
if (tagIndex != -1) {
hyprlandVersionLong = hlSystemVersion.sliced(tagIndex + 5);
auto commaIndex = hyprlandVersionLong.indexOf(',');
if (commaIndex != -1)
hyprlandVersionLong = hyprlandVersionLong.first(commaIndex);
auto dashIndex = hyprlandVersionLong.indexOf('-');
if (dashIndex == -1)
hyprlandVersion = hyprlandVersionLong;
else
hyprlandVersion = hyprlandVersionLong.first(dashIndex);
if (DATA.contains("Tag: ")) {
auto temp = DATA.substr(DATA.find("Tag: ") + 5);
temp = temp.substr(0, temp.find(","));
hyprlandVersionLong = QString::fromLocal8Bit(temp);
hyprlandVersion = QString::fromLocal8Bit(temp.substr(0, temp.find("-")));
}
if (hyprlandVersionLong.isEmpty() && hlSystemVersion.contains("at commit")) {
auto commitIndex = hlSystemVersion.indexOf("at commit ");
if (commitIndex != -1) {
hyprlandVersionLong = hlSystemVersion.sliced(commitIndex + 10);
hyprlandVersionLong = substrUntil(hyprlandVersionLong, ' ').left(7);
hyprlandVersion = hyprlandVersionLong;
}
if (hyprlandVersionLong.length() <= 0 && DATA.contains("at commit")) {
auto temp = DATA.substr(DATA.find("at commit") + 10);
temp = temp.substr(0, temp.find(" "));
hyprlandVersionLong = QString::fromLocal8Bit(temp.substr(0, 7));
hyprlandVersion = QString::fromLocal8Bit(temp.substr(0, 7));
}
if (hyprlandVersionLong.isEmpty()) {
hyprlandVersionLong = "unknown";
hyprlandVersion = "unknown";
hyprlandVersionLong = QStringLiteral("unknown");
hyprlandVersion = QStringLiteral("unknown");
}
hlSystemInfo = execAndGet("hyprctl", {"systeminfo"});
@ -97,168 +90,125 @@ CSystemInternals::CSystemInternals(QObject* parent) : QObject(parent) {
// get cpu info
{
auto DATA = execAndGet("lscpu");
const auto DATA = execAndGet("lscpu").toStdString();
if (DATA.contains("odel name")) {
QString arch, model, ghz, nproc;
auto textStream = QTextStream(&DATA);
std::string arch, model, ghz, nproc;
while (!textStream.atEnd()) {
auto line = textStream.readLine();
auto indexOfColon = line.indexOf(':');
if (indexOfColon == -1)
continue;
auto left = line.sliced(0, indexOfColon).trimmed();
auto right = line.sliced(indexOfColon + 1).trimmed();
CVarList data(DATA, 0, '\n');
for (auto& line : data) {
std::string left, right;
left = trim(line.substr(0, line.find(":")));
right = trim(line.substr(line.find(":") + 1));
if (left == "Architecture") {
arch = right;
continue;
}
if (left == "Model name") {
model = right;
continue;
}
if (left == "CPU(s)") {
nproc = right;
continue;
}
if (left == "CPU max MHz") {
auto ok = false;
auto ghzFloat = right.toFloat(&ok);
if (ok)
ghz = QString("%1Ghz").arg(ghzFloat / 1000.F, 2, 'g', 2);
else
ghz = "?Ghz";
try {
ghz = std::format("{:.02}GHz", std::stof(right) / 1000.F);
} catch (...) { ghz = "?GHz"; }
continue;
}
}
cpuInfo = QString("%1 at %2x%3 (%4)").arg(model).arg(nproc).arg(ghz).arg(arch);
cpuInfo = QString::fromLocal8Bit(std::format("{} at {}x{} ({})", model, nproc, ghz, arch));
}
}
// get gpu info
{
auto DATA = execAndGet("lspci", {"-vnn"});
auto textStream = QTextStream(&DATA);
auto ok = false;
const auto DATA = execAndGet("lspci", {"-vnn"}, &ok).toStdString();
CVarList lines(DATA, 0, '\n');
if (!DATA.isEmpty())
gpuInfo.clear();
if (ok) {
for (auto& line : lines) {
if (!line.contains("VGA"))
continue;
gpuInfo.emplace_back(QString::fromLocal8Bit(std::format("{}", line.substr(line.find(":", line.find("VGA")) + 2))));
}
while (!textStream.atEnd()) {
auto line = textStream.readLine();
auto indexOfVga = line.indexOf("VGA");
if (indexOfVga == -1)
continue;
line = line.sliced(indexOfVga);
auto indexOfColon = line.indexOf(": ");
if (indexOfColon == -1)
continue;
line = line.sliced(indexOfColon + 2);
gpuInfo.emplaceBack(line);
}
if (gpuInfo.isEmpty()) {
gpuInfo.emplaceBack("No GPUs found");
}
if (gpuInfo.isEmpty())
gpuInfo.emplaceBack(QStringLiteral("No GPUs found"));
} else
gpuInfo.emplaceBack(QStringLiteral("missing dependency: lspci"));
}
// get ram info
{
auto DATA = execAndGet("free");
auto textStream = QTextStream(&DATA);
const auto DATA = execAndGet("free").toStdString();
if (DATA.contains("total")) {
CVarList data(DATA, 0, '\n');
if (textStream.readLine().contains("total")) {
auto ramIntToReadable = [](QStringView datapoint) -> QString {
auto ok = false;
auto ghzFloat = datapoint.toULongLong(&ok);
if (ok)
return QString("%1GB").arg(ghzFloat / 1000000.0, 3, 'g', 3);
else
return "[error]";
auto ramIntToReadable = [](const std::string& datapoint) -> std::string {
try {
auto asInt = std::stoull(datapoint);
return std::format("{:.03}GB", asInt / 1000000.0);
} catch (...) { return "[error]"; }
};
auto props = textStream.readLine().simplified().split(' ');
ramInfo = QString("%1 / %2").arg(ramIntToReadable(props[2])).arg(ramIntToReadable(props[1]));
CVarList props(data[1], 0, 's', true);
ramInfo = QString::fromLocal8Bit(std::format("{} / {}", ramIntToReadable(props[2]), ramIntToReadable(props[1])));
}
}
// other, misc
if (auto DE = qEnvironmentVariable("XDG_CURRENT_DESKTOP"); !DE.isEmpty())
this->DE = DE;
if (auto current = qEnvironmentVariable("XDG_CURRENT_DESKTOP"); !current.isEmpty())
DE = current;
{
QFile uptimeFile("/proc/uptime");
if (uptimeFile.open(QFile::ReadOnly | QFile::Text)) {
auto ok = false;
auto uptime = substrUntil(uptimeFile.readAll(), ' ').toFloat(&ok);
if (auto procUptime = readFile("/proc/uptime")) {
CVarList data(procUptime.value(), 0, 's', true);
if (ok) {
int uptimeSeconds = std::round(uptime);
int uptimeDays = std::floor(uptimeSeconds / 3600.0 / 24.0);
int uptimeHours = std::floor((uptimeSeconds % (3600 * 24)) / 3600.0);
int uptimeMinutes = std::floor((uptimeSeconds % (3600)) / 60.0);
try {
int uptimeSeconds = std::round(std::stof(data[0]));
int uptimeDays = std::floor(uptimeSeconds / 3600.0 / 24.0);
int uptimeHours = std::floor((uptimeSeconds % (3600 * 24)) / 3600.0);
int uptimeMinutes = std::floor((uptimeSeconds % (3600)) / 60.0);
QString upStr;
auto textStream = QTextStream(&upStr);
auto upStr = std::format("{}{}{}", (uptimeDays > 0 ? std::format("{} days, ", uptimeDays) : ""), (uptimeHours > 0 ? std::format("{} hours, ", uptimeHours) : ""),
(uptimeMinutes > 0 ? std::format("{} minutes, ", uptimeMinutes) : ""));
if (uptimeDays > 0)
textStream << uptimeDays << " days, ";
if (!upStr.empty())
upStr = upStr.substr(0, upStr.length() - 2);
if (uptimeHours > 0)
textStream << uptimeHours << " hours, ";
if (uptimeMinutes > 0)
textStream << uptimeMinutes << " minutes, ";
if (!upStr.isEmpty())
upStr.chop(2);
this->uptime = upStr;
}
}
uptime = QString::fromLocal8Bit(upStr);
} catch (...) { ; }
}
{
QString screens;
QTextStream textStream(&screens);
std::string screens;
for (auto* s : QGuiApplication::screens()) {
textStream << s->name() << ' ' << '(' << s->geometry().width() << 'x' << s->geometry().height() << "), ";
auto ratio = s->devicePixelRatio();
screens += std::format("{} ({}x{}), ", s->name().toStdString(), s->geometry().width() * ratio, s->geometry().height() * ratio);
}
if (!screens.isEmpty())
screens.chop(2);
if (!screens.empty())
screens = screens.substr(0, screens.length() - 2);
this->screens = screens;
this->screens = QString::fromLocal8Bit(screens);
}
if (auto* username = getlogin()) {
std::array<char, 128> hostname;
if (gethostname(hostname.data(), hostname.size()) == 0)
user = QString("%1@%2").arg(QLatin1StringView(username)).arg(QLatin1StringView(hostname.data()));
user = QString::fromLocal8Bit(std::format("{}@{}", username, hostname.data()));
}
{
QFile productFile("/sys/devices/virtual/dmi/id/product_name");
if (productFile.open(QFile::ReadOnly | QFile::Text))
board = productFile.readAll().trimmed();
else {
productFile.setFileName("/sys/devices/virtual/dmi/id/board_name");
if (productFile.open(QFile::ReadOnly | QFile::Text))
board = productFile.readAll().trimmed();
}
if (auto productName = readFile("/sys/devices/virtual/dmi/id/product_name"))
board = QString::fromLocal8Bit(trim(productName.value()));
else if (auto boardName = readFile("/sys/devices/virtual/dmi/id/board_name"))
board = QString::fromLocal8Bit(trim(boardName.value()));
}
}

View file

@ -34,7 +34,7 @@ class CSystemInternals : public QObject {
QString hyprlandVersion, hyprlandVersionLong;
QString cpuInfo = "missing dependency: lscpu";
QVector<QString> gpuInfo = {"missing dependency: lspci"};
QVector<QString> gpuInfo;
QString ramInfo = "?";
QString hlSystemInfo = "[error]", hlSystemVersion = "[error]";

View file

@ -1,32 +1,46 @@
#include "Utils.hpp"
#include <fstream>
#include <qdebug.h>
#include <qlogging.h>
#include <qprocess.h>
#include <optional>
QString execAndGet(const QString& program, const QStringList& arguments) {
QString execAndGet(const QString& program, const QStringList& arguments, bool* ok) {
QProcess process;
process.setProcessChannelMode(QProcess::SeparateChannels);
process.start(program, arguments, QIODevice::ReadOnly);
if (!process.waitForStarted(-1)) {
qCritical() << "Failed to start process" << program << arguments;
if (ok)
*ok = false;
return "";
}
if (!process.waitForFinished(-1)) {
qCritical() << "Failed to run process" << program << arguments;
if (ok)
*ok = false;
return "";
}
if (ok)
*ok = true;
return process.readAll();
}
QString substrUntil(const QString& string, char until) {
auto index = string.indexOf(until);
std::optional<std::string> readFile(const std::string& filename) {
try {
std::ifstream ifs(filename);
if (ifs.good()) {
std::string data(std::istreambuf_iterator<char>{ifs}, {});
ifs.close();
return data;
}
} catch (...) {}
if (index == -1)
return string;
else
return string.first(index);
return {};
}

View file

@ -2,6 +2,7 @@
#include <qlist.h>
#include <qstring.h>
#include <optional>
QString execAndGet(const QString& program, const QStringList& arguments = {});
QString substrUntil(const QString& string, char until);
QString execAndGet(const QString& program, const QStringList& arguments = {}, bool* ok = nullptr);
std::optional<std::string> readFile(const std::string& filename);