diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2023-09-10 02:06:00 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2023-09-10 02:06:00 -0400 |
commit | 0e97bbc5f0f6c8678d58618cc073abbf2d2fccd7 (patch) | |
tree | d5ac9be4dfa6de1e9b444ac84059354b79a4d311 | |
parent | 1056596dfc77bee54707097aa60ee2fef2c8d83b (diff) | |
download | abaddon-portaudio-0e97bbc5f0f6c8678d58618cc073abbf2d2fccd7.tar.gz abaddon-portaudio-0e97bbc5f0f6c8678d58618cc073abbf2d2fccd7.zip |
add profile pics and colors to member list
-rw-r--r-- | src/components/cellrenderermemberlist.cpp | 34 | ||||
-rw-r--r-- | src/components/cellrenderermemberlist.hpp | 11 | ||||
-rw-r--r-- | src/components/memberlist.cpp | 50 | ||||
-rw-r--r-- | src/components/memberlist.hpp | 11 |
4 files changed, 97 insertions, 9 deletions
diff --git a/src/components/cellrenderermemberlist.cpp b/src/components/cellrenderermemberlist.cpp index 187b82c..66b223e 100644 --- a/src/components/cellrenderermemberlist.cpp +++ b/src/components/cellrenderermemberlist.cpp @@ -2,10 +2,11 @@ CellRendererMemberList::CellRendererMemberList() : Glib::ObjectBase(typeid(CellRendererMemberList)) - , Gtk::CellRenderer() , m_property_type(*this, "render-type") , m_property_id(*this, "id") - , m_property_name(*this, "name") { + , m_property_name(*this, "name") + , m_property_pixbuf(*this, "pixbuf") + , m_property_color(*this, "color") { property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; property_xpad() = 2; property_ypad() = 2; @@ -26,6 +27,14 @@ Glib::PropertyProxy<Glib::ustring> CellRendererMemberList::property_name() { return m_property_name.get_proxy(); } +Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> CellRendererMemberList::property_pixbuf() { + return m_property_pixbuf.get_proxy(); +} + +Glib::PropertyProxy<Gdk::RGBA> CellRendererMemberList::property_color() { + return m_property_color.get_proxy(); +} + void CellRendererMemberList::get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const { switch (m_property_type.get_value()) { case MemberListRenderType::Role: @@ -108,5 +117,24 @@ void CellRendererMemberList::get_preferred_height_for_width_vfunc_member(Gtk::Wi } void CellRendererMemberList::render_vfunc_member(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) { - m_renderer_text.render(cr, widget, background_area, cell_area, flags); + Gdk::Rectangle text_cell_area = cell_area; + text_cell_area.set_x(22); + const auto color = m_property_color.get_value(); + if (color.get_alpha_u() > 0) { + m_renderer_text.property_foreground_rgba().set_value(color); + } + m_renderer_text.render(cr, widget, background_area, text_cell_area, flags); + m_renderer_text.property_foreground_set().set_value(false); + + const double icon_x = background_area.get_x() + 6.0; + const double icon_y = background_area.get_y() + background_area.get_height() / 2.0 - 8.0; + Gdk::Cairo::set_source_pixbuf(cr, m_property_pixbuf.get_value(), icon_x, icon_y); + cr->rectangle(icon_x, icon_y, 16.0, 16.0); + cr->fill(); + + m_signal_render.emit(m_property_id.get_value()); +} + +CellRendererMemberList::type_signal_render CellRendererMemberList::signal_render() { + return m_signal_render; } diff --git a/src/components/cellrenderermemberlist.hpp b/src/components/cellrenderermemberlist.hpp index c0f68e8..7a49ccf 100644 --- a/src/components/cellrenderermemberlist.hpp +++ b/src/components/cellrenderermemberlist.hpp @@ -14,6 +14,8 @@ public: Glib::PropertyProxy<MemberListRenderType> property_type(); Glib::PropertyProxy<uint64_t> property_id(); Glib::PropertyProxy<Glib::ustring> property_name(); + Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> property_pixbuf(); + Glib::PropertyProxy<Gdk::RGBA> property_color(); protected: void get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const override; @@ -48,9 +50,16 @@ protected: private: Gtk::CellRendererText m_renderer_text; - Gtk::CellRendererPixbuf m_renderer_pixbuf; Glib::Property<MemberListRenderType> m_property_type; Glib::Property<uint64_t> m_property_id; Glib::Property<Glib::ustring> m_property_name; + Glib::Property<Glib::RefPtr<Gdk::Pixbuf>> m_property_pixbuf; + Glib::Property<Gdk::RGBA> m_property_color; + + using type_signal_render = sigc::signal<void(uint64_t)>; + type_signal_render m_signal_render; + +public: + type_signal_render signal_render(); }; diff --git a/src/components/memberlist.cpp b/src/components/memberlist.cpp index 86f568b..2dd608d 100644 --- a/src/components/memberlist.cpp +++ b/src/components/memberlist.cpp @@ -22,7 +22,11 @@ MemberList::MemberList() column->add_attribute(renderer->property_type(), m_columns.m_type); column->add_attribute(renderer->property_id(), m_columns.m_id); column->add_attribute(renderer->property_name(), m_columns.m_name); + column->add_attribute(renderer->property_pixbuf(), m_columns.m_pixbuf); + column->add_attribute(renderer->property_color(), m_columns.m_color); m_view.append_column(*column); + + renderer->signal_render().connect(sigc::mem_fun(*this, &MemberList::OnCellRender)); } Gtk::Widget *MemberList::GetRoot() { @@ -85,19 +89,29 @@ void MemberList::UpdateMemberList() { if (col_role.has_value()) user_to_color[user_id] = col_role->Color; } - const auto add_user = [this, &guild](const UserData &user, const Gtk::TreeRow &parent) { - auto row = *m_model->append(parent->children()); + const auto add_user = [this, &guild, &user_to_color](const UserData &user, const Gtk::TreeRow &parent) { + auto test = m_model->append(parent->children()); + auto row = *test; row[m_columns.m_type] = MemberListRenderType::Member; row[m_columns.m_id] = user.ID; row[m_columns.m_name] = user.GetDisplayNameEscaped(); - return row; + row[m_columns.m_pixbuf] = Abaddon::Get().GetImageManager().GetPlaceholder(16); + row[m_columns.m_av_requested] = false; + if (const auto iter = user_to_color.find(user.ID); iter != user_to_color.end()) { + row[m_columns.m_color] = IntToRGBA(iter->second); + } else { + const static auto transparent = Gdk::RGBA("rgba(0,0,0,0)"); + row[m_columns.m_color] = transparent; + } + m_pending_avatars[user.ID] = test; + return test; }; const auto add_role = [this](const RoleData &role) { auto row = *m_model->append(); row[m_columns.m_type] = MemberListRenderType::Role; row[m_columns.m_id] = role.ID; - row[m_columns.m_name] = role.GetEscapedName(); + row[m_columns.m_name] = "<b>" + role.GetEscapedName() + "</b>"; return row; }; @@ -118,7 +132,7 @@ void MemberList::UpdateMemberList() { auto everyone_role = *m_model->append(); everyone_role[m_columns.m_type] = MemberListRenderType::Role; everyone_role[m_columns.m_id] = m_active_guild; // yes thats how the role works - everyone_role[m_columns.m_name] = "@everyone"; + everyone_role[m_columns.m_name] = "<b>@everyone</b>"; for (const auto id : roleless_users) { const auto user = discord.GetUser(id); @@ -130,6 +144,7 @@ void MemberList::UpdateMemberList() { void MemberList::Clear() { m_model->clear(); + m_pending_avatars.clear(); } void MemberList::SetActiveChannel(Snowflake id) { @@ -141,8 +156,33 @@ void MemberList::SetActiveChannel(Snowflake id) { } } +void MemberList::OnCellRender(uint64_t id) { + Snowflake real_id = id; + if (const auto iter = m_pending_avatars.find(real_id); iter != m_pending_avatars.end()) { + auto row = iter->second; + m_pending_avatars.erase(iter); + if (!row) return; + if ((*row)[m_columns.m_av_requested]) return; + (*row)[m_columns.m_av_requested] = true; + const auto user = Abaddon::Get().GetDiscordClient().GetUser(real_id); + if (!user.has_value()) return; + const auto cb = [this, row](const Glib::RefPtr<Gdk::Pixbuf> &pb) { + // for some reason row::operator bool() returns true when m_model->iter_is_valid returns false + // idk why since other code already does essentially the same thing im doing here + // iter_is_valid is "slow" according to gtk but the only other workaround i can think of would be worse + if (row && m_model->iter_is_valid(row)) { + (*row)[m_columns.m_pixbuf] = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR); + } + }; + Abaddon::Get().GetImageManager().LoadFromURL(user->GetAvatarURL("png", "16"), cb); + } +} + MemberList::ModelColumns::ModelColumns() { add(m_type); add(m_id); add(m_name); + add(m_pixbuf); + add(m_av_requested); + add(m_color); } diff --git a/src/components/memberlist.hpp b/src/components/memberlist.hpp index d61b2b3..bc44845 100644 --- a/src/components/memberlist.hpp +++ b/src/components/memberlist.hpp @@ -1,8 +1,11 @@ #pragma once +#include <gdkmm/pixbuf.h> #include <gtkmm/treemodel.h> #include <gtkmm/treestore.h> #include <gtkmm/treeview.h> +#include <unordered_map> + #include "cellrenderermemberlist.hpp" #include "discord/snowflake.hpp" @@ -16,6 +19,8 @@ public: void SetActiveChannel(Snowflake id); private: + void OnCellRender(uint64_t id); + class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns(); @@ -23,6 +28,10 @@ private: Gtk::TreeModelColumn<MemberListRenderType> m_type; Gtk::TreeModelColumn<uint64_t> m_id; Gtk::TreeModelColumn<Glib::ustring> m_name; + Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> m_pixbuf; + Gtk::TreeModelColumn<Gdk::RGBA> m_color; + + Gtk::TreeModelColumn<bool> m_av_requested; }; ModelColumns m_columns; @@ -33,4 +42,6 @@ private: Snowflake m_active_channel; Snowflake m_active_guild; + + std::unordered_map<Snowflake, Gtk::TreeIter> m_pending_avatars; }; |