diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2022-04-08 23:47:12 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2022-04-08 23:47:12 -0400 |
commit | 5b806a25894bf183515c64ac8099911da8f4a0c7 (patch) | |
tree | 405f58152c12e1c3d25ebe5644cac6c45d0622cc /src/components | |
parent | 5a13c7fef71662ca5c829a80ef57d42741e23f3a (diff) | |
download | abaddon-portaudio-5b806a25894bf183515c64ac8099911da8f4a0c7.tar.gz abaddon-portaudio-5b806a25894bf183515c64ac8099911da8f4a0c7.zip |
basic tabs system
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/channels.cpp | 18 | ||||
-rw-r--r-- | src/components/channels.hpp | 21 | ||||
-rw-r--r-- | src/components/channeltabswitcherhandy.cpp | 58 | ||||
-rw-r--r-- | src/components/channeltabswitcherhandy.hpp | 37 | ||||
-rw-r--r-- | src/components/chatwindow.cpp | 24 | ||||
-rw-r--r-- | src/components/chatwindow.hpp | 28 |
6 files changed, 174 insertions, 12 deletions
diff --git a/src/components/channels.cpp b/src/components/channels.cpp index 4a6b1bc..929eeb8 100644 --- a/src/components/channels.cpp +++ b/src/components/channels.cpp @@ -17,6 +17,9 @@ ChannelList::ChannelList() , m_menu_category_copy_id("_Copy ID", true) , m_menu_channel_copy_id("_Copy ID", true) , m_menu_channel_mark_as_read("Mark as _Read", true) +#ifdef WITH_LIBHANDY + , m_menu_channel_open_tab("Open in New _Tab", true) +#endif , m_menu_dm_copy_id("_Copy ID", true) , m_menu_dm_close("") // changes depending on if group or not , m_menu_thread_copy_id("_Copy ID", true) @@ -143,6 +146,15 @@ ChannelList::ChannelList() else discord.MuteChannel(id, NOOP_CALLBACK); }); + +#ifdef WITH_LIBHANDY + m_menu_channel_open_tab.signal_activate().connect([this] { + const auto id = static_cast<Snowflake>((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); + m_signal_action_open_new_tab.emit(id); + }); + m_menu_channel.append(m_menu_channel_open_tab); +#endif + m_menu_channel.append(m_menu_channel_mark_as_read); m_menu_channel.append(m_menu_channel_toggle_mute); m_menu_channel.append(m_menu_channel_copy_id); @@ -960,6 +972,12 @@ ChannelList::type_signal_action_guild_settings ChannelList::signal_action_guild_ return m_signal_action_guild_settings; } +#ifdef WITH_LIBHANDY +ChannelList::type_signal_action_open_new_tab ChannelList::signal_action_open_new_tab() { + return m_signal_action_open_new_tab; +} +#endif + ChannelList::ModelColumns::ModelColumns() { add(m_type); add(m_id); diff --git a/src/components/channels.hpp b/src/components/channels.hpp index 044d0b5..e8032af 100644 --- a/src/components/channels.hpp +++ b/src/components/channels.hpp @@ -121,6 +121,10 @@ protected: Gtk::MenuItem m_menu_channel_mark_as_read; Gtk::MenuItem m_menu_channel_toggle_mute; +#ifdef WITH_LIBHANDY + Gtk::MenuItem m_menu_channel_open_tab; +#endif + Gtk::Menu m_menu_dm; Gtk::MenuItem m_menu_dm_copy_id; Gtk::MenuItem m_menu_dm_close; @@ -149,16 +153,25 @@ protected: std::unordered_map<Snowflake, Gtk::TreeModel::iterator> m_tmp_channel_map; public: - typedef sigc::signal<void, Snowflake> type_signal_action_channel_item_select; - typedef sigc::signal<void, Snowflake> type_signal_action_guild_leave; - typedef sigc::signal<void, Snowflake> type_signal_action_guild_settings; + using type_signal_action_channel_item_select = sigc::signal<void, Snowflake>; + using type_signal_action_guild_leave = sigc::signal<void, Snowflake>; + using type_signal_action_guild_settings = sigc::signal<void, Snowflake>; + +#ifdef WITH_LIBHANDY + using type_signal_action_open_new_tab = sigc::signal<void, Snowflake>; + type_signal_action_open_new_tab signal_action_open_new_tab(); +#endif type_signal_action_channel_item_select signal_action_channel_item_select(); type_signal_action_guild_leave signal_action_guild_leave(); type_signal_action_guild_settings signal_action_guild_settings(); -protected: +private: type_signal_action_channel_item_select m_signal_action_channel_item_select; type_signal_action_guild_leave m_signal_action_guild_leave; type_signal_action_guild_settings m_signal_action_guild_settings; + +#ifdef WITH_LIBHANDY + type_signal_action_open_new_tab m_signal_action_open_new_tab; +#endif }; diff --git a/src/components/channeltabswitcherhandy.cpp b/src/components/channeltabswitcherhandy.cpp new file mode 100644 index 0000000..94d5c29 --- /dev/null +++ b/src/components/channeltabswitcherhandy.cpp @@ -0,0 +1,58 @@ +#ifdef WITH_LIBHANDY + + #include "channeltabswitcherhandy.hpp" + #include "abaddon.hpp" + +void selected_page_notify_cb(HdyTabView *view, GParamSpec *pspec, ChannelTabSwitcherHandy *switcher) { + auto *page = hdy_tab_view_get_selected_page(view); + if (auto it = switcher->m_pages_rev.find(page); it != switcher->m_pages_rev.end()) { + switcher->m_signal_channel_switched_to.emit(it->second); + } +} + +ChannelTabSwitcherHandy::ChannelTabSwitcherHandy() { + m_tab_bar = hdy_tab_bar_new(); + m_tab_bar_wrapped = Glib::wrap(GTK_WIDGET(m_tab_bar)); + m_tab_view = hdy_tab_view_new(); + m_tab_view_wrapped = Glib::wrap(GTK_WIDGET(m_tab_view)); + + g_signal_connect(m_tab_view, "notify::selected-page", G_CALLBACK(selected_page_notify_cb), this); + + hdy_tab_bar_set_view(m_tab_bar, m_tab_view); + add(*m_tab_bar_wrapped); + m_tab_bar_wrapped->show(); +} + +void ChannelTabSwitcherHandy::AddChannelTab(Snowflake id) { + auto &discord = Abaddon::Get().GetDiscordClient(); + const auto channel = discord.GetChannel(id); + if (!channel.has_value()) return; + + auto *dummy = Gtk::make_managed<Gtk::Box>(); // minimal + auto *page = hdy_tab_view_append(m_tab_view, GTK_WIDGET(dummy->gobj())); + + hdy_tab_page_set_title(page, ("#" + *channel->Name).c_str()); + + m_pages[id] = page; + m_pages_rev[page] = id; +} + +void ChannelTabSwitcherHandy::ReplaceActiveTab(Snowflake id) { + auto *page = hdy_tab_view_get_selected_page(m_tab_view); + if (page == nullptr) { + AddChannelTab(id); + } else { + auto &discord = Abaddon::Get().GetDiscordClient(); + const auto channel = discord.GetChannel(id); + if (!channel.has_value()) return; + + hdy_tab_page_set_title(page, ("#" + *channel->Name).c_str()); + m_pages_rev[page] = id; + } +} + +ChannelTabSwitcherHandy::type_signal_channel_switched_to ChannelTabSwitcherHandy::signal_channel_switched_to() { + return m_signal_channel_switched_to; +} + +#endif diff --git a/src/components/channeltabswitcherhandy.hpp b/src/components/channeltabswitcherhandy.hpp new file mode 100644 index 0000000..53e1624 --- /dev/null +++ b/src/components/channeltabswitcherhandy.hpp @@ -0,0 +1,37 @@ +#pragma once +// perhaps this should be conditionally included within cmakelists? +#ifdef WITH_LIBHANDY + #include <gtkmm/box.h> + #include <unordered_map> + #include <handy.h> + #include "discord/snowflake.hpp" + +// thin wrapper over c api +// HdyTabBar + invisible HdyTabView since it needs one +class ChannelTabSwitcherHandy : public Gtk::Box { +public: + ChannelTabSwitcherHandy(); + + void AddChannelTab(Snowflake id); + void ReplaceActiveTab(Snowflake id); + +private: + HdyTabBar *m_tab_bar; + Gtk::Widget *m_tab_bar_wrapped; + HdyTabView *m_tab_view; + Gtk::Widget *m_tab_view_wrapped; + + std::unordered_map<Snowflake, HdyTabPage *> m_pages; + std::unordered_map<HdyTabPage *, Snowflake> m_pages_rev; + + friend void selected_page_notify_cb(HdyTabView *, GParamSpec *, ChannelTabSwitcherHandy *); + +public: + using type_signal_channel_switched_to = sigc::signal<void, Snowflake>; + + type_signal_channel_switched_to signal_channel_switched_to(); + +private: + type_signal_channel_switched_to m_signal_channel_switched_to; +}; +#endif diff --git a/src/components/chatwindow.cpp b/src/components/chatwindow.cpp index 582343d..99ec8a0 100644 --- a/src/components/chatwindow.cpp +++ b/src/components/chatwindow.cpp @@ -4,6 +4,9 @@ #include "ratelimitindicator.hpp" #include "chatinput.hpp" #include "chatlist.hpp" +#ifdef WITH_LIBHANDY + #include "channeltabswitcherhandy.hpp" +#endif ChatWindow::ChatWindow() { Abaddon::Get().GetDiscordClient().signal_message_send_fail().connect(sigc::mem_fun(*this, &ChatWindow::OnMessageSendFail)); @@ -15,6 +18,13 @@ ChatWindow::ChatWindow() { m_rate_limit_indicator = Gtk::manage(new RateLimitIndicator); m_meta = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL)); +#ifdef WITH_LIBHANDY + m_tab_switcher = Gtk::make_managed<ChannelTabSwitcherHandy>(); + m_tab_switcher->signal_channel_switched_to().connect([this](Snowflake id) { + m_signal_action_channel_click.emit(id); + }); +#endif + m_rate_limit_indicator->set_margin_end(5); m_rate_limit_indicator->set_hexpand(true); m_rate_limit_indicator->set_halign(Gtk::ALIGN_END); @@ -88,6 +98,10 @@ ChatWindow::ChatWindow() { m_meta->add(*m_input_indicator); m_meta->add(*m_rate_limit_indicator); // m_scroll->add(*m_list); +#ifdef WITH_LIBHANDY + m_main->add(*m_tab_switcher); + m_tab_switcher->show(); +#endif m_main->add(m_topic); m_main->add(*m_chat); m_main->add(m_completer); @@ -115,6 +129,10 @@ void ChatWindow::SetActiveChannel(Snowflake id) { m_rate_limit_indicator->SetActiveChannel(id); if (m_is_replying) StopReplying(); + +#ifdef WITH_LIBHANDY + m_tab_switcher->ReplaceActiveTab(id); +#endif } void ChatWindow::AddNewMessage(const Message &data) { @@ -150,6 +168,12 @@ void ChatWindow::SetTopic(const std::string &text) { m_topic.set_visible(text.length() > 0); } +#ifdef WITH_LIBHANDY +void ChatWindow::OpenNewTab(Snowflake id) { + m_tab_switcher->AddChannelTab(id); +} +#endif + Snowflake ChatWindow::GetActiveChannel() const { return m_active_channel; } diff --git a/src/components/chatwindow.hpp b/src/components/chatwindow.hpp index 0f40e88..d77afec 100644 --- a/src/components/chatwindow.hpp +++ b/src/components/chatwindow.hpp @@ -5,6 +5,10 @@ #include "discord/discord.hpp" #include "completer.hpp" +#ifdef WITH_LIBHANDY +class ChannelTabSwitcherHandy; +#endif + class ChatMessageHeader; class ChatMessageItemContainer; class ChatInput; @@ -25,11 +29,15 @@ public: void DeleteMessage(Snowflake id); // add [deleted] indicator void UpdateMessage(Snowflake id); // add [edited] indicator void AddNewHistory(const std::vector<Message> &msgs); // prepend messages - void InsertChatInput(const std::string& text); + void InsertChatInput(const std::string &text); Snowflake GetOldestListedMessage(); // oldest message that is currently in the ListBox void UpdateReactions(Snowflake id); void SetTopic(const std::string &text); +#ifdef WITH_LIBHANDY + void OpenNewTab(Snowflake id); +#endif + protected: bool m_is_replying = false; Snowflake m_replying_to; @@ -62,14 +70,18 @@ protected: RateLimitIndicator *m_rate_limit_indicator; Gtk::Box *m_meta; +#ifdef WITH_LIBHANDY + ChannelTabSwitcherHandy *m_tab_switcher; +#endif + public: - typedef sigc::signal<void, Snowflake, Snowflake> type_signal_action_message_edit; - typedef sigc::signal<void, std::string, Snowflake, Snowflake> type_signal_action_chat_submit; - typedef sigc::signal<void, Snowflake> type_signal_action_chat_load_history; - typedef sigc::signal<void, Snowflake> type_signal_action_channel_click; - typedef sigc::signal<void, Snowflake> type_signal_action_insert_mention; - typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_add; - typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_remove; + using type_signal_action_message_edit = sigc::signal<void, Snowflake, Snowflake>; + using type_signal_action_chat_submit = sigc::signal<void, std::string, Snowflake, Snowflake>; + using type_signal_action_chat_load_history = sigc::signal<void, Snowflake>; + using type_signal_action_channel_click = sigc::signal<void, Snowflake>; + using type_signal_action_insert_mention = sigc::signal<void, Snowflake>; + using type_signal_action_reaction_add = sigc::signal<void, Snowflake, Glib::ustring>; + using type_signal_action_reaction_remove = sigc::signal<void, Snowflake, Glib::ustring>; type_signal_action_message_edit signal_action_message_edit(); type_signal_action_chat_submit signal_action_chat_submit(); |