mirror of
https://github.com/edisionnano/QDiskInfo.git
synced 2026-03-07 20:09:55 +03:00
First commit
This commit is contained in:
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
73
CMakeLists.txt
Normal file
73
CMakeLists.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(KDiskInfo VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
mainwindow.ui
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(KDiskInfo
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
mainwindow.ui
|
||||
statusdot.h statusdot.cpp
|
||||
custombutton.h custombutton.cpp
|
||||
)
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET KDiskInfo APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||
else()
|
||||
if(ANDROID)
|
||||
add_library(KDiskInfo SHARED
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||
else()
|
||||
add_executable(KDiskInfo
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(KDiskInfo PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.KDiskInfo)
|
||||
endif()
|
||||
set_target_properties(KDiskInfo PROPERTIES
|
||||
${BUNDLE_ID_OPTION}
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS KDiskInfo
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(KDiskInfo)
|
||||
endif()
|
||||
22
custombutton.cpp
Normal file
22
custombutton.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "custombutton.h"
|
||||
|
||||
CustomButton::CustomButton(const QString &text1, const QString &text2, const QString &text3, const QColor &lineColor, QWidget *parent)
|
||||
: QPushButton(parent), text1(text1), text2(text2), text3(text3), lineColor(lineColor) {
|
||||
setMinimumHeight(60);
|
||||
setMinimumWidth(100);
|
||||
}
|
||||
|
||||
void CustomButton::paintEvent(QPaintEvent *event) {
|
||||
QPushButton::paintEvent(event);
|
||||
QPainter painter(this);
|
||||
QPalette pal = palette();
|
||||
QColor textColor = pal.color(QPalette::ButtonText);
|
||||
|
||||
QPen pen(lineColor, 5);
|
||||
painter.setPen(pen);
|
||||
painter.drawLine(10, 9, 10, 50);
|
||||
|
||||
QRect rect(20, 0, width() - 25, height());
|
||||
painter.setPen(textColor);
|
||||
painter.drawText(rect, Qt::AlignVCenter | Qt::AlignLeft, text1 + "\n" + text2 + "\n" + text3);
|
||||
}
|
||||
23
custombutton.h
Normal file
23
custombutton.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef CUSTOMBUTTON_H
|
||||
#define CUSTOMBUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QPainter>
|
||||
|
||||
class CustomButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CustomButton(const QString &text1, const QString &text2, const QString &text3, const QColor &lineColor, QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
QString text1;
|
||||
QString text2;
|
||||
QString text3;
|
||||
QColor lineColor;
|
||||
};
|
||||
|
||||
#endif
|
||||
11
main.cpp
Normal file
11
main.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
348
mainwindow.cpp
Normal file
348
mainwindow.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
buttonGroup = new QButtonGroup(this);
|
||||
buttonGroup->setExclusive(true);
|
||||
|
||||
horizontalLayout = ui->horizontalLayout;
|
||||
|
||||
diskName = qobject_cast<QLabel *>(ui->centralwidget->findChild<QLabel*>("diskName"));
|
||||
temperatureValue = qobject_cast<QLabel *>(ui->centralwidget->findChild<QLabel*>("temperatureValueLabel"));
|
||||
healthStatusValue = qobject_cast<QLabel *>(ui->centralwidget->findChild<QLabel*>("healthStatusValueLabel"));
|
||||
|
||||
firmwareLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("firmwareLineEdit"));
|
||||
serialNumberLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("serialNumberLineEdit"));
|
||||
typeLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("typeLineEdit"));
|
||||
protocolLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("protocolLineEdit"));
|
||||
deviceNodeLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("deviceNodeLineEdit"));
|
||||
|
||||
totalReadsLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("totalReadsLineEdit"));
|
||||
totalWritesLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("totalWritesLineEdit"));
|
||||
rotationRateLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("rotationRateLineEdit"));
|
||||
powerOnCountLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("powerOnCountLineEdit"));
|
||||
powerOnHoursLineEdit = qobject_cast<QLineEdit *>(ui->centralwidget->findChild<QLineEdit*>("powerOnHoursLineEdit"));
|
||||
|
||||
tableWidget = qobject_cast<QTableWidget *>(ui->centralwidget->findChild<QTableWidget*>("dataTable"));;
|
||||
serialNumberLineEdit->setEchoMode(QLineEdit::Password);
|
||||
|
||||
QAction *toggleEchoModeAction = serialNumberLineEdit->addAction(QIcon::fromTheme(QStringLiteral("visibility")), QLineEdit::TrailingPosition);
|
||||
connect(toggleEchoModeAction, &QAction::triggered, [=]() {
|
||||
if (serialNumberLineEdit->echoMode() == QLineEdit::Password) {
|
||||
serialNumberLineEdit->setEchoMode(QLineEdit::Normal);
|
||||
toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("hint")));
|
||||
} else if (serialNumberLineEdit->echoMode() == QLineEdit::Normal) {
|
||||
serialNumberLineEdit->setEchoMode(QLineEdit::Password);
|
||||
toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("visibility")));
|
||||
}
|
||||
});
|
||||
|
||||
scanDevices();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::scanDevices()
|
||||
{
|
||||
QString output = getSmartctlOutput({"--scan", "--json"}, false);
|
||||
QJsonDocument doc = QJsonDocument::fromJson(output.toUtf8());
|
||||
QJsonObject jsonObj = doc.object();
|
||||
QJsonArray devices = jsonObj["devices"].toArray();
|
||||
QJsonObject globalObj;
|
||||
QString globalHealth;
|
||||
bool firstTime = true;
|
||||
|
||||
for (const QJsonValue &value : devices) {
|
||||
QJsonObject device = value.toObject();
|
||||
QString deviceName = device["name"].toString();
|
||||
|
||||
QString allOutput = getSmartctlOutput({"--all", "--json", deviceName}, true);
|
||||
|
||||
QJsonDocument localDoc = QJsonDocument::fromJson(allOutput.toUtf8());
|
||||
QJsonObject localObj = localDoc.object();
|
||||
|
||||
QJsonArray attributes = localObj["ata_smart_attributes"].toObject()["table"].toArray();
|
||||
QString temperature = "N/A";
|
||||
bool healthPassed = localObj["smart_status"].toObject()["passed"].toBool();
|
||||
bool caution = false;
|
||||
QString health;
|
||||
QColor healthColor;
|
||||
|
||||
bool isNvme = false;
|
||||
QString protocol = localObj["device"].toObject()["protocol"].toString();
|
||||
if (protocol == "NVMe") {
|
||||
isNvme = true;
|
||||
}
|
||||
|
||||
for (const QJsonValue &attr : attributes) { // Need different logic for NVMe
|
||||
QJsonObject attrObj = attr.toObject();
|
||||
if (attrObj["id"] == 194 && !isNvme) {
|
||||
QString raw = attrObj["raw"].toObject()["string"].toString();
|
||||
int spaceIndex = raw.indexOf(' ');
|
||||
if (spaceIndex != -1) {
|
||||
raw = raw.left(spaceIndex);
|
||||
}
|
||||
int tempInt = raw.toInt();
|
||||
temperature = QString::number(tempInt) + " °C";
|
||||
} else if (!isNvme && (attrObj["id"] == 5 || attrObj["id"] == 197 || attrObj["id"] == 198) && (attrObj["raw"].toObject()["value"].toInt() != 0)) {
|
||||
caution = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (healthPassed && !caution) {
|
||||
health = "Good";
|
||||
healthColor = Qt::green;
|
||||
} else if (healthPassed && caution) {
|
||||
health = "Caution";
|
||||
healthColor = Qt::yellow;
|
||||
} else {
|
||||
health = "Bad";
|
||||
healthColor = Qt::red;
|
||||
}
|
||||
|
||||
CustomButton *button = new CustomButton(health, deviceName, temperature, healthColor, this);
|
||||
|
||||
buttonGroup->addButton(button);
|
||||
horizontalLayout->addWidget(button);
|
||||
|
||||
button->setCheckable(true);
|
||||
button->setAutoExclusive(true);
|
||||
|
||||
connect(button, &QPushButton::clicked, this, [=]() {
|
||||
populateWindow(localObj, health);
|
||||
});
|
||||
|
||||
if (firstTime) {
|
||||
globalObj = localObj;
|
||||
globalHealth = health;
|
||||
button->setChecked(true);
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
}
|
||||
horizontalLayout->addStretch();
|
||||
populateWindow(globalObj, globalHealth);
|
||||
}
|
||||
|
||||
void MainWindow::populateWindow(const QJsonObject &localObj, const QString &health)
|
||||
{
|
||||
QJsonArray attributes = localObj["ata_smart_attributes"].toObject()["table"].toArray();
|
||||
QString modelName = localObj["model_name"].toString();
|
||||
QString firmwareVersion = localObj["firmware_version"].toString();
|
||||
float userCapacityGB = localObj.value("user_capacity").toObject().value("bytes").toDouble() / 1e9;
|
||||
QString userCapacityString = QString::number(static_cast<int>(userCapacityGB)) + "." + QString::number(static_cast<int>((userCapacityGB - static_cast<int>(userCapacityGB)) * 10)) + " GB";
|
||||
QString totalReads = "----";
|
||||
QString totalWrites = "----";
|
||||
QString serialNumber = localObj["serial_number"].toString();
|
||||
QJsonObject deviceObj = localObj["device"].toObject();
|
||||
QString protocol = deviceObj["protocol"].toString();
|
||||
QString type = deviceObj["type"].toString();
|
||||
QString name = deviceObj["name"].toString();
|
||||
int tempInt = 0;
|
||||
|
||||
bool isNvme = false;
|
||||
if (protocol == "NVMe") {
|
||||
isNvme = true;
|
||||
}
|
||||
|
||||
diskName->setText("<html><head/><body><p><span style='font-size:14pt; font-weight:bold;'>" + modelName + " " + userCapacityString + "</span></p></body></html>");
|
||||
firmwareLineEdit->setText(firmwareVersion);
|
||||
serialNumberLineEdit->setText(serialNumber);
|
||||
typeLineEdit->setText(type);
|
||||
protocolLineEdit->setText(protocol);
|
||||
deviceNodeLineEdit->setText(name);
|
||||
|
||||
int rotationRateInt = localObj["rotation_rate"].toInt(-1);
|
||||
QString rotationRate;
|
||||
if (rotationRateInt > 0) {
|
||||
rotationRate = QString::number(rotationRateInt);
|
||||
} else if (rotationRateInt == 0) {
|
||||
rotationRate = "---- (SSD)";
|
||||
} else {
|
||||
rotationRate = "----";
|
||||
}
|
||||
|
||||
rotationRateLineEdit->setText(rotationRate);
|
||||
rotationRateLineEdit->setAlignment(Qt::AlignRight);
|
||||
|
||||
int powerCycleCountInt = localObj["power_cycle_count"].toInt(-1);
|
||||
QString powerCycleCount;
|
||||
if (powerCycleCountInt >= 0) {
|
||||
powerCycleCount = QString::number(powerCycleCountInt) + " count";
|
||||
} else {
|
||||
powerCycleCount = "Unknown";
|
||||
}
|
||||
|
||||
powerOnCountLineEdit->setText(powerCycleCount);
|
||||
powerOnCountLineEdit->setAlignment(Qt::AlignRight);
|
||||
|
||||
int powerOnTimeInt = localObj["power_on_time"].toObject().value("hours").toInt(-1);
|
||||
QString powerOnTime;
|
||||
if (powerOnTimeInt >= 0) {
|
||||
powerOnTime = QString::number(powerOnTimeInt) + " hours";
|
||||
} else {
|
||||
powerOnTime = "Unknown";
|
||||
}
|
||||
|
||||
powerOnHoursLineEdit->setText(powerOnTime);
|
||||
powerOnHoursLineEdit->setAlignment(Qt::AlignRight);
|
||||
|
||||
for (const QJsonValue &attr : attributes) { //Need different logic for NVMe
|
||||
QJsonObject attrObj = attr.toObject();
|
||||
if (attrObj["id"] == 241 && !isNvme) {
|
||||
totalWrites = QString::number(attrObj["raw"].toObject()["value"].toInt()) + " GB";
|
||||
} else if (attrObj["id"] == 242 && !isNvme) {
|
||||
totalReads = QString::number(attrObj["raw"].toObject()["value"].toInt()) + " GB";
|
||||
} else if (attrObj["id"] == 194 && !isNvme) {
|
||||
QString raw = attrObj["raw"].toObject()["string"].toString();
|
||||
int spaceIndex = raw.indexOf(' ');
|
||||
if (spaceIndex != -1) {
|
||||
raw = raw.left(spaceIndex);
|
||||
}
|
||||
tempInt = raw.toInt();
|
||||
}
|
||||
}
|
||||
|
||||
totalReadsLineEdit->setText(totalReads);
|
||||
totalReadsLineEdit->setAlignment(Qt::AlignRight);
|
||||
|
||||
totalWritesLineEdit->setText(totalWrites);
|
||||
totalWritesLineEdit->setAlignment(Qt::AlignRight);
|
||||
|
||||
if (tempInt > 55) {
|
||||
temperatureValue->setStyleSheet("background-color: " + QColor(Qt::red).name() + ";");
|
||||
} else if ((tempInt < 55) && (tempInt > 50)){
|
||||
temperatureValue->setStyleSheet("background-color: " + QColor(Qt::yellow).name() + ";");
|
||||
} else if (tempInt == 0) {
|
||||
temperatureValue->setStyleSheet("background-color: " + QColor(Qt::gray).name() + ";");
|
||||
} else {
|
||||
temperatureValue->setStyleSheet("background-color: " + QColor(Qt::green).name() + ";");
|
||||
}
|
||||
|
||||
QString labelStyle = "font-size:12pt; font-weight:700; color:black";
|
||||
|
||||
if (tempInt > 0) {
|
||||
temperatureValue->setText("<html><head/><body><p><span style='" + labelStyle +"'>" + QString::number(tempInt) + " °C</span></p></body></html>");
|
||||
} else {
|
||||
temperatureValue->setText("<html><head/><body><p><span style='" + labelStyle +"'>N/A</span></p></body></html>");
|
||||
}
|
||||
|
||||
temperatureValue->setAlignment(Qt::AlignCenter);
|
||||
|
||||
if (health == "Bad") {
|
||||
healthStatusValue->setStyleSheet("background-color: " + QColor(Qt::red).name() + ";");
|
||||
} else if (health == "Caution"){
|
||||
healthStatusValue->setStyleSheet("background-color: " + QColor(Qt::yellow).name() + ";");
|
||||
} else {
|
||||
healthStatusValue->setStyleSheet("background-color: " + QColor(Qt::green).name() + ";");
|
||||
}
|
||||
|
||||
healthStatusValue->setText("<html><head/><body><p><span style='" + labelStyle +"'>" + health + "</span></p></body></html>");
|
||||
healthStatusValue->setAlignment(Qt::AlignCenter);
|
||||
|
||||
if (protocol != "NVMe") {
|
||||
addSmartAttributesTable(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addSmartAttributesTable(const QJsonArray &attributes)
|
||||
{
|
||||
tableWidget->setColumnCount(7);
|
||||
tableWidget->setHorizontalHeaderLabels({"", "ID", "Attribute Name", "Current", "Worst", "Threshold", "Raw Values"});
|
||||
tableWidget->verticalHeader()->setVisible(false);
|
||||
tableWidget->setItemDelegateForColumn(0, new StatusDot(tableWidget));
|
||||
tableWidget->setRowCount(attributes.size());
|
||||
|
||||
int row = 0;
|
||||
for (const QJsonValue &attr : attributes) {
|
||||
QJsonObject attrObj = attr.toObject();
|
||||
QString id = QString("%1").arg(attrObj["id"].toInt(), 2, 16, QChar('0')).toUpper();
|
||||
QString name = attrObj["name"].toString().replace("_", " ");
|
||||
int value = attrObj["value"].toInt();
|
||||
int worst = attrObj["worst"].toInt();
|
||||
int thresh = attrObj["thresh"].toInt();
|
||||
QString raw = attrObj["raw"].toObject()["string"].toString();
|
||||
|
||||
int spaceIndex = raw.indexOf(' ');
|
||||
if (spaceIndex != -1) {
|
||||
raw = raw.left(spaceIndex);
|
||||
}
|
||||
raw = QString("%1").arg(raw.toUInt(nullptr), 12, 16, QChar('0')).toUpper();
|
||||
|
||||
QColor statusColor;
|
||||
if ((thresh != 0) && (value < thresh)) {
|
||||
statusColor = Qt::red;
|
||||
} else if ((id == "05" || id == "C5" || id == "C6") && (raw != "0")) {
|
||||
statusColor = Qt::yellow;
|
||||
} else {
|
||||
statusColor = Qt::green;
|
||||
}
|
||||
|
||||
QTableWidgetItem *statusItem = new QTableWidgetItem();
|
||||
statusItem->setBackground(Qt::transparent);
|
||||
statusItem->setData(Qt::BackgroundRole, QVariant(statusColor));
|
||||
|
||||
QTableWidgetItem *idItem = new QTableWidgetItem(id);
|
||||
idItem->setTextAlignment(Qt::AlignCenter);
|
||||
|
||||
QTableWidgetItem *nameItem = new QTableWidgetItem(name);
|
||||
QTableWidgetItem *valueItem = new QTableWidgetItem(QString::number(value));
|
||||
valueItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
QTableWidgetItem *worstItem = new QTableWidgetItem(QString::number(worst));
|
||||
worstItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
QTableWidgetItem *threshItem = new QTableWidgetItem(QString::number(thresh));
|
||||
threshItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
QTableWidgetItem *rawItem = new QTableWidgetItem(raw);
|
||||
rawItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
tableWidget->setItem(row, 0, statusItem);
|
||||
tableWidget->setItem(row, 1, idItem);
|
||||
tableWidget->setItem(row, 2, nameItem);
|
||||
tableWidget->setItem(row, 3, valueItem);
|
||||
tableWidget->setItem(row, 4, worstItem);
|
||||
tableWidget->setItem(row, 5, threshItem);
|
||||
tableWidget->setItem(row, 6, rawItem);
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
|
||||
for (int i = 0; i < tableWidget->columnCount(); ++i) {
|
||||
if (i != 2) {
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
}
|
||||
|
||||
tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
}
|
||||
|
||||
QString MainWindow::getSmartctlOutput(const QStringList &arguments, bool root)
|
||||
{
|
||||
QProcess process;
|
||||
QString command;
|
||||
QStringList commandArgs;
|
||||
if(root) {
|
||||
command = "pkexec";
|
||||
commandArgs = {"smartctl"};
|
||||
} else {
|
||||
command = "smartctl";
|
||||
commandArgs = {};
|
||||
}
|
||||
|
||||
commandArgs.append(arguments);
|
||||
process.start(command, commandArgs);
|
||||
process.waitForFinished();
|
||||
return process.readAllStandardOutput();
|
||||
}
|
||||
|
||||
44
mainwindow.h
Normal file
44
mainwindow.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QProcess>
|
||||
#include <QWidget>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QButtonGroup>
|
||||
|
||||
#include "statusdot.h"
|
||||
#include "custombutton.h"
|
||||
#include "./ui_mainwindow.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
QButtonGroup *buttonGroup;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QLabel *diskName, *temperatureValue, *healthStatusValue;
|
||||
QLineEdit *firmwareLineEdit, *serialNumberLineEdit, *typeLineEdit, *protocolLineEdit, *deviceNodeLineEdit;
|
||||
QLineEdit *totalReadsLineEdit, *totalWritesLineEdit, *rotationRateLineEdit, *powerOnCountLineEdit, *powerOnHoursLineEdit;
|
||||
QTableWidget *tableWidget;
|
||||
|
||||
void scanDevices();
|
||||
void populateWindow(const QJsonObject &tempObj, const QString &health);
|
||||
void addSmartAttributesTable(const QJsonArray &attributes);
|
||||
QString getSmartctlOutput(const QStringList &arguments, bool root);
|
||||
};
|
||||
#endif
|
||||
326
mainwindow.ui
Normal file
326
mainwindow.ui
Normal file
@@ -0,0 +1,326 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModality::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>KDiskInfo</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="disks">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="navigation">
|
||||
<item>
|
||||
<widget class="QPushButton" name="previousButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::GoPrevious"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="diskName">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><span style=" font-size:14pt; font-weight:700;">Hard Drive Name</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="nextButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::GoNext"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="info">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="healthStatusLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Health Status</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="healthStatusValueLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(0, 255, 0);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:700; color:#000000;">Good</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="temperatureLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Temperature</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="temperatureValueLabel">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(0, 255, 0);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:700; color:#000000;">23° C</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="firmwareLabel">
|
||||
<property name="text">
|
||||
<string>Firmware</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="firmwareLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="serialNumberLabel">
|
||||
<property name="text">
|
||||
<string>Serial Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="serialNumberLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="protocolLabel">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="protocolLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="deviceNodeLabel">
|
||||
<property name="text">
|
||||
<string>Device Node</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="deviceNodeLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="typeLabel">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="typeLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="totalReadsLabel">
|
||||
<property name="text">
|
||||
<string>Total Host Reads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="totalReadsLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="totalWritesLabel">
|
||||
<property name="text">
|
||||
<string>Total Host Writes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="totalWritesLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="rotationRateLabel">
|
||||
<property name="text">
|
||||
<string>Rotation Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="rotationRateLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="powerOnCountLabel">
|
||||
<property name="text">
|
||||
<string>Power On Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="powerOnCountLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="powerOnHoursLabel">
|
||||
<property name="text">
|
||||
<string>Power On Hours</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="powerOnHoursLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QTableWidget" name="dataTable">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
17
statusdot.cpp
Normal file
17
statusdot.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "statusdot.h"
|
||||
|
||||
void StatusDot::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
int dotSize = qMin(opt.rect.width(), opt.rect.height()) * 0.5;
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
QRect dotRect(opt.rect.center().x() - dotSize / 2, opt.rect.center().y() - dotSize / 2, dotSize, dotSize);
|
||||
QColor color = QColor(index.data(Qt::BackgroundRole).value<QColor>());
|
||||
painter->setBrush(color);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawEllipse(dotRect);
|
||||
painter->restore();
|
||||
}
|
||||
20
statusdot.h
Normal file
20
statusdot.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef STATUSDOT_H
|
||||
#define STATUSDOT_H
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionViewItem>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class StatusDot : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
StatusDot(QObject *parent = nullptr)
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user