1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 05:47:36 +00:00

SystemMonitor: Consolidate hardware tabs + remove interrupts tab

Combine the "PCI devices" and "Processors" tabs into a "Hardware" tab.

And then remove the "Interrupts" tab because the number of received
IRQ's per device is not really useful information to expose in this GUI.
If the user needs this, he can check lsirq.
This commit is contained in:
Andreas Kling 2021-08-18 12:50:24 +02:00
parent 9994b81931
commit f91c499a41
4 changed files with 91 additions and 173 deletions

View file

@ -6,7 +6,6 @@ serenity_component(
set(SOURCES set(SOURCES
GraphWidget.cpp GraphWidget.cpp
InterruptsWidget.cpp
main.cpp main.cpp
MemoryStatsWidget.cpp MemoryStatsWidget.cpp
NetworkStatisticsWidget.cpp NetworkStatisticsWidget.cpp

View file

@ -1,48 +0,0 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "InterruptsWidget.h"
#include <LibGUI/BoxLayout.h>
#include <LibGUI/GroupBox.h>
#include <LibGUI/JsonArrayModel.h>
#include <LibGUI/SortingProxyModel.h>
#include <LibGUI/TableView.h>
InterruptsWidget::InterruptsWidget()
{
on_first_show = [this](auto&) {
set_layout<GUI::VerticalBoxLayout>();
layout()->set_margins(4);
Vector<GUI::JsonArrayModel::FieldSpec> interrupts_field;
interrupts_field.empend("interrupt_line", "Line", Gfx::TextAlignment::CenterRight);
interrupts_field.empend("purpose", "Purpose", Gfx::TextAlignment::CenterLeft);
interrupts_field.empend("controller", "Controller", Gfx::TextAlignment::CenterLeft);
interrupts_field.empend("cpu_handler", "CPU Handler", Gfx::TextAlignment::CenterRight);
interrupts_field.empend("device_sharing", "# Devices Sharing", Gfx::TextAlignment::CenterRight);
interrupts_field.empend("call_count", "Call Count", Gfx::TextAlignment::CenterRight);
m_interrupt_table_view = add<GUI::TableView>();
m_interrupt_model = GUI::JsonArrayModel::create("/proc/interrupts", move(interrupts_field));
m_interrupt_table_view->set_model(GUI::SortingProxyModel::create(*m_interrupt_model));
m_update_timer = add<Core::Timer>(
1000, [this] {
update_model();
});
update_model();
};
}
InterruptsWidget::~InterruptsWidget()
{
}
void InterruptsWidget::update_model()
{
m_interrupt_model->invalidate();
}

View file

@ -1,24 +0,0 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibCore/Timer.h>
#include <LibGUI/LazyWidget.h>
class InterruptsWidget final : public GUI::LazyWidget {
C_OBJECT(InterruptsWidget)
public:
virtual ~InterruptsWidget() override;
private:
InterruptsWidget();
void update_model();
RefPtr<GUI::TableView> m_interrupt_table_view;
RefPtr<GUI::JsonArrayModel> m_interrupt_model;
RefPtr<Core::Timer> m_update_timer;
};

View file

@ -5,7 +5,6 @@
*/ */
#include "GraphWidget.h" #include "GraphWidget.h"
#include "InterruptsWidget.h"
#include "MemoryStatsWidget.h" #include "MemoryStatsWidget.h"
#include "NetworkStatisticsWidget.h" #include "NetworkStatisticsWidget.h"
#include "ProcessFileDescriptorMapWidget.h" #include "ProcessFileDescriptorMapWidget.h"
@ -49,9 +48,8 @@
static NonnullRefPtr<GUI::Window> build_process_window(pid_t); static NonnullRefPtr<GUI::Window> build_process_window(pid_t);
static NonnullRefPtr<GUI::Widget> build_file_systems_tab(); static NonnullRefPtr<GUI::Widget> build_file_systems_tab();
static NonnullRefPtr<GUI::Widget> build_pci_devices_tab(); static NonnullRefPtr<GUI::Widget> build_hardware_tab();
static NonnullRefPtr<GUI::Widget> build_graphs_tab(); static NonnullRefPtr<GUI::Widget> build_graphs_tab();
static NonnullRefPtr<GUI::Widget> build_processors_tab();
static RefPtr<GUI::Statusbar> statusbar; static RefPtr<GUI::Statusbar> statusbar;
@ -157,7 +155,7 @@ int main(int argc, char** argv)
const char* args_tab = "processes"; const char* args_tab = "processes";
Core::ArgsParser parser; Core::ArgsParser parser;
parser.add_option(args_tab, "Tab, one of 'processes', 'graphs', 'fs', 'pci', 'devices', 'network', 'processors' or 'interrupts'", "open-tab", 't', "tab"); parser.add_option(args_tab, "Tab, one of 'processes', 'graphs', 'fs', 'hardware', or 'network'", "open-tab", 't', "tab");
parser.parse(argc, argv); parser.parse(argc, argv);
StringView args_tab_view = args_tab; StringView args_tab_view = args_tab;
@ -196,18 +194,12 @@ int main(int argc, char** argv)
auto file_systems_widget = build_file_systems_tab(); auto file_systems_widget = build_file_systems_tab();
tabwidget.add_widget("File systems", file_systems_widget); tabwidget.add_widget("File systems", file_systems_widget);
auto pci_devices_widget = build_pci_devices_tab(); auto hardware_widget = build_hardware_tab();
tabwidget.add_widget("PCI devices", pci_devices_widget); tabwidget.add_widget("Hardware", hardware_widget);
auto network_stats_widget = NetworkStatisticsWidget::construct(); auto network_stats_widget = NetworkStatisticsWidget::construct();
tabwidget.add_widget("Network", network_stats_widget); tabwidget.add_widget("Network", network_stats_widget);
auto processors_widget = build_processors_tab();
tabwidget.add_widget("Processors", processors_widget);
auto interrupts_widget = InterruptsWidget::construct();
tabwidget.add_widget("Interrupts", interrupts_widget);
process_table_container.set_layout<GUI::VerticalBoxLayout>(); process_table_container.set_layout<GUI::VerticalBoxLayout>();
process_table_container.layout()->set_margins(4); process_table_container.layout()->set_margins(4);
process_table_container.layout()->set_spacing(0); process_table_container.layout()->set_spacing(0);
@ -384,14 +376,10 @@ int main(int argc, char** argv)
tabwidget.set_active_widget(graphs_widget); tabwidget.set_active_widget(graphs_widget);
else if (args_tab_view == "fs") else if (args_tab_view == "fs")
tabwidget.set_active_widget(file_systems_widget); tabwidget.set_active_widget(file_systems_widget);
else if (args_tab_view == "pci") else if (args_tab_view == "hardware")
tabwidget.set_active_widget(pci_devices_widget); tabwidget.set_active_widget(hardware_widget);
else if (args_tab_view == "network") else if (args_tab_view == "network")
tabwidget.set_active_widget(network_stats_widget); tabwidget.set_active_widget(network_stats_widget);
else if (args_tab_view == "processors")
tabwidget.set_active_widget(processors_widget);
else if (args_tab_view == "interrupts")
tabwidget.set_active_widget(interrupts_widget);
return app->exec(); return app->exec();
} }
@ -576,63 +564,101 @@ NonnullRefPtr<GUI::Widget> build_file_systems_tab()
return fs_widget; return fs_widget;
} }
NonnullRefPtr<GUI::Widget> build_pci_devices_tab() NonnullRefPtr<GUI::Widget> build_hardware_tab()
{ {
auto pci_widget = GUI::LazyWidget::construct(); auto widget = GUI::LazyWidget::construct();
pci_widget->on_first_show = [](GUI::LazyWidget& self) { widget->on_first_show = [](GUI::LazyWidget& self) {
self.set_layout<GUI::VerticalBoxLayout>(); self.set_layout<GUI::VerticalBoxLayout>();
self.layout()->set_margins(4); self.layout()->set_margins(4);
auto& pci_table_view = self.add<GUI::TableView>();
auto db = PCIDB::Database::open(); {
if (!db) auto& cpu_group_box = self.add<GUI::GroupBox>("CPUs");
warnln("Couldn't open PCI ID database!"); cpu_group_box.set_layout<GUI::VerticalBoxLayout>();
cpu_group_box.layout()->set_margins({ 16, 6, 6 });
Vector<GUI::JsonArrayModel::FieldSpec> pci_fields; Vector<GUI::JsonArrayModel::FieldSpec> processors_field;
pci_fields.empend( processors_field.empend("processor", "Processor", Gfx::TextAlignment::CenterRight);
"Address", Gfx::TextAlignment::CenterLeft, processors_field.empend("cpuid", "CPUID", Gfx::TextAlignment::CenterLeft);
[](const JsonObject& object) { processors_field.empend("brandstr", "Brand", Gfx::TextAlignment::CenterLeft);
auto seg = object.get("seg").to_u32(); processors_field.empend("Features", Gfx::TextAlignment::CenterLeft, [](auto& object) {
auto bus = object.get("bus").to_u32(); StringBuilder builder;
auto device = object.get("device").to_u32(); auto features = object.get("features").as_array();
auto function = object.get("function").to_u32(); for (auto& feature : features.values()) {
return String::formatted("{:04x}:{:02x}:{:02x}.{}", seg, bus, device, function); builder.append(feature.to_string());
}); builder.append(' ');
pci_fields.empend( }
"Class", Gfx::TextAlignment::CenterLeft, return GUI::Variant(builder.to_string());
[db](const JsonObject& object) {
auto class_id = object.get("class").to_u32();
String class_name = db ? db->get_class(class_id) : nullptr;
return class_name.is_empty() ? String::formatted("{:04x}", class_id) : class_name;
});
pci_fields.empend(
"Vendor", Gfx::TextAlignment::CenterLeft,
[db](const JsonObject& object) {
auto vendor_id = object.get("vendor_id").to_u32();
String vendor_name = db ? db->get_vendor(vendor_id) : nullptr;
return vendor_name.is_empty() ? String::formatted("{:02x}", vendor_id) : vendor_name;
});
pci_fields.empend(
"Device", Gfx::TextAlignment::CenterLeft,
[db](const JsonObject& object) {
auto vendor_id = object.get("vendor_id").to_u32();
auto device_id = object.get("device_id").to_u32();
String device_name = db ? db->get_device(vendor_id, device_id) : nullptr;
return device_name.is_empty() ? String::formatted("{:02x}", device_id) : device_name;
});
pci_fields.empend(
"Revision", Gfx::TextAlignment::CenterRight,
[](const JsonObject& object) {
auto revision_id = object.get("revision_id").to_u32();
return String::formatted("{:02x}", revision_id);
}); });
processors_field.empend("family", "Family", Gfx::TextAlignment::CenterRight);
processors_field.empend("model", "Model", Gfx::TextAlignment::CenterRight);
processors_field.empend("stepping", "Stepping", Gfx::TextAlignment::CenterRight);
processors_field.empend("type", "Type", Gfx::TextAlignment::CenterRight);
pci_table_view.set_model(GUI::SortingProxyModel::create(GUI::JsonArrayModel::create("/proc/pci", move(pci_fields)))); auto& processors_table_view = cpu_group_box.add<GUI::TableView>();
pci_table_view.model()->invalidate(); auto json_model = GUI::JsonArrayModel::create("/proc/cpuinfo", move(processors_field));
processors_table_view.set_model(json_model);
json_model->invalidate();
cpu_group_box.set_fixed_height(128);
}
{
auto& pci_group_box = self.add<GUI::GroupBox>("PCI devices");
pci_group_box.set_layout<GUI::VerticalBoxLayout>();
pci_group_box.layout()->set_margins({ 16, 6, 6 });
auto& pci_table_view = pci_group_box.add<GUI::TableView>();
auto db = PCIDB::Database::open();
if (!db)
warnln("Couldn't open PCI ID database!");
Vector<GUI::JsonArrayModel::FieldSpec> pci_fields;
pci_fields.empend(
"Address", Gfx::TextAlignment::CenterLeft,
[](const JsonObject& object) {
auto seg = object.get("seg").to_u32();
auto bus = object.get("bus").to_u32();
auto device = object.get("device").to_u32();
auto function = object.get("function").to_u32();
return String::formatted("{:04x}:{:02x}:{:02x}.{}", seg, bus, device, function);
});
pci_fields.empend(
"Class", Gfx::TextAlignment::CenterLeft,
[db](const JsonObject& object) {
auto class_id = object.get("class").to_u32();
String class_name = db ? db->get_class(class_id) : nullptr;
return class_name.is_empty() ? String::formatted("{:04x}", class_id) : class_name;
});
pci_fields.empend(
"Vendor", Gfx::TextAlignment::CenterLeft,
[db](const JsonObject& object) {
auto vendor_id = object.get("vendor_id").to_u32();
String vendor_name = db ? db->get_vendor(vendor_id) : nullptr;
return vendor_name.is_empty() ? String::formatted("{:02x}", vendor_id) : vendor_name;
});
pci_fields.empend(
"Device", Gfx::TextAlignment::CenterLeft,
[db](const JsonObject& object) {
auto vendor_id = object.get("vendor_id").to_u32();
auto device_id = object.get("device_id").to_u32();
String device_name = db ? db->get_device(vendor_id, device_id) : nullptr;
return device_name.is_empty() ? String::formatted("{:02x}", device_id) : device_name;
});
pci_fields.empend(
"Revision", Gfx::TextAlignment::CenterRight,
[](const JsonObject& object) {
auto revision_id = object.get("revision_id").to_u32();
return String::formatted("{:02x}", revision_id);
});
pci_table_view.set_model(GUI::SortingProxyModel::create(GUI::JsonArrayModel::create("/proc/pci", move(pci_fields))));
pci_table_view.model()->invalidate();
}
}; };
return pci_widget; return widget;
} }
NonnullRefPtr<GUI::Widget> build_graphs_tab() NonnullRefPtr<GUI::Widget> build_graphs_tab()
@ -704,38 +730,3 @@ NonnullRefPtr<GUI::Widget> build_graphs_tab()
graphs_container->add<MemoryStatsWidget>(memory_graph); graphs_container->add<MemoryStatsWidget>(memory_graph);
return graphs_container; return graphs_container;
} }
NonnullRefPtr<GUI::Widget> build_processors_tab()
{
auto processors_widget = GUI::LazyWidget::construct();
processors_widget->on_first_show = [](GUI::LazyWidget& self) {
self.set_layout<GUI::VerticalBoxLayout>();
self.layout()->set_margins(4);
Vector<GUI::JsonArrayModel::FieldSpec> processors_field;
processors_field.empend("processor", "Processor", Gfx::TextAlignment::CenterRight);
processors_field.empend("cpuid", "CPUID", Gfx::TextAlignment::CenterLeft);
processors_field.empend("brandstr", "Brand", Gfx::TextAlignment::CenterLeft);
processors_field.empend("Features", Gfx::TextAlignment::CenterLeft, [](auto& object) {
StringBuilder builder;
auto features = object.get("features").as_array();
for (auto& feature : features.values()) {
builder.append(feature.to_string());
builder.append(' ');
}
return GUI::Variant(builder.to_string());
});
processors_field.empend("family", "Family", Gfx::TextAlignment::CenterRight);
processors_field.empend("model", "Model", Gfx::TextAlignment::CenterRight);
processors_field.empend("stepping", "Stepping", Gfx::TextAlignment::CenterRight);
processors_field.empend("type", "Type", Gfx::TextAlignment::CenterRight);
auto& processors_table_view = self.add<GUI::TableView>();
auto json_model = GUI::JsonArrayModel::create("/proc/cpuinfo", move(processors_field));
processors_table_view.set_model(json_model);
json_model->invalidate();
};
return processors_widget;
}