improve image loading a bit (close #6)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include "chatmessage.hpp"
|
#include "chatmessage.hpp"
|
||||||
#include "../abaddon.hpp"
|
#include "../abaddon.hpp"
|
||||||
#include "../util.hpp"
|
#include "../util.hpp"
|
||||||
|
#include "lazyimage.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
constexpr const int EmojiSize = 24; // settings eventually
|
constexpr const int EmojiSize = 24; // settings eventually
|
||||||
@@ -116,35 +117,11 @@ void ChatMessageItemContainer::UpdateContent() {
|
|||||||
|
|
||||||
if (data->Embeds.size() == 1) {
|
if (data->Embeds.size() == 1) {
|
||||||
m_embed_component = CreateEmbedComponent(data->Embeds[0]);
|
m_embed_component = CreateEmbedComponent(data->Embeds[0]);
|
||||||
if (m_embed_imgurl.size() > 0) {
|
|
||||||
m_signal_image_load.emit(m_embed_imgurl);
|
|
||||||
}
|
|
||||||
AttachEventHandlers(*m_embed_component);
|
AttachEventHandlers(*m_embed_component);
|
||||||
m_main->add(*m_embed_component);
|
m_main->add(*m_embed_component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatMessageItemContainer::UpdateImage(std::string url, Glib::RefPtr<Gdk::Pixbuf> buf) {
|
|
||||||
if (!buf) return;
|
|
||||||
|
|
||||||
if (m_embed_img != nullptr && m_embed_imgurl == url) {
|
|
||||||
int w, h;
|
|
||||||
m_embed_img->get_size_request(w, h);
|
|
||||||
m_embed_img->property_pixbuf() = buf->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = m_img_loadmap.find(url);
|
|
||||||
if (it != m_img_loadmap.end()) {
|
|
||||||
const auto inw = it->second.second.first;
|
|
||||||
const auto inh = it->second.second.second;
|
|
||||||
int w, h;
|
|
||||||
GetImageDimensions(inw, inh, w, h);
|
|
||||||
it->second.first->property_pixbuf() = buf->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageItemContainer::UpdateReactions() {
|
void ChatMessageItemContainer::UpdateReactions() {
|
||||||
if (m_reactions_component != nullptr)
|
if (m_reactions_component != nullptr)
|
||||||
delete m_reactions_component;
|
delete m_reactions_component;
|
||||||
@@ -179,11 +156,6 @@ void ChatMessageItemContainer::UpdateAttributes() {
|
|||||||
m_attrib_label->set_markup("<span color='#999999'>[edited]</span>");
|
m_attrib_label->set_markup("<span color='#999999'>[edited]</span>");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatMessageItemContainer::EmitImageLoad(std::string url) {
|
|
||||||
m_signal_image_load.emit(url);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageItemContainer::AddClickHandler(Gtk::Widget *widget, std::string url) {
|
void ChatMessageItemContainer::AddClickHandler(Gtk::Widget *widget, std::string url) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
widget->signal_button_press_event().connect([url](GdkEventButton *event) -> bool {
|
widget->signal_button_press_event().connect([url](GdkEventButton *event) -> bool {
|
||||||
@@ -351,24 +323,23 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const EmbedData &emb
|
|||||||
bool is_img = embed.Image.has_value() && embed.Image->ProxyURL.has_value();
|
bool is_img = embed.Image.has_value() && embed.Image->ProxyURL.has_value();
|
||||||
bool is_thumb = embed.Thumbnail.has_value() && embed.Thumbnail->ProxyURL.has_value();
|
bool is_thumb = embed.Thumbnail.has_value() && embed.Thumbnail->ProxyURL.has_value();
|
||||||
if (is_img || is_thumb) {
|
if (is_img || is_thumb) {
|
||||||
auto *img = Gtk::manage(new Gtk::Image);
|
|
||||||
img->set_halign(Gtk::ALIGN_CENTER);
|
|
||||||
img->set_margin_top(5);
|
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
if (is_img)
|
if (is_img)
|
||||||
GetImageDimensions(*embed.Image->Width, *embed.Image->Height, w, h, EmbedImageWidth, EmbedImageHeight);
|
GetImageDimensions(*embed.Image->Width, *embed.Image->Height, w, h, EmbedImageWidth, EmbedImageHeight);
|
||||||
else
|
else
|
||||||
GetImageDimensions(*embed.Thumbnail->Width, *embed.Thumbnail->Height, w, h, EmbedImageWidth, EmbedImageHeight);
|
GetImageDimensions(*embed.Thumbnail->Width, *embed.Thumbnail->Height, w, h, EmbedImageWidth, EmbedImageHeight);
|
||||||
|
|
||||||
|
std::string url;
|
||||||
|
if (is_img)
|
||||||
|
url = *embed.Image->ProxyURL;
|
||||||
|
else
|
||||||
|
url = *embed.Thumbnail->ProxyURL;
|
||||||
|
|
||||||
|
auto *img = Gtk::manage(new LazyImage(url, w, h, false));
|
||||||
|
img->set_halign(Gtk::ALIGN_CENTER);
|
||||||
|
img->set_margin_top(5);
|
||||||
img->set_size_request(w, h);
|
img->set_size_request(w, h);
|
||||||
main->pack_start(*img);
|
main->pack_start(*img);
|
||||||
m_embed_img = img;
|
|
||||||
if (is_img)
|
|
||||||
m_embed_imgurl = *embed.Image->ProxyURL;
|
|
||||||
else
|
|
||||||
m_embed_imgurl = *embed.Thumbnail->ProxyURL;
|
|
||||||
|
|
||||||
Abaddon::Get().GetImageManager().LoadFromURL(m_embed_imgurl,
|
|
||||||
sigc::mem_fun(*this, &ChatMessageItemContainer::OnEmbedImageLoad));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.Footer.has_value()) {
|
if (embed.Footer.has_value()) {
|
||||||
@@ -410,14 +381,13 @@ Gtk::Widget *ChatMessageItemContainer::CreateImageComponent(const std::string &p
|
|||||||
GetImageDimensions(inw, inh, w, h);
|
GetImageDimensions(inw, inh, w, h);
|
||||||
|
|
||||||
Gtk::EventBox *ev = Gtk::manage(new Gtk::EventBox);
|
Gtk::EventBox *ev = Gtk::manage(new Gtk::EventBox);
|
||||||
Gtk::Image *widget = Gtk::manage(new Gtk::Image);
|
Gtk::Image *widget = Gtk::manage(new LazyImage(proxy_url, w, h, false));
|
||||||
ev->add(*widget);
|
ev->add(*widget);
|
||||||
widget->set_halign(Gtk::ALIGN_START);
|
widget->set_halign(Gtk::ALIGN_START);
|
||||||
widget->set_size_request(w, h);
|
widget->set_size_request(w, h);
|
||||||
|
|
||||||
AttachEventHandlers(*ev);
|
AttachEventHandlers(*ev);
|
||||||
AddClickHandler(ev, url);
|
AddClickHandler(ev, url);
|
||||||
HandleImage(w, h, *widget, proxy_url);
|
|
||||||
|
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
@@ -608,18 +578,6 @@ void ChatMessageItemContainer::ReactionUpdateImage(Gtk::Image *img, const Glib::
|
|||||||
img->property_pixbuf() = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR);
|
img->property_pixbuf() = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatMessageItemContainer::HandleImage(int w, int h, Gtk::Image &img, std::string url) {
|
|
||||||
m_img_loadmap[url] = { &img, { w, h } };
|
|
||||||
// ask the chatwindow to call UpdateImage because dealing with lifetimes sucks
|
|
||||||
Glib::signal_idle().connect(sigc::bind(sigc::mem_fun(*this, &ChatMessageItemContainer::EmitImageLoad), url));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageItemContainer::OnEmbedImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf) {
|
|
||||||
int w, h;
|
|
||||||
m_embed_img->get_size_request(w, h);
|
|
||||||
m_embed_img->property_pixbuf() = pixbuf->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
Glib::ustring ChatMessageItemContainer::GetText(const Glib::RefPtr<Gtk::TextBuffer> &buf) {
|
Glib::ustring ChatMessageItemContainer::GetText(const Glib::RefPtr<Gtk::TextBuffer> &buf) {
|
||||||
Gtk::TextBuffer::iterator a, b;
|
Gtk::TextBuffer::iterator a, b;
|
||||||
buf->get_bounds(a, b);
|
buf->get_bounds(a, b);
|
||||||
@@ -986,10 +944,6 @@ ChatMessageItemContainer::type_signal_action_reaction_remove ChatMessageItemCont
|
|||||||
return m_signal_action_reaction_remove;
|
return m_signal_action_reaction_remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessageItemContainer::type_signal_image_load ChatMessageItemContainer::signal_image_load() {
|
|
||||||
return m_signal_image_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMessageItemContainer::AttachEventHandlers(Gtk::Widget &widget) {
|
void ChatMessageItemContainer::AttachEventHandlers(Gtk::Widget &widget) {
|
||||||
const auto on_button_press_event = [this](GdkEventButton *event) -> bool {
|
const auto on_button_press_event = [this](GdkEventButton *event) -> bool {
|
||||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) {
|
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) {
|
||||||
|
@@ -13,12 +13,9 @@ public:
|
|||||||
// attributes = edited, deleted
|
// attributes = edited, deleted
|
||||||
void UpdateAttributes();
|
void UpdateAttributes();
|
||||||
void UpdateContent();
|
void UpdateContent();
|
||||||
void UpdateImage(std::string url, Glib::RefPtr<Gdk::Pixbuf> buf);
|
|
||||||
void UpdateReactions();
|
void UpdateReactions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool EmitImageLoad(std::string url);
|
|
||||||
|
|
||||||
void AddClickHandler(Gtk::Widget *widget, std::string);
|
void AddClickHandler(Gtk::Widget *widget, std::string);
|
||||||
Gtk::TextView *CreateTextComponent(const Message *data); // Message.Content
|
Gtk::TextView *CreateTextComponent(const Message *data); // Message.Content
|
||||||
void UpdateTextComponent(Gtk::TextView *tv);
|
void UpdateTextComponent(Gtk::TextView *tv);
|
||||||
@@ -29,9 +26,6 @@ protected:
|
|||||||
Gtk::Widget *CreateReactionsComponent(const Message &data);
|
Gtk::Widget *CreateReactionsComponent(const Message &data);
|
||||||
Gtk::Widget *CreateReplyComponent(const Message &data);
|
Gtk::Widget *CreateReplyComponent(const Message &data);
|
||||||
void ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb);
|
void ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb);
|
||||||
void HandleImage(int w, int h, Gtk::Image &img, std::string url);
|
|
||||||
|
|
||||||
void OnEmbedImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf);
|
|
||||||
|
|
||||||
static Glib::ustring GetText(const Glib::RefPtr<Gtk::TextBuffer> &buf);
|
static Glib::ustring GetText(const Glib::RefPtr<Gtk::TextBuffer> &buf);
|
||||||
|
|
||||||
@@ -59,8 +53,6 @@ protected:
|
|||||||
std::map<Glib::RefPtr<Gtk::TextTag>, std::string> m_link_tagmap;
|
std::map<Glib::RefPtr<Gtk::TextTag>, std::string> m_link_tagmap;
|
||||||
std::map<Glib::RefPtr<Gtk::TextTag>, Snowflake> m_channel_tagmap;
|
std::map<Glib::RefPtr<Gtk::TextTag>, Snowflake> m_channel_tagmap;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::pair<Gtk::Image *, std::pair<int, int>>> m_img_loadmap; // url -> [img, [w, h]]
|
|
||||||
|
|
||||||
void AttachEventHandlers(Gtk::Widget &widget);
|
void AttachEventHandlers(Gtk::Widget &widget);
|
||||||
void ShowMenu(GdkEvent *event);
|
void ShowMenu(GdkEvent *event);
|
||||||
|
|
||||||
@@ -78,16 +70,12 @@ protected:
|
|||||||
Gtk::EventBox *m_ev;
|
Gtk::EventBox *m_ev;
|
||||||
Gtk::Box *m_main;
|
Gtk::Box *m_main;
|
||||||
Gtk::Label *m_attrib_label = nullptr;
|
Gtk::Label *m_attrib_label = nullptr;
|
||||||
Gtk::Image *m_embed_img = nullptr; // yes this is hacky no i dont care (for now)
|
|
||||||
std::string m_embed_imgurl;
|
|
||||||
|
|
||||||
Gtk::TextView *m_text_component = nullptr;
|
Gtk::TextView *m_text_component = nullptr;
|
||||||
Gtk::Widget *m_embed_component = nullptr;
|
Gtk::Widget *m_embed_component = nullptr;
|
||||||
Gtk::Widget *m_reactions_component = nullptr;
|
Gtk::Widget *m_reactions_component = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef sigc::signal<void, std::string> type_signal_image_load;
|
|
||||||
|
|
||||||
typedef sigc::signal<void> type_signal_action_delete;
|
typedef sigc::signal<void> type_signal_action_delete;
|
||||||
typedef sigc::signal<void> type_signal_action_edit;
|
typedef sigc::signal<void> type_signal_action_edit;
|
||||||
typedef sigc::signal<void, Snowflake> type_signal_channel_click;
|
typedef sigc::signal<void, Snowflake> type_signal_channel_click;
|
||||||
@@ -101,17 +89,12 @@ public:
|
|||||||
type_signal_channel_click signal_action_channel_click();
|
type_signal_channel_click signal_action_channel_click();
|
||||||
type_signal_action_reaction_add signal_action_reaction_add();
|
type_signal_action_reaction_add signal_action_reaction_add();
|
||||||
type_signal_action_reaction_remove signal_action_reaction_remove();
|
type_signal_action_reaction_remove signal_action_reaction_remove();
|
||||||
|
|
||||||
type_signal_image_load signal_image_load();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type_signal_action_delete m_signal_action_delete;
|
type_signal_action_delete m_signal_action_delete;
|
||||||
type_signal_action_edit m_signal_action_edit;
|
type_signal_action_edit m_signal_action_edit;
|
||||||
type_signal_channel_click m_signal_action_channel_click;
|
type_signal_channel_click m_signal_action_channel_click;
|
||||||
type_signal_action_reaction_add m_signal_action_reaction_add;
|
type_signal_action_reaction_add m_signal_action_reaction_add;
|
||||||
type_signal_action_reaction_remove m_signal_action_reaction_remove;
|
type_signal_action_reaction_remove m_signal_action_reaction_remove;
|
||||||
|
|
||||||
type_signal_image_load m_signal_image_load;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatMessageHeader : public Gtk::ListBoxRow {
|
class ChatMessageHeader : public Gtk::ListBoxRow {
|
||||||
|
@@ -250,16 +250,6 @@ void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
|||||||
content->signal_action_reaction_remove().connect([this, id](const Glib::ustring ¶m) {
|
content->signal_action_reaction_remove().connect([this, id](const Glib::ustring ¶m) {
|
||||||
m_signal_action_reaction_remove.emit(id, param);
|
m_signal_action_reaction_remove.emit(id, param);
|
||||||
});
|
});
|
||||||
content->signal_image_load().connect([this, id](std::string url) {
|
|
||||||
auto &mgr = Abaddon::Get().GetImageManager();
|
|
||||||
mgr.LoadFromURL(url, [this, id, url](Glib::RefPtr<Gdk::Pixbuf> buf) {
|
|
||||||
if (m_id_to_widget.find(id) != m_id_to_widget.end()) {
|
|
||||||
auto *x = dynamic_cast<ChatMessageItemContainer *>(m_id_to_widget.at(id));
|
|
||||||
if (x != nullptr)
|
|
||||||
x->UpdateImage(url, buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
content->signal_action_channel_click().connect([this](const Snowflake &id) {
|
content->signal_action_channel_click().connect([this](const Snowflake &id) {
|
||||||
m_signal_action_channel_click.emit(id);
|
m_signal_action_channel_click.emit(id);
|
||||||
});
|
});
|
||||||
|
41
components/lazyimage.cpp
Normal file
41
components/lazyimage.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "lazyimage.hpp"
|
||||||
|
#include "../abaddon.hpp"
|
||||||
|
|
||||||
|
LazyImage::LazyImage(int w, int h, bool use_placeholder)
|
||||||
|
: m_width(w)
|
||||||
|
, m_height(h) {
|
||||||
|
static int sidx = 0;
|
||||||
|
sidx++;
|
||||||
|
m_idx = sidx;
|
||||||
|
if (use_placeholder)
|
||||||
|
property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(w)->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
||||||
|
signal_draw().connect(sigc::mem_fun(*this, &LazyImage::OnDraw));
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyImage::LazyImage(const std::string &url, int w, int h, bool use_placeholder)
|
||||||
|
: m_url(url)
|
||||||
|
, m_width(w)
|
||||||
|
, m_height(h) {
|
||||||
|
static int sidx = 0;
|
||||||
|
sidx++;
|
||||||
|
m_idx = sidx;
|
||||||
|
if (use_placeholder)
|
||||||
|
property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(w)->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
||||||
|
signal_draw().connect(sigc::mem_fun(*this, &LazyImage::OnDraw));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyImage::SetURL(const std::string &url) {
|
||||||
|
m_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LazyImage::OnDraw(const Cairo::RefPtr<Cairo::Context> &context) {
|
||||||
|
if (!m_needs_request || m_url == "") return false;
|
||||||
|
m_needs_request = false;
|
||||||
|
|
||||||
|
auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||||
|
property_pixbuf() = pb->scale_simple(m_width, m_height, Gdk::INTERP_BILINEAR);
|
||||||
|
};
|
||||||
|
Abaddon::Get().GetImageManager().LoadFromURL(m_url, sigc::track_obj(cb, *this));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
20
components/lazyimage.hpp
Normal file
20
components/lazyimage.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <gtkmm.h>
|
||||||
|
|
||||||
|
// loads an image only when the widget is drawn for the first time
|
||||||
|
class LazyImage : public Gtk::Image {
|
||||||
|
public:
|
||||||
|
LazyImage(int w, int h, bool use_placeholder = true);
|
||||||
|
LazyImage(const std::string &url, int w, int h, bool use_placeholder = true);
|
||||||
|
|
||||||
|
void SetURL(const std::string &url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool OnDraw(const Cairo::RefPtr<Cairo::Context> &context);
|
||||||
|
|
||||||
|
bool m_needs_request = true;
|
||||||
|
int m_idx;
|
||||||
|
std::string m_url;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
};
|
@@ -7,7 +7,10 @@ MemberListUserRow::MemberListUserRow(Snowflake guild_id, const UserData *data) {
|
|||||||
m_ev = Gtk::manage(new Gtk::EventBox);
|
m_ev = Gtk::manage(new Gtk::EventBox);
|
||||||
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||||
m_label = Gtk::manage(new Gtk::Label);
|
m_label = Gtk::manage(new Gtk::Label);
|
||||||
m_avatar = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(16)));
|
m_avatar = Gtk::manage(new LazyImage(16, 16));
|
||||||
|
|
||||||
|
if (data->HasAvatar())
|
||||||
|
m_avatar->SetURL(data->GetAvatarURL("png"));
|
||||||
|
|
||||||
get_style_context()->add_class("members-row");
|
get_style_context()->add_class("members-row");
|
||||||
get_style_context()->add_class("members-row-member");
|
get_style_context()->add_class("members-row-member");
|
||||||
@@ -142,22 +145,6 @@ void MemberList::UpdateMemberListInternal() {
|
|||||||
auto add_user = [this, &user_to_color](const UserData *data) {
|
auto add_user = [this, &user_to_color](const UserData *data) {
|
||||||
auto *row = Gtk::manage(new MemberListUserRow(m_guild_id, data));
|
auto *row = Gtk::manage(new MemberListUserRow(m_guild_id, data));
|
||||||
m_id_to_row[data->ID] = row;
|
m_id_to_row[data->ID] = row;
|
||||||
|
|
||||||
if (data->HasAvatar()) {
|
|
||||||
Snowflake id = data->ID;
|
|
||||||
Abaddon::Get().GetImageManager().LoadFromURL(data->GetAvatarURL("png", "16"), [this, id](Glib::RefPtr<Gdk::Pixbuf> pbuf) {
|
|
||||||
Glib::signal_idle().connect([this, id, pbuf]() -> bool {
|
|
||||||
if (m_id_to_row.find(id) != m_id_to_row.end()) {
|
|
||||||
auto *foundrow = static_cast<MemberListUserRow *>(m_id_to_row.at(id));
|
|
||||||
if (foundrow != nullptr)
|
|
||||||
foundrow->SetAvatarFromPixbuf(pbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachUserMenuHandler(row, data->ID);
|
AttachUserMenuHandler(row, data->ID);
|
||||||
m_listbox->add(*row);
|
m_listbox->add(*row);
|
||||||
};
|
};
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "../discord/discord.hpp"
|
#include "../discord/discord.hpp"
|
||||||
|
#include "lazyimage.hpp"
|
||||||
|
|
||||||
class MemberListUserRow : public Gtk::ListBoxRow {
|
class MemberListUserRow : public Gtk::ListBoxRow {
|
||||||
public:
|
public:
|
||||||
@@ -14,7 +15,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Gtk::EventBox *m_ev;
|
Gtk::EventBox *m_ev;
|
||||||
Gtk::Box *m_box;
|
Gtk::Box *m_box;
|
||||||
Gtk::Image *m_avatar;
|
LazyImage *m_avatar;
|
||||||
Gtk::Label *m_label;
|
Gtk::Label *m_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user