core: initial commit

This commit is contained in:
Vaxry 2024-10-13 16:48:22 +01:00
parent 7f09b49cff
commit a264ee9d76
13 changed files with 628 additions and 0 deletions

65
.clang-format Normal file
View file

@ -0,0 +1,65 @@
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignEscapedNewlines: Right
AlignOperands: false
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
ColumnLimit: 180
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentWidth: 4
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 4
UseTab: Never
AllowShortEnumsOnASingleLine: false
BraceWrapping:
AfterEnum: false
AlignConsecutiveDeclarations: AcrossEmptyLines
NamespaceIndentation: All

5
.gitignore vendored
View file

@ -30,3 +30,8 @@
*.exe
*.out
*.app
.vscode/
.cache/
build/

52
CMakeLists.txt Normal file
View file

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.16)
# Get version
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
string(STRIP ${VER_RAW} VER)
project(hsi VERSION ${VER} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick QuickControls2)
find_package(PkgConfig REQUIRED)
set(CMAKE_CXX_STANDARD 23)
pkg_check_modules(
deps
REQUIRED
IMPORTED_TARGET
hyprutils)
qt_standard_project_setup(REQUIRES 6.5)
qt_add_executable(hyprsysteminfo
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"
PREFIX "/"
FILES
resource/hyprlandlogo.svg
resource/hyprlandlogo.png
)
target_link_libraries(hyprsysteminfo
PRIVATE Qt6::Quick Qt6::Gui Qt6::QuickControls2 PkgConfig::deps
)
include(GNUInstallDirs)
install(TARGETS hyprsysteminfo
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

1
VERSION Normal file
View file

@ -0,0 +1 @@
0.1.0

217
qml/main.qml Normal file
View file

@ -0,0 +1,217 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
property var _width: 620
property var _height: 400
property var _first_panel_height: 120
minimumWidth: _width
maximumWidth: _width
width: _width
minimumHeight: _height
maximumHeight: _height
height: _height
visible: true
SystemPalette {
id: system
colorGroup: SystemPalette.Active
}
ColumnLayout {
id: mainLayout
anchors.margins: 4
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
}
RowLayout {
// First panel hyprland and distro info
Layout.fillWidth: true
Layout.preferredHeight: _first_panel_height
Layout.alignment: Qt.AlignHCenter
RowLayout {
id: distroLogoName
Layout.preferredWidth: _width / 2 - 40
spacing: 10
Image {
visible: hsi.hasSystemLogoName()
source: "image://systemIcons/" + hsi.getSystemLogoName()
sourceSize.width: _first_panel_height - 10
sourceSize.height: _first_panel_height - 10
Layout.preferredWidth: _first_panel_height - 10
Layout.preferredHeight: _first_panel_height - 10
Layout.alignment: Qt.AlignCenter
smooth: true
}
ColumnLayout {
spacing: 2
Text {
text: hsi.getSystemName()
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
Text {
text: hsi.getSystemURL()
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
Text {
text: hsi.getSystemKernel()
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
}
}
Rectangle {
visible: hsi.hasHyprland()
color: Qt.darker(system.text, 1.5)
Layout.preferredWidth: 1
Layout.preferredHeight: _first_panel_height - 40
Layout.leftMargin: 20
Layout.rightMargin: 20
Layout.alignment: Qt.AlignVCenter
}
RowLayout {
id: hyprlandInfo
visible: hsi.hasHyprland()
Layout.preferredWidth: _width / 2 - 40
spacing: 10
Image {
source: "qrc:/resource/hyprlandlogo.svg"
sourceSize.width: _first_panel_height - 10
sourceSize.height: _first_panel_height - 10
Layout.preferredWidth: _first_panel_height - 10
Layout.preferredHeight: _first_panel_height - 10
Layout.alignment: Qt.AlignCenter
smooth: true
}
ColumnLayout {
spacing: 2
Text {
text: "Hyprland"
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
Text {
text: hsi.getHyprlandVersion()
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
Text {
text: hsi.getHyprlandVersionLong()
Layout.alignment: Qt.AlignHCenter
color: system.windowText
}
}
}
}
Rectangle {
color: Qt.darker(system.text, 1.5)
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.leftMargin: 180
Layout.rightMargin: 180
Layout.topMargin: 10
Layout.bottomMargin: 10
}
ColumnLayout {
spacing: 6
Layout.leftMargin: 60
Layout.rightMargin: 60
Text {
text: "CPU: " + hsi.getCPUInfo()
Layout.maximumWidth: _width - 120
color: system.windowText
elide: Text.ElideRight
textFormat: Text.PlainText
wrapMode: Text.NoWrap
}
Text {
text: hsi.getGPUInfo()
Layout.maximumWidth: _width - 120
color: system.windowText
elide: Text.ElideRight
textFormat: Text.PlainText
wrapMode: Text.NoWrap
}
Text {
text: "Memory: " + hsi.getRAMInfo()
Layout.maximumWidth: _width - 120
color: system.windowText
elide: Text.ElideRight
textFormat: Text.PlainText
wrapMode: Text.NoWrap
}
}
Rectangle {
color: "transparent"
Layout.fillWidth: true
Layout.fillHeight: true
}
Rectangle {
color: Qt.darker(system.text, 1.5)
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.leftMargin: 180
Layout.rightMargin: 180
Layout.topMargin: 10
Layout.bottomMargin: 10
}
RowLayout {
spacing: 6
Layout.leftMargin: 20
Layout.rightMargin: 20
Button {
text: "Copy Hyprland System Info"
onClicked: (e) => {hsi.copySystemInfo();}
}
Button {
text: "Copy Hyprland Version"
onClicked: (e) => {hsi.copyVersion();}
}
}
}
}

View file

@ -0,0 +1,20 @@
#ifndef SYSTEMICONPROVIDER_H
#define SYSTEMICONPROVIDER_H
#include <QIcon>
#include <QObject>
#include <QPixmap>
#include <QQmlApplicationEngine>
#include <QQuickImageProvider>
#include <iostream>
class CSystemIconProvider : public QQuickImageProvider {
public:
CSystemIconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {}
QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override {
return QIcon::fromTheme(id).pixmap({512, 512});
}
};
#endif // SYSTEMICONPROVIDER_H

View file

@ -0,0 +1,11 @@
#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());
}

View file

@ -0,0 +1,74 @@
#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";
QString gpuInfo = "GPU: missing dependency: lspci";
QString ramInfo = "?";
QString hlSystemInfo = "[error]", hlSystemVersion = "[error]";
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 QString getGPUInfo() {
return gpuInfo;
}
Q_INVOKABLE QString getRAMInfo() {
return ramInfo;
}
Q_INVOKABLE void copySystemInfo();
Q_INVOKABLE void copyVersion();
};
#endif // SYSTEMINTERNALS_H

BIN
resource/hyprlandlogo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

View file

@ -0,0 +1 @@
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="989.93" height="989.93" viewBox="0 0 989.93 989.93"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="302.13" y1="952.85" x2="790.13" y2="305.25" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#449ad4"/><stop offset="1" stop-color="#5cc4bc"/></linearGradient></defs><path class="cls-1" d="M540,1030.5l8.9-.06c34,.6,100.62-3,172-40.4,72.34-37.94,111-90.44,127.94-114C902.06,802.16,914.31,731,916.67,716c11.76-74.4-3.6-131.87-15-174.56-18.69-69.89-47-117.89-75.11-164.72-36.7-61.17-59.82-83.93-124.84-168.34-29.33-38.1-72.19-95.22-122.24-167.83V184.05c13.36,20.09,34.67,51.48,62.16,89.09C708,364,734.31,387,770.6,448.74c27.47,46.71,45.64,77.6,57,123.8,6.88,28.07,31.86,129.83-25.39,232.58-10.86,19.49-58.38,99.51-157.46,134.15C603.34,953.75,564.31,955.72,540,955c-24.31.76-63.34-1.21-104.73-15.69-99.08-34.64-146.6-114.66-157.46-134.15-57.25-102.75-32.27-204.51-25.39-232.58,11.34-46.2,29.51-77.09,57-123.8C345.69,387,372,364,438.38,273.14c27.49-37.61,48.8-69,62.16-89.09V40.57C450.49,113.18,407.63,170.3,378.3,208.4c-65,84.41-88.14,107.17-124.84,168.34-28.09,46.83-56.42,94.83-75.11,164.72-11.42,42.69-26.78,100.16-15,174.56,2.36,14.94,14.61,86.14,67.86,160.06,16.94,23.52,55.6,76,127.94,114,71.35,37.42,137.94,41,172,40.4Z" transform="translate(-159.11 -40.57)"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

159
src/main.cpp Normal file
View file

@ -0,0 +1,159 @@
#include "qmlSources/SystemIconProvider.hpp"
#include "qmlSources/SystemInternals.hpp"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickStyle>
#include <fstream>
#include <format>
#include "util/Utils.hpp"
#include <hyprutils/string/VarList.hpp>
#include <hyprutils/string/String.hpp>
using namespace Hyprutils::String;
static void getSystemInfo(CSystemInternals* hsi) {
// 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 = execAndGet("uname -r").c_str();
// get hyprland info
if (getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
const auto DATA = execAndGet("hyprctl version");
if (DATA.contains("Tag:")) {
hsi->hlSystemVersion = DATA.c_str();
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();
}
const auto DATA2 = execAndGet("hyprctl systeminfo");
if (DATA2.contains("Tag:"))
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');
std::string gpuInfo;
for (auto& line : data) {
if (!line.contains("VGA"))
continue;
gpuInfo += std::format("GPU: {}\n", line.substr(line.find(":", line.find("VGA")) + 1));
}
hsi->gpuInfo = gpuInfo.substr(0, gpuInfo.length() - 1).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();
}
}
}
int main(int argc, char* argv[]) {
QGuiApplication app(argc, argv);
app.setApplicationName("Hyprland System Info");
QQuickStyle::setStyle("org.kde.desktop");
auto systemInternals = new CSystemInternals;
getSystemInfo(systemInternals);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("hsi", systemInternals);
engine.addImageProvider("systemIcons", new CSystemIconProvider);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
engine.load(QUrl{u"qrc:/qt/qml/hsi/qml/main.qml"_qs});
return app.exec();
}

18
src/util/Utils.cpp Normal file
View file

@ -0,0 +1,18 @@
#include "Utils.hpp"
#include <memory>
#include <array>
#include <cstdio>
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 "";
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}

5
src/util/Utils.hpp Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string execAndGet(const char* cmd);