mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:37:35 +00:00
Calendar/EventManager: Store events as structs
Previously, the EventManager stored the calendar events as a raw JsonArray of objects. Now, we parse the JSON into a Vector<Event> structure and store that in the EventManager. This makes it easier to access the events from the outside, as you now don't have to know the JSON structure anymore.
This commit is contained in:
parent
7df936b660
commit
887f040d0e
4 changed files with 94 additions and 50 deletions
|
@ -112,25 +112,13 @@ AddEventDialog::AddEventDialog(Core::DateTime date_time, EventManager& event_man
|
||||||
|
|
||||||
ErrorOr<void> AddEventDialog::add_event_to_calendar()
|
ErrorOr<void> AddEventDialog::add_event_to_calendar()
|
||||||
{
|
{
|
||||||
auto to_date_string = [](Core::DateTime date_time) -> ErrorOr<String> {
|
|
||||||
return String::formatted("{}-{:0>2d}-{:0>2d}", date_time.year(), date_time.month(), date_time.day());
|
|
||||||
};
|
|
||||||
auto to_time_string = [](Core::DateTime date_time) -> ErrorOr<String> {
|
|
||||||
return String::formatted("{}:{:0>2d}", date_time.hour(), date_time.minute());
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonObject event;
|
|
||||||
auto start_date = TRY(to_date_string(m_start_date_time));
|
|
||||||
auto start_time = TRY(to_time_string(m_start_date_time));
|
|
||||||
auto end_date = TRY(to_date_string(m_end_date_time));
|
|
||||||
auto end_time = TRY(to_time_string(m_end_date_time));
|
|
||||||
auto summary = find_descendant_of_type_named<GUI::TextBox>("event_title_textbox")->get_text();
|
auto summary = find_descendant_of_type_named<GUI::TextBox>("event_title_textbox")->get_text();
|
||||||
event.set("start_date", JsonValue(start_date));
|
m_event_manager.add_event(Event {
|
||||||
event.set("start_time", JsonValue(start_time));
|
.summary = TRY(String::from_byte_string(summary)),
|
||||||
event.set("end_date", JsonValue(end_date));
|
.start = m_start_date_time,
|
||||||
event.set("end_time", JsonValue(end_time));
|
.end = m_end_date_time,
|
||||||
event.set("summary", JsonValue(summary));
|
});
|
||||||
TRY(m_event_manager.add_event(event));
|
|
||||||
m_event_manager.set_dirty(true);
|
m_event_manager.set_dirty(true);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -25,28 +25,28 @@ void EventCalendar::paint_tile(GUI::Painter& painter, GUI::Calendar::Tile& tile,
|
||||||
{
|
{
|
||||||
Calendar::paint_tile(painter, tile, tile_rect, x_offset, y_offset, day_offset);
|
Calendar::paint_tile(painter, tile, tile_rect, x_offset, y_offset, day_offset);
|
||||||
|
|
||||||
auto events = m_event_manager->events();
|
if (tile.width < tile_breakpoint || tile.height < tile_breakpoint)
|
||||||
|
return;
|
||||||
|
|
||||||
if (tile.width > tile_breakpoint && tile.height > tile_breakpoint) {
|
auto index = 0;
|
||||||
auto index = 0;
|
auto font_height = font().x_height();
|
||||||
auto font_height = font().x_height();
|
for (auto const& event : m_event_manager->events()) {
|
||||||
events.for_each([&](JsonValue const& value) {
|
auto start = event.start;
|
||||||
auto const& event = value.as_object();
|
if (start.year() == tile.year && start.month() == tile.month && start.day() == tile.day) {
|
||||||
|
auto text_rect = tile.rect.translated(4, 4 + (font_height + 4) * ++index);
|
||||||
|
|
||||||
if (!event.has("start_date"sv) || !event.has("start_date"sv) || !event.has("summary"sv))
|
auto event_text = String::formatted("{} {}", start.to_byte_string("%H:%M"sv), event.summary);
|
||||||
return;
|
if (event_text.is_error())
|
||||||
|
continue;
|
||||||
|
|
||||||
auto start_date = event.get("start_date"sv).value().to_byte_string();
|
painter.draw_text(
|
||||||
auto start_time = event.get("start_time"sv).value().to_byte_string();
|
text_rect,
|
||||||
auto summary = event.get("summary"sv).value().to_byte_string();
|
event_text.release_value(),
|
||||||
auto combined_text = ByteString::formatted("{} {}", start_time, summary);
|
Gfx::FontDatabase::default_font(),
|
||||||
|
Gfx::TextAlignment::TopLeft,
|
||||||
if (start_date == ByteString::formatted("{}-{:0>2d}-{:0>2d}", tile.year, tile.month, tile.day)) {
|
palette().base_text(),
|
||||||
|
Gfx::TextElision::Right);
|
||||||
auto text_rect = tile.rect.translated(4, 4 + (font_height + 4) * ++index);
|
}
|
||||||
painter.draw_text(text_rect, combined_text, Gfx::FontDatabase::default_font(), Gfx::TextAlignment::TopLeft, palette().base_text(), Gfx::TextElision::Right);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, the SerenityOS developers.
|
* Copyright (c) 2023, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2023, David Ganz <david.g.ganz@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +12,8 @@
|
||||||
|
|
||||||
namespace Calendar {
|
namespace Calendar {
|
||||||
|
|
||||||
|
static constexpr StringView DATE_FORMAT = "%Y-%m-%dT%H:%M:%S"sv;
|
||||||
|
|
||||||
EventManager::EventManager()
|
EventManager::EventManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -20,16 +23,14 @@ OwnPtr<EventManager> EventManager::create()
|
||||||
return adopt_own(*new EventManager());
|
return adopt_own(*new EventManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> EventManager::add_event(JsonObject event)
|
void EventManager::add_event(Event event)
|
||||||
{
|
{
|
||||||
TRY(m_events.append(move(event)));
|
m_events.append(move(event));
|
||||||
set_dirty(true);
|
set_dirty(true);
|
||||||
on_events_change();
|
on_events_change();
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::set_events(JsonArray events)
|
void EventManager::set_events(Vector<Event> events)
|
||||||
{
|
{
|
||||||
m_events = move(events);
|
m_events = move(events);
|
||||||
on_events_change();
|
on_events_change();
|
||||||
|
@ -41,21 +42,65 @@ ErrorOr<void> EventManager::save(FileSystemAccessClient::File& file)
|
||||||
set_dirty(false);
|
set_dirty(false);
|
||||||
|
|
||||||
auto stream = file.release_stream();
|
auto stream = file.release_stream();
|
||||||
TRY(stream->write_some(m_events.to_byte_string().bytes()));
|
auto json = TRY(serialize_events());
|
||||||
|
TRY(stream->write_some(json.to_byte_string().bytes()));
|
||||||
stream->close();
|
stream->close();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<JsonArray> EventManager::serialize_events()
|
||||||
|
{
|
||||||
|
JsonArray result;
|
||||||
|
for (auto const& event : m_events) {
|
||||||
|
JsonObject object;
|
||||||
|
object.set("start", JsonValue(event.start.to_byte_string(DATE_FORMAT)));
|
||||||
|
object.set("end", JsonValue(event.end.to_byte_string(DATE_FORMAT)));
|
||||||
|
object.set("summary", JsonValue(event.summary));
|
||||||
|
TRY(result.append(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<Vector<Event>> EventManager::deserialize_events(JsonArray const& json)
|
||||||
|
{
|
||||||
|
Vector<Event> result;
|
||||||
|
|
||||||
|
for (auto const& value : json.values()) {
|
||||||
|
auto const& object = value.as_object();
|
||||||
|
if (!object.has("summary"sv) || !object.has("start"sv) || !object.has("end"sv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto summary = TRY(String::from_byte_string(object.get("summary"sv).release_value().as_string()));
|
||||||
|
auto start = Core::DateTime::parse(DATE_FORMAT, object.get("start"sv).release_value().as_string());
|
||||||
|
if (!start.has_value())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto end = Core::DateTime::parse(DATE_FORMAT, object.get("end"sv).release_value().as_string());
|
||||||
|
if (!end.has_value())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Event event = {
|
||||||
|
.summary = summary,
|
||||||
|
.start = start.release_value(),
|
||||||
|
.end = end.release_value(),
|
||||||
|
};
|
||||||
|
result.append(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<void> EventManager::load_file(FileSystemAccessClient::File& file)
|
ErrorOr<void> EventManager::load_file(FileSystemAccessClient::File& file)
|
||||||
{
|
{
|
||||||
set_filename(file.filename());
|
set_filename(file.filename());
|
||||||
set_dirty(false);
|
set_dirty(false);
|
||||||
|
|
||||||
auto content = TRY(file.stream().read_until_eof());
|
auto content = TRY(file.stream().read_until_eof());
|
||||||
auto events = TRY(AK::JsonParser(content).parse());
|
auto json = TRY(AK::JsonParser(content).parse());
|
||||||
|
auto events = TRY(deserialize_events(json.as_array()));
|
||||||
set_events(events.as_array());
|
set_events(events);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, the SerenityOS developers.
|
* Copyright (c) 2023, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2023, David Ganz <david.g.ganz@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -10,11 +11,18 @@
|
||||||
#include <AK/JsonValue.h>
|
#include <AK/JsonValue.h>
|
||||||
#include <AK/Noncopyable.h>
|
#include <AK/Noncopyable.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
|
#include <LibCore/DateTime.h>
|
||||||
#include <LibFileSystemAccessClient/Client.h>
|
#include <LibFileSystemAccessClient/Client.h>
|
||||||
#include <LibGUI/Window.h>
|
#include <LibGUI/Window.h>
|
||||||
|
|
||||||
namespace Calendar {
|
namespace Calendar {
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
String summary;
|
||||||
|
Core::DateTime start;
|
||||||
|
Core::DateTime end;
|
||||||
|
};
|
||||||
|
|
||||||
class EventManager {
|
class EventManager {
|
||||||
AK_MAKE_NONCOPYABLE(EventManager);
|
AK_MAKE_NONCOPYABLE(EventManager);
|
||||||
AK_MAKE_NONMOVABLE(EventManager);
|
AK_MAKE_NONMOVABLE(EventManager);
|
||||||
|
@ -29,18 +37,21 @@ public:
|
||||||
|
|
||||||
ErrorOr<void> save(FileSystemAccessClient::File& file);
|
ErrorOr<void> save(FileSystemAccessClient::File& file);
|
||||||
ErrorOr<void> load_file(FileSystemAccessClient::File& file);
|
ErrorOr<void> load_file(FileSystemAccessClient::File& file);
|
||||||
ErrorOr<void> add_event(JsonObject);
|
void add_event(Event);
|
||||||
void set_events(JsonArray events);
|
void set_events(Vector<Event>);
|
||||||
void clear() { m_events.clear(); }
|
void clear() { m_events.clear(); }
|
||||||
|
|
||||||
JsonArray const& events() const { return m_events; }
|
Span<Event const> events() const { return m_events.span(); }
|
||||||
|
|
||||||
Function<void()> on_events_change;
|
Function<void()> on_events_change;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit EventManager();
|
explicit EventManager();
|
||||||
|
|
||||||
JsonArray m_events;
|
ErrorOr<JsonArray> serialize_events();
|
||||||
|
ErrorOr<Vector<Event>> deserialize_events(JsonArray const& json);
|
||||||
|
|
||||||
|
Vector<Event> m_events;
|
||||||
|
|
||||||
String m_current_filename;
|
String m_current_filename;
|
||||||
bool m_dirty { false };
|
bool m_dirty { false };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue