summaryrefslogtreecommitdiff
path: root/Userland/Applications
diff options
context:
space:
mode:
authorcflip <cflip@cflip.net>2022-04-03 17:13:52 -0600
committerAndreas Kling <kling@serenityos.org>2022-04-04 13:15:13 +0200
commit5bb0b6ba7ab1bcb6e11f081a3103bcd44d597090 (patch)
tree43676efd1019225f1369912b595a12770ec9be1a /Userland/Applications
parent36b6356ce51375a99b08cabd7bce8e5455a8fb0d (diff)
downloadserenity-5bb0b6ba7ab1bcb6e11f081a3103bcd44d597090.zip
ClockSettings+Taskbar: Add settings for taskbar clock format
Diffstat (limited to 'Userland/Applications')
-rw-r--r--Userland/Applications/ClockSettings/CMakeLists.txt4
-rw-r--r--Userland/Applications/ClockSettings/ClockSettingsWidget.cpp166
-rw-r--r--Userland/Applications/ClockSettings/ClockSettingsWidget.gml35
-rw-r--r--Userland/Applications/ClockSettings/ClockSettingsWidget.h21
-rw-r--r--Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp165
-rw-r--r--Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml42
-rw-r--r--Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h38
-rw-r--r--Userland/Applications/ClockSettings/main.cpp4
8 files changed, 302 insertions, 173 deletions
diff --git a/Userland/Applications/ClockSettings/CMakeLists.txt b/Userland/Applications/ClockSettings/CMakeLists.txt
index 94186a3efb..39cee55209 100644
--- a/Userland/Applications/ClockSettings/CMakeLists.txt
+++ b/Userland/Applications/ClockSettings/CMakeLists.txt
@@ -5,12 +5,16 @@ serenity_component(
)
compile_gml(ClockSettingsWidget.gml ClockSettingsWidgetGML.h clock_settings_widget_gml)
+compile_gml(TimeZoneSettingsWidget.gml TimeZoneSettingsWidgetGML.h time_zone_settings_widget_gml)
set(SOURCES
main.cpp
ClockSettingsWidget.cpp
ClockSettingsWidget.h
ClockSettingsWidgetGML.h
+ TimeZoneSettingsWidget.cpp
+ TimeZoneSettingsWidget.h
+ TimeZoneSettingsWidgetGML.h
)
serenity_app(ClockSettings ICON app-analog-clock) # FIXME: Create a ClockSettings icon.
diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp b/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp
index 98c86b18d8..9c8dc78eb5 100644
--- a/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp
+++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp
@@ -1,165 +1,49 @@
/*
- * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
+ * Copyright (c) 2022, cflip <cflip@cflip.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "ClockSettingsWidget.h"
-#include <AK/Time.h>
#include <Applications/ClockSettings/ClockSettingsWidgetGML.h>
-#include <LibGUI/ComboBox.h>
-#include <LibGUI/Event.h>
-#include <LibGUI/ImageWidget.h>
-#include <LibGUI/ItemListModel.h>
-#include <LibGUI/Label.h>
-#include <LibGUI/Layout.h>
-#include <LibGUI/Margins.h>
-#include <LibGUI/Painter.h>
-#include <LibGfx/Palette.h>
-#include <LibTimeZone/TimeZone.h>
-#include <LibUnicode/DateTimeFormat.h>
-#include <LibUnicode/Locale.h>
-#include <math.h>
-#include <spawn.h>
-#include <unistd.h>
-
-using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>;
-
-static constexpr auto PI_OVER_180 = M_PIf32 / 180.0f;
-static constexpr auto PI_OVER_4 = M_PIf32 / 4.0f;
-static constexpr auto TAU = M_PIf32 * 2.0f;
-
-// The map as stored on disk is a valid Mercadian projected map. But it has quite a bit of dead space that
-// we can remove. This makes the map non-Mercadian, so we need to adjust our math based on what we removed.
-static constexpr auto TIME_ZONE_MAP_NORTHERN_TRIM = 78;
-static constexpr auto TIME_ZONE_MAP_SOUTHERN_TRIM = 50;
-
-static constexpr auto TIME_ZONE_TEXT_WIDTH = 210;
-static constexpr auto TIME_ZONE_TEXT_HEIGHT = 40;
-static constexpr auto TIME_ZONE_TEXT_PADDING = 5;
-static constexpr auto TIME_ZONE_TEXT_COLOR = Gfx::Color::from_rgb(0xeaf688);
+#include <LibConfig/Client.h>
+#include <LibGUI/RadioButton.h>
+#include <LibGUI/TextBox.h>
ClockSettingsWidget::ClockSettingsWidget()
{
load_from_gml(clock_settings_widget_gml);
- static auto time_zones = TimeZone::all_time_zones();
- m_time_zone = TimeZone::system_time_zone();
-
- m_time_zone_combo_box = *find_descendant_of_type_named<GUI::ComboBox>("time_zone_input");
- m_time_zone_combo_box->set_only_allow_values_from_model(true);
- m_time_zone_combo_box->set_model(*StringViewListModel::create(time_zones));
- m_time_zone_combo_box->set_text(m_time_zone);
-
- auto time_zone_map_bitmap = Gfx::Bitmap::try_load_from_file("/res/graphics/map.png"sv).release_value_but_fixme_should_propagate_errors();
- auto time_zone_rect = time_zone_map_bitmap->rect().shrunken(TIME_ZONE_MAP_NORTHERN_TRIM, 0, TIME_ZONE_MAP_SOUTHERN_TRIM, 0);
- time_zone_map_bitmap = time_zone_map_bitmap->cropped(time_zone_rect).release_value_but_fixme_should_propagate_errors();
-
- m_time_zone_map = *find_descendant_of_type_named<GUI::ImageWidget>("time_zone_map");
- m_time_zone_map->set_bitmap(time_zone_map_bitmap);
-
- auto time_zone_marker = Gfx::Bitmap::try_load_from_file("/res/icons/32x32/ladyball.png").release_value_but_fixme_should_propagate_errors();
- m_time_zone_marker = time_zone_marker->scaled(0.75f, 0.75f).release_value_but_fixme_should_propagate_errors();
-
- set_time_zone_location();
-}
-
-void ClockSettingsWidget::second_paint_event(GUI::PaintEvent& event)
-{
- GUI::Widget::second_paint_event(event);
-
- if (!m_time_zone_location.has_value())
- return;
-
- GUI::Painter painter(*this);
- painter.add_clip_rect(event.rect());
- painter.add_clip_rect(m_time_zone_map->relative_rect());
-
- auto x = m_time_zone_map->x() + m_time_zone_map->parent_widget()->layout()->margins().left();
- auto y = m_time_zone_map->y() + m_time_zone_map->parent_widget()->layout()->margins().top();
+ m_24_hour_radio = *find_descendant_of_type_named<GUI::RadioButton>("24hour_radio");
+ auto& twelve_hour_radio = *find_descendant_of_type_named<GUI::RadioButton>("12hour_radio");
+ auto& custom_radio = *find_descendant_of_type_named<GUI::RadioButton>("custom_radio");
+ custom_radio.set_checked(true);
- auto point = m_time_zone_location->to_type<int>().translated(x, y);
- point.translate_by(-m_time_zone_marker->width() / 2, -m_time_zone_marker->height() / 2);
- painter.blit(point, *m_time_zone_marker, rect());
+ m_custom_format_input = *find_descendant_of_type_named<GUI::TextBox>("custom_format_input");
+ m_custom_format_input->set_text(Config::read_string("Taskbar", "Clock", "TimeFormat"));
- point = m_time_zone_location->to_type<int>().translated(x, y);
- point.translate_by(0, -TIME_ZONE_TEXT_HEIGHT / 2);
+ m_24_hour_radio->on_checked = [&](bool) {
+ m_custom_format_input->set_enabled(false);
+ m_custom_format_input->set_text("%T");
+ };
- if (point.x() <= (m_time_zone_map->width() / 2))
- point.translate_by(m_time_zone_marker->width() / 2 + TIME_ZONE_TEXT_PADDING, 0);
- else
- point.translate_by(-m_time_zone_marker->width() / 2 - TIME_ZONE_TEXT_PADDING - TIME_ZONE_TEXT_WIDTH, 0);
+ twelve_hour_radio.on_checked = [&](bool) {
+ m_custom_format_input->set_enabled(false);
+ m_custom_format_input->set_text("%I:%M %p");
+ };
- auto text_area = Gfx::IntRect { point.x(), point.y(), TIME_ZONE_TEXT_WIDTH, TIME_ZONE_TEXT_HEIGHT };
- painter.draw_rect(text_area, palette().active_window_border1());
-
- text_area.shrink(2, 2);
- painter.fill_rect(text_area, TIME_ZONE_TEXT_COLOR);
- painter.draw_text(text_area, m_time_zone_text, Gfx::TextAlignment::Center);
-}
-
-void ClockSettingsWidget::reset_default_values()
-{
- m_time_zone = "UTC"sv;
- m_time_zone_combo_box->set_text(m_time_zone);
- m_time_zone_location.clear();
-
- set_time_zone();
- update();
+ custom_radio.on_checked = [&](bool) {
+ m_custom_format_input->set_enabled(true);
+ };
}
void ClockSettingsWidget::apply_settings()
{
- m_time_zone = m_time_zone_combo_box->text();
-
- set_time_zone_location();
- set_time_zone();
- update();
-}
-
-void ClockSettingsWidget::set_time_zone_location()
-{
- m_time_zone_location = compute_time_zone_location();
-
- auto locale = Unicode::default_locale();
- auto now = AK::Time::now_realtime();
-
- auto name = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::Long, now);
- auto offset = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::LongOffset, now);
-
- m_time_zone_text = String::formatted("{}\n({})", name, offset);
+ Config::write_string("Taskbar", "Clock", "TimeFormat", m_custom_format_input->text());
}
-// https://en.wikipedia.org/wiki/Mercator_projection#Derivation
-Optional<Gfx::FloatPoint> ClockSettingsWidget::compute_time_zone_location() const
-{
- auto location = TimeZone::get_time_zone_location(m_time_zone);
- if (!location.has_value())
- return {};
-
- auto latitude = location->latitude.decimal_coordinate();
- auto longitude = location->longitude.decimal_coordinate();
-
- auto rect = m_time_zone_map->bitmap()->rect().to_type<float>();
-
- latitude = logf(tanf(PI_OVER_4 + (latitude * PI_OVER_180 / 2.0f)));
-
- auto mercadian_x = (longitude + 180.0f) * (rect.width() / 360.0f);
- auto mercadian_y = (rect.height() / 2.0f) - (rect.width() * latitude / TAU);
-
- mercadian_y -= TIME_ZONE_MAP_NORTHERN_TRIM / 2;
- mercadian_y += TIME_ZONE_MAP_SOUTHERN_TRIM / 2;
-
- return Gfx::FloatPoint { mercadian_x, mercadian_y };
-}
-
-void ClockSettingsWidget::set_time_zone() const
+void ClockSettingsWidget::reset_default_values()
{
- pid_t child_pid = 0;
- char const* argv[] = { "/bin/timezone", m_time_zone.characters(), nullptr };
-
- if ((errno = posix_spawn(&child_pid, "/bin/timezone", nullptr, nullptr, const_cast<char**>(argv), environ))) {
- perror("posix_spawn");
- exit(1);
- }
+ m_24_hour_radio->set_checked(true);
+ Config::write_string("Taskbar", "Clock", "TimeFormat", "%T");
}
diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.gml b/Userland/Applications/ClockSettings/ClockSettingsWidget.gml
index f0b10cd4a8..f6f66dc92d 100644
--- a/Userland/Applications/ClockSettings/ClockSettingsWidget.gml
+++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.gml
@@ -6,37 +6,42 @@
}
@GUI::GroupBox {
- title: "Time Zone Settings"
+ title: "Time Format"
+ shrink_to_fit: false
+ fixed_height: 160
layout: @GUI::VerticalBoxLayout {
margins: [16, 8, 8]
- spacing: 16
}
@GUI::Label {
- text: "Change the system's time zone used for the clock and other applications."
+ text: "Set the date/time format used by the taskbar clock."
text_alignment: "TopLeft"
}
@GUI::Widget {
- layout: @GUI::HorizontalBoxLayout {
+ shrink_to_fit: true
+ layout: @GUI::VerticalBoxLayout {
spacing: 4
}
- @GUI::Label {
- text: "Time Zone:"
- fixed_width: 80
- name: "time_zone_label"
- text_alignment: "CenterLeft"
+ @GUI::RadioButton {
+ name: "24hour_radio"
+ text: "24-hour (12:34:56)"
}
- @GUI::ComboBox {
- name: "time_zone_input"
+ @GUI::RadioButton {
+ name: "12hour_radio"
+ text: "12-hour (12:34 a.m)"
+ }
+
+ @GUI::RadioButton {
+ name: "custom_radio"
+ text: "Custom:"
}
- }
- @GUI::ImageWidget {
- name: "time_zone_map"
- auto_resize: true
+ @GUI::TextBox {
+ name: "custom_format_input"
+ }
}
}
}
diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.h b/Userland/Applications/ClockSettings/ClockSettingsWidget.h
index b2394a783a..35f5becc62 100644
--- a/Userland/Applications/ClockSettings/ClockSettingsWidget.h
+++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.h
@@ -1,17 +1,13 @@
/*
- * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
+ * Copyright (c) 2022, cflip <cflip@cflip.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
-#include <AK/Optional.h>
#include <AK/RefPtr.h>
-#include <AK/String.h>
#include <LibGUI/SettingsWindow.h>
-#include <LibGUI/TextEditor.h>
-#include <LibGUI/Window.h>
class ClockSettingsWidget final : public GUI::SettingsWindow::Tab {
C_OBJECT(ClockSettingsWidget)
@@ -19,20 +15,11 @@ class ClockSettingsWidget final : public GUI::SettingsWindow::Tab {
private:
ClockSettingsWidget();
- virtual void second_paint_event(GUI::PaintEvent&) override;
-
virtual void apply_settings() override;
virtual void reset_default_values() override;
- void set_time_zone_location();
- Optional<Gfx::FloatPoint> compute_time_zone_location() const;
- void set_time_zone() const;
-
- String m_time_zone;
- RefPtr<GUI::ComboBox> m_time_zone_combo_box;
- RefPtr<GUI::ImageWidget> m_time_zone_map;
- RefPtr<Gfx::Bitmap> m_time_zone_marker;
+ RefPtr<GUI::RadioButton> m_24_hour_radio;
+ RefPtr<GUI::TextBox> m_custom_format_input;
- Optional<Gfx::FloatPoint> m_time_zone_location;
- String m_time_zone_text;
+ String m_date_format;
};
diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp
new file mode 100644
index 0000000000..6dcfc93fa4
--- /dev/null
+++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "TimeZoneSettingsWidget.h"
+#include <AK/Time.h>
+#include <Applications/ClockSettings/TimeZoneSettingsWidgetGML.h>
+#include <LibGUI/ComboBox.h>
+#include <LibGUI/Event.h>
+#include <LibGUI/ImageWidget.h>
+#include <LibGUI/ItemListModel.h>
+#include <LibGUI/Label.h>
+#include <LibGUI/Layout.h>
+#include <LibGUI/Margins.h>
+#include <LibGUI/Painter.h>
+#include <LibGfx/Palette.h>
+#include <LibTimeZone/TimeZone.h>
+#include <LibUnicode/DateTimeFormat.h>
+#include <LibUnicode/Locale.h>
+#include <math.h>
+#include <spawn.h>
+#include <unistd.h>
+
+using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>;
+
+static constexpr auto PI_OVER_180 = M_PIf32 / 180.0f;
+static constexpr auto PI_OVER_4 = M_PIf32 / 4.0f;
+static constexpr auto TAU = M_PIf32 * 2.0f;
+
+// The map as stored on disk is a valid Mercadian projected map. But it has quite a bit of dead space that
+// we can remove. This makes the map non-Mercadian, so we need to adjust our math based on what we removed.
+static constexpr auto TIME_ZONE_MAP_NORTHERN_TRIM = 78;
+static constexpr auto TIME_ZONE_MAP_SOUTHERN_TRIM = 50;
+
+static constexpr auto TIME_ZONE_TEXT_WIDTH = 210;
+static constexpr auto TIME_ZONE_TEXT_HEIGHT = 40;
+static constexpr auto TIME_ZONE_TEXT_PADDING = 5;
+static constexpr auto TIME_ZONE_TEXT_COLOR = Gfx::Color::from_rgb(0xeaf688);
+
+TimeZoneSettingsWidget::TimeZoneSettingsWidget()
+{
+ load_from_gml(time_zone_settings_widget_gml);
+
+ static auto time_zones = TimeZone::all_time_zones();
+ m_time_zone = TimeZone::system_time_zone();
+
+ m_time_zone_combo_box = *find_descendant_of_type_named<GUI::ComboBox>("time_zone_input");
+ m_time_zone_combo_box->set_only_allow_values_from_model(true);
+ m_time_zone_combo_box->set_model(*StringViewListModel::create(time_zones));
+ m_time_zone_combo_box->set_text(m_time_zone);
+
+ auto time_zone_map_bitmap = Gfx::Bitmap::try_load_from_file("/res/graphics/map.png"sv).release_value_but_fixme_should_propagate_errors();
+ auto time_zone_rect = time_zone_map_bitmap->rect().shrunken(TIME_ZONE_MAP_NORTHERN_TRIM, 0, TIME_ZONE_MAP_SOUTHERN_TRIM, 0);
+ time_zone_map_bitmap = time_zone_map_bitmap->cropped(time_zone_rect).release_value_but_fixme_should_propagate_errors();
+
+ m_time_zone_map = *find_descendant_of_type_named<GUI::ImageWidget>("time_zone_map");
+ m_time_zone_map->set_bitmap(time_zone_map_bitmap);
+
+ auto time_zone_marker = Gfx::Bitmap::try_load_from_file("/res/icons/32x32/ladyball.png").release_value_but_fixme_should_propagate_errors();
+ m_time_zone_marker = time_zone_marker->scaled(0.75f, 0.75f).release_value_but_fixme_should_propagate_errors();
+
+ set_time_zone_location();
+}
+
+void TimeZoneSettingsWidget::second_paint_event(GUI::PaintEvent& event)
+{
+ GUI::Widget::second_paint_event(event);
+
+ if (!m_time_zone_location.has_value())
+ return;
+
+ GUI::Painter painter(*this);
+ painter.add_clip_rect(event.rect());
+ painter.add_clip_rect(m_time_zone_map->relative_rect());
+
+ auto x = m_time_zone_map->x() + m_time_zone_map->parent_widget()->layout()->margins().left();
+ auto y = m_time_zone_map->y() + m_time_zone_map->parent_widget()->layout()->margins().top();
+
+ auto point = m_time_zone_location->to_type<int>().translated(x, y);
+ point.translate_by(-m_time_zone_marker->width() / 2, -m_time_zone_marker->height() / 2);
+ painter.blit(point, *m_time_zone_marker, rect());
+
+ point = m_time_zone_location->to_type<int>().translated(x, y);
+ point.translate_by(0, -TIME_ZONE_TEXT_HEIGHT / 2);
+
+ if (point.x() <= (m_time_zone_map->width() / 2))
+ point.translate_by(m_time_zone_marker->width() / 2 + TIME_ZONE_TEXT_PADDING, 0);
+ else
+ point.translate_by(-m_time_zone_marker->width() / 2 - TIME_ZONE_TEXT_PADDING - TIME_ZONE_TEXT_WIDTH, 0);
+
+ auto text_area = Gfx::IntRect { point.x(), point.y(), TIME_ZONE_TEXT_WIDTH, TIME_ZONE_TEXT_HEIGHT };
+ painter.draw_rect(text_area, palette().active_window_border1());
+
+ text_area.shrink(2, 2);
+ painter.fill_rect(text_area, TIME_ZONE_TEXT_COLOR);
+ painter.draw_text(text_area, m_time_zone_text, Gfx::TextAlignment::Center);
+}
+
+void TimeZoneSettingsWidget::reset_default_values()
+{
+ m_time_zone = "UTC"sv;
+ m_time_zone_combo_box->set_text(m_time_zone);
+ m_time_zone_location.clear();
+
+ set_time_zone();
+ update();
+}
+
+void TimeZoneSettingsWidget::apply_settings()
+{
+ m_time_zone = m_time_zone_combo_box->text();
+
+ set_time_zone_location();
+ set_time_zone();
+ update();
+}
+
+void TimeZoneSettingsWidget::set_time_zone_location()
+{
+ m_time_zone_location = compute_time_zone_location();
+
+ auto locale = Unicode::default_locale();
+ auto now = AK::Time::now_realtime();
+
+ auto name = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::Long, now);
+ auto offset = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::LongOffset, now);
+
+ m_time_zone_text = String::formatted("{}\n({})", name, offset);
+}
+
+// https://en.wikipedia.org/wiki/Mercator_projection#Derivation
+Optional<Gfx::FloatPoint> TimeZoneSettingsWidget::compute_time_zone_location() const
+{
+ auto location = TimeZone::get_time_zone_location(m_time_zone);
+ if (!location.has_value())
+ return {};
+
+ auto latitude = location->latitude.decimal_coordinate();
+ auto longitude = location->longitude.decimal_coordinate();
+
+ auto rect = m_time_zone_map->bitmap()->rect().to_type<float>();
+
+ latitude = logf(tanf(PI_OVER_4 + (latitude * PI_OVER_180 / 2.0f)));
+
+ auto mercadian_x = (longitude + 180.0f) * (rect.width() / 360.0f);
+ auto mercadian_y = (rect.height() / 2.0f) - (rect.width() * latitude / TAU);
+
+ mercadian_y -= TIME_ZONE_MAP_NORTHERN_TRIM / 2;
+ mercadian_y += TIME_ZONE_MAP_SOUTHERN_TRIM / 2;
+
+ return Gfx::FloatPoint { mercadian_x, mercadian_y };
+}
+
+void TimeZoneSettingsWidget::set_time_zone() const
+{
+ pid_t child_pid = 0;
+ char const* argv[] = { "/bin/timezone", m_time_zone.characters(), nullptr };
+
+ if ((errno = posix_spawn(&child_pid, "/bin/timezone", nullptr, nullptr, const_cast<char**>(argv), environ))) {
+ perror("posix_spawn");
+ exit(1);
+ }
+}
diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml
new file mode 100644
index 0000000000..f0b10cd4a8
--- /dev/null
+++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml
@@ -0,0 +1,42 @@
+@GUI::Frame {
+ fill_with_background_color: true
+ layout: @GUI::VerticalBoxLayout {
+ margins: [10]
+ spacing: 5
+ }
+
+ @GUI::GroupBox {
+ title: "Time Zone Settings"
+ layout: @GUI::VerticalBoxLayout {
+ margins: [16, 8, 8]
+ spacing: 16
+ }
+
+ @GUI::Label {
+ text: "Change the system's time zone used for the clock and other applications."
+ text_alignment: "TopLeft"
+ }
+
+ @GUI::Widget {
+ layout: @GUI::HorizontalBoxLayout {
+ spacing: 4
+ }
+
+ @GUI::Label {
+ text: "Time Zone:"
+ fixed_width: 80
+ name: "time_zone_label"
+ text_alignment: "CenterLeft"
+ }
+
+ @GUI::ComboBox {
+ name: "time_zone_input"
+ }
+ }
+
+ @GUI::ImageWidget {
+ name: "time_zone_map"
+ auto_resize: true
+ }
+ }
+}
diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h
new file mode 100644
index 0000000000..768fb0b421
--- /dev/null
+++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Optional.h>
+#include <AK/RefPtr.h>
+#include <AK/String.h>
+#include <LibGUI/SettingsWindow.h>
+#include <LibGUI/TextEditor.h>
+#include <LibGUI/Window.h>
+
+class TimeZoneSettingsWidget final : public GUI::SettingsWindow::Tab {
+ C_OBJECT(TimeZoneSettingsWidget)
+
+private:
+ TimeZoneSettingsWidget();
+
+ virtual void second_paint_event(GUI::PaintEvent&) override;
+
+ virtual void apply_settings() override;
+ virtual void reset_default_values() override;
+
+ void set_time_zone_location();
+ Optional<Gfx::FloatPoint> compute_time_zone_location() const;
+ void set_time_zone() const;
+
+ String m_time_zone;
+ RefPtr<GUI::ComboBox> m_time_zone_combo_box;
+ RefPtr<GUI::ImageWidget> m_time_zone_map;
+ RefPtr<Gfx::Bitmap> m_time_zone_marker;
+
+ Optional<Gfx::FloatPoint> m_time_zone_location;
+ String m_time_zone_text;
+};
diff --git a/Userland/Applications/ClockSettings/main.cpp b/Userland/Applications/ClockSettings/main.cpp
index 7463e3547c..72e81ea944 100644
--- a/Userland/Applications/ClockSettings/main.cpp
+++ b/Userland/Applications/ClockSettings/main.cpp
@@ -5,6 +5,8 @@
*/
#include "ClockSettingsWidget.h"
+#include "TimeZoneSettingsWidget.h"
+#include <LibConfig/Client.h>
#include <LibCore/System.h>
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
@@ -17,6 +19,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto app = TRY(GUI::Application::try_create(arguments));
+ Config::pledge_domain("Taskbar");
TRY(Core::System::pledge("stdio rpath recvfd sendfd proc exec"));
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil("/bin/timezone", "x"));
@@ -27,6 +30,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto window = TRY(GUI::SettingsWindow::create("Clock Settings", GUI::SettingsWindow::ShowDefaultsButton::Yes));
(void)TRY(window->add_tab<ClockSettingsWidget>("Clock"));
+ (void)TRY(window->add_tab<TimeZoneSettingsWidget>("Time Zone"));
window->set_icon(app_icon.bitmap_for_size(16));
window->resize(540, 570);