mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 17:35:07 +00:00

The calendar now verifies that the user can't input invalid date ranges, i.e. date ranges where the end is before the start. The UI elements do this implicitly, by adjusting the values when changing the dates in an illegal way (e.g. when picking an end date that is before the start date, the end date will change to the start date).
162 lines
6.5 KiB
C++
162 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) 2019-2020, Ryan Grieb <ryan.m.grieb@gmail.com>
|
|
* Copyright (c) 2022-2023, the SerenityOS developers.
|
|
* Copyright (c) 2023, David Ganz <david.g.ganz@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include "AddEventDialog.h"
|
|
#include <Applications/Calendar/AddEventDialogGML.h>
|
|
#include <LibCore/DateTime.h>
|
|
#include <LibGUI/BoxLayout.h>
|
|
#include <LibGUI/Button.h>
|
|
#include <LibGUI/ComboBox.h>
|
|
#include <LibGUI/DatePicker.h>
|
|
#include <LibGUI/Label.h>
|
|
#include <LibGUI/MessageBox.h>
|
|
#include <LibGUI/Painter.h>
|
|
#include <LibGUI/SpinBox.h>
|
|
#include <LibGUI/TextBox.h>
|
|
#include <LibGUI/Widget.h>
|
|
#include <LibGUI/Window.h>
|
|
#include <LibGfx/Color.h>
|
|
#include <LibGfx/Font/FontDatabase.h>
|
|
|
|
namespace Calendar {
|
|
|
|
static constexpr StringView DATE_FORMAT = "%Y-%m-%d"sv;
|
|
|
|
AddEventDialog::AddEventDialog(Core::DateTime date_time, EventManager& event_manager, Window* parent_window)
|
|
: Dialog(parent_window)
|
|
, m_start_date_time(date_time)
|
|
, m_end_date_time(Core::DateTime::from_timestamp(date_time.timestamp() + (15 * 60)))
|
|
, m_event_manager(event_manager)
|
|
{
|
|
resize(360, 140);
|
|
set_title("Add Event");
|
|
set_resizable(false);
|
|
set_icon(parent_window->icon());
|
|
|
|
dbgln("start time: {}", m_start_date_time.to_string().release_value_but_fixme_should_propagate_errors());
|
|
dbgln("end time: {}", m_end_date_time.to_string().release_value_but_fixme_should_propagate_errors());
|
|
|
|
m_start_date_time = Core::DateTime::create(m_start_date_time.year(), m_start_date_time.month(), m_start_date_time.day(), 12, 0);
|
|
|
|
auto widget = set_main_widget<GUI::Widget>();
|
|
widget->load_from_gml(add_event_dialog_gml).release_value_but_fixme_should_propagate_errors();
|
|
|
|
auto& event_title_textbox = *widget->find_descendant_of_type_named<GUI::TextBox>("event_title_textbox");
|
|
event_title_textbox.set_focus(true);
|
|
|
|
m_start_date_box = *widget->find_descendant_of_type_named<GUI::TextBox>("start_date");
|
|
|
|
auto calendar_date_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/calendar-date.png"sv).release_value_but_fixme_should_propagate_errors();
|
|
|
|
auto& pick_start_date_button = *widget->find_descendant_of_type_named<GUI::Button>("pick_start_date");
|
|
pick_start_date_button.set_icon(calendar_date_icon);
|
|
pick_start_date_button.on_click = [&](auto) {
|
|
if (auto new_date = GUI::DatePicker::show(this, "Pick Start Date"_string, m_start_date_time); new_date.has_value()) {
|
|
m_start_date_time.set_date(new_date.value());
|
|
if (m_end_date_time < m_start_date_time) {
|
|
m_end_date_time.set_date(new_date.value());
|
|
update_end_date();
|
|
}
|
|
|
|
m_start_date_box->set_text(MUST(m_start_date_time.to_string(DATE_FORMAT)));
|
|
}
|
|
};
|
|
|
|
m_start_hour_box = *widget->find_descendant_of_type_named<GUI::SpinBox>("start_hour");
|
|
m_start_minute_box = *widget->find_descendant_of_type_named<GUI::SpinBox>("start_minute");
|
|
|
|
m_end_date_box = *widget->find_descendant_of_type_named<GUI::TextBox>("end_date");
|
|
|
|
auto& pick_end_date_button = *widget->find_descendant_of_type_named<GUI::Button>("pick_end_date");
|
|
pick_end_date_button.set_icon(calendar_date_icon);
|
|
pick_end_date_button.on_click = [&](auto) {
|
|
if (auto new_date = GUI::DatePicker::show(this, "Pick End Date"_string, m_end_date_time); new_date.has_value()) {
|
|
m_end_date_time.set_date(new_date.value());
|
|
if (m_end_date_time < m_start_date_time) {
|
|
m_start_date_time.set_date(new_date.value());
|
|
update_start_date();
|
|
}
|
|
|
|
m_end_date_box->set_text(MUST(m_end_date_time.to_string(DATE_FORMAT)));
|
|
}
|
|
};
|
|
|
|
m_end_hour_box = *widget->find_descendant_of_type_named<GUI::SpinBox>("end_hour");
|
|
m_end_minute_box = *widget->find_descendant_of_type_named<GUI::SpinBox>("end_minute");
|
|
|
|
auto& ok_button = *widget->find_descendant_of_type_named<GUI::Button>("ok_button");
|
|
ok_button.on_click = [&](auto) {
|
|
auto successful = add_event_to_calendar().release_value_but_fixme_should_propagate_errors();
|
|
if (!successful)
|
|
return;
|
|
done(ExecResult::OK);
|
|
};
|
|
|
|
auto& cancel_button = *widget->find_descendant_of_type_named<GUI::Button>("cancel_button");
|
|
cancel_button.on_click = [&](auto) { done(ExecResult::Cancel); };
|
|
|
|
auto update_starting_input_values = [&, this]() {
|
|
auto hour = m_start_hour_box->value();
|
|
auto minute = m_start_minute_box->value();
|
|
m_start_date_time.set_time_only(hour, minute);
|
|
if (m_end_date_time < m_start_date_time) {
|
|
m_end_date_time.set_time_only(hour, minute);
|
|
update_end_date();
|
|
}
|
|
};
|
|
auto update_ending_input_values = [&, this]() {
|
|
auto hour = m_end_hour_box->value();
|
|
auto minute = m_end_minute_box->value();
|
|
m_end_date_time.set_time_only(hour, minute);
|
|
if (m_end_date_time < m_start_date_time) {
|
|
m_start_date_time.set_time_only(hour, minute);
|
|
update_start_date();
|
|
}
|
|
};
|
|
|
|
m_start_hour_box->on_change = [update_starting_input_values](auto) { update_starting_input_values(); };
|
|
m_start_minute_box->on_change = [update_starting_input_values](auto) { update_starting_input_values(); };
|
|
m_end_hour_box->on_change = [update_ending_input_values](auto) { update_ending_input_values(); };
|
|
m_end_minute_box->on_change = [update_ending_input_values](auto) { update_ending_input_values(); };
|
|
|
|
update_start_date();
|
|
update_end_date();
|
|
}
|
|
|
|
ErrorOr<bool> AddEventDialog::add_event_to_calendar()
|
|
{
|
|
if (m_end_date_time < m_start_date_time) {
|
|
GUI::MessageBox::show_error(this, "The end date has to be after the start date."sv);
|
|
return false;
|
|
}
|
|
|
|
auto summary = find_descendant_of_type_named<GUI::TextBox>("event_title_textbox")->get_text();
|
|
m_event_manager.add_event(Event {
|
|
.summary = TRY(String::from_byte_string(summary)),
|
|
.start = m_start_date_time,
|
|
.end = m_end_date_time,
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
void AddEventDialog::update_start_date()
|
|
{
|
|
m_start_date_box->set_text(MUST(m_start_date_time.to_string(DATE_FORMAT)));
|
|
m_start_hour_box->set_value(m_start_date_time.hour(), GUI::AllowCallback::No);
|
|
m_start_minute_box->set_value(m_start_date_time.minute(), GUI::AllowCallback::No);
|
|
}
|
|
|
|
void AddEventDialog::update_end_date()
|
|
{
|
|
m_end_date_box->set_text(MUST(m_end_date_time.to_string(DATE_FORMAT)));
|
|
m_end_hour_box->set_value(m_end_date_time.hour(), GUI::AllowCallback::No);
|
|
m_end_minute_box->set_value(m_end_date_time.minute(), GUI::AllowCallback::No);
|
|
}
|
|
|
|
}
|