optimized

This commit is contained in:
rdavidek 2026-01-11 13:01:53 +01:00
parent c8668e5f00
commit fc1ca721fc
8 changed files with 88 additions and 74 deletions

View File

@ -32,6 +32,7 @@ public:
private:
std::string getConfigFilePath() const;
mutable std::string cachedConfigPath;
int windowWidth;
int windowHeight;
int pollingTime;

View File

@ -2,6 +2,8 @@
#define MAINWINDOW_H
#include <gtk/gtk.h>
#include <memory>
#include <map>
#include "temp_monitor.h"
#include "temperature_chart.h"
#include "config_manager.h"
@ -30,9 +32,9 @@ private:
GtkWidget *window;
GtkWidget *statusLabel;
GtkSpinButton *refreshRateSpinBox;
TemperatureChart *chart;
TempMonitor *monitor;
ConfigManager *config;
std::unique_ptr<TemperatureChart> chart;
std::unique_ptr<TempMonitor> monitor;
std::unique_ptr<ConfigManager> config;
guint timerID;
int refreshRateSec;
GtkWidget *legendBox;

View File

@ -22,7 +22,7 @@ struct SeriesData {
class TemperatureChart {
public:
TemperatureChart(GtkWidget *parent = nullptr);
TemperatureChart();
~TemperatureChart();
GtkWidget* getWidget() const { return drawingArea; }
@ -48,7 +48,7 @@ private:
void redraw();
void updateThemeColors();
static gboolean onTick(gpointer userData);
static void onLeave(GtkEventControllerMotion *motion, gpointer userData);
struct NearestPoint {

View File

@ -5,27 +5,20 @@ window {
.small-entry {
font-size: 9px;
min-height: 0;
min-width: 0;
padding: 0px 1px;
padding: 1px;
margin: 0;
border: none;
background: transparent;
}
.small-entry:focus {
background: rgba(255,255,255,0.1);
}
.temp-label-small {
font-size: 9px;
font-size: 10px;
font-weight: bold;
margin-left: 1px;
color: #ccc;
margin-left: 2px;
color: #888;
}
/* Compact box items */
.legend-item {
margin: 0 4px;
padding: 0;
margin: 0 5px;
padding: 2px;
}

View File

@ -13,13 +13,18 @@ ConfigManager::ConfigManager()
std::string ConfigManager::getConfigFilePath() const
{
if (!cachedConfigPath.empty()) {
return cachedConfigPath;
}
// Get the directory of the executable using /proc/self/exe
char path[1024];
ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1);
if (len == -1) {
// Fallback to current directory
return "./nvme-monitor.conf";
cachedConfigPath = "./nvme-monitor.conf";
return cachedConfigPath;
}
path[len] = '\0';
@ -29,10 +34,12 @@ std::string ConfigManager::getConfigFilePath() const
size_t lastSlash = fullPath.find_last_of('/');
if (lastSlash != std::string::npos) {
std::string exeDir = fullPath.substr(0, lastSlash);
return exeDir + "/nvme-monitor.conf";
cachedConfigPath = exeDir + "/nvme-monitor.conf";
return cachedConfigPath;
}
return "./nvme-monitor.conf";
cachedConfigPath = "./nvme-monitor.conf";
return cachedConfigPath;
}
void ConfigManager::load()
@ -61,16 +68,20 @@ void ConfigManager::load()
value.erase(0, value.find_first_not_of(" \t"));
value.erase(value.find_last_not_of(" \t") + 1);
if (key == "window_width") {
windowWidth = std::stoi(value);
} else if (key == "window_height") {
windowHeight = std::stoi(value);
} else if (key == "polling_time") {
pollingTime = std::stoi(value);
} else if (key.find("color_") == 0) {
sensorColors[key.substr(6)] = value;
} else if (key.find("name_") == 0) {
sensorNames[key.substr(5)] = value;
try {
if (key == "window_width") {
windowWidth = std::stoi(value);
} else if (key == "window_height") {
windowHeight = std::stoi(value);
} else if (key == "polling_time") {
pollingTime = std::stoi(value);
} else if (key.find("color_") == 0) {
sensorColors[key.substr(6)] = value;
} else if (key.find("name_") == 0) {
sensorNames[key.substr(5)] = value;
}
} catch (const std::exception &e) {
std::cerr << "Config error: invalid value for '" << key << "': " << value << " (" << e.what() << ")" << std::endl;
}
}

View File

@ -51,19 +51,13 @@ int main(int argc, char *argv[])
gtk_init();
std::cerr << "GTK Initialized" << std::endl;
// Register resources containing the application icon
GResource *resource = resources_get_resource();
g_resources_register(resource);
std::cerr << "Resources registered" << std::endl;
gMainLoop = g_main_loop_new(nullptr, FALSE);
std::cerr << "Creating MainWindow" << std::endl;
MainWindow *window = new MainWindow();
std::cerr << "MainWindow created" << std::endl;
window->show();
// Run the main event loop

View File

@ -9,11 +9,10 @@
MainWindow::MainWindow()
: window(nullptr), statusLabel(nullptr), refreshRateSpinBox(nullptr),
chart(nullptr), monitor(nullptr), config(nullptr), timerID(0),
refreshRateSec(3)
timerID(0), refreshRateSec(3)
{
monitor = new TempMonitor();
config = new ConfigManager();
monitor = std::make_unique<TempMonitor>();
config = std::make_unique<ConfigManager>();
config->load();
refreshRateSec = config->getPollingTime();
@ -35,15 +34,8 @@ MainWindow::~MainWindow()
if (timerID) {
g_source_remove(timerID);
}
if (monitor) {
delete monitor;
}
if (chart) {
delete chart;
}
if (config) {
config->save();
delete config;
}
}
@ -95,7 +87,8 @@ void MainWindow::setupUI()
// Refresh rate spinner
GtkAdjustment *adjustment = gtk_adjustment_new(refreshRateSec, 1, 60, 1, 5, 0);
refreshRateSpinBox = GTK_SPIN_BUTTON(gtk_spin_button_new(adjustment, 100, 0));
refreshRateSpinBox = GTK_SPIN_BUTTON(gtk_spin_button_new(adjustment, 1, 0));
gtk_widget_set_size_request(GTK_WIDGET(refreshRateSpinBox), 80, -1);
g_signal_connect(refreshRateSpinBox, "value-changed", G_CALLBACK(onRefreshRateChanged), this);
gtk_box_append(GTK_BOX(controlBox), GTK_WIDGET(refreshRateSpinBox));
@ -118,16 +111,17 @@ void MainWindow::setupUI()
gtk_box_append(GTK_BOX(mainBox), controlBox);
// Chart
chart = new TemperatureChart();
chart = std::make_unique<TemperatureChart>();
gtk_box_append(GTK_BOX(mainBox), chart->getWidget());
gtk_widget_set_vexpand(chart->getWidget(), TRUE);
// Legend box with horizontal scrolling only
// Legend box with horizontal scrolling
legendBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget *legendScroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(legendScroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(legendScroll), legendBox);
gtk_widget_set_vexpand(legendScroll, FALSE);
gtk_widget_set_margin_top(legendScroll, 2);
gtk_box_append(GTK_BOX(mainBox), legendScroll);
@ -199,7 +193,6 @@ void MainWindow::saveWindowState()
void MainWindow::updateTemperatures()
{
std::cerr << "updateTemperatures starting" << std::endl;
auto allTemps = monitor->getAllTemperatures();
// Get current real time in milliseconds since epoch
@ -213,14 +206,10 @@ void MainWindow::updateTemperatures()
const std::string &device = deviceEntry.first;
const auto &temps = deviceEntry.second;
std::cerr << "Processing device: " << device << " with " << temps.size() << " sensors" << std::endl;
for (const auto &tempEntry : temps) {
const std::string &sensorName = tempEntry.first;
double temperature = tempEntry.second;
std::cerr << " Sensor: " << sensorName << " Temp: " << temperature << std::endl;
if (chart->addTemperatureData(device, sensorName, temperature, currentTime)) {
needsLegendUpdate = true;
@ -297,7 +286,7 @@ void MainWindow::updateLegend()
GtkColorDialog *dialog = gtk_color_dialog_new();
GtkWidget *colorButton = gtk_color_dialog_button_new(dialog);
gtk_color_dialog_button_set_rgba(GTK_COLOR_DIALOG_BUTTON(colorButton), &color);
gtk_widget_set_size_request(colorButton, 12, 12);
gtk_widget_set_size_request(colorButton, 16, 16);
// Store series id in user data
g_object_set_data_full(G_OBJECT(colorButton), "series-name", g_strdup(seriesId.c_str()), g_free);
@ -307,8 +296,8 @@ void MainWindow::updateLegend()
// Create editable label for series name
GtkWidget *entry = gtk_entry_new();
gtk_editable_set_text(GTK_EDITABLE(entry), displayName.c_str());
gtk_widget_set_size_request(entry, 60, -1);
gtk_widget_add_css_class(entry, "small-entry");
gtk_editable_set_width_chars(GTK_EDITABLE(entry), 8);
// Store series id in user data
g_object_set_data_full(G_OBJECT(entry), "series-name", g_strdup(seriesId.c_str()), g_free);

View File

@ -6,7 +6,7 @@
#include <limits>
#include <string>
TemperatureChart::TemperatureChart(GtkWidget *parent)
TemperatureChart::TemperatureChart()
: drawingArea(nullptr), tooltipWindow(nullptr), tooltipLabel(nullptr),
maxDataPoints(600), tickHandler(0),
minTemp(MIN_TEMP), maxTemp(MAX_TEMP), minTime(0), maxTime(0),
@ -51,9 +51,16 @@ TemperatureChart::TemperatureChart(GtkWidget *parent)
gtk_widget_add_controller(drawingArea, motion);
setupColors();
// Setup tick callback for redrawing
tickHandler = g_timeout_add(100, onTick, this);
// Listen for theme changes
GtkSettings *settings = gtk_settings_get_default();
if (settings) {
g_signal_connect_swapped(settings, "notify::gtk-theme-name",
G_CALLBACK(+[](TemperatureChart *self) {
self->updateThemeColors();
gtk_widget_queue_draw(self->drawingArea);
}), this);
}
}
TemperatureChart::~TemperatureChart()
@ -203,9 +210,35 @@ bool TemperatureChart::addTemperatureData(const std::string &device, const std::
}
}
// Update temperature range
minTemp = MIN_TEMP;
maxTemp = MAX_TEMP;
// Update temperature range dynamically
double currentMin = 1000.0;
double currentMax = -1000.0;
bool hasData = false;
for (const auto &entry : seriesMap) {
for (const auto &p : entry.second.points) {
if (p.temperature < currentMin) currentMin = p.temperature;
if (p.temperature > currentMax) currentMax = p.temperature;
hasData = true;
}
}
if (hasData) {
// Round down min to nearest 10, round up max to nearest 10
minTemp = std::floor(currentMin / 10.0) * 10.0;
maxTemp = std::ceil(currentMax / 10.0) * 10.0;
// Ensure at least 20 degrees range
if (maxTemp - minTemp < 20.0) {
maxTemp = minTemp + 20.0;
}
// Don't let it be too small
if (minTemp > 30.0) minTemp = 30.0;
} else {
minTemp = MIN_TEMP;
maxTemp = MAX_TEMP;
}
// Update time range - keep 10 minute window
maxTime = timestamp;
@ -266,18 +299,9 @@ void TemperatureChart::setSeriesName(const std::string &seriesId, const std::str
}
}
gboolean TemperatureChart::onTick(gpointer userData)
{
TemperatureChart *self = static_cast<TemperatureChart*>(userData);
gtk_widget_queue_draw(self->drawingArea);
return TRUE;
}
void TemperatureChart::drawChart(GtkDrawingArea *area, cairo_t *cr, int width, int height)
{
// Update theme colors before drawing
updateThemeColors();
// Background with theme color
cairo_set_source_rgb(cr, bgColor.red, bgColor.green, bgColor.blue);
cairo_paint(cr);