Merge pull request #1277 from dartkron/master
Refactor Clock: generalize multi timezones and single timezone casespull/1332/head^2
commit
9e8a71c4ef
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
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 (fixed_time_zone_) {
|
|
||||||
|
// 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)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const date::time_zone* waybar::modules::Clock::current_timezone() {
|
||||||
|
return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_] : 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 waybar::modules::Clock::update() -> void {
|
||||||
if (!fixed_time_zone_) {
|
auto time_zone = current_timezone();
|
||||||
// Time zone can change. Be sure to pick that.
|
auto now = std::chrono::system_clock::now();
|
||||||
time_zone_ = date::current_zone();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = "";
|
||||||
auto tooltip_format = config_["tooltip-format"].asString();
|
if (is_calendar_in_tooltip_) {
|
||||||
auto tooltip_text = fmt::format(tooltip_format, wtime, fmt::arg("calendar", calendar));
|
calendar_lines = calendar_text(wtime);
|
||||||
label_.set_tooltip_markup(tooltip_text);
|
}
|
||||||
} else {
|
auto tooltip_format = config_["tooltip-format"].asString();
|
||||||
label_.set_tooltip_markup(text);
|
text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue