Merge pull request #1277 from dartkron/master

Refactor Clock: generalize multi timezones and single timezone cases
This commit is contained in:
Alex 2021-12-01 11:51:35 +01:00 committed by GitHub
commit 9e8a71c4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 45 deletions

View File

@ -17,6 +17,8 @@ struct waybar_time {
date::zoned_seconds ztime; date::zoned_seconds ztime;
}; };
const std::string kCalendarPlaceholder = "calendar";
class Clock : public ALabel { class Clock : public ALabel {
public: public:
Clock(const std::string&, const Json::Value&); Clock(const std::string&, const Json::Value&);
@ -26,18 +28,19 @@ class Clock : public ALabel {
private: private:
util::SleeperThread thread_; util::SleeperThread thread_;
std::locale locale_; std::locale locale_;
const date::time_zone* time_zone_; std::vector<const date::time_zone*> time_zones_;
bool fixed_time_zone_; int current_time_zone_idx_;
int time_zone_idx_;
date::year_month_day cached_calendar_ymd_ = date::January/1/0; date::year_month_day cached_calendar_ymd_ = date::January/1/0;
std::string cached_calendar_text_; std::string cached_calendar_text_;
bool is_calendar_in_tooltip_;
bool handleScroll(GdkEventScroll* e); bool handleScroll(GdkEventScroll* e);
auto calendar_text(const waybar_time& wtime) -> std::string; auto calendar_text(const waybar_time& wtime) -> std::string;
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void; auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
auto first_day_of_week() -> date::weekday; auto first_day_of_week() -> date::weekday;
bool setTimeZone(Json::Value zone_name); const date::time_zone* current_timezone();
bool is_timezone_fixed();
}; };
} // namespace waybar::modules } // namespace waybar::modules

View File

@ -14,17 +14,51 @@
using waybar::modules::waybar_time; using waybar::modules::waybar_time;
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
: ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true), fixed_time_zone_(false) { : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
current_time_zone_idx_(0),
is_calendar_in_tooltip_(false)
{
if (config_["timezones"].isArray() && !config_["timezones"].empty()) { if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
time_zone_idx_ = 0; for (const auto& zone_name: config_["timezones"]) {
setTimeZone(config_["timezones"][time_zone_idx_]); if (!zone_name.isString() || zone_name.asString().empty()) {
} else { time_zones_.push_back(nullptr);
setTimeZone(config_["timezone"]); continue;
} }
if (fixed_time_zone_) { time_zones_.push_back(
date::locate_zone(
zone_name.asString()
)
);
}
} else if (config_["timezone"].isString() && !config_["timezone"].asString().empty()) {
time_zones_.push_back(
date::locate_zone(
config_["timezone"].asString()
)
);
}
// If all timezones are parsed and no one is good, add nullptr to the timezones vector, to mark that local time should be shown.
if (!time_zones_.size()) {
time_zones_.push_back(nullptr);
}
if (!is_timezone_fixed()) {
spdlog::warn("As using a timezone, some format args may be missing as the date library haven't got a release since 2018."); spdlog::warn("As using a timezone, some format args may be missing as the date library haven't got a release since 2018.");
} }
// Check if a particular placeholder is present in the tooltip format, to know what to calculate on update.
if (config_["tooltip-format"].isString()) {
std::string trimmed_format = config_["tooltip-format"].asString();
trimmed_format.erase(std::remove_if(trimmed_format.begin(),
trimmed_format.end(),
[](unsigned char x){return std::isspace(x);}),
trimmed_format.end());
if (trimmed_format.find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
is_calendar_in_tooltip_ = true;
}
}
if (config_["locale"].isString()) { if (config_["locale"].isString()) {
locale_ = std::locale(config_["locale"].asString()); locale_ = std::locale(config_["locale"].asString());
} else { } else {
@ -40,53 +74,46 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
}; };
} }
auto waybar::modules::Clock::update() -> void { const date::time_zone* waybar::modules::Clock::current_timezone() {
if (!fixed_time_zone_) { return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_] : date::current_zone();
// Time zone can change. Be sure to pick that.
time_zone_ = date::current_zone();
} }
bool waybar::modules::Clock::is_timezone_fixed() {
return time_zones_[current_time_zone_idx_] != nullptr;
}
auto waybar::modules::Clock::update() -> void {
auto time_zone = current_timezone();
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
waybar_time wtime = {locale_, waybar_time wtime = {locale_,
date::make_zoned(time_zone_, date::floor<std::chrono::seconds>(now))}; date::make_zoned(time_zone, date::floor<std::chrono::seconds>(now))};
std::string text = "";
std::string text; if (!is_timezone_fixed()) {
if (!fixed_time_zone_) {
// As date dep is not fully compatible, prefer fmt // As date dep is not fully compatible, prefer fmt
tzset(); tzset();
auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now)); auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
text = fmt::format(format_, localtime); text = fmt::format(format_, localtime);
label_.set_markup(text);
} else { } else {
text = fmt::format(format_, wtime); text = fmt::format(format_, wtime);
label_.set_markup(text);
} }
label_.set_markup(text);
if (tooltipEnabled()) { if (tooltipEnabled()) {
if (config_["tooltip-format"].isString()) { if (config_["tooltip-format"].isString()) {
const auto calendar = calendar_text(wtime); std::string calendar_lines = "";
if (is_calendar_in_tooltip_) {
calendar_lines = calendar_text(wtime);
}
auto tooltip_format = config_["tooltip-format"].asString(); auto tooltip_format = config_["tooltip-format"].asString();
auto tooltip_text = fmt::format(tooltip_format, wtime, fmt::arg("calendar", calendar)); text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines));
label_.set_tooltip_markup(tooltip_text); }
} else { }
label_.set_tooltip_markup(text); label_.set_tooltip_markup(text);
}
}
// Call parent update // Call parent update
ALabel::update(); ALabel::update();
} }
bool waybar::modules::Clock::setTimeZone(Json::Value zone_name) {
if (!zone_name.isString() || zone_name.asString().empty()) {
fixed_time_zone_ = false;
return false;
}
time_zone_ = date::locate_zone(zone_name.asString());
fixed_time_zone_ = true;
return true;
}
bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) { bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
// defer to user commands if set // defer to user commands if set
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
@ -97,17 +124,18 @@ bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
if (dir != SCROLL_DIR::UP && dir != SCROLL_DIR::DOWN) { if (dir != SCROLL_DIR::UP && dir != SCROLL_DIR::DOWN) {
return true; return true;
} }
if (!config_["timezones"].isArray() || config_["timezones"].empty()) { if (time_zones_.size() == 1) {
return true; return true;
} }
auto nr_zones = config_["timezones"].size();
auto nr_zones = time_zones_.size();
if (dir == SCROLL_DIR::UP) { if (dir == SCROLL_DIR::UP) {
size_t new_idx = time_zone_idx_ + 1; size_t new_idx = current_time_zone_idx_ + 1;
time_zone_idx_ = new_idx == nr_zones ? 0 : new_idx; current_time_zone_idx_ = new_idx == nr_zones ? 0 : new_idx;
} else { } else {
time_zone_idx_ = time_zone_idx_ == 0 ? nr_zones - 1 : time_zone_idx_ - 1; current_time_zone_idx_ = current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
} }
setTimeZone(config_["timezones"][time_zone_idx_]);
update(); update();
return true; return true;
} }