瀏覽代碼

ClockSettings: Add a GUI application to set the system time zone

This application can be expanded with other clock-related options. For
an initial iteration, it has just an option to change the time zone.
Timothy Flynn 3 年之前
父節點
當前提交
d365559839

+ 5 - 0
Base/res/apps/ClockSettings.af

@@ -0,0 +1,5 @@
+[App]
+Name=Clock Settings
+Executable=/bin/ClockSettings
+Category=Settings
+Description=Configure the system clock

+ 1 - 0
Userland/Applications/CMakeLists.txt

@@ -7,6 +7,7 @@ add_subdirectory(BrowserSettings)
 add_subdirectory(Calculator)
 add_subdirectory(Calendar)
 add_subdirectory(CharacterMap)
+add_subdirectory(ClockSettings)
 add_subdirectory(CrashReporter)
 add_subdirectory(Debugger)
 add_subdirectory(DisplaySettings)

+ 17 - 0
Userland/Applications/ClockSettings/CMakeLists.txt

@@ -0,0 +1,17 @@
+serenity_component(
+    ClockSettings
+    RECOMMENDED
+    TARGETS ClockSettings
+)
+
+compile_gml(ClockSettingsWidget.gml ClockSettingsWidgetGML.h clock_settings_widget_gml)
+
+set(SOURCES
+    main.cpp
+    ClockSettingsWidget.cpp
+    ClockSettingsWidget.h
+    ClockSettingsWidgetGML.h
+)
+
+serenity_app(ClockSettings ICON app-analog-clock) # FIXME: Create a ClockSettings icon.
+target_link_libraries(ClockSettings LibGUI LibMain)

+ 53 - 0
Userland/Applications/ClockSettings/ClockSettingsWidget.cpp

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "ClockSettingsWidget.h"
+#include <Applications/ClockSettings/ClockSettingsWidgetGML.h>
+#include <LibGUI/ComboBox.h>
+#include <LibGUI/ItemListModel.h>
+#include <LibGUI/Label.h>
+#include <LibTimeZone/TimeZone.h>
+#include <spawn.h>
+#include <unistd.h>
+
+using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>;
+
+ClockSettingsWidget::ClockSettingsWidget()
+{
+    load_from_gml(clock_settings_widget_gml);
+
+    static auto time_zones = TimeZone::all_time_zones();
+    m_time_zone = TimeZone::current_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);
+}
+
+void ClockSettingsWidget::reset_default_values()
+{
+    m_time_zone = "UTC"sv;
+    m_time_zone_combo_box->set_text(m_time_zone);
+    set_time_zone();
+}
+
+void ClockSettingsWidget::apply_settings()
+{
+    m_time_zone = m_time_zone_combo_box->text();
+    set_time_zone();
+}
+
+void ClockSettingsWidget::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);
+    }
+}

+ 40 - 0
Userland/Applications/ClockSettings/ClockSettingsWidget.gml

@@ -0,0 +1,40 @@
+@GUI::Frame {
+    fill_with_background_color: true
+
+    layout: @GUI::VerticalBoxLayout {
+        margins: [10]
+        spacing: 5
+    }
+
+    @GUI::GroupBox {
+        title: "Time Zone Settings"
+        fixed_height: 120
+
+        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"
+            }
+        }
+    }
+}

+ 27 - 0
Userland/Applications/ClockSettings/ClockSettingsWidget.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#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)
+
+private:
+    ClockSettingsWidget();
+
+    virtual void apply_settings() override;
+    virtual void reset_default_values() override;
+    void set_time_zone() const;
+
+    String m_time_zone;
+    RefPtr<GUI::ComboBox> m_time_zone_combo_box;
+};

+ 34 - 0
Userland/Applications/ClockSettings/main.cpp

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "ClockSettingsWidget.h"
+#include <LibCore/System.h>
+#include <LibGUI/Application.h>
+#include <LibGUI/Icon.h>
+#include <LibGUI/SettingsWindow.h>
+#include <LibMain/Main.h>
+
+ErrorOr<int> serenity_main(Main::Arguments arguments)
+{
+    TRY(Core::System::pledge("stdio rpath recvfd sendfd unix proc exec"));
+
+    auto app = TRY(GUI::Application::try_create(arguments));
+
+    TRY(Core::System::pledge("stdio rpath recvfd sendfd proc exec"));
+    TRY(Core::System::unveil("/res", "r"));
+    TRY(Core::System::unveil("/bin/timezone", "x"));
+    TRY(Core::System::unveil("/etc/timezone", "r"));
+    TRY(Core::System::unveil(nullptr, nullptr));
+
+    auto app_icon = GUI::Icon::default_icon("app-analog-clock"); // FIXME: Create a ClockSettings icon.
+
+    auto window = TRY(GUI::SettingsWindow::create("Clock Settings", GUI::SettingsWindow::ShowDefaultsButton::Yes));
+    (void)TRY(window->add_tab<ClockSettingsWidget>("Clock"));
+    window->set_icon(app_icon.bitmap_for_size(16));
+
+    window->show();
+    return app->exec();
+}