diff options
Diffstat (limited to 'components/channels.cpp')
-rw-r--r-- | components/channels.cpp | 126 |
1 files changed, 104 insertions, 22 deletions
diff --git a/components/channels.cpp b/components/channels.cpp index 3e7862b..a80cfd8 100644 --- a/components/channels.cpp +++ b/components/channels.cpp @@ -22,15 +22,20 @@ ChannelList::ChannelList() const auto cb = [this](const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column) { auto row = *m_model->get_iter(path); - if (row[m_columns.m_expanded]) { - m_view.collapse_row(path); - row[m_columns.m_expanded] = false; - } else { - m_view.expand_row(path, false); - row[m_columns.m_expanded] = true; + 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 + if (type != RenderType::TextChannel) { + if (row[m_columns.m_expanded]) { + m_view.collapse_row(path); + row[m_columns.m_expanded] = false; + } else { + m_view.expand_row(path, false); + row[m_columns.m_expanded] = true; + } } - if (row[m_columns.m_type] == RenderType::TextChannel || row[m_columns.m_type] == RenderType::DM) { + if (type == RenderType::TextChannel || type == RenderType::DM || type == RenderType::Thread) { m_signal_action_channel_item_select.emit(static_cast<Snowflake>(row[m_columns.m_id])); } }; @@ -123,6 +128,7 @@ ChannelList::ChannelList() discord.signal_channel_delete().connect(sigc::mem_fun(*this, &ChannelList::UpdateRemoveChannel)); discord.signal_channel_update().connect(sigc::mem_fun(*this, &ChannelList::UpdateChannel)); discord.signal_channel_create().connect(sigc::mem_fun(*this, &ChannelList::UpdateCreateChannel)); + discord.signal_thread_create().connect(sigc::mem_fun(*this, &ChannelList::UpdateCreateThread)); discord.signal_guild_update().connect(sigc::mem_fun(*this, &ChannelList::UpdateGuild)); } @@ -206,32 +212,31 @@ void ChannelList::UpdateChannel(Snowflake id) { channel_row[m_columns.m_sort] = *channel->Position; } -void ChannelList::UpdateCreateChannel(Snowflake id) { - const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(id); - if (!channel.has_value()) return; - if (channel->Type == ChannelType::GUILD_CATEGORY) return (void)UpdateCreateChannelCategory(*channel); - if (channel->Type == ChannelType::DM || channel->Type == ChannelType::GROUP_DM) return UpdateCreateDMChannel(*channel); - if (channel->Type != ChannelType::GUILD_TEXT && channel->Type != ChannelType::GUILD_NEWS) return; +void ChannelList::UpdateCreateChannel(const ChannelData &channel) { + ; + if (channel.Type == ChannelType::GUILD_CATEGORY) return (void)UpdateCreateChannelCategory(channel); + if (channel.Type == ChannelType::DM || channel.Type == ChannelType::GROUP_DM) return UpdateCreateDMChannel(channel); + if (channel.Type != ChannelType::GUILD_TEXT && channel.Type != ChannelType::GUILD_NEWS) return; Gtk::TreeRow channel_row; bool orphan; - if (channel->ParentID.has_value()) { + if (channel.ParentID.has_value()) { orphan = false; - auto iter = GetIteratorForChannelFromID(*channel->ParentID); + auto iter = GetIteratorForChannelFromID(*channel.ParentID); channel_row = *m_model->append(iter->children()); } else { orphan = true; - auto iter = GetIteratorForGuildFromID(*channel->GuildID); + auto iter = GetIteratorForGuildFromID(*channel.GuildID); channel_row = *m_model->append(iter->children()); } channel_row[m_columns.m_type] = RenderType::TextChannel; - 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_nsfw] = channel->NSFW(); + 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_nsfw] = channel.NSFW(); if (orphan) - channel_row[m_columns.m_sort] = *channel->Position + OrphanChannelSortOffset; + channel_row[m_columns.m_sort] = *channel.Position + OrphanChannelSortOffset; else - channel_row[m_columns.m_sort] = *channel->Position; + channel_row[m_columns.m_sort] = *channel.Position; } void ChannelList::UpdateGuild(Snowflake id) { @@ -260,6 +265,12 @@ void ChannelList::UpdateGuild(Snowflake id) { } } +void ChannelList::UpdateCreateThread(const ChannelData &channel) { + auto parent_row = GetIteratorForChannelFromID(*channel.ParentID); + if (parent_row) + CreateThreadRow(parent_row->children(), channel); +} + void ChannelList::SetActiveChannel(Snowflake id) { const auto channel_iter = GetIteratorForChannelFromID(id); if (channel_iter) { @@ -313,6 +324,22 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) { } } + std::map<Snowflake, std::vector<ChannelData>> threads; + for (const auto &tmp : *guild.Threads) { + const auto thread = discord.GetChannel(tmp.ID); + if (thread.has_value()) + threads[*thread->ParentID].push_back(*thread); + } + const auto add_threads = [&](const ChannelData &channel, Gtk::TreeRow row) { + row[m_columns.m_expanded] = true; + + const auto it = threads.find(channel.ID); + if (it == threads.end()) return; + + for (const auto &thread : it->second) + CreateThreadRow(row.children(), thread); + }; + for (const auto &channel : orphan_channels) { auto channel_row = *m_model->append(guild_row.children()); channel_row[m_columns.m_type] = RenderType::TextChannel; @@ -320,6 +347,7 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) { channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); channel_row[m_columns.m_sort] = *channel.Position + OrphanChannelSortOffset; channel_row[m_columns.m_nsfw] = channel.NSFW(); + add_threads(channel, channel_row); } for (const auto &[category_id, channels] : categories) { @@ -340,6 +368,7 @@ Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) { channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); channel_row[m_columns.m_sort] = *channel.Position; channel_row[m_columns.m_nsfw] = channel.NSFW(); + add_threads(channel, channel_row); } } @@ -360,6 +389,18 @@ Gtk::TreeModel::iterator ChannelList::UpdateCreateChannelCategory(const ChannelD return cat_row; } +Gtk::TreeModel::iterator ChannelList::CreateThreadRow(const Gtk::TreeNodeChildren &children, const ChannelData &channel) { + auto thread_iter = m_model->append(children); + auto thread_row = *thread_iter; + thread_row[m_columns.m_type] = RenderType::Thread; + thread_row[m_columns.m_id] = channel.ID; + thread_row[m_columns.m_name] = "- " + Glib::Markup::escape_text(*channel.Name); + thread_row[m_columns.m_sort] = channel.ID; + thread_row[m_columns.m_nsfw] = false; + + return thread_iter; +} + void ChannelList::UpdateChannelCategory(const ChannelData &channel) { auto iter = GetIteratorForChannelFromID(channel.ID); if (!iter) return; @@ -423,7 +464,7 @@ bool ChannelList::SelectionFunc(const Glib::RefPtr<Gtk::TreeModel> &model, const m_last_selected = m_model->get_path(row); auto type = (*m_model->get_iter(path))[m_columns.m_type]; - return type == RenderType::TextChannel || type == RenderType::DM; + return type == RenderType::TextChannel || type == RenderType::DM || type == RenderType::Thread; } void ChannelList::AddPrivateChannels() { @@ -614,6 +655,8 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m return get_preferred_width_vfunc_category(widget, minimum_width, natural_width); case RenderType::TextChannel: 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); case RenderType::DMHeader: return get_preferred_width_vfunc_dmheader(widget, minimum_width, natural_width); case RenderType::DM: @@ -629,6 +672,8 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid return get_preferred_width_for_height_vfunc_category(widget, height, minimum_width, natural_width); case RenderType::TextChannel: 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); case RenderType::DMHeader: return get_preferred_width_for_height_vfunc_dmheader(widget, height, minimum_width, natural_width); case RenderType::DM: @@ -644,6 +689,8 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int & return get_preferred_height_vfunc_category(widget, minimum_height, natural_height); case RenderType::TextChannel: 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); case RenderType::DMHeader: return get_preferred_height_vfunc_dmheader(widget, minimum_height, natural_height); case RenderType::DM: @@ -659,6 +706,8 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid return get_preferred_height_for_width_vfunc_category(widget, width, minimum_height, natural_height); case RenderType::TextChannel: 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); case RenderType::DMHeader: return get_preferred_height_for_width_vfunc_dmheader(widget, width, minimum_height, natural_height); case RenderType::DM: @@ -674,6 +723,8 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr, return render_vfunc_category(cr, widget, background_area, cell_area, flags); case RenderType::TextChannel: 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); case RenderType::DMHeader: return render_vfunc_dmheader(cr, widget, background_area, cell_area, flags); case RenderType::DM: @@ -883,6 +934,37 @@ void CellRendererChannels::render_vfunc_channel(const Cairo::RefPtr<Cairo::Conte m_renderer_text.property_foreground_set() = false; } +// thread + +void CellRendererChannels::get_preferred_width_vfunc_thread(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_thread(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const { + get_preferred_width_vfunc_thread(widget, minimum_width, natural_width); +} + +void CellRendererChannels::get_preferred_height_vfunc_thread(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_thread(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const { + get_preferred_height_vfunc_thread(widget, minimum_height, natural_height); +} + +void CellRendererChannels::render_vfunc_thread(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() + 26; + 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.render(cr, widget, background_area, text_cell_area, flags); +} + // dm header void CellRendererChannels::get_preferred_width_vfunc_dmheader(Gtk::Widget &widget, int &minimum_width, int &natural_width) const { |