diff options
Diffstat (limited to 'ui/src/windows/tracker.cpp')
| -rw-r--r-- | ui/src/windows/tracker.cpp | 238 |
1 files changed, 37 insertions, 201 deletions
diff --git a/ui/src/windows/tracker.cpp b/ui/src/windows/tracker.cpp index 6c248fe..e64eb18 100644 --- a/ui/src/windows/tracker.cpp +++ b/ui/src/windows/tracker.cpp @@ -1,68 +1,50 @@ #include "turns/ui/windows/tracker.hpp" -#include "turns/core/participant.hpp" #include "turns/core/turn_order.hpp" #include "turns/lang/messages.hpp" -#include "turns/ui/windows/participant_editor.hpp" +#include "turns/ui/widgets/turn_order_view.hpp" -#include <sigc++/bind.h> +#include <sigc++/adaptors/bind.h> #include <sigc++/functors/mem_fun.h> #include <glibmm/binding.h> #include <glibmm/i18n.h> +#include <glibmm/refptr.h> +#include <glibmm/varianttype.h> #include <giomm/liststore.h> +#include <gtkmm/applicationwindow.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> #include <gtkmm/error.h> #include <gtkmm/filedialog.h> +#include <gtkmm/object.h> +#include <gtkmm/revealer.h> +#include <gtkmm/stack.h> +#include <gtkmm/widget.h> #include <adwaita.h> #include <nlohmann/json.hpp> +#include <exception> #include <format> -#include <stdexcept> -#include <string_view> -#include <utility> +#include <string> namespace turns::ui::windows { - namespace - { - auto editor_for(Glib::RefPtr<core::participant> participant) - { - auto builder = Gtk::Builder::create_from_resource("/windows/participant_editor.ui"); - return std::pair{builder, Gtk::Builder::get_widget_derived<windows::participant_editor>(builder, "participant_editor", participant)}; - } - - auto stop_dialog_callback(AdwAlertDialog * dialog, GAsyncResult * result, core::turn_order * order) - { - auto response = Glib::ustring{adw_alert_dialog_choose_finish(dialog, result)}; - if (response == "cancel") - { - return; - } - if (response == "clear") - { - order->clear(); - } - order->stop(); - } - - } // namespace - tracker::tracker(BaseObjectType * base, Glib::RefPtr<Gtk::Builder> const builder) : Gtk::ApplicationWindow{base} - , m_adw{ADW_APPLICATION_WINDOW(gobj())} , m_controls{builder->get_widget<Gtk::Revealer>("controls")} - , m_empty(builder->get_widget<Gtk::Widget>("empty")) - , m_overlay{ADW_TOAST_OVERLAY(builder->get_widget<Gtk::Widget>("overlay")->gobj())} + , m_empty{builder->get_widget<Gtk::Widget>("empty")} + , m_overlay{builder->get_widget<Gtk::Widget>("overlay")} , m_stack{builder->get_widget<Gtk::Stack>("stack")} , m_start{builder->get_widget<Gtk::Button>("start")} - , m_title(ADW_WINDOW_TITLE(builder->get_widget<Gtk::Widget>("title")->gobj())) + , m_title{builder->get_widget<Gtk::Widget>("title")} , m_turn_order{core::turn_order::create()} , m_turn_order_view{Gtk::make_managed<widgets::turn_order_view>(m_turn_order)} - , m_subtitle{Glib::wrap(GTK_WIDGET(m_title)), "subtitle"} + , m_subtitle{m_title, "subtitle"} { setup_actions(); @@ -84,168 +66,12 @@ namespace turns::ui::windows // clang-format on } - auto tracker::do_save() -> void - { - m_buffer = m_turn_order->serialize().dump(2); - m_file->replace_contents_async(sigc::mem_fun(*this, &tracker::handle_save_done), m_buffer, m_file_tag); - } - - auto tracker::handle_add_participant() -> void - { - auto [lifeline, dialog] = editor_for(nullptr); - dialog->present(this); - dialog->signal_finished().connect([this](auto n, auto p, auto d) { m_turn_order->add(n, p, d); }); - } - - auto tracker::handle_delete_participant(Glib::VariantBase param) -> void - { - auto index = Glib::VariantBase::cast_dynamic<Glib::Variant<int>>(param); - m_turn_order->remove(index.get()); - } - - auto tracker::handle_edit_participant(Glib::VariantBase param) -> void - { - static_cast<void>(param); - auto index = Glib::VariantBase::cast_dynamic<Glib::Variant<int>>(param); - auto participant = m_turn_order->get_typed_object<core::participant>(index.get()); - auto [lifeline, dialog] = editor_for(participant); - dialog->present(this); - } - - auto tracker::handle_open() -> void - { - auto filters = Gio::ListStore<Gtk::FileFilter>::create(); - auto filter = Gtk::FileFilter::create(); - filter->set_name(_("Turns Files")); - filter->add_pattern("*.trns"); - filters->append(filter); - - auto dialog = Gtk::FileDialog::create(); - dialog->set_filters(filters); - dialog->open(sigc::bind(sigc::mem_fun(*this, &tracker::handle_open_response), dialog)); - } - - auto tracker::handle_open_done(Glib::RefPtr<Gio::AsyncResult> result) -> void - try - { - set_sensitive(); - char * data{}; - auto size = std::size_t{}; - if (!m_file->load_contents_finish(result, data, size, m_file_tag)) - { - m_file.reset(); - m_file_tag.clear(); - return; - } - auto deserialized = nlohmann::json::parse(std::string_view{data, size}); - m_turn_order->load(deserialized); - auto name = m_file->get_basename(); - auto message = std::vformat(_(lang::successfully_opened_format), std::make_format_args(name)); - auto toast = adw_toast_new(message.c_str()); - adw_toast_overlay_add_toast(m_overlay, toast); - set_title(std::format("{} - {}", _(lang::turns), name)); - } - catch (std::exception const & e) - { - show_error_toast(e); - } - - auto tracker::handle_open_response(Glib::RefPtr<Gio::AsyncResult> result, Glib::RefPtr<Gtk::FileDialog> dialog) -> void - try - { - m_file = dialog->open_finish(result); - m_file->load_contents_async(sigc::mem_fun(*this, &tracker::handle_open_done)); - set_sensitive(false); - } - catch (std::exception const & e) - { - set_sensitive(); - show_error_toast(e); - } - - auto tracker::handle_save(bool force_ask) -> void - { - if (m_file && !force_ask) - { - do_save(); - } - else - { - auto filters = Gio::ListStore<Gtk::FileFilter>::create(); - auto filter = Gtk::FileFilter::create(); - filter->set_name(_("Turns Files")); - filter->add_pattern("*.trns"); - filters->append(filter); - - auto dialog = Gtk::FileDialog::create(); - if (m_file) - { - dialog->set_initial_file(m_file); - } - else - { - dialog->set_initial_name(_(lang::new_turn_order_file_name)); - } - dialog->set_filters(filters); - dialog->save(*this, sigc::bind(sigc::mem_fun(*this, &tracker::handle_save_response), dialog)); - } - } - - auto tracker::handle_save_done(Glib::RefPtr<Gio::AsyncResult> result) -> void - try - { - set_sensitive(); - m_file->replace_contents_finish(result, m_file_tag); - auto name = m_file->get_basename(); - auto message = std::vformat(_(lang::successfully_saved_format), std::make_format_args(name)); - auto toast = adw_toast_new(message.c_str()); - adw_toast_overlay_add_toast(m_overlay, toast); - set_title(std::format("{} - {}", _(lang::turns), name)); - } - catch (Gio::Error const & e) - { - show_error_toast(e); - } - - auto tracker::handle_save_response(Glib::RefPtr<Gio::AsyncResult> result, Glib::RefPtr<Gtk::FileDialog> dialog) -> void - try - { - m_file = dialog->save_finish(result); - do_save(); - set_sensitive(false); - } - catch (Gtk::DialogError const & e) - { - if (e.code() == Gtk::DialogError::FAILED) - { - show_error_toast(e); - } - } - - auto tracker::handle_stop() -> void - { - auto dialog = ADW_ALERT_DIALOG(adw_alert_dialog_new(_(lang::stop_turn_order), _(lang::question_clear_turn_order))); - adw_alert_dialog_add_response(dialog, "stop", _(lang::stop)); - adw_alert_dialog_set_response_appearance(dialog, "stop", ADW_RESPONSE_SUGGESTED); - adw_alert_dialog_add_response(dialog, "clear", _(lang::stop_and_clear)); - adw_alert_dialog_set_response_appearance(dialog, "clear", ADW_RESPONSE_DESTRUCTIVE); - adw_alert_dialog_add_response(dialog, "cancel", _(lang::cancel)); - adw_alert_dialog_set_response_appearance(dialog, "cancel", ADW_RESPONSE_DEFAULT); - adw_alert_dialog_set_close_response(dialog, "cancel"); - adw_alert_dialog_set_default_response(dialog, "cancel"); - adw_alert_dialog_choose(dialog, - GTK_WIDGET(this->gobj()), - NULL, - reinterpret_cast<GAsyncReadyCallback>(stop_dialog_callback), - m_turn_order.get()); - } - auto tracker::setup_actions() -> void { // win.add_participant // depends-on: turn_order:state == stopped { - auto action = add_action("add_participant", sigc::mem_fun(*this, &tracker::handle_add_participant)); + auto action = add_action("add_participant", sigc::mem_fun(*this, &tracker::add_participant)); Glib::Binding::bind_property(m_turn_order->is_running(), action->property_enabled(), @@ -295,7 +121,7 @@ namespace turns::ui::windows // win.stop // depends-on: turn_order:running == true { - auto action = add_action("stop", sigc::mem_fun(*this, &tracker::handle_stop)); + auto action = add_action("stop", sigc::mem_fun(*this, &tracker::stop)); Glib::Binding::bind_property(m_turn_order->is_running(), action->property_enabled(), Glib::Binding::Flags::SYNC_CREATE); } @@ -304,15 +130,15 @@ namespace turns::ui::windows // win.edit // win.open { - add_action_with_parameter("delete", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::handle_delete_participant)); - add_action_with_parameter("edit", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::handle_edit_participant)); - add_action("open", sigc::mem_fun(*this, &tracker::handle_open)); + add_action_with_parameter("delete", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::delete_participant)); + add_action_with_parameter("edit", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::edit_participant)); + add_action("open", sigc::mem_fun(*this, &tracker::open)); } // win.save // depends-on: turn_order:is_empty == false { - auto action = add_action("save", sigc::bind(sigc::mem_fun(*this, &tracker::handle_save), false)); + auto action = add_action("save", sigc::bind(sigc::mem_fun(*this, &tracker::save), false)); Glib::Binding::bind_property(m_turn_order->is_empty(), action->property_enabled(), @@ -322,7 +148,7 @@ namespace turns::ui::windows // win.save-as // depends-on: turn_order:is_empty == false { - auto action = add_action("save-as", sigc::bind(sigc::mem_fun(*this, &tracker::handle_save), true)); + auto action = add_action("save-as", sigc::bind(sigc::mem_fun(*this, &tracker::save), true)); Glib::Binding::bind_property(m_turn_order->is_empty(), action->property_enabled(), @@ -330,12 +156,22 @@ namespace turns::ui::windows } } - auto tracker::show_error_toast(std::exception const & e) -> void + auto tracker::start_replace_content() -> void + { + m_file_buffer = m_turn_order->serialize().dump(2); + m_file->replace_contents_async(sigc::mem_fun(*this, &tracker::on_replace_content_done), m_file_buffer, m_file_etag); + } + + auto tracker::show_error(std::exception const & e) -> void { auto error = e.what(); - auto message = std::vformat(_(lang::saving_failed_format), std::make_format_args(error)); + show_toast(std::vformat(_(lang::saving_failed_format), std::make_format_args(error))); + } + + auto tracker::show_toast(std::string const & message) -> void + { auto toast = adw_toast_new(message.c_str()); - adw_toast_overlay_add_toast(m_overlay, toast); + adw_toast_overlay_add_toast(ADW_TOAST_OVERLAY(m_overlay->gobj()), toast); } auto tracker::update_subtitle() -> void |
