Serenity Operating System
1/*
2 * Copyright (c) 2020, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "ShutdownDialog.h"
8#include <AK/DeprecatedString.h>
9#include <AK/Vector.h>
10#include <LibGUI/BoxLayout.h>
11#include <LibGUI/Button.h>
12#include <LibGUI/ImageWidget.h>
13#include <LibGUI/Label.h>
14#include <LibGUI/RadioButton.h>
15#include <LibGUI/Widget.h>
16#include <LibGfx/Font/Font.h>
17#include <LibGfx/Font/FontDatabase.h>
18
19struct Option {
20 DeprecatedString title;
21 Vector<char const*> cmd;
22 bool enabled;
23 bool default_action;
24};
25
26static Vector<Option> const options = {
27 { "Power off computer", { "/bin/shutdown", "--now", nullptr }, true, true },
28 { "Reboot", { "/bin/reboot", nullptr }, true, false },
29 { "Log out", { "/bin/logout", nullptr }, true, false },
30};
31
32Vector<char const*> ShutdownDialog::show()
33{
34 auto dialog = ShutdownDialog::construct();
35 auto rc = dialog->exec();
36 if (rc == ExecResult::OK && dialog->m_selected_option != -1)
37 return options[dialog->m_selected_option].cmd;
38
39 return {};
40}
41
42ShutdownDialog::ShutdownDialog()
43 : Dialog(nullptr)
44{
45 auto widget = set_main_widget<GUI::Widget>().release_value_but_fixme_should_propagate_errors();
46 widget->set_fill_with_background_color(true);
47 widget->set_layout<GUI::VerticalBoxLayout>(GUI::Margins {}, 0);
48
49 auto& banner_image = widget->add<GUI::ImageWidget>();
50 banner_image.load_from_file("/res/graphics/brand-banner.png"sv);
51
52 auto& content_container = widget->add<GUI::Widget>();
53 content_container.set_layout<GUI::HorizontalBoxLayout>();
54
55 auto& left_container = content_container.add<GUI::Widget>();
56 left_container.set_fixed_width(60);
57 left_container.set_layout<GUI::VerticalBoxLayout>(GUI::Margins { 12, 0, 0 });
58
59 auto& icon_wrapper = left_container.add<GUI::Widget>();
60 icon_wrapper.set_fixed_size(32, 48);
61 icon_wrapper.set_layout<GUI::VerticalBoxLayout>();
62
63 auto& icon_image = icon_wrapper.add<GUI::ImageWidget>();
64 icon_image.set_bitmap(Gfx::Bitmap::load_from_file("/res/icons/32x32/shutdown.png"sv).release_value_but_fixme_should_propagate_errors());
65
66 auto& right_container = content_container.add<GUI::Widget>();
67 right_container.set_layout<GUI::VerticalBoxLayout>(GUI::Margins { 12, 12, 8, 0 });
68
69 auto& label = right_container.add<GUI::Label>("What would you like to do?");
70 label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
71 label.set_fixed_height(22);
72 label.set_font(Gfx::FontDatabase::default_font().bold_variant());
73
74 for (size_t i = 0; i < options.size(); i++) {
75 auto action = options[i];
76 auto& radio = right_container.add<GUI::RadioButton>();
77 radio.set_enabled(action.enabled);
78 radio.set_text(String::from_deprecated_string(action.title).release_value_but_fixme_should_propagate_errors());
79
80 radio.on_checked = [this, i](auto) {
81 m_selected_option = i;
82 };
83
84 if (action.default_action) {
85 radio.set_checked(true);
86 m_selected_option = i;
87 }
88 }
89
90 right_container.add_spacer().release_value_but_fixme_should_propagate_errors();
91
92 auto& button_container = right_container.add<GUI::Widget>();
93 button_container.set_fixed_height(23);
94 button_container.set_layout<GUI::HorizontalBoxLayout>(GUI::Margins {}, 5);
95 button_container.add_spacer().release_value_but_fixme_should_propagate_errors();
96 auto& ok_button = button_container.add<GUI::Button>("OK"_short_string);
97 ok_button.set_fixed_size(80, 23);
98 ok_button.on_click = [this](auto) {
99 done(ExecResult::OK);
100 };
101 ok_button.set_default(true);
102 auto& cancel_button = button_container.add<GUI::Button>("Cancel"_short_string);
103 cancel_button.set_fixed_size(80, 23);
104 cancel_button.on_click = [this](auto) {
105 done(ExecResult::Cancel);
106 };
107
108 resize(413, 235);
109 center_on_screen();
110 set_resizable(false);
111 set_title("Exit SerenityOS");
112 set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/power.png"sv).release_value_but_fixme_should_propagate_errors());
113
114 // Request WindowServer to re-update us on the current theme as we might've not been alive for the last notification.
115 refresh_system_theme();
116}