Merge pull request #4929 from c4rlo/failed-units-tooltip
systemd-failed-units: add tooltip with list of failed units
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <giomm/dbusproxy.h>
|
#include <giomm/dbusproxy.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
|
|
||||||
@@ -11,23 +12,42 @@ namespace waybar::modules {
|
|||||||
class SystemdFailedUnits : public ALabel {
|
class SystemdFailedUnits : public ALabel {
|
||||||
public:
|
public:
|
||||||
SystemdFailedUnits(const std::string&, const Json::Value&);
|
SystemdFailedUnits(const std::string&, const Json::Value&);
|
||||||
virtual ~SystemdFailedUnits();
|
virtual ~SystemdFailedUnits() = default;
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool hide_on_ok;
|
struct FailedUnit {
|
||||||
std::string format_ok;
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
std::string load_state;
|
||||||
|
std::string active_state;
|
||||||
|
std::string sub_state;
|
||||||
|
std::string scope;
|
||||||
|
};
|
||||||
|
|
||||||
bool update_pending;
|
bool hide_on_ok_;
|
||||||
std::string system_state, user_state, overall_state;
|
std::string format_ok_;
|
||||||
uint32_t nr_failed_system, nr_failed_user, nr_failed;
|
std::string tooltip_format_;
|
||||||
std::string last_status;
|
std::string tooltip_format_ok_;
|
||||||
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
|
std::string tooltip_unit_format_;
|
||||||
|
|
||||||
|
bool update_pending_;
|
||||||
|
std::string system_state_, user_state_, overall_state_;
|
||||||
|
uint32_t nr_failed_system_, nr_failed_user_, nr_failed_;
|
||||||
|
std::string last_status_;
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy> system_props_proxy_, user_props_proxy_;
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy> system_manager_proxy_, user_manager_proxy_;
|
||||||
|
std::vector<FailedUnit> failed_units_;
|
||||||
|
|
||||||
void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||||
const Glib::VariantContainerBase& arguments);
|
const Glib::VariantContainerBase& arguments);
|
||||||
void RequestFailedUnits();
|
void RequestFailedUnits();
|
||||||
|
void RequestFailedUnitsList();
|
||||||
void RequestSystemState();
|
void RequestSystemState();
|
||||||
|
std::vector<FailedUnit> LoadFailedUnitsList(const char* kind,
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy>& proxy,
|
||||||
|
const std::string& scope);
|
||||||
|
std::string BuildTooltipFailedList() const;
|
||||||
void updateData();
|
void updateData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Addressed by *systemd-failed-units*
|
|||||||
|
|
||||||
*format-ok*: ++
|
*format-ok*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
This format is used when there is no failing units.
|
This format is used when there are no failing units.
|
||||||
|
|
||||||
*user*: ++
|
*user*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
@@ -34,15 +34,30 @@ Addressed by *systemd-failed-units*
|
|||||||
*hide-on-ok*: ++
|
*hide-on-ok*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: *true* ++
|
default: *true* ++
|
||||||
Option to hide this module when there is no failing units.
|
Option to hide this module when there are no failed units.
|
||||||
|
|
||||||
|
*tooltip-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *System: {system_state}\nUser: {user_state}\nFailed units ({nr_failed}):\n{failed_units_list}* ++
|
||||||
|
Tooltip format shown when there are failed units.
|
||||||
|
|
||||||
|
*tooltip-format-ok*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *System: {system_state}\nUser: {user_state}* ++
|
||||||
|
Tooltip format used when there are no failed units.
|
||||||
|
|
||||||
|
*tooltip-unit-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *{name}: {description}* ++
|
||||||
|
Format used to render each failed unit inside the tooltip. Each item is prefixed with a bullet.
|
||||||
|
|
||||||
*menu*: ++
|
*menu*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Action that popups the menu.
|
Action that pops up the menu.
|
||||||
|
|
||||||
*menu-file*: ++
|
*menu-file*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Location of the menu descriptor file. There need to be an element of type
|
Location of the menu descriptor file. There needs to be an element of type
|
||||||
GtkMenu with id *menu*
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
*menu-actions*: ++
|
*menu-actions*: ++
|
||||||
@@ -52,7 +67,7 @@ Addressed by *systemd-failed-units*
|
|||||||
*expand*: ++
|
*expand*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
Enables this module to consume all left over space dynamically.
|
Enables this module to consume all leftover space dynamically.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
@@ -62,11 +77,23 @@ Addressed by *systemd-failed-units*
|
|||||||
|
|
||||||
*{nr_failed}*: Number of total failed units.
|
*{nr_failed}*: Number of total failed units.
|
||||||
|
|
||||||
*{systemd_state}:* State of the systemd system session
|
*{system_state}:* State of the systemd system session.
|
||||||
|
|
||||||
*{user_state}:* State of the systemd user session
|
*{user_state}:* State of the systemd user session.
|
||||||
|
|
||||||
*{overall_state}:* Overall state of the systemd and user session. ("Ok" or "Degraded")
|
*{overall_state}:* Overall state of the systemd and user session. ("ok" or "degraded")
|
||||||
|
|
||||||
|
*{failed_units_list}:* Bulleted list of failed units using *tooltip-unit-format*. Empty when
|
||||||
|
there are no failed units.
|
||||||
|
|
||||||
|
The *tooltip-unit-format* string supports the following replacements:
|
||||||
|
|
||||||
|
*{name}*: Unit name ++
|
||||||
|
*{description}*: Unit description ++
|
||||||
|
*{load_state}*: Unit load state ++
|
||||||
|
*{active_state}*: Unit active state ++
|
||||||
|
*{sub_state}*: Unit sub state ++
|
||||||
|
*{scope}*: Either *system* or *user* depending on where the unit originated
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
@@ -77,6 +104,8 @@ Addressed by *systemd-failed-units*
|
|||||||
"format-ok": "✓",
|
"format-ok": "✓",
|
||||||
"system": true,
|
"system": true,
|
||||||
"user": false,
|
"user": false,
|
||||||
|
"tooltip-format": "{nr_failed} failed units:\n{failed_units_list}",
|
||||||
|
"tooltip-unit-format": "{scope}: {name} ({active_state})",
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
#include "modules/systemd_failed_units.hpp"
|
#include "modules/systemd_failed_units.hpp"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <giomm/dbusproxy.h>
|
#include <giomm/dbusproxy.h>
|
||||||
|
#include <glibmm/markup.h>
|
||||||
#include <glibmm/variant.h>
|
#include <glibmm/variant.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <exception>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
static const unsigned UPDATE_DEBOUNCE_TIME_MS = 1000;
|
static const unsigned UPDATE_DEBOUNCE_TIME_MS = 1000;
|
||||||
|
|
||||||
@@ -12,39 +17,71 @@ namespace waybar::modules {
|
|||||||
|
|
||||||
SystemdFailedUnits::SystemdFailedUnits(const std::string& id, const Json::Value& config)
|
SystemdFailedUnits::SystemdFailedUnits(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "systemd-failed-units", id, "{nr_failed} failed", 1),
|
: ALabel(config, "systemd-failed-units", id, "{nr_failed} failed", 1),
|
||||||
hide_on_ok(true),
|
hide_on_ok_(true),
|
||||||
update_pending(false),
|
tooltip_format_(
|
||||||
nr_failed_system(0),
|
"System: {system_state}\nUser: {user_state}\nFailed units ({nr_failed}):\n"
|
||||||
nr_failed_user(0),
|
"{failed_units_list}"),
|
||||||
nr_failed(0),
|
tooltip_format_ok_("System: {system_state}\nUser: {user_state}"),
|
||||||
last_status() {
|
tooltip_unit_format_("{name}: {description}"),
|
||||||
|
update_pending_(false),
|
||||||
|
nr_failed_system_(0),
|
||||||
|
nr_failed_user_(0),
|
||||||
|
nr_failed_(0),
|
||||||
|
last_status_() {
|
||||||
if (config["hide-on-ok"].isBool()) {
|
if (config["hide-on-ok"].isBool()) {
|
||||||
hide_on_ok = config["hide-on-ok"].asBool();
|
hide_on_ok_ = config["hide-on-ok"].asBool();
|
||||||
}
|
}
|
||||||
if (config["format-ok"].isString()) {
|
if (config["format-ok"].isString()) {
|
||||||
format_ok = config["format-ok"].asString();
|
format_ok_ = config["format-ok"].asString();
|
||||||
} else {
|
} else {
|
||||||
format_ok = format_;
|
format_ok_ = format_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config["tooltip-format"].isString()) {
|
||||||
|
tooltip_format_ = config["tooltip-format"].asString();
|
||||||
|
}
|
||||||
|
if (config["tooltip-format-ok"].isString()) {
|
||||||
|
tooltip_format_ok_ = config["tooltip-format-ok"].asString();
|
||||||
|
}
|
||||||
|
if (config["tooltip-unit-format"].isString()) {
|
||||||
|
tooltip_unit_format_ = config["tooltip-unit-format"].asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default to enable both "system" and "user". */
|
/* Default to enable both "system" and "user". */
|
||||||
if (!config["system"].isBool() || config["system"].asBool()) {
|
if (!config["system"].isBool() || config["system"].asBool()) {
|
||||||
system_proxy = Gio::DBus::Proxy::create_for_bus_sync(
|
system_props_proxy_ = Gio::DBus::Proxy::create_for_bus_sync(
|
||||||
Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.systemd1",
|
Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.systemd1",
|
||||||
"/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties");
|
"/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties");
|
||||||
if (!system_proxy) {
|
if (!system_props_proxy_) {
|
||||||
throw std::runtime_error("Unable to connect to systemwide systemd DBus!");
|
throw std::runtime_error("Unable to connect to systemwide systemd DBus!");
|
||||||
}
|
}
|
||||||
system_proxy->signal_signal().connect(sigc::mem_fun(*this, &SystemdFailedUnits::notify_cb));
|
system_props_proxy_->signal_signal().connect(
|
||||||
|
sigc::mem_fun(*this, &SystemdFailedUnits::notify_cb));
|
||||||
|
try {
|
||||||
|
system_manager_proxy_ = Gio::DBus::Proxy::create_for_bus_sync(
|
||||||
|
Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
||||||
|
} catch (const Glib::Error& e) {
|
||||||
|
spdlog::warn("Unable to connect to systemwide systemd Manager interface: {}",
|
||||||
|
e.what().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!config["user"].isBool() || config["user"].asBool()) {
|
if (!config["user"].isBool() || config["user"].asBool()) {
|
||||||
user_proxy = Gio::DBus::Proxy::create_for_bus_sync(
|
user_props_proxy_ = Gio::DBus::Proxy::create_for_bus_sync(
|
||||||
Gio::DBus::BusType::BUS_TYPE_SESSION, "org.freedesktop.systemd1",
|
Gio::DBus::BusType::BUS_TYPE_SESSION, "org.freedesktop.systemd1",
|
||||||
"/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties");
|
"/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties");
|
||||||
if (!user_proxy) {
|
if (!user_props_proxy_) {
|
||||||
throw std::runtime_error("Unable to connect to user systemd DBus!");
|
throw std::runtime_error("Unable to connect to user systemd DBus!");
|
||||||
}
|
}
|
||||||
user_proxy->signal_signal().connect(sigc::mem_fun(*this, &SystemdFailedUnits::notify_cb));
|
user_props_proxy_->signal_signal().connect(
|
||||||
|
sigc::mem_fun(*this, &SystemdFailedUnits::notify_cb));
|
||||||
|
try {
|
||||||
|
user_manager_proxy_ = Gio::DBus::Proxy::create_for_bus_sync(
|
||||||
|
Gio::DBus::BusType::BUS_TYPE_SESSION, "org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
||||||
|
} catch (const Glib::Error& e) {
|
||||||
|
spdlog::warn("Unable to connect to user systemd Manager interface: {}", e.what().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateData();
|
updateData();
|
||||||
@@ -52,16 +89,11 @@ SystemdFailedUnits::SystemdFailedUnits(const std::string& id, const Json::Value&
|
|||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemdFailedUnits::~SystemdFailedUnits() {
|
|
||||||
if (system_proxy) system_proxy.reset();
|
|
||||||
if (user_proxy) user_proxy.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SystemdFailedUnits::notify_cb(const Glib::ustring& sender_name,
|
auto SystemdFailedUnits::notify_cb(const Glib::ustring& sender_name,
|
||||||
const Glib::ustring& signal_name,
|
const Glib::ustring& signal_name,
|
||||||
const Glib::VariantContainerBase& arguments) -> void {
|
const Glib::VariantContainerBase& arguments) -> void {
|
||||||
if (signal_name == "PropertiesChanged" && !update_pending) {
|
if (signal_name == "PropertiesChanged" && !update_pending_) {
|
||||||
update_pending = true;
|
update_pending_ = true;
|
||||||
/* The fail count may fluctuate due to restarting. */
|
/* The fail count may fluctuate due to restarting. */
|
||||||
Glib::signal_timeout().connect_once(sigc::mem_fun(*this, &SystemdFailedUnits::updateData),
|
Glib::signal_timeout().connect_once(sigc::mem_fun(*this, &SystemdFailedUnits::updateData),
|
||||||
UPDATE_DEBOUNCE_TIME_MS);
|
UPDATE_DEBOUNCE_TIME_MS);
|
||||||
@@ -88,12 +120,12 @@ void SystemdFailedUnits::RequestSystemState() {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
};
|
};
|
||||||
|
|
||||||
system_state = load("systemwide", system_proxy);
|
system_state_ = load("systemwide", system_props_proxy_);
|
||||||
user_state = load("user", user_proxy);
|
user_state_ = load("user", user_props_proxy_);
|
||||||
if (system_state == "running" && user_state == "running")
|
if (system_state_ == "running" && user_state_ == "running")
|
||||||
overall_state = "ok";
|
overall_state_ = "ok";
|
||||||
else
|
else
|
||||||
overall_state = "degraded";
|
overall_state_ = "degraded";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemdFailedUnits::RequestFailedUnits() {
|
void SystemdFailedUnits::RequestFailedUnits() {
|
||||||
@@ -116,46 +148,153 @@ void SystemdFailedUnits::RequestFailedUnits() {
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
nr_failed_system = load("systemwide", system_proxy);
|
nr_failed_system_ = load("systemwide", system_props_proxy_);
|
||||||
nr_failed_user = load("user", user_proxy);
|
nr_failed_user_ = load("user", user_props_proxy_);
|
||||||
nr_failed = nr_failed_system + nr_failed_user;
|
nr_failed_ = nr_failed_system_ + nr_failed_user_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemdFailedUnits::RequestFailedUnitsList() {
|
||||||
|
failed_units_.clear();
|
||||||
|
if (!tooltipEnabled() || nr_failed_ == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system_manager_proxy_) {
|
||||||
|
auto units = LoadFailedUnitsList("systemwide", system_manager_proxy_, "system");
|
||||||
|
failed_units_.insert(failed_units_.end(), units.begin(), units.end());
|
||||||
|
}
|
||||||
|
if (user_manager_proxy_) {
|
||||||
|
auto units = LoadFailedUnitsList("user", user_manager_proxy_, "user");
|
||||||
|
failed_units_.insert(failed_units_.end(), units.begin(), units.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SystemdFailedUnits::LoadFailedUnitsList(const char* kind,
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy>& proxy,
|
||||||
|
const std::string& scope) -> std::vector<FailedUnit> {
|
||||||
|
// org.freedesktop.systemd1.Manager.ListUnits returns
|
||||||
|
// (name, description, load_state, active_state, sub_state, followed, unit_path, job_id,
|
||||||
|
// job_type, job_path).
|
||||||
|
using UnitRow = std::tuple<Glib::ustring, Glib::ustring, Glib::ustring, Glib::ustring,
|
||||||
|
Glib::ustring, Glib::ustring, Glib::DBusObjectPathString, guint32,
|
||||||
|
Glib::ustring, Glib::DBusObjectPathString>;
|
||||||
|
using ListUnitsReply = Glib::Variant<std::tuple<std::vector<UnitRow>>>;
|
||||||
|
|
||||||
|
std::vector<FailedUnit> units;
|
||||||
|
if (!proxy) {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto data = proxy->call_sync("ListUnits");
|
||||||
|
if (!data) return units;
|
||||||
|
if (!data.is_of_type(ListUnitsReply::variant_type())) {
|
||||||
|
spdlog::warn("Unexpected DBus signature for ListUnits: {}", data.get_type_string());
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [rows] = Glib::VariantBase::cast_dynamic<ListUnitsReply>(data).get();
|
||||||
|
for (const auto& row : rows) {
|
||||||
|
const auto& name = std::get<0>(row);
|
||||||
|
const auto& description = std::get<1>(row);
|
||||||
|
const auto& load_state = std::get<2>(row);
|
||||||
|
const auto& active_state = std::get<3>(row);
|
||||||
|
const auto& sub_state = std::get<4>(row);
|
||||||
|
if (active_state == "failed" || sub_state == "failed") {
|
||||||
|
units.push_back({name, description, load_state, active_state, sub_state, scope});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const Glib::Error& e) {
|
||||||
|
spdlog::error("Failed to list {} units: {}", kind, e.what().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SystemdFailedUnits::BuildTooltipFailedList() const {
|
||||||
|
if (failed_units_.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string list;
|
||||||
|
list.reserve(failed_units_.size() * 16);
|
||||||
|
bool first = true;
|
||||||
|
for (const auto& unit : failed_units_) {
|
||||||
|
try {
|
||||||
|
auto line = fmt::format(
|
||||||
|
fmt::runtime(tooltip_unit_format_),
|
||||||
|
fmt::arg("name", Glib::Markup::escape_text(unit.name).raw()),
|
||||||
|
fmt::arg("description", Glib::Markup::escape_text(unit.description).raw()),
|
||||||
|
fmt::arg("load_state", unit.load_state), fmt::arg("active_state", unit.active_state),
|
||||||
|
fmt::arg("sub_state", unit.sub_state), fmt::arg("scope", unit.scope));
|
||||||
|
if (!first) {
|
||||||
|
list += "\n";
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
list += "- ";
|
||||||
|
list += line;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
spdlog::warn("Failed to format tooltip for unit {}: {}", unit.name, e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemdFailedUnits::updateData() {
|
void SystemdFailedUnits::updateData() {
|
||||||
update_pending = false;
|
update_pending_ = false;
|
||||||
|
|
||||||
RequestSystemState();
|
RequestSystemState();
|
||||||
if (overall_state == "degraded") RequestFailedUnits();
|
if (overall_state_ == "degraded") {
|
||||||
|
RequestFailedUnits();
|
||||||
|
RequestFailedUnitsList();
|
||||||
|
} else {
|
||||||
|
nr_failed_system_ = nr_failed_user_ = nr_failed_ = 0;
|
||||||
|
failed_units_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SystemdFailedUnits::update() -> void {
|
auto SystemdFailedUnits::update() -> void {
|
||||||
if (last_status == overall_state) return;
|
|
||||||
|
|
||||||
// Hide if needed.
|
// Hide if needed.
|
||||||
if (overall_state == "ok" && hide_on_ok) {
|
if (overall_state_ == "ok" && hide_on_ok_) {
|
||||||
event_box_.set_visible(false);
|
event_box_.set_visible(false);
|
||||||
|
last_status_ = overall_state_;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_box_.set_visible(true);
|
event_box_.set_visible(true);
|
||||||
|
|
||||||
// Set state class.
|
// Set state class.
|
||||||
if (!last_status.empty() && label_.get_style_context()->has_class(last_status)) {
|
if (!last_status_.empty() && label_.get_style_context()->has_class(last_status_)) {
|
||||||
label_.get_style_context()->remove_class(last_status);
|
label_.get_style_context()->remove_class(last_status_);
|
||||||
}
|
}
|
||||||
if (!label_.get_style_context()->has_class(overall_state)) {
|
if (!label_.get_style_context()->has_class(overall_state_)) {
|
||||||
label_.get_style_context()->add_class(overall_state);
|
label_.get_style_context()->add_class(overall_state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_status = overall_state;
|
last_status_ = overall_state_;
|
||||||
|
|
||||||
label_.set_markup(fmt::format(
|
label_.set_markup(fmt::format(
|
||||||
fmt::runtime(nr_failed == 0 ? format_ok : format_), fmt::arg("nr_failed", nr_failed),
|
fmt::runtime(nr_failed_ == 0 ? format_ok_ : format_), fmt::arg("nr_failed", nr_failed_),
|
||||||
fmt::arg("nr_failed_system", nr_failed_system), fmt::arg("nr_failed_user", nr_failed_user),
|
fmt::arg("nr_failed_system", nr_failed_system_), fmt::arg("nr_failed_user", nr_failed_user_),
|
||||||
fmt::arg("system_state", system_state), fmt::arg("user_state", user_state),
|
fmt::arg("system_state", system_state_), fmt::arg("user_state", user_state_),
|
||||||
fmt::arg("overall_state", overall_state)));
|
fmt::arg("overall_state", overall_state_)));
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
std::string failed_list = BuildTooltipFailedList();
|
||||||
|
auto tooltip_template = overall_state_ == "ok" ? tooltip_format_ok_ : tooltip_format_;
|
||||||
|
if (!tooltip_template.empty()) {
|
||||||
|
label_.set_tooltip_markup(fmt::format(
|
||||||
|
fmt::runtime(tooltip_template), fmt::arg("nr_failed", nr_failed_),
|
||||||
|
fmt::arg("nr_failed_system", nr_failed_system_),
|
||||||
|
fmt::arg("nr_failed_user", nr_failed_user_), fmt::arg("system_state", system_state_),
|
||||||
|
fmt::arg("user_state", user_state_), fmt::arg("overall_state", overall_state_),
|
||||||
|
fmt::arg("failed_units_list", failed_list)));
|
||||||
|
} else {
|
||||||
|
label_.set_tooltip_text("");
|
||||||
|
}
|
||||||
|
}
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user