feat(disk)!: handle multiple disks at once
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
@@ -19,7 +20,9 @@ class Disk : public ALabel {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
std::string path_;
|
std::string header_;
|
||||||
|
std::vector<std::string> paths_;
|
||||||
|
std::string separator_;
|
||||||
std::string unit_;
|
std::string unit_;
|
||||||
|
|
||||||
float calc_specific_divisor(const std::string divisor);
|
float calc_specific_divisor(const std::string divisor);
|
||||||
|
|||||||
+36
-9
@@ -6,17 +6,12 @@ waybar - disk module
|
|||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
The *disk* module displays the current disk space used.
|
The *disk* module displays information of multiple disks.
|
||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
Addressed by *disk*
|
Addressed by *disk*
|
||||||
|
|
||||||
*path*: ++
|
|
||||||
typeof: string ++
|
|
||||||
default: "/" ++
|
|
||||||
Any path residing in the filesystem or mountpoint for which the information should be displayed.
|
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer++
|
typeof: integer++
|
||||||
default: 30 ++
|
default: 30 ++
|
||||||
@@ -25,7 +20,7 @@ Addressed by *disk*
|
|||||||
*format*: ++
|
*format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: "{percentage_used}%" ++
|
default: "{percentage_used}%" ++
|
||||||
The format, how information should be displayed.
|
The format, how information for each disk should be displayed.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
@@ -75,6 +70,26 @@ Addressed by *disk*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when scrolling down on the module.
|
Command to execute when scrolling down on the module.
|
||||||
|
|
||||||
|
*path*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: "/" ++
|
||||||
|
Deprecated path of filesystem or mountpoint to monitor.
|
||||||
|
|
||||||
|
*paths*: ++
|
||||||
|
typeof: array ++
|
||||||
|
default: ["/"] ++
|
||||||
|
Array of paths residing in the filesystem or mountpoint for which the information should be displayed.
|
||||||
|
|
||||||
|
*header*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: "" ++
|
||||||
|
Text to appear before the disk information defined in the format.
|
||||||
|
|
||||||
|
*separator*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: " " ++
|
||||||
|
Separator string between multiple disk information.
|
||||||
|
|
||||||
*smooth-scrolling-threshold*: ++
|
*smooth-scrolling-threshold*: ++
|
||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
@@ -123,7 +138,7 @@ Addressed by *disk*
|
|||||||
|
|
||||||
*{free}*: Amount of available disk space for normal users. Automatically selects unit based on size remaining.
|
*{free}*: Amount of available disk space for normal users. Automatically selects unit based on size remaining.
|
||||||
|
|
||||||
*{path}*: The path specified in the configuration.
|
*{path}*: The path for each disk specified in the configuration.
|
||||||
|
|
||||||
*{specific_total}*: Total amount of space on the disk, partition, or mountpoint in a specific unit. Defaults to bytes.
|
*{specific_total}*: Total amount of space on the disk, partition, or mountpoint in a specific unit. Defaults to bytes.
|
||||||
|
|
||||||
@@ -143,10 +158,22 @@ Addressed by *disk*
|
|||||||
```
|
```
|
||||||
"disk": {
|
"disk": {
|
||||||
"interval": 30,
|
"interval": 30,
|
||||||
|
"format": "{percentage_free}% free on {path}",
|
||||||
|
"header": "Disks: ",
|
||||||
|
"paths": ["/", "/home"],
|
||||||
|
"separator": " ",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
"disk": {
|
||||||
|
"interval": 30,
|
||||||
|
"paths": ["/"],
|
||||||
"format": "{specific_free:0.2f} GB out of {specific_total:0.2f} GB available. Alternatively {free} out of {total} available",
|
"format": "{specific_free:0.2f} GB out of {specific_total:0.2f} GB available. Alternatively {free} out of {total} available",
|
||||||
"unit": "GB"
|
"unit": "GB"
|
||||||
// 1434.25 GB out of 2000.00 GB available. Alternatively 1.4TiB out of 1.9TiB available.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1434.25 GB out of 2000.00 GB available. Alternatively 1.4TiB out of 1.9TiB available.
|
||||||
```
|
```
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|||||||
+111
-62
@@ -1,15 +1,32 @@
|
|||||||
#include "modules/disk.hpp"
|
#include "modules/disk.hpp"
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
using namespace waybar::util;
|
using namespace waybar::util;
|
||||||
|
|
||||||
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "disk", id, "{}%", 30), path_("/") {
|
: ALabel(config, "disk", id, "{}%", 30), header_(""), paths_(), separator_(" ") {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
thread_.sleep_for(interval_);
|
thread_.sleep_for(interval_);
|
||||||
};
|
};
|
||||||
if (config["path"].isString()) {
|
if (config["header"].isString()) {
|
||||||
path_ = config["path"].asString();
|
header_ = config["header"].asString();
|
||||||
|
}
|
||||||
|
if (config["path"].isString() && !config["paths"].isArray()) {
|
||||||
|
spdlog::warn("Disk: path is deprecated use paths instead!");
|
||||||
|
paths_.push_back(config["path"].asString());
|
||||||
|
}
|
||||||
|
if (config["paths"].isArray()) {
|
||||||
|
for (const auto& path : config["paths"]) {
|
||||||
|
paths_.push_back(path.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!config["path"].isString() && !config["paths"].isArray()) {
|
||||||
|
paths_.emplace_back("/");
|
||||||
|
}
|
||||||
|
if (config["separator"].isString()) {
|
||||||
|
separator_ = config["separator"].asString();
|
||||||
}
|
}
|
||||||
if (config["unit"].isString()) {
|
if (config["unit"].isString()) {
|
||||||
unit_ = config["unit"].asString();
|
unit_ = config["unit"].asString();
|
||||||
@@ -17,76 +34,108 @@ waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Disk::update() -> void {
|
auto waybar::modules::Disk::update() -> void {
|
||||||
struct statvfs /* {
|
std::string tooltip_label;
|
||||||
unsigned long f_bsize; // filesystem block size
|
std::string label = header_;
|
||||||
unsigned long f_frsize; // fragment size
|
|
||||||
fsblkcnt_t f_blocks; // size of fs in f_frsize units
|
|
||||||
fsblkcnt_t f_bfree; // # free blocks
|
|
||||||
fsblkcnt_t f_bavail; // # free blocks for unprivileged users
|
|
||||||
fsfilcnt_t f_files; // # inodes
|
|
||||||
fsfilcnt_t f_ffree; // # free inodes
|
|
||||||
fsfilcnt_t f_favail; // # free inodes for unprivileged users
|
|
||||||
unsigned long f_fsid; // filesystem ID
|
|
||||||
unsigned long f_flag; // mount flags
|
|
||||||
unsigned long f_namemax; // maximum filename length
|
|
||||||
}; */
|
|
||||||
stats;
|
|
||||||
int err = statvfs(path_.c_str(), &stats);
|
|
||||||
|
|
||||||
/* Conky options
|
bool had_valid_disk = false;
|
||||||
fs_bar - Bar that shows how much space is used
|
|
||||||
fs_free - Free space on a file system
|
|
||||||
fs_free_perc - Free percentage of space
|
|
||||||
fs_size - File system size
|
|
||||||
fs_used - File system used space
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (err != 0) {
|
for (size_t i = 0; i < paths_.size(); ++i) {
|
||||||
event_box_.hide();
|
const auto& path = paths_[i];
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float specific_free, specific_used, specific_total, divisor;
|
struct statvfs /* {
|
||||||
|
unsigned long f_bsize; // filesystem block size
|
||||||
|
unsigned long f_frsize; // fragment size
|
||||||
|
fsblkcnt_t f_blocks; // size of fs in f_frsize units
|
||||||
|
fsblkcnt_t f_bfree; // # free blocks
|
||||||
|
fsblkcnt_t f_bavail; // # free blocks for unprivileged users
|
||||||
|
fsfilcnt_t f_files; // # inodes
|
||||||
|
fsfilcnt_t f_ffree; // # free inodes
|
||||||
|
fsfilcnt_t f_favail; // # free inodes for unprivileged users
|
||||||
|
unsigned long f_fsid; // filesystem ID
|
||||||
|
unsigned long f_flag; // mount flags
|
||||||
|
unsigned long f_namemax; // maximum filename length
|
||||||
|
}; */
|
||||||
|
stats;
|
||||||
|
|
||||||
divisor = calc_specific_divisor(unit_);
|
int err = statvfs(path.c_str(), &stats);
|
||||||
specific_free = (stats.f_bavail * stats.f_frsize) / divisor;
|
|
||||||
specific_used = ((stats.f_blocks - stats.f_bfree) * stats.f_frsize) / divisor;
|
|
||||||
specific_total = (stats.f_blocks * stats.f_frsize) / divisor;
|
|
||||||
|
|
||||||
auto free = pow_format(stats.f_bavail * stats.f_frsize, "B", true);
|
/* Conky options
|
||||||
auto used = pow_format((stats.f_blocks - stats.f_bfree) * stats.f_frsize, "B", true);
|
fs_bar - Bar that shows how much space is used
|
||||||
auto total = pow_format(stats.f_blocks * stats.f_frsize, "B", true);
|
fs_free - Free space on a file system
|
||||||
auto percentage_used = (stats.f_blocks - stats.f_bfree) * 100 / stats.f_blocks;
|
fs_free_perc - Free percentage of space
|
||||||
|
fs_size - File system size
|
||||||
|
fs_used - File system used space
|
||||||
|
*/
|
||||||
|
|
||||||
auto format = format_;
|
if (err != 0) {
|
||||||
auto state = getState(percentage_used);
|
spdlog::warn("Disk: statvfs failed for path '{}' (errno={})", path, errno);
|
||||||
if (!state.empty() && config_["format-" + state].isString()) {
|
continue;
|
||||||
format = config_["format-" + state].asString();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (format.empty()) {
|
float specific_free, specific_used, specific_total, divisor;
|
||||||
event_box_.hide();
|
|
||||||
} else {
|
divisor = calc_specific_divisor(unit_);
|
||||||
event_box_.show();
|
specific_free = (stats.f_bavail * stats.f_frsize) / divisor;
|
||||||
label_.set_markup(fmt::format(
|
specific_used = ((stats.f_blocks - stats.f_bfree) * stats.f_frsize) / divisor;
|
||||||
fmt::runtime(format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
specific_total = (stats.f_blocks * stats.f_frsize) / divisor;
|
||||||
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used),
|
|
||||||
fmt::arg("percentage_used", percentage_used), fmt::arg("total", total),
|
auto free = pow_format(stats.f_bavail * stats.f_frsize, "B", true);
|
||||||
fmt::arg("path", path_), fmt::arg("specific_free", specific_free),
|
auto used = pow_format((stats.f_blocks - stats.f_bfree) * stats.f_frsize, "B", true);
|
||||||
fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total)));
|
auto total = pow_format(stats.f_blocks * stats.f_frsize, "B", true);
|
||||||
}
|
auto percentage_used = (stats.f_blocks - stats.f_bfree) * 100 / stats.f_blocks;
|
||||||
|
|
||||||
|
std::string disk_format = format_;
|
||||||
|
auto state = getState(percentage_used);
|
||||||
|
if (!state.empty() && config_["format-" + state].isString()) {
|
||||||
|
disk_format = config_["format-" + state].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!disk_format.empty()) {
|
||||||
|
if (had_valid_disk) {
|
||||||
|
label += separator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
label += fmt::format(
|
||||||
|
fmt::runtime(disk_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
||||||
|
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
|
||||||
|
fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
|
||||||
|
fmt::arg("total", total), fmt::arg("path", path),
|
||||||
|
fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used),
|
||||||
|
fmt::arg("specific_total", specific_total));
|
||||||
|
}
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
|
||||||
std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)";
|
std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)";
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(fmt::format(
|
|
||||||
fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
if (!tooltip_format.empty()) {
|
||||||
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used),
|
if (had_valid_disk) {
|
||||||
fmt::arg("percentage_used", percentage_used), fmt::arg("total", total),
|
tooltip_label += "\n";
|
||||||
fmt::arg("path", path_), fmt::arg("specific_free", specific_free),
|
}
|
||||||
fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total)));
|
|
||||||
|
tooltip_label += fmt::format(
|
||||||
|
fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks,
|
||||||
|
fmt::arg("free", free),
|
||||||
|
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
|
||||||
|
fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
|
||||||
|
fmt::arg("total", total), fmt::arg("path", path),
|
||||||
|
fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used),
|
||||||
|
fmt::arg("specific_total", specific_total));
|
||||||
|
}
|
||||||
|
|
||||||
|
had_valid_disk = true;
|
||||||
|
}
|
||||||
|
if (had_valid_disk) {
|
||||||
|
event_box_.show();
|
||||||
|
} else {
|
||||||
|
event_box_.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
label_.set_markup(label);
|
||||||
|
|
||||||
|
if (tooltipEnabled() && !tooltip_label.empty()) {
|
||||||
|
label_.set_tooltip_text(tooltip_label);
|
||||||
}
|
}
|
||||||
// Call parent update
|
// Call parent update
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
@@ -109,7 +158,7 @@ float waybar::modules::Disk::calc_specific_divisor(std::string divisor) {
|
|||||||
return 1000.0 * 1000.0 * 1000.0 * 1000.0;
|
return 1000.0 * 1000.0 * 1000.0 * 1000.0;
|
||||||
} else if (divisor == "TiB") {
|
} else if (divisor == "TiB") {
|
||||||
return 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
return 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
||||||
} else { // default to Bytes if it is anything that we don't recongnise
|
} else { // default to Bytes if it is anything that we don't recognise
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user