add profile pics and colors to member list
This commit is contained in:
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
CellRendererMemberList::CellRendererMemberList()
|
CellRendererMemberList::CellRendererMemberList()
|
||||||
: Glib::ObjectBase(typeid(CellRendererMemberList))
|
: Glib::ObjectBase(typeid(CellRendererMemberList))
|
||||||
, Gtk::CellRenderer()
|
|
||||||
, m_property_type(*this, "render-type")
|
, m_property_type(*this, "render-type")
|
||||||
, m_property_id(*this, "id")
|
, 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_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
|
||||||
property_xpad() = 2;
|
property_xpad() = 2;
|
||||||
property_ypad() = 2;
|
property_ypad() = 2;
|
||||||
@@ -26,6 +27,14 @@ Glib::PropertyProxy<Glib::ustring> CellRendererMemberList::property_name() {
|
|||||||
return m_property_name.get_proxy();
|
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 {
|
void CellRendererMemberList::get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
|
||||||
switch (m_property_type.get_value()) {
|
switch (m_property_type.get_value()) {
|
||||||
case MemberListRenderType::Role:
|
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) {
|
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;
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,8 @@ public:
|
|||||||
Glib::PropertyProxy<MemberListRenderType> property_type();
|
Glib::PropertyProxy<MemberListRenderType> property_type();
|
||||||
Glib::PropertyProxy<uint64_t> property_id();
|
Glib::PropertyProxy<uint64_t> property_id();
|
||||||
Glib::PropertyProxy<Glib::ustring> property_name();
|
Glib::PropertyProxy<Glib::ustring> property_name();
|
||||||
|
Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> property_pixbuf();
|
||||||
|
Glib::PropertyProxy<Gdk::RGBA> property_color();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const override;
|
void get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const override;
|
||||||
@@ -48,9 +50,16 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Gtk::CellRendererText m_renderer_text;
|
Gtk::CellRendererText m_renderer_text;
|
||||||
Gtk::CellRendererPixbuf m_renderer_pixbuf;
|
|
||||||
|
|
||||||
Glib::Property<MemberListRenderType> m_property_type;
|
Glib::Property<MemberListRenderType> m_property_type;
|
||||||
Glib::Property<uint64_t> m_property_id;
|
Glib::Property<uint64_t> m_property_id;
|
||||||
Glib::Property<Glib::ustring> m_property_name;
|
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();
|
||||||
};
|
};
|
||||||
|
@@ -22,7 +22,11 @@ MemberList::MemberList()
|
|||||||
column->add_attribute(renderer->property_type(), m_columns.m_type);
|
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_id(), m_columns.m_id);
|
||||||
column->add_attribute(renderer->property_name(), m_columns.m_name);
|
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);
|
m_view.append_column(*column);
|
||||||
|
|
||||||
|
renderer->signal_render().connect(sigc::mem_fun(*this, &MemberList::OnCellRender));
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk::Widget *MemberList::GetRoot() {
|
Gtk::Widget *MemberList::GetRoot() {
|
||||||
@@ -85,19 +89,29 @@ void MemberList::UpdateMemberList() {
|
|||||||
if (col_role.has_value()) user_to_color[user_id] = col_role->Color;
|
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) {
|
const auto add_user = [this, &guild, &user_to_color](const UserData &user, const Gtk::TreeRow &parent) {
|
||||||
auto row = *m_model->append(parent->children());
|
auto test = m_model->append(parent->children());
|
||||||
|
auto row = *test;
|
||||||
row[m_columns.m_type] = MemberListRenderType::Member;
|
row[m_columns.m_type] = MemberListRenderType::Member;
|
||||||
row[m_columns.m_id] = user.ID;
|
row[m_columns.m_id] = user.ID;
|
||||||
row[m_columns.m_name] = user.GetDisplayNameEscaped();
|
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) {
|
const auto add_role = [this](const RoleData &role) {
|
||||||
auto row = *m_model->append();
|
auto row = *m_model->append();
|
||||||
row[m_columns.m_type] = MemberListRenderType::Role;
|
row[m_columns.m_type] = MemberListRenderType::Role;
|
||||||
row[m_columns.m_id] = role.ID;
|
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;
|
return row;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +132,7 @@ void MemberList::UpdateMemberList() {
|
|||||||
auto everyone_role = *m_model->append();
|
auto everyone_role = *m_model->append();
|
||||||
everyone_role[m_columns.m_type] = MemberListRenderType::Role;
|
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_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) {
|
for (const auto id : roleless_users) {
|
||||||
const auto user = discord.GetUser(id);
|
const auto user = discord.GetUser(id);
|
||||||
@@ -130,6 +144,7 @@ void MemberList::UpdateMemberList() {
|
|||||||
|
|
||||||
void MemberList::Clear() {
|
void MemberList::Clear() {
|
||||||
m_model->clear();
|
m_model->clear();
|
||||||
|
m_pending_avatars.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemberList::SetActiveChannel(Snowflake id) {
|
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() {
|
MemberList::ModelColumns::ModelColumns() {
|
||||||
add(m_type);
|
add(m_type);
|
||||||
add(m_id);
|
add(m_id);
|
||||||
add(m_name);
|
add(m_name);
|
||||||
|
add(m_pixbuf);
|
||||||
|
add(m_av_requested);
|
||||||
|
add(m_color);
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <gdkmm/pixbuf.h>
|
||||||
#include <gtkmm/treemodel.h>
|
#include <gtkmm/treemodel.h>
|
||||||
#include <gtkmm/treestore.h>
|
#include <gtkmm/treestore.h>
|
||||||
#include <gtkmm/treeview.h>
|
#include <gtkmm/treeview.h>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "cellrenderermemberlist.hpp"
|
#include "cellrenderermemberlist.hpp"
|
||||||
#include "discord/snowflake.hpp"
|
#include "discord/snowflake.hpp"
|
||||||
|
|
||||||
@@ -16,6 +19,8 @@ public:
|
|||||||
void SetActiveChannel(Snowflake id);
|
void SetActiveChannel(Snowflake id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void OnCellRender(uint64_t id);
|
||||||
|
|
||||||
class ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
class ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
||||||
public:
|
public:
|
||||||
ModelColumns();
|
ModelColumns();
|
||||||
@@ -23,6 +28,10 @@ private:
|
|||||||
Gtk::TreeModelColumn<MemberListRenderType> m_type;
|
Gtk::TreeModelColumn<MemberListRenderType> m_type;
|
||||||
Gtk::TreeModelColumn<uint64_t> m_id;
|
Gtk::TreeModelColumn<uint64_t> m_id;
|
||||||
Gtk::TreeModelColumn<Glib::ustring> m_name;
|
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;
|
ModelColumns m_columns;
|
||||||
@@ -33,4 +42,6 @@ private:
|
|||||||
|
|
||||||
Snowflake m_active_channel;
|
Snowflake m_active_channel;
|
||||||
Snowflake m_active_guild;
|
Snowflake m_active_guild;
|
||||||
|
|
||||||
|
std::unordered_map<Snowflake, Gtk::TreeIter> m_pending_avatars;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user