mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
shell: general date and time format. applied to lockscreen and control center
This commit is contained in:
@@ -201,8 +201,8 @@
|
||||
"nightlight": "Night Light",
|
||||
"nightlight-states": {
|
||||
"off": "Night Light",
|
||||
"scheduled-day": "Scheduled — day",
|
||||
"scheduled-night": "Night Light",
|
||||
"scheduled-day": "Scheduled",
|
||||
"scheduled-night": "Running",
|
||||
"forced": "Always on"
|
||||
},
|
||||
"notification": "DND",
|
||||
@@ -729,6 +729,7 @@
|
||||
"directories": "Directories",
|
||||
"effects": "Effects",
|
||||
"focus-styling": "Focus Styling",
|
||||
"formats": "Formats",
|
||||
"general": "General",
|
||||
"grouping": "Grouping",
|
||||
"lifecycle": "Lifecycle",
|
||||
@@ -1252,6 +1253,14 @@
|
||||
"label": "Middle Click Opens Widget Settings",
|
||||
"description": "Open a bar widget's settings from the bar with middle click"
|
||||
},
|
||||
"time-format": {
|
||||
"label": "Time Format",
|
||||
"description": "Default time format for shell UI without its own setting"
|
||||
},
|
||||
"date-format": {
|
||||
"label": "Date Format",
|
||||
"description": "Default date format for shell UI without its own setting"
|
||||
},
|
||||
"show-location": {
|
||||
"label": "Show Location",
|
||||
"description": "Show location name in weather widgets"
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
[shell]
|
||||
ui_scale = 1.0
|
||||
font_family = "sans-serif"
|
||||
time_format = "{:%H:%M}" # default shell UI time format
|
||||
date_format = "%A, %x" # default shell UI date format
|
||||
offline_mode = false # block all outgoing HTTP when true
|
||||
telemetry_enabled = false # send an anonymous usage ping on startup
|
||||
polkit_agent = false
|
||||
|
||||
@@ -285,10 +285,11 @@ namespace {
|
||||
|
||||
bool shellConfigEqual(const ShellConfig& a, const ShellConfig& b) {
|
||||
return nearlyEqual(a.uiScale, b.uiScale) && a.fontFamily == b.fontFamily && a.lang == b.lang &&
|
||||
a.offlineMode == b.offlineMode && a.telemetryEnabled == b.telemetryEnabled &&
|
||||
a.polkitAgent == b.polkitAgent && a.passwordMaskStyle == b.passwordMaskStyle &&
|
||||
a.animation.enabled == b.animation.enabled && nearlyEqual(a.animation.speed, b.animation.speed) &&
|
||||
a.avatarPath == b.avatarPath && a.settingsShowAdvanced == b.settingsShowAdvanced &&
|
||||
a.timeFormat == b.timeFormat && a.dateFormat == b.dateFormat && a.offlineMode == b.offlineMode &&
|
||||
a.telemetryEnabled == b.telemetryEnabled && a.polkitAgent == b.polkitAgent &&
|
||||
a.passwordMaskStyle == b.passwordMaskStyle && a.animation.enabled == b.animation.enabled &&
|
||||
nearlyEqual(a.animation.speed, b.animation.speed) && a.avatarPath == b.avatarPath &&
|
||||
a.settingsShowAdvanced == b.settingsShowAdvanced &&
|
||||
a.middleClickOpensWidgetSettings == b.middleClickOpensWidgetSettings && a.showLocation == b.showLocation &&
|
||||
a.clipboardAutoPaste == b.clipboardAutoPaste && a.shadow.blur == b.shadow.blur &&
|
||||
a.shadow.offsetX == b.shadow.offsetX && a.shadow.offsetY == b.shadow.offsetY &&
|
||||
|
||||
@@ -1181,6 +1181,12 @@ void ConfigService::parseTableInto(const toml::table& tbl, Config& config, bool
|
||||
if (auto v = (*shellTbl)["lang"].value<std::string>()) {
|
||||
shell.lang = *v;
|
||||
}
|
||||
if (auto v = (*shellTbl)["time_format"].value<std::string>()) {
|
||||
shell.timeFormat = *v;
|
||||
}
|
||||
if (auto v = (*shellTbl)["date_format"].value<std::string>()) {
|
||||
shell.dateFormat = *v;
|
||||
}
|
||||
if (auto v = (*shellTbl)["offline_mode"].value<bool>()) {
|
||||
shell.offlineMode = *v;
|
||||
}
|
||||
|
||||
@@ -370,6 +370,8 @@ struct ShellConfig {
|
||||
float uiScale = 1.0f;
|
||||
std::string fontFamily = "sans-serif";
|
||||
std::string lang; // empty = auto-detect from $LC_ALL/$LC_MESSAGES/$LANG
|
||||
std::string timeFormat = "{:%H:%M}";
|
||||
std::string dateFormat = "%A, %x";
|
||||
bool offlineMode = false;
|
||||
bool telemetryEnabled = false;
|
||||
bool polkitAgent = false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "shell/control_center/calendar_tab.h"
|
||||
|
||||
#include "config/config_service.h"
|
||||
#include "core/ui_phase.h"
|
||||
#include "i18n/i18n.h"
|
||||
#include "render/core/renderer.h"
|
||||
@@ -84,8 +85,15 @@ namespace {
|
||||
return state;
|
||||
}
|
||||
|
||||
std::string formatShellDate(const ConfigService* config) {
|
||||
const char* format = config != nullptr ? config->config().shell.dateFormat.c_str() : "%A, %x";
|
||||
return formatLocalTime(format);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CalendarTab::CalendarTab(ConfigService* config) : m_config(config) {}
|
||||
|
||||
std::unique_ptr<Flex> CalendarTab::create() {
|
||||
const float scale = contentScale();
|
||||
|
||||
@@ -159,7 +167,7 @@ std::unique_ptr<Flex> CalendarTab::create() {
|
||||
monthWrap->addChild(std::move(month));
|
||||
|
||||
auto monthSub = std::make_unique<Label>();
|
||||
monthSub->setText(i18n::tr("control-center.calendar.today"));
|
||||
monthSub->setText(formatShellDate(m_config));
|
||||
monthSub->setCaptionStyle();
|
||||
monthSub->setFontSize(Style::fontSizeCaption * scale);
|
||||
monthSub->setColor(colorSpecFromRole(ColorRole::OnSurfaceVariant));
|
||||
@@ -257,6 +265,13 @@ void CalendarTab::doLayout(Renderer& renderer, float contentWidth, float bodyHei
|
||||
m_rootLayout->layout(renderer);
|
||||
}
|
||||
|
||||
void CalendarTab::doUpdate(Renderer& renderer) {
|
||||
(void)renderer;
|
||||
if (m_monthSubLabel != nullptr) {
|
||||
m_monthSubLabel->setText(formatShellDate(m_config));
|
||||
}
|
||||
}
|
||||
|
||||
void CalendarTab::onClose() {
|
||||
m_rootLayout = nullptr;
|
||||
m_calendarArea = nullptr;
|
||||
@@ -328,7 +343,7 @@ void CalendarTab::rebuild() {
|
||||
m_monthLabel->setText(monthName(month) + " " + std::to_string(year));
|
||||
m_monthLabel->setMaxWidth(monthWidth);
|
||||
if (m_monthSubLabel != nullptr) {
|
||||
m_monthSubLabel->setText(formatCurrentDate());
|
||||
m_monthSubLabel->setText(formatShellDate(m_config));
|
||||
m_monthSubLabel->setMaxWidth(monthWidth);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,23 @@
|
||||
#include <limits>
|
||||
|
||||
class Button;
|
||||
class ConfigService;
|
||||
class InputArea;
|
||||
class Label;
|
||||
|
||||
class CalendarTab : public Tab {
|
||||
public:
|
||||
explicit CalendarTab(ConfigService* config = nullptr);
|
||||
|
||||
std::unique_ptr<Flex> create() override;
|
||||
void onClose() override;
|
||||
|
||||
private:
|
||||
void doLayout(Renderer& renderer, float contentWidth, float bodyHeight) override;
|
||||
void doUpdate(Renderer& renderer) override;
|
||||
void rebuild();
|
||||
|
||||
ConfigService* m_config = nullptr;
|
||||
Flex* m_rootLayout = nullptr;
|
||||
InputArea* m_calendarArea = nullptr;
|
||||
Flex* m_card = nullptr;
|
||||
|
||||
@@ -34,7 +34,7 @@ ControlCenterPanel::ControlCenterPanel(
|
||||
m_tabs[tabIndex(TabId::Audio)] =
|
||||
std::make_unique<AudioTab>(audio, mpris, config, wayland, PanelManager::instance().renderContext());
|
||||
m_tabs[tabIndex(TabId::Weather)] = std::make_unique<WeatherTab>(weather, config);
|
||||
m_tabs[tabIndex(TabId::Calendar)] = std::make_unique<CalendarTab>();
|
||||
m_tabs[tabIndex(TabId::Calendar)] = std::make_unique<CalendarTab>(config);
|
||||
m_tabs[tabIndex(TabId::Notifications)] = std::make_unique<NotificationsTab>(notifications);
|
||||
m_tabs[tabIndex(TabId::Network)] = std::make_unique<NetworkTab>(network, networkSecrets);
|
||||
m_tabs[tabIndex(TabId::Bluetooth)] = std::make_unique<BluetoothTab>(bluetooth, bluetoothAgent);
|
||||
|
||||
@@ -45,6 +45,16 @@ namespace {
|
||||
|
||||
float dashboardAvatarSize(float scale) { return Style::controlHeightLg * kDashboardAvatarScale * scale; }
|
||||
|
||||
std::string formatShellTime(const ConfigService* config) {
|
||||
const char* format = config != nullptr ? config->config().shell.timeFormat.c_str() : "{:%H:%M}";
|
||||
return formatLocalTime(format);
|
||||
}
|
||||
|
||||
std::string formatShellDate(const ConfigService* config) {
|
||||
const char* format = config != nullptr ? config->config().shell.dateFormat.c_str() : "%A, %x";
|
||||
return formatLocalTime(format);
|
||||
}
|
||||
|
||||
void applyDashboardCardStyle(Flex& card, float scale) {
|
||||
applySectionCardStyle(card, scale);
|
||||
card.setGap(Style::spaceSm * scale);
|
||||
@@ -262,7 +272,7 @@ std::unique_ptr<Flex> DashboardTab::create() {
|
||||
m_dateTimeCard = dateTimeCard.get();
|
||||
|
||||
auto timeLabel = std::make_unique<Label>();
|
||||
timeLabel->setText(formatLocalTime("{:%H:%M}"));
|
||||
timeLabel->setText(formatShellTime(m_config));
|
||||
timeLabel->setBold(true);
|
||||
timeLabel->setFontSize(Style::fontSizeTitle * 1.7f * scale);
|
||||
timeLabel->setColor(colorSpecFromRole(ColorRole::Primary));
|
||||
@@ -276,7 +286,7 @@ std::unique_ptr<Flex> DashboardTab::create() {
|
||||
dateTimeRight->setGap(Style::spaceXs * 0.5f * scale);
|
||||
|
||||
auto dateLabel = std::make_unique<Label>();
|
||||
dateLabel->setText(formatCurrentDate());
|
||||
dateLabel->setText(formatShellDate(m_config));
|
||||
dateLabel->setFontSize(Style::fontSizeBody * 0.9f * scale);
|
||||
dateLabel->setColor(colorSpecFromRole(ColorRole::OnSurface));
|
||||
m_dateLabel = dateLabel.get();
|
||||
@@ -744,10 +754,10 @@ void DashboardTab::sync(Renderer& renderer) {
|
||||
syncShortcuts();
|
||||
|
||||
if (m_timeLabel != nullptr) {
|
||||
m_timeLabel->setText(formatLocalTime("{:%H:%M}"));
|
||||
m_timeLabel->setText(formatShellTime(m_config));
|
||||
}
|
||||
if (m_dateLabel != nullptr) {
|
||||
m_dateLabel->setText(formatCurrentDate());
|
||||
m_dateLabel->setText(formatShellDate(m_config));
|
||||
}
|
||||
|
||||
syncWallpaperBackground(renderer);
|
||||
|
||||
@@ -329,7 +329,7 @@ void LockScreen::syncInstances() {
|
||||
}
|
||||
|
||||
void LockScreen::createInstance(const WaylandOutput& output) {
|
||||
auto surface = std::make_unique<LockSurface>(*m_wayland);
|
||||
auto surface = std::make_unique<LockSurface>(*m_wayland, m_configService);
|
||||
surface->setRenderContext(m_renderContext);
|
||||
surface->setTextureCache(m_textureCache);
|
||||
surface->setLockedState(m_locked);
|
||||
|
||||
@@ -37,9 +37,13 @@ namespace {
|
||||
return tryParseHexColor(path.substr(kPrefix.size()), out);
|
||||
}
|
||||
|
||||
const char* shellTimeFormat(const ConfigService* config) {
|
||||
return config != nullptr ? config->config().shell.timeFormat.c_str() : "{:%H:%M}";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LockSurface::LockSurface(WaylandConnection& connection) : Surface(connection) {
|
||||
LockSurface::LockSurface(WaylandConnection& connection, ConfigService* config) : Surface(connection), m_config(config) {
|
||||
auto wallpaper = std::make_unique<WallpaperNode>();
|
||||
m_wallpaper = static_cast<WallpaperNode*>(m_root.addChild(std::move(wallpaper)));
|
||||
m_wallpaper->setZIndex(0);
|
||||
@@ -254,7 +258,7 @@ void LockSurface::onPointerEvent(const PointerEvent& event) {
|
||||
}
|
||||
|
||||
void LockSurface::onSecondTick() {
|
||||
const auto text = formatLocalTime("{:%H:%M}");
|
||||
const auto text = formatLocalTime(shellTimeFormat(m_config));
|
||||
if (m_clock != nullptr && m_clock->text() != text) {
|
||||
requestUpdate();
|
||||
}
|
||||
@@ -405,4 +409,4 @@ void LockSurface::applyWallpaperTexture() {
|
||||
m_wallpaperDirty = false;
|
||||
}
|
||||
|
||||
void LockSurface::updateClockText() { m_clock->setText(formatLocalTime("{:%H:%M}")); }
|
||||
void LockSurface::updateClockText() { m_clock->setText(formatLocalTime(shellTimeFormat(m_config))); }
|
||||
|
||||
@@ -27,7 +27,7 @@ struct PointerEvent;
|
||||
|
||||
class LockSurface : public Surface {
|
||||
public:
|
||||
explicit LockSurface(WaylandConnection& connection);
|
||||
explicit LockSurface(WaylandConnection& connection, ConfigService* config = nullptr);
|
||||
~LockSurface() override;
|
||||
|
||||
using Surface::initialize;
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
|
||||
ext_session_lock_surface_v1* m_lockSurface = nullptr;
|
||||
wl_output* m_output = nullptr;
|
||||
ConfigService* m_config = nullptr;
|
||||
Node m_root;
|
||||
WallpaperNode* m_wallpaper = nullptr;
|
||||
Box* m_backdrop = nullptr;
|
||||
|
||||
@@ -1309,6 +1309,9 @@ void PanelManager::onConfigReloaded() {
|
||||
// Re-apply compositor blur for any open panel — covers both attached and layer-shell
|
||||
// panels reacting to shell.panel.background_blur changes.
|
||||
applyPanelCompositorBlur();
|
||||
if (m_surface != nullptr) {
|
||||
m_surface->requestUpdate();
|
||||
}
|
||||
|
||||
// The remaining work is bar-config-driven and only applies to attached panels.
|
||||
if (!isAttachedOpen() || m_output == nullptr) {
|
||||
|
||||
@@ -569,6 +569,12 @@ namespace settings {
|
||||
tr("settings.schema.shell.middle-click-opens-widget-settings.description"),
|
||||
{"shell", "middle_click_opens_widget_settings"}, ToggleSetting{cfg.shell.middleClickOpensWidgetSettings},
|
||||
"bar widget settings middle click configure"));
|
||||
entries.push_back(makeEntry("shell", "formats", tr("settings.schema.shell.time-format.label"),
|
||||
tr("settings.schema.shell.time-format.description"), {"shell", "time_format"},
|
||||
TextSetting{cfg.shell.timeFormat, "{:%H:%M}"}, "clock time format strftime chrono"));
|
||||
entries.push_back(makeEntry("shell", "formats", tr("settings.schema.shell.date-format.label"),
|
||||
tr("settings.schema.shell.date-format.description"), {"shell", "date_format"},
|
||||
TextSetting{cfg.shell.dateFormat, "%A, %x"}, "calendar date format strftime chrono"));
|
||||
entries.push_back(makeEntry("shell", "location", tr("settings.schema.shell.show-location.label"),
|
||||
tr("settings.schema.shell.show-location.description"), {"shell", "show_location"},
|
||||
ToggleSetting{cfg.shell.showLocation}, "weather"));
|
||||
|
||||
Reference in New Issue
Block a user