summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Findglib.cmake92
-rw-r--r--src/components/channels.cpp18
-rw-r--r--src/components/channels.hpp21
-rw-r--r--src/components/channeltabswitcherhandy.cpp58
-rw-r--r--src/components/channeltabswitcherhandy.hpp37
-rw-r--r--src/components/chatwindow.cpp24
-rw-r--r--src/components/chatwindow.hpp28
-rw-r--r--src/windows/mainwindow.cpp6
8 files changed, 230 insertions, 54 deletions
diff --git a/cmake/Findglib.cmake b/cmake/Findglib.cmake
index b2c730b..f60f75d 100644
--- a/cmake/Findglib.cmake
+++ b/cmake/Findglib.cmake
@@ -2,56 +2,64 @@ find_package(PkgConfig)
pkg_check_modules(PC_GLIB2 QUIET glib-2.0)
find_path(GLIB_INCLUDE_DIR
- NAMES glib.h
- HINTS ${PC_GLIB2_INCLUDEDIR}
- ${PC_GLIB2_INCLUDE_DIRS}
- $ENV{GLIB2_HOME}/include
- $ENV{GLIB2_ROOT}/include
- /usr/local/include
- /usr/include
- /glib2/include
- /glib-2.0/include
- PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
-)
+ NAMES glib.h
+ HINTS ${PC_GLIB2_INCLUDEDIR}
+ ${PC_GLIB2_INCLUDE_DIRS}
+ $ENV{GLIB2_HOME}/include
+ $ENV{GLIB2_ROOT}/include
+ /usr/local/include
+ /usr/include
+ /glib2/include
+ /glib-2.0/include
+ PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
+ )
set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR})
find_library(GLIB_LIBRARIES
- NAMES glib2
- glib-2.0
- HINTS ${PC_GLIB2_LIBDIR}
- ${PC_GLIB2_LIBRARY_DIRS}
- $ENV{GLIB2_HOME}/lib
- $ENV{GLIB2_ROOT}/lib
- /usr/local/lib
- /usr/lib
- /lib
- /glib-2.0/lib
- PATH_SUFFIXES glib2 glib-2.0
-)
+ NAMES glib2
+ glib-2.0
+ HINTS ${PC_GLIB2_LIBDIR}
+ ${PC_GLIB2_LIBRARY_DIRS}
+ $ENV{GLIB2_HOME}/lib
+ $ENV{GLIB2_ROOT}/lib
+ /usr/local/lib
+ /usr/lib
+ /lib
+ /glib-2.0/lib
+ PATH_SUFFIXES glib2 glib-2.0
+ )
+
+find_library(glib_GOBJECT_LIBRARIES
+ NAMES gobject-2.0
+ HINTS ${PC_GLIB2_LIBDIR}
+ ${PC_GLIB2_LIBRARY_DIRS}
+ )
get_filename_component(_GLIB2_LIB_DIR "${GLIB_LIBRARIES}" PATH)
find_path(GLIB_CONFIG_INCLUDE_DIR
- NAMES glibconfig.h
- HINTS ${PC_GLIB2_INCLUDEDIR}
- ${PC_GLIB2_INCLUDE_DIRS}
- $ENV{GLIB2_HOME}/include
- $ENV{GLIB2_ROOT}/include
- /usr/local/include
- /usr/include
- /glib2/include
- /glib-2.0/include
- ${_GLIB2_LIB_DIR}
- ${CMAKE_SYSTEM_LIBRARY_PATH}
- PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
-)
+ NAMES glibconfig.h
+ HINTS ${PC_GLIB2_INCLUDEDIR}
+ ${PC_GLIB2_INCLUDE_DIRS}
+ $ENV{GLIB2_HOME}/include
+ $ENV{GLIB2_ROOT}/include
+ /usr/local/include
+ /usr/include
+ /glib2/include
+ /glib-2.0/include
+ ${_GLIB2_LIB_DIR}
+ ${CMAKE_SYSTEM_LIBRARY_PATH}
+ PATH_SUFFIXES glib2 glib-2.0 glib-2.0/include
+ )
if (GLIB_CONFIG_INCLUDE_DIR)
set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIRS} ${GLIB_CONFIG_INCLUDE_DIR})
-endif()
+endif ()
+
+set(GLIB_LIBRARIES ${GLIB_LIBRARIES} ${glib_GOBJECT_LIBRARIES})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(glib
- REQUIRED_VARS
- GLIB_LIBRARIES
- GLIB_INCLUDE_DIRS
- VERSION_VAR GLIB_VERSION)
-mark_as_advanced(GLIB_INCLUDE_DIR GLIB_CONFIG_INCLUDE_DIR)
+ REQUIRED_VARS
+ GLIB_LIBRARIES
+ GLIB_INCLUDE_DIRS
+ VERSION_VAR GLIB_VERSION)
+mark_as_advanced(GLIB_INCLUDE_DIR GLIB_CONFIG_INCLUDE_DIR glib_GOBJECT_LIBRARIES)
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();
diff --git a/src/windows/mainwindow.cpp b/src/windows/mainwindow.cpp
index e12e9bd..b518b93 100644
--- a/src/windows/mainwindow.cpp
+++ b/src/windows/mainwindow.cpp
@@ -27,6 +27,12 @@ MainWindow::MainWindow()
chat->set_hexpand(true);
chat->show();
+#ifdef WITH_LIBHANDY
+ m_channel_list.signal_action_open_new_tab().connect([this](Snowflake id) {
+ m_chat.OpenNewTab(id);
+ });
+#endif
+
m_channel_list.set_vexpand(true);
m_channel_list.set_size_request(-1, -1);
m_channel_list.show();