summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/channels.cpp73
-rw-r--r--src/components/channels.hpp23
-rw-r--r--src/components/channelscellrenderer.cpp55
-rw-r--r--src/components/channelscellrenderer.hpp17
4 files changed, 166 insertions, 2 deletions
diff --git a/src/components/channels.cpp b/src/components/channels.cpp
index 497c021..eb9d688 100644
--- a/src/components/channels.cpp
+++ b/src/components/channels.cpp
@@ -21,6 +21,10 @@ ChannelList::ChannelList()
, m_menu_channel_open_tab("Open in New _Tab", true)
, m_menu_dm_open_tab("Open in New _Tab", true)
#endif
+#ifdef WITH_VOICE
+ , m_menu_voice_channel_join("_Join", true)
+ , m_menu_voice_channel_disconnect("_Disconnect", 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)
@@ -36,7 +40,11 @@ ChannelList::ChannelList()
const auto type = row[m_columns.m_type];
// text channels should not be allowed to be collapsed
// maybe they should be but it seems a little difficult to handle expansion to permit this
+#ifdef WITH_VOICE
+ if (type != RenderType::TextChannel && type != RenderType::VoiceChannel) {
+#else
if (type != RenderType::TextChannel) {
+#endif
if (row[m_columns.m_expanded]) {
m_view.collapse_row(path);
row[m_columns.m_expanded] = false;
@@ -161,6 +169,21 @@ ChannelList::ChannelList()
m_menu_channel.append(m_menu_channel_copy_id);
m_menu_channel.show_all();
+#ifdef WITH_VOICE
+ m_menu_voice_channel_join.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_join_voice_channel.emit(id);
+ });
+
+ m_menu_voice_channel_disconnect.signal_activate().connect([this]() {
+ m_signal_action_disconnect_voice.emit();
+ });
+
+ m_menu_voice_channel.append(m_menu_voice_channel_join);
+ m_menu_voice_channel.append(m_menu_voice_channel_disconnect);
+ m_menu_voice_channel.show_all();
+#endif
+
m_menu_dm_copy_id.signal_activate().connect([this] {
Gtk::Clipboard::get()->set_text(std::to_string((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]));
});
@@ -579,7 +602,11 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) {
for (const auto &channel_ : *guild.Channels) {
const auto channel = discord.GetChannel(channel_.ID);
if (!channel.has_value()) continue;
+#ifdef WITH_VOICE
+ if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE) {
+#else
if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS) {
+#endif
if (channel->ParentID.has_value())
categories[*channel->ParentID].push_back(*channel);
else
@@ -607,7 +634,12 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) {
for (const auto &channel : orphan_channels) {
auto channel_row = *m_model->append(guild_row.children());
- channel_row[m_columns.m_type] = RenderType::TextChannel;
+ if (IsTextChannel(channel.Type))
+ channel_row[m_columns.m_type] = RenderType::TextChannel;
+#ifdef WITH_VOICE
+ else
+ channel_row[m_columns.m_type] = RenderType::VoiceChannel;
+#endif
channel_row[m_columns.m_id] = channel.ID;
channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name);
channel_row[m_columns.m_sort] = *channel.Position + OrphanChannelSortOffset;
@@ -630,7 +662,12 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) {
for (const auto &channel : channels) {
auto channel_row = *m_model->append(cat_row.children());
- channel_row[m_columns.m_type] = RenderType::TextChannel;
+ if (IsTextChannel(channel.Type))
+ channel_row[m_columns.m_type] = RenderType::TextChannel;
+#ifdef WITH_VOICE
+ else
+ channel_row[m_columns.m_type] = RenderType::VoiceChannel;
+#endif
channel_row[m_columns.m_id] = channel.ID;
channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name);
channel_row[m_columns.m_sort] = *channel.Position;
@@ -856,6 +893,12 @@ bool ChannelList::OnButtonPressEvent(GdkEventButton *ev) {
OnChannelSubmenuPopup();
m_menu_channel.popup_at_pointer(reinterpret_cast<GdkEvent *>(ev));
break;
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ OnVoiceChannelSubmenuPopup();
+ m_menu_voice_channel.popup_at_pointer(reinterpret_cast<GdkEvent *>(ev));
+ break;
+#endif
case RenderType::DM: {
OnDMSubmenuPopup();
const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(static_cast<Snowflake>(row[m_columns.m_id]));
@@ -947,6 +990,22 @@ void ChannelList::OnChannelSubmenuPopup() {
m_menu_channel_toggle_mute.set_label("Mute");
}
+#ifdef WITH_VOICE
+void ChannelList::OnVoiceChannelSubmenuPopup() {
+ const auto iter = m_model->get_iter(m_path_for_menu);
+ if (!iter) return;
+ const auto id = static_cast<Snowflake>((*iter)[m_columns.m_id]);
+ auto &discord = Abaddon::Get().GetDiscordClient();
+ if (discord.IsConnectedToVoice()) {
+ m_menu_voice_channel_join.set_sensitive(false);
+ m_menu_voice_channel_disconnect.set_sensitive(discord.GetVoiceChannelID() == id);
+ } else {
+ m_menu_voice_channel_join.set_sensitive(true);
+ m_menu_voice_channel_disconnect.set_sensitive(false);
+ }
+}
+#endif
+
void ChannelList::OnDMSubmenuPopup() {
auto iter = m_model->get_iter(m_path_for_menu);
if (!iter) return;
@@ -997,6 +1056,16 @@ ChannelList::type_signal_action_open_new_tab ChannelList::signal_action_open_new
}
#endif
+#ifdef WITH_VOICE
+ChannelList::type_signal_action_join_voice_channel ChannelList::signal_action_join_voice_channel() {
+ return m_signal_action_join_voice_channel;
+}
+
+ChannelList::type_signal_action_disconnect_voice ChannelList::signal_action_disconnect_voice() {
+ return m_signal_action_disconnect_voice;
+}
+#endif
+
ChannelList::ModelColumns::ModelColumns() {
add(m_type);
add(m_id);
diff --git a/src/components/channels.hpp b/src/components/channels.hpp
index 53a68c9..2d2b257 100644
--- a/src/components/channels.hpp
+++ b/src/components/channels.hpp
@@ -125,6 +125,12 @@ protected:
Gtk::MenuItem m_menu_channel_open_tab;
#endif
+#ifdef WITH_VOICE
+ Gtk::Menu m_menu_voice_channel;
+ Gtk::MenuItem m_menu_voice_channel_join;
+ Gtk::MenuItem m_menu_voice_channel_disconnect;
+#endif
+
Gtk::Menu m_menu_dm;
Gtk::MenuItem m_menu_dm_copy_id;
Gtk::MenuItem m_menu_dm_close;
@@ -148,6 +154,10 @@ protected:
void OnDMSubmenuPopup();
void OnThreadSubmenuPopup();
+#ifdef WITH_VOICE
+ void OnVoiceChannelSubmenuPopup();
+#endif
+
bool m_updating_listing = false;
Snowflake m_active_channel;
@@ -166,6 +176,14 @@ public:
type_signal_action_open_new_tab signal_action_open_new_tab();
#endif
+#ifdef WITH_VOICE
+ using type_signal_action_join_voice_channel = sigc::signal<void, Snowflake>;
+ using type_signal_action_disconnect_voice = sigc::signal<void>;
+
+ type_signal_action_join_voice_channel signal_action_join_voice_channel();
+ type_signal_action_disconnect_voice signal_action_disconnect_voice();
+#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();
@@ -178,4 +196,9 @@ private:
#ifdef WITH_LIBHANDY
type_signal_action_open_new_tab m_signal_action_open_new_tab;
#endif
+
+#ifdef WITH_VOICE
+ type_signal_action_join_voice_channel m_signal_action_join_voice_channel;
+ type_signal_action_disconnect_voice m_signal_action_disconnect_voice;
+#endif
};
diff --git a/src/components/channelscellrenderer.cpp b/src/components/channelscellrenderer.cpp
index 9afce8a..23ee3f0 100644
--- a/src/components/channelscellrenderer.cpp
+++ b/src/components/channelscellrenderer.cpp
@@ -65,6 +65,10 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m
return get_preferred_width_vfunc_channel(widget, minimum_width, natural_width);
case RenderType::Thread:
return get_preferred_width_vfunc_thread(widget, minimum_width, natural_width);
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ return get_preferred_width_vfunc_voice_channel(widget, minimum_width, natural_width);
+#endif
case RenderType::DMHeader:
return get_preferred_width_vfunc_dmheader(widget, minimum_width, natural_width);
case RenderType::DM:
@@ -82,6 +86,10 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid
return get_preferred_width_for_height_vfunc_channel(widget, height, minimum_width, natural_width);
case RenderType::Thread:
return get_preferred_width_for_height_vfunc_thread(widget, height, minimum_width, natural_width);
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ return get_preferred_width_for_height_vfunc_voice_channel(widget, height, minimum_width, natural_width);
+#endif
case RenderType::DMHeader:
return get_preferred_width_for_height_vfunc_dmheader(widget, height, minimum_width, natural_width);
case RenderType::DM:
@@ -99,6 +107,10 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int &
return get_preferred_height_vfunc_channel(widget, minimum_height, natural_height);
case RenderType::Thread:
return get_preferred_height_vfunc_thread(widget, minimum_height, natural_height);
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ return get_preferred_height_vfunc_voice_channel(widget, minimum_height, natural_height);
+#endif
case RenderType::DMHeader:
return get_preferred_height_vfunc_dmheader(widget, minimum_height, natural_height);
case RenderType::DM:
@@ -116,6 +128,10 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid
return get_preferred_height_for_width_vfunc_channel(widget, width, minimum_height, natural_height);
case RenderType::Thread:
return get_preferred_height_for_width_vfunc_thread(widget, width, minimum_height, natural_height);
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ return get_preferred_height_for_width_vfunc_voice_channel(widget, width, minimum_height, natural_height);
+#endif
case RenderType::DMHeader:
return get_preferred_height_for_width_vfunc_dmheader(widget, width, minimum_height, natural_height);
case RenderType::DM:
@@ -133,6 +149,10 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
return render_vfunc_channel(cr, widget, background_area, cell_area, flags);
case RenderType::Thread:
return render_vfunc_thread(cr, widget, background_area, cell_area, flags);
+#ifdef WITH_VOICE
+ case RenderType::VoiceChannel:
+ return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags);
+#endif
case RenderType::DMHeader:
return render_vfunc_dmheader(cr, widget, background_area, cell_area, flags);
case RenderType::DM:
@@ -499,6 +519,41 @@ void CellRendererChannels::render_vfunc_thread(const Cairo::RefPtr<Cairo::Contex
}
}
+// voice channel
+
+#ifdef WITH_VOICE
+void CellRendererChannels::get_preferred_width_vfunc_voice_channel(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
+ m_renderer_text.get_preferred_width(widget, minimum_width, natural_width);
+}
+
+void CellRendererChannels::get_preferred_width_for_height_vfunc_voice_channel(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const {
+ m_renderer_text.get_preferred_width_for_height(widget, height, minimum_width, natural_width);
+}
+
+void CellRendererChannels::get_preferred_height_vfunc_voice_channel(Gtk::Widget &widget, int &minimum_height, int &natural_height) const {
+ m_renderer_text.get_preferred_height(widget, minimum_height, natural_height);
+}
+
+void CellRendererChannels::get_preferred_height_for_width_vfunc_voice_channel(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const {
+ m_renderer_text.get_preferred_height_for_width(widget, width, minimum_height, natural_height);
+}
+
+void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
+ Gtk::Requisition minimum_size, natural_size;
+ m_renderer_text.get_preferred_size(widget, minimum_size, natural_size);
+
+ const int text_x = background_area.get_x() + 21;
+ const int text_y = background_area.get_y() + background_area.get_height() / 2 - natural_size.height / 2;
+ const int text_w = natural_size.width;
+ const int text_h = natural_size.height;
+
+ Gdk::Rectangle text_cell_area(text_x, text_y, text_w, text_h);
+ m_renderer_text.property_foreground_rgba() = Gdk::RGBA("#0f0");
+ m_renderer_text.render(cr, widget, background_area, text_cell_area, flags);
+ m_renderer_text.property_foreground_set() = false;
+}
+#endif
+
// dm header
void CellRendererChannels::get_preferred_width_vfunc_dmheader(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
diff --git a/src/components/channelscellrenderer.hpp b/src/components/channelscellrenderer.hpp
index e2be9b2..8e4025a 100644
--- a/src/components/channelscellrenderer.hpp
+++ b/src/components/channelscellrenderer.hpp
@@ -11,6 +11,10 @@ enum class RenderType : uint8_t {
TextChannel,
Thread,
+#ifdef WITH_VOICE
+ VoiceChannel,
+#endif
+
DMHeader,
DM,
};
@@ -83,6 +87,19 @@ protected:
const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags);
+#ifdef WITH_VOICE
+ // voice channel
+ void get_preferred_width_vfunc_voice_channel(Gtk::Widget &widget, int &minimum_width, int &natural_width) const;
+ void get_preferred_width_for_height_vfunc_voice_channel(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const;
+ void get_preferred_height_vfunc_voice_channel(Gtk::Widget &widget, int &minimum_height, int &natural_height) const;
+ void get_preferred_height_for_width_vfunc_voice_channel(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const;
+ void render_vfunc_voice_channel(const Cairo::RefPtr<Cairo::Context> &cr,
+ Gtk::Widget &widget,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+#endif
+
// dm header
void get_preferred_width_vfunc_dmheader(Gtk::Widget &widget, int &minimum_width, int &natural_width) const;
void get_preferred_width_for_height_vfunc_dmheader(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const;