mirror of
https://github.com/hyprwm/hyprsysteminfo.git
synced 2024-11-21 17:25:58 +01:00
core: use qt libraries and follow qml module conventions (#8)
* core: use qt libraries and follow qml module conventions Uses a qml module instead of a context property. Replaces usages of std and hyprutils with qtbase where applicable. Removes dependencies: hyprutils, wl-copy, whoami, uname. Rolls c++ version back to 20, as 23 isn't currently required for anything. * core: use hyprutils and std again
This commit is contained in:
parent
9b50bb2c29
commit
00beba904f
14 changed files with 390 additions and 395 deletions
|
@ -6,42 +6,22 @@ string(STRIP ${VER_RAW} VER)
|
||||||
|
|
||||||
project(hsi VERSION ${VER} LANGUAGES CXX)
|
project(hsi VERSION ${VER} LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Widgets Quick QuickControls2)
|
find_package(Qt6 6.5 REQUIRED COMPONENTS Widgets Quick QuickControls2)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
|
|
||||||
pkg_check_modules(
|
pkg_check_modules(hyprutils REQUIRED IMPORTED_TARGET hyprutils)
|
||||||
deps
|
|
||||||
REQUIRED
|
|
||||||
IMPORTED_TARGET
|
|
||||||
hyprutils)
|
|
||||||
|
|
||||||
qt_standard_project_setup(REQUIRES 6.5)
|
qt_standard_project_setup(REQUIRES 6.5)
|
||||||
|
|
||||||
qt_add_executable(hyprsysteminfo
|
add_subdirectory(src)
|
||||||
src/main.cpp src/util/Utils.cpp src/util/Utils.hpp
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_add_qml_module(hyprsysteminfo
|
|
||||||
URI hsi
|
|
||||||
VERSION 1.0
|
|
||||||
QML_FILES
|
|
||||||
qml/main.qml
|
|
||||||
SOURCES
|
|
||||||
qmlSources/SystemInternals.hpp qmlSources/SystemInternals.cpp qmlSources/SystemIconProvider.hpp
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_add_resources(hyprsysteminfo "resource"
|
qt_add_resources(hyprsysteminfo "resource"
|
||||||
PREFIX "/"
|
PREFIX "/"
|
||||||
FILES
|
FILES
|
||||||
resource/hyprlandlogo.svg
|
resource/hyprlandlogo.svg
|
||||||
resource/hyprlandlogo.png
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(hyprsysteminfo
|
|
||||||
PRIVATE Qt6::Widgets Qt6::Quick Qt6::Gui Qt6::QuickControls2 PkgConfig::deps
|
|
||||||
)
|
)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
lib,
|
lib,
|
||||||
stdenv,
|
stdenv,
|
||||||
cmake,
|
cmake,
|
||||||
pkg-config,
|
|
||||||
hyprutils,
|
|
||||||
kdePackages,
|
kdePackages,
|
||||||
pciutils,
|
pciutils,
|
||||||
qt6,
|
qt6,
|
||||||
|
pkg-config,
|
||||||
|
hyprutils,
|
||||||
version ? "0",
|
version ? "0",
|
||||||
}: let
|
}: let
|
||||||
inherit (lib.sources) cleanSource cleanSourceWith;
|
inherit (lib.sources) cleanSource cleanSourceWith;
|
||||||
|
@ -31,11 +31,11 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
hyprutils
|
|
||||||
kdePackages.kirigami-addons
|
kdePackages.kirigami-addons
|
||||||
qt6.qtbase
|
qt6.qtbase
|
||||||
qt6.qtsvg
|
qt6.qtsvg
|
||||||
qt6.qtwayland
|
qt6.qtwayland
|
||||||
|
hyprutils
|
||||||
];
|
];
|
||||||
|
|
||||||
preFixup = ''
|
preFixup = ''
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#include "SystemInternals.hpp"
|
|
||||||
#include "src/util/Utils.hpp"
|
|
||||||
#include <format>
|
|
||||||
|
|
||||||
void CSystemInternals::copySystemInfo() {
|
|
||||||
execAndGet(std::format("echo '{}' | wl-copy && hyprctl notify 5 5000 0 'Copied system info to the clipboard.'", hlSystemInfo.toStdString()).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSystemInternals::copyVersion() {
|
|
||||||
execAndGet(std::format("echo '{}' | wl-copy && hyprctl notify 5 5000 0 'Copied version info to the clipboard.'", hlSystemVersion.toStdString()).c_str());
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
#ifndef SYSTEMINTERNALS_H
|
|
||||||
#define SYSTEMINTERNALS_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QQmlApplicationEngine>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
class CSystemInternals : public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CSystemInternals(QObject* parent = nullptr) : QObject(parent) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString systemLogoName, systemName = "Linux", systemURL = "https://kernel.org/", systemKernel = "unknown";
|
|
||||||
QString hyprlandVersion, hyprlandVersionLong;
|
|
||||||
|
|
||||||
QString cpuInfo = "missing dependency: lscpu";
|
|
||||||
std::vector<QString> gpuInfo = {"missing dependency: lspci"};
|
|
||||||
QString ramInfo = "?";
|
|
||||||
|
|
||||||
QString hlSystemInfo = "[error]", hlSystemVersion = "[error]";
|
|
||||||
|
|
||||||
QString uptime = "unknown", DE = "Unknown", screens = "unknown", board = "", user = "";
|
|
||||||
|
|
||||||
Q_INVOKABLE bool hasSystemLogoName() {
|
|
||||||
return systemLogoName.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getSystemLogoName() {
|
|
||||||
return systemLogoName;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getSystemName() {
|
|
||||||
return systemName;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getSystemURL() {
|
|
||||||
return systemURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getSystemKernel() {
|
|
||||||
return systemKernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE bool hasHyprland() {
|
|
||||||
return hyprlandVersionLong.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getHyprlandVersion() {
|
|
||||||
return hyprlandVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getHyprlandVersionLong() {
|
|
||||||
return hyprlandVersionLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getCPUInfo() {
|
|
||||||
return cpuInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE int getGPUInfoCount() {
|
|
||||||
return gpuInfo.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getGPUInfo(int idx) {
|
|
||||||
if (idx >= gpuInfo.size())
|
|
||||||
return "[error]";
|
|
||||||
return gpuInfo.at(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getRAMInfo() {
|
|
||||||
return ramInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getDE() {
|
|
||||||
return DE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getUptime() {
|
|
||||||
return uptime;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getDisplays() {
|
|
||||||
return screens;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getModel() {
|
|
||||||
return board;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE QString getUserAt() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE void copySystemInfo();
|
|
||||||
Q_INVOKABLE void copyVersion();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SYSTEMINTERNALS_H
|
|
Binary file not shown.
Before Width: | Height: | Size: 346 KiB |
14
src/CMakeLists.txt
Normal file
14
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
qt_add_executable(hyprsysteminfo
|
||||||
|
main.cpp
|
||||||
|
util/Utils.cpp
|
||||||
|
SystemInfo.cpp
|
||||||
|
SystemIconProvider.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
qt_add_qml_module(hyprsysteminfo
|
||||||
|
URI org.hyprland.systeminfo
|
||||||
|
VERSION 1.0
|
||||||
|
QML_FILES main.qml
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(hyprsysteminfo PRIVATE Qt6::Widgets Qt6::QuickControls2 PkgConfig::hyprutils)
|
25
src/SystemIconProvider.cpp
Normal file
25
src/SystemIconProvider.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "SystemIconProvider.hpp"
|
||||||
|
#include <qicon.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qpixmap.h>
|
||||||
|
|
||||||
|
QPixmap CSystemIconProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) {
|
||||||
|
auto icon = QIcon::fromTheme(id);
|
||||||
|
|
||||||
|
if (!requestedSize.isValid()) {
|
||||||
|
qCritical() << "Icon requests without an explicit size are not allowed.";
|
||||||
|
return QPixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pixmap = icon.pixmap(requestedSize.width(), requestedSize.height());
|
||||||
|
|
||||||
|
if (pixmap.isNull()) {
|
||||||
|
qWarning() << "Could not load icon" << id;
|
||||||
|
return QPixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != nullptr)
|
||||||
|
*size = pixmap.size();
|
||||||
|
|
||||||
|
return pixmap;
|
||||||
|
}
|
|
@ -1,20 +1,14 @@
|
||||||
#ifndef SYSTEMICONPROVIDER_H
|
#pragma once
|
||||||
#define SYSTEMICONPROVIDER_H
|
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QQuickImageProvider>
|
#include <QQuickImageProvider>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class CSystemIconProvider : public QQuickImageProvider {
|
class CSystemIconProvider : public QQuickImageProvider {
|
||||||
public:
|
public:
|
||||||
CSystemIconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {}
|
CSystemIconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {}
|
||||||
|
|
||||||
QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override {
|
QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override;
|
||||||
return QIcon::fromTheme(id).pixmap({512, 512});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SYSTEMICONPROVIDER_H
|
|
223
src/SystemInfo.cpp
Normal file
223
src/SystemInfo.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
#include "SystemInfo.hpp"
|
||||||
|
#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
|
||||||
|
if (auto data = readFile("/etc/os-release")) {
|
||||||
|
CVarList lines(data.value(), 0, '\n');
|
||||||
|
|
||||||
|
for (auto& line : lines) {
|
||||||
|
CVarList param(line, 2, '=');
|
||||||
|
|
||||||
|
const auto& key = param[0];
|
||||||
|
auto value = param[1];
|
||||||
|
|
||||||
|
if (value.length() >= 2 && value.at(0) == '\"')
|
||||||
|
value = value.substr(1, value.length() - 2);
|
||||||
|
|
||||||
|
if (key == "PRETTY_NAME") {
|
||||||
|
systemName = QString::fromLocal8Bit(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == "HOME_URL") {
|
||||||
|
systemURL = QString::fromLocal8Bit(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == "LOGO") {
|
||||||
|
systemLogoName = QString::fromLocal8Bit(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get kernel ver
|
||||||
|
utsname unamebuf;
|
||||||
|
if (uname(&unamebuf) == 0) {
|
||||||
|
systemKernel = unamebuf.release;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get hyprland info
|
||||||
|
if (getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
|
||||||
|
hlSystemVersion = execAndGet("hyprctl", {"version"});
|
||||||
|
auto DATA = hlSystemVersion.toStdString();
|
||||||
|
|
||||||
|
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.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 = QStringLiteral("unknown");
|
||||||
|
hyprlandVersion = QStringLiteral("unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
hlSystemInfo = execAndGet("hyprctl", {"systeminfo"});
|
||||||
|
if (!hlSystemInfo.contains("Hyprland"))
|
||||||
|
hlSystemInfo = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// get cpu info
|
||||||
|
{
|
||||||
|
const auto DATA = execAndGet("lscpu").toStdString();
|
||||||
|
if (DATA.contains("odel name")) {
|
||||||
|
std::string arch, model, ghz, nproc;
|
||||||
|
|
||||||
|
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") {
|
||||||
|
try {
|
||||||
|
ghz = std::format("{:.02}GHz", std::stof(right) / 1000.F);
|
||||||
|
} catch (...) { ghz = "?GHz"; }
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuInfo = QString::fromLocal8Bit(std::format("{} at {}x{} ({})", model, nproc, ghz, arch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get gpu info
|
||||||
|
{
|
||||||
|
auto ok = false;
|
||||||
|
const auto DATA = execAndGet("lspci", {"-vnn"}, &ok).toStdString();
|
||||||
|
CVarList lines(DATA, 0, '\n');
|
||||||
|
|
||||||
|
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))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpuInfo.isEmpty())
|
||||||
|
gpuInfo.emplaceBack(QStringLiteral("No GPUs found"));
|
||||||
|
} else
|
||||||
|
gpuInfo.emplaceBack(QStringLiteral("missing dependency: lspci"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get ram info
|
||||||
|
{
|
||||||
|
const auto DATA = execAndGet("free").toStdString();
|
||||||
|
if (DATA.contains("total")) {
|
||||||
|
CVarList data(DATA, 0, '\n');
|
||||||
|
|
||||||
|
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]"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
CVarList props(data[1], 0, 's', true);
|
||||||
|
|
||||||
|
ramInfo = QString::fromLocal8Bit(std::format("{} / {}", ramIntToReadable(props[2]), ramIntToReadable(props[1])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// other, misc
|
||||||
|
if (auto current = qEnvironmentVariable("XDG_CURRENT_DESKTOP"); !current.isEmpty())
|
||||||
|
DE = current;
|
||||||
|
|
||||||
|
if (auto procUptime = readFile("/proc/uptime")) {
|
||||||
|
CVarList data(procUptime.value(), 0, 's', true);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
auto upStr = std::format("{}{}{}", (uptimeDays > 0 ? std::format("{} days, ", uptimeDays) : ""), (uptimeHours > 0 ? std::format("{} hours, ", uptimeHours) : ""),
|
||||||
|
(uptimeMinutes > 0 ? std::format("{} minutes, ", uptimeMinutes) : ""));
|
||||||
|
|
||||||
|
if (!upStr.empty())
|
||||||
|
upStr = upStr.substr(0, upStr.length() - 2);
|
||||||
|
|
||||||
|
uptime = QString::fromLocal8Bit(upStr);
|
||||||
|
} catch (...) { ; }
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string screens;
|
||||||
|
for (auto* s : QGuiApplication::screens()) {
|
||||||
|
auto ratio = s->devicePixelRatio();
|
||||||
|
screens += std::format("{} ({}x{}), ", s->name().toStdString(), s->geometry().width() * ratio, s->geometry().height() * ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!screens.empty())
|
||||||
|
screens = screens.substr(0, screens.length() - 2);
|
||||||
|
|
||||||
|
this->screens = QString::fromLocal8Bit(screens);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto* username = getlogin()) {
|
||||||
|
std::array<char, 128> hostname;
|
||||||
|
if (gethostname(hostname.data(), hostname.size()) == 0)
|
||||||
|
user = QString::fromLocal8Bit(std::format("{}@{}", username, hostname.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSystemInternals::copySystemInfo() {
|
||||||
|
QGuiApplication::clipboard()->setText(hlSystemInfo);
|
||||||
|
execAndGet("hyprctl", {"notify", "5", "5000", "0", "Copied system info to the clipboard."});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSystemInternals::copyVersion() {
|
||||||
|
QGuiApplication::clipboard()->setText(hlSystemVersion);
|
||||||
|
execAndGet("hyprctl", {"notify", "5", "5000", "0", "Copied version info to the clipboard."});
|
||||||
|
}
|
46
src/SystemInfo.hpp
Normal file
46
src/SystemInfo.hpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class CSystemInternals : public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
QML_NAMED_ELEMENT(SystemInfo);
|
||||||
|
QML_SINGLETON;
|
||||||
|
Q_PROPERTY(QString systemLogoName MEMBER systemLogoName CONSTANT);
|
||||||
|
Q_PROPERTY(QString systemName MEMBER systemName CONSTANT);
|
||||||
|
Q_PROPERTY(QString systemUrl MEMBER systemURL CONSTANT);
|
||||||
|
Q_PROPERTY(QString systemKernel MEMBER systemKernel CONSTANT);
|
||||||
|
Q_PROPERTY(QString hyprlandVersion MEMBER hyprlandVersion CONSTANT);
|
||||||
|
Q_PROPERTY(QString hyprlandVersionLong MEMBER hyprlandVersionLong CONSTANT);
|
||||||
|
Q_PROPERTY(QString cpuInfo MEMBER cpuInfo CONSTANT);
|
||||||
|
Q_PROPERTY(QVector<QString> gpuInfo MEMBER gpuInfo CONSTANT);
|
||||||
|
Q_PROPERTY(QString ramInfo MEMBER ramInfo CONSTANT);
|
||||||
|
Q_PROPERTY(QString uptime MEMBER uptime CONSTANT);
|
||||||
|
Q_PROPERTY(QString de MEMBER DE CONSTANT);
|
||||||
|
Q_PROPERTY(QString screens MEMBER screens CONSTANT);
|
||||||
|
Q_PROPERTY(QString model MEMBER board CONSTANT);
|
||||||
|
Q_PROPERTY(QString user MEMBER user CONSTANT);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CSystemInternals(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QString systemLogoName, systemName = "Linux", systemURL = "https://kernel.org/", systemKernel = "unknown";
|
||||||
|
QString hyprlandVersion, hyprlandVersionLong;
|
||||||
|
|
||||||
|
QString cpuInfo = "missing dependency: lscpu";
|
||||||
|
QVector<QString> gpuInfo;
|
||||||
|
QString ramInfo = "?";
|
||||||
|
|
||||||
|
QString hlSystemInfo = "[error]", hlSystemVersion = "[error]";
|
||||||
|
|
||||||
|
QString uptime = "unknown", DE = "Unknown", screens = "unknown", board = "", user = "";
|
||||||
|
|
||||||
|
Q_INVOKABLE void copySystemInfo();
|
||||||
|
Q_INVOKABLE void copyVersion();
|
||||||
|
};
|
216
src/main.cpp
216
src/main.cpp
|
@ -1,209 +1,8 @@
|
||||||
#include "qmlSources/SystemIconProvider.hpp"
|
#include "SystemIconProvider.hpp"
|
||||||
#include "qmlSources/SystemInternals.hpp"
|
#include <qapplication.h>
|
||||||
#include <QApplication>
|
#include <qqmlapplicationengine.h>
|
||||||
#include <QQmlApplicationEngine>
|
#include <qquickstyle.h>
|
||||||
#include <QQmlContext>
|
|
||||||
#include <QQuickStyle>
|
|
||||||
#include <QScreen>
|
|
||||||
#include <fstream>
|
|
||||||
#include <format>
|
|
||||||
#include "util/Utils.hpp"
|
|
||||||
|
|
||||||
#include <hyprutils/string/VarList.hpp>
|
|
||||||
#include <hyprutils/string/String.hpp>
|
|
||||||
#include <qtenvironmentvariables.h>
|
#include <qtenvironmentvariables.h>
|
||||||
using namespace Hyprutils::String;
|
|
||||||
|
|
||||||
static 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 trim(data);
|
|
||||||
}
|
|
||||||
} catch (...) { return "[error]"; }
|
|
||||||
return "[error]";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getSystemInfo(CSystemInternals* hsi, QGuiApplication* app) {
|
|
||||||
|
|
||||||
// gather data from os-release
|
|
||||||
std::ifstream osInfo("/etc/os-release");
|
|
||||||
if (osInfo.good()) {
|
|
||||||
std::string data(std::istreambuf_iterator<char>{osInfo}, {});
|
|
||||||
|
|
||||||
osInfo.close();
|
|
||||||
|
|
||||||
CVarList lines(data, 0, '\n');
|
|
||||||
|
|
||||||
for (auto& line : lines) {
|
|
||||||
CVarList param(line, 2, '=');
|
|
||||||
|
|
||||||
static auto stripName = [](const std::string& in) -> std::string { return in.length() > 0 && in.at(0) == '\"' ? in.substr(1, in.length() - 2) : in; };
|
|
||||||
|
|
||||||
if (param[0] == "PRETTY_NAME") {
|
|
||||||
hsi->systemName = stripName(param[1]).c_str();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param[0] == "HOME_URL") {
|
|
||||||
hsi->systemURL = stripName(param[1]).c_str();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param[0] == "LOGO") {
|
|
||||||
hsi->systemLogoName = stripName(param[1]).c_str();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get kernel ver
|
|
||||||
hsi->systemKernel = trim(execAndGet("uname -r")).c_str();
|
|
||||||
|
|
||||||
// get hyprland info
|
|
||||||
if (getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
|
|
||||||
const auto DATA = execAndGet("hyprctl version");
|
|
||||||
hsi->hlSystemVersion = DATA.c_str();
|
|
||||||
|
|
||||||
if (DATA.contains("Tag:")) {
|
|
||||||
auto temp = DATA.substr(DATA.find("Tag:") + 5);
|
|
||||||
temp = temp.substr(0, temp.find(","));
|
|
||||||
hsi->hyprlandVersionLong = temp.c_str();
|
|
||||||
hsi->hyprlandVersion = temp.substr(0, temp.find("-")).c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hsi->hyprlandVersionLong.length() <= 0 && DATA.contains("at commit")) {
|
|
||||||
auto temp = DATA.substr(DATA.find("at commit") + 10);
|
|
||||||
temp = temp.substr(0, temp.find(" "));
|
|
||||||
hsi->hyprlandVersionLong = temp.substr(0, 7).c_str();
|
|
||||||
hsi->hyprlandVersion = temp.substr(0, 7).c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hsi->hyprlandVersionLong.length() <= 0) {
|
|
||||||
hsi->hyprlandVersionLong = "unknown";
|
|
||||||
hsi->hyprlandVersion = "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto DATA2 = execAndGet("hyprctl systeminfo");
|
|
||||||
if (DATA2.contains("Hyprland"))
|
|
||||||
hsi->hlSystemInfo = DATA2.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get cpu info
|
|
||||||
{
|
|
||||||
const auto DATA = execAndGet("lscpu");
|
|
||||||
if (DATA.contains("odel name")) {
|
|
||||||
std::string arch, model, ghz, nproc;
|
|
||||||
|
|
||||||
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") {
|
|
||||||
try {
|
|
||||||
ghz = std::format("{:.02}GHz", std::stof(right) / 1000.F);
|
|
||||||
} catch (...) { ghz = "?GHz"; }
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hsi->cpuInfo = std::format("{} at {}x{} ({})", model, nproc, ghz, arch).c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get gpu info
|
|
||||||
{
|
|
||||||
const auto DATA = execAndGet("lspci -vnn | grep VGA");
|
|
||||||
if (DATA.contains("VGA")) {
|
|
||||||
CVarList data(DATA, 0, '\n');
|
|
||||||
hsi->gpuInfo.clear();
|
|
||||||
for (auto& line : data) {
|
|
||||||
if (!line.contains("VGA"))
|
|
||||||
continue;
|
|
||||||
hsi->gpuInfo.emplace_back(std::format("{}", line.substr(line.find(":", line.find("VGA")) + 2)).c_str());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hsi->gpuInfo = {"No GPUs found"};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get ram info
|
|
||||||
{
|
|
||||||
const auto DATA = execAndGet("free");
|
|
||||||
if (DATA.contains("total")) {
|
|
||||||
CVarList data(DATA, 0, '\n');
|
|
||||||
|
|
||||||
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]"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
CVarList props(data[1], 0, 's', true);
|
|
||||||
|
|
||||||
hsi->ramInfo = std::format("{} / {}", ramIntToReadable(props[2]), ramIntToReadable(props[1])).c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// other, misc
|
|
||||||
if (const auto DE = getenv("XDG_CURRENT_DESKTOP"); DE)
|
|
||||||
hsi->DE = DE;
|
|
||||||
|
|
||||||
if (const auto UPTIME = readFile("/proc/uptime"); UPTIME != "[error]") {
|
|
||||||
CVarList data(UPTIME, 0, 's', true);
|
|
||||||
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);
|
|
||||||
|
|
||||||
auto upStr = std::format("{}{}{}", (uptimeDays > 0 ? std::format("{} days, ", uptimeDays) : ""), (uptimeHours > 0 ? std::format("{} hours, ", uptimeHours) : ""),
|
|
||||||
(uptimeMinutes > 0 ? std::format("{} minutes, ", uptimeMinutes) : ""));
|
|
||||||
|
|
||||||
if (!upStr.empty())
|
|
||||||
upStr = upStr.substr(0, upStr.length() - 2);
|
|
||||||
|
|
||||||
hsi->uptime = upStr.c_str();
|
|
||||||
} catch (...) { ; }
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string screens;
|
|
||||||
|
|
||||||
for (auto& s : app->screens()) {
|
|
||||||
screens += std::format("{} ({}x{}), ", s->name().toStdString(), s->geometry().width(), s->geometry().height());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!screens.empty())
|
|
||||||
screens = screens.substr(0, screens.length() - 2);
|
|
||||||
|
|
||||||
hsi->screens = screens.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
hsi->user = std::format("{}@{}", trim(execAndGet("whoami")), readFile("/etc/hostname")).c_str();
|
|
||||||
|
|
||||||
if (const auto PRODUCT = readFile("/sys/devices/virtual/dmi/id/product_name"); PRODUCT != "[error]")
|
|
||||||
hsi->board = PRODUCT.c_str();
|
|
||||||
else if (const auto BOARD = readFile("/sys/devices/virtual/dmi/id/board_name"); BOARD != "[error]")
|
|
||||||
hsi->board = BOARD.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
@ -213,15 +12,10 @@ int main(int argc, char* argv[]) {
|
||||||
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE"))
|
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE"))
|
||||||
QQuickStyle::setStyle("org.kde.desktop");
|
QQuickStyle::setStyle("org.kde.desktop");
|
||||||
|
|
||||||
auto systemInternals = new CSystemInternals;
|
|
||||||
|
|
||||||
getSystemInfo(systemInternals, &app);
|
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
engine.rootContext()->setContextProperty("hsi", systemInternals);
|
|
||||||
engine.addImageProvider("systemIcons", new CSystemIconProvider);
|
engine.addImageProvider("systemIcons", new CSystemIconProvider);
|
||||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
|
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
|
||||||
engine.load(QUrl{u"qrc:/qt/qml/hsi/qml/main.qml"_qs});
|
engine.load("qrc:/qt/qml/org/hyprland/systeminfo/main.qml");
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import org.hyprland.systeminfo
|
||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: window
|
id: window
|
||||||
|
@ -58,8 +59,8 @@ ApplicationWindow {
|
||||||
spacing: fontMetrics.height
|
spacing: fontMetrics.height
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
visible: hsi.hasSystemLogoName()
|
visible: SystemInfo.systemLogoName != ""
|
||||||
source: "image://systemIcons/" + hsi.getSystemLogoName()
|
source: "image://systemIcons/" + SystemInfo.systemLogoName
|
||||||
sourceSize.width: firstPanelHeight
|
sourceSize.width: firstPanelHeight
|
||||||
sourceSize.height: firstPanelHeight
|
sourceSize.height: firstPanelHeight
|
||||||
Layout.preferredWidth: firstPanelHeight
|
Layout.preferredWidth: firstPanelHeight
|
||||||
|
@ -76,17 +77,17 @@ ApplicationWindow {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: hsi.getSystemName()
|
text: SystemInfo.systemName
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: hsi.getSystemURL()
|
text: SystemInfo.systemUrl
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: hsi.getSystemKernel()
|
text: SystemInfo.systemKernel
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +99,7 @@ ApplicationWindow {
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: hyprlandInfo
|
id: hyprlandInfo
|
||||||
visible: hsi.hasHyprland()
|
visible: SystemInfo.hyprlandVersionLong != ""
|
||||||
spacing: fontMetrics.height
|
spacing: fontMetrics.height
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -123,13 +124,13 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: hsi.getHyprlandVersion()
|
text: SystemInfo.hyprlandVersion
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
visible: hsi.getHyprlandVersion() != hsi.getHyprlandVersionLong()
|
visible: SystemInfo.hyprlandVersion != text
|
||||||
text: hsi.getHyprlandVersionLong()
|
text: SystemInfo.hyprlandVersionLong
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,23 +152,23 @@ ApplicationWindow {
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
DetailsLabel { text: "User: " + hsi.getUserAt(); visible: hsi.getUserAt() != "" }
|
DetailsLabel { text: "User: " + SystemInfo.user; visible: text != "" }
|
||||||
DetailsLabel { text: "Model: " + hsi.getModel(); visible: hsi.getModel() != "" }
|
DetailsLabel { text: "Model: " + SystemInfo.model; visible: text != "" }
|
||||||
DetailsLabel { text: "CPU: " + hsi.getCPUInfo() }
|
DetailsLabel { text: "CPU: " + SystemInfo.cpuInfo }
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: hsi.getGPUInfoCount()
|
model: SystemInfo.gpuInfo
|
||||||
|
|
||||||
DetailsLabel {
|
DetailsLabel {
|
||||||
required property int index
|
required property string modelData
|
||||||
text: "GPU: " + hsi.getGPUInfo(index)
|
text: "GPU: " + modelData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DetailsLabel { text: "Memory: " + hsi.getRAMInfo() }
|
DetailsLabel { text: "Memory: " + SystemInfo.ramInfo }
|
||||||
DetailsLabel { text: "DE: " + hsi.getDE() }
|
DetailsLabel { text: "DE: " + SystemInfo.de }
|
||||||
DetailsLabel { text: "Uptime: " + hsi.getUptime() }
|
DetailsLabel { text: "Uptime: " + SystemInfo.uptime }
|
||||||
DetailsLabel { text: "Displays: " + hsi.getDisplays() }
|
DetailsLabel { text: "Displays: " + SystemInfo.screens }
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { Layout.fillHeight: true }
|
Item { Layout.fillHeight: true }
|
||||||
|
@ -175,19 +176,19 @@ ApplicationWindow {
|
||||||
HSeparator {}
|
HSeparator {}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
visible: hsi.hasHyprland()
|
visible: SystemInfo.hyprlandVersionLong != ""
|
||||||
spacing: 6
|
spacing: 6
|
||||||
Layout.leftMargin: 20
|
Layout.leftMargin: 20
|
||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Copy Hyprland System Info"
|
text: "Copy Hyprland System Info"
|
||||||
onClicked: hsi.copySystemInfo();
|
onClicked: SystemInfo.copySystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Copy Hyprland Version"
|
text: "Copy Hyprland Version"
|
||||||
onClicked: hsi.copyVersion();
|
onClicked: SystemInfo.copyVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,18 +1,46 @@
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <fstream>
|
||||||
#include <array>
|
#include <qdebug.h>
|
||||||
#include <cstdio>
|
#include <qlogging.h>
|
||||||
|
#include <qprocess.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
std::string execAndGet(const char* cmd) {
|
|
||||||
std::array<char, 128> buffer;
|
|
||||||
std::string result;
|
|
||||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
|
||||||
result += buffer.data();
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
if (!process.waitForFinished(-1)) {
|
||||||
|
qCritical() << "Failed to run process" << program << arguments;
|
||||||
|
if (ok)
|
||||||
|
*ok = false;
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
*ok = true;
|
||||||
|
return process.readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (...) {}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <qlist.h>
|
||||||
|
#include <qstring.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
std::string execAndGet(const char* cmd);
|
QString execAndGet(const QString& program, const QStringList& arguments = {}, bool* ok = nullptr);
|
||||||
|
std::optional<std::string> readFile(const std::string& filename);
|
||||||
|
|
Loading…
Reference in a new issue