basic folder support

This commit is contained in:
ouwou
2022-12-23 20:14:10 -05:00
parent e0e0a6c767
commit 1ba3daa04a
7 changed files with 176 additions and 9 deletions

View File

@@ -262,7 +262,42 @@ void ChannelList::UpdateListing() {
auto &discord = Abaddon::Get().GetDiscordClient();
const auto guild_ids = discord.GetUserSortedGuilds();
/*
guild_folders looks something like this
"guild_folders": [
{
"color": null,
"guild_ids": [
"8009060___________"
],
"id": null,
"name": null
},
{
"color": null,
"guild_ids": [
"99615594__________",
"86132141__________",
"35450138__________",
"83714048__________"
],
"id": 2853066769,
"name": null
}
]
so if id != null then its a folder (they can have single entries)
*/
int sort_value = 0;
const auto folders = discord.GetUserSettings().GuildFolders;
for (const auto &group : folders) {
auto iter = AddFolder(group);
(*iter)[m_columns.m_sort] = sort_value++;
}
/*
int sortnum = 0;
for (const auto &guild_id : guild_ids) {
const auto guild = discord.GetGuild(guild_id);
@@ -271,6 +306,7 @@ void ChannelList::UpdateListing() {
auto iter = AddGuild(*guild);
(*iter)[m_columns.m_sort] = sortnum++;
}
*/
m_updating_listing = false;
@@ -278,7 +314,7 @@ void ChannelList::UpdateListing() {
}
void ChannelList::UpdateNewGuild(const GuildData &guild) {
AddGuild(guild);
AddGuild(guild, m_model->children());
// update sort order
int sortnum = 0;
for (const auto guild_id : Abaddon::Get().GetDiscordClient().GetUserSortedGuilds()) {
@@ -405,6 +441,8 @@ void ChannelList::OnThreadListSync(const ThreadListSyncData &data) {
// get the threads in the guild
std::vector<Snowflake> threads;
auto guild_iter = GetIteratorForGuildFromID(data.GuildID);
if (!guild_iter) return;
std::queue<Gtk::TreeModel::iterator> queue;
queue.push(guild_iter);
@@ -546,11 +584,45 @@ ExpansionStateRoot ChannelList::GetExpansionState() const {
return r;
}
Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild) {
Gtk::TreeModel::iterator ChannelList::AddFolder(const UserSettingsGuildFoldersEntry &folder) {
if (!folder.ID.has_value()) {
// just a guild
if (!folder.GuildIDs.empty()) {
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(folder.GuildIDs[0]);
if (guild.has_value()) {
return AddGuild(*guild, m_model->children());
}
}
} else {
auto folder_row = *m_model->append();
folder_row[m_columns.m_type] = RenderType::Folder;
folder_row[m_columns.m_id] = *folder.ID;
if (folder.Name.has_value()) {
folder_row[m_columns.m_name] = Glib::Markup::escape_text(*folder.Name);
} else {
folder_row[m_columns.m_name] = "Folder";
}
int sort_value = 0;
for (const auto &guild_id : folder.GuildIDs) {
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(guild_id);
if (guild.has_value()) {
auto guild_row = AddGuild(*guild, folder_row->children());
(*guild_row)[m_columns.m_sort] = sort_value++;
}
}
return folder_row;
}
return {};
}
Gtk::TreeModel::iterator ChannelList::AddGuild(const GuildData &guild, const Gtk::TreeNodeChildren &root) {
auto &discord = Abaddon::Get().GetDiscordClient();
auto &img = Abaddon::Get().GetImageManager();
auto guild_row = *m_model->append();
auto guild_row = *m_model->append(root);
guild_row[m_columns.m_type] = RenderType::Guild;
guild_row[m_columns.m_id] = guild.ID;
guild_row[m_columns.m_name] = "<b>" + Glib::Markup::escape_text(guild.Name) + "</b>";
@@ -679,8 +751,15 @@ void ChannelList::UpdateChannelCategory(const ChannelData &channel) {
Gtk::TreeModel::iterator ChannelList::GetIteratorForGuildFromID(Snowflake id) {
for (const auto &child : m_model->children()) {
if (child[m_columns.m_id] == id)
if (child[m_columns.m_type] == RenderType::Guild && child[m_columns.m_id] == id) {
return child;
} else if (child[m_columns.m_type] == RenderType::Folder) {
for (const auto &folder_child : child->children()) {
if (folder_child[m_columns.m_id] == id) {
return folder_child;
}
}
}
}
return {};
}

View File

@@ -72,7 +72,8 @@ protected:
ModelColumns m_columns;
Glib::RefPtr<Gtk::TreeStore> m_model;
Gtk::TreeModel::iterator AddGuild(const GuildData &guild);
Gtk::TreeModel::iterator AddFolder(const UserSettingsGuildFoldersEntry &folder);
Gtk::TreeModel::iterator AddGuild(const GuildData &guild, const Gtk::TreeNodeChildren &root);
Gtk::TreeModel::iterator UpdateCreateChannelCategory(const ChannelData &channel);
Gtk::TreeModel::iterator CreateThreadRow(const Gtk::TreeNodeChildren &children, const ChannelData &channel);

View File

@@ -57,6 +57,8 @@ Glib::PropertyProxy<bool> CellRendererChannels::property_nsfw() {
void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
switch (m_property_type.get_value()) {
case RenderType::Folder:
return get_preferred_width_vfunc_folder(widget, minimum_width, natural_width);
case RenderType::Guild:
return get_preferred_width_vfunc_guild(widget, minimum_width, natural_width);
case RenderType::Category:
@@ -74,6 +76,8 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m
void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const {
switch (m_property_type.get_value()) {
case RenderType::Folder:
return get_preferred_width_for_height_vfunc_folder(widget, height, minimum_width, natural_width);
case RenderType::Guild:
return get_preferred_width_for_height_vfunc_guild(widget, height, minimum_width, natural_width);
case RenderType::Category:
@@ -91,6 +95,8 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid
void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int &minimum_height, int &natural_height) const {
switch (m_property_type.get_value()) {
case RenderType::Folder:
return get_preferred_height_vfunc_folder(widget, minimum_height, natural_height);
case RenderType::Guild:
return get_preferred_height_vfunc_guild(widget, minimum_height, natural_height);
case RenderType::Category:
@@ -108,6 +114,8 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int &
void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const {
switch (m_property_type.get_value()) {
case RenderType::Folder:
return get_preferred_height_for_width_vfunc_folder(widget, width, minimum_height, natural_height);
case RenderType::Guild:
return get_preferred_height_for_width_vfunc_guild(widget, width, minimum_height, natural_height);
case RenderType::Category:
@@ -125,6 +133,8 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid
void CellRendererChannels::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
switch (m_property_type.get_value()) {
case RenderType::Folder:
return render_vfunc_folder(cr, widget, background_area, cell_area, flags);
case RenderType::Guild:
return render_vfunc_guild(cr, widget, background_area, cell_area, flags);
case RenderType::Category:
@@ -140,6 +150,65 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
}
}
// folder functions
void CellRendererChannels::get_preferred_width_vfunc_folder(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_folder(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_folder(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_folder(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_folder(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
constexpr static int len = 5;
int x1, y1, x2, y2, x3, y3;
if (property_expanded()) {
x1 = background_area.get_x() + 7;
y1 = background_area.get_y() + background_area.get_height() / 2 - len;
x2 = background_area.get_x() + 7 + len;
y2 = background_area.get_y() + background_area.get_height() / 2 + len;
x3 = background_area.get_x() + 7 + len * 2;
y3 = background_area.get_y() + background_area.get_height() / 2 - len;
} else {
x1 = background_area.get_x() + 7;
y1 = background_area.get_y() + background_area.get_height() / 2 - len;
x2 = background_area.get_x() + 7 + len * 2;
y2 = background_area.get_y() + background_area.get_height() / 2;
x3 = background_area.get_x() + 7;
y3 = background_area.get_y() + background_area.get_height() / 2 + len;
}
cr->move_to(x1, y1);
cr->line_to(x2, y2);
cr->line_to(x3, y3);
const auto expander_color = Gdk::RGBA(Abaddon::Get().GetSettings().ChannelsExpanderColor);
cr->set_source_rgb(expander_color.get_red(), expander_color.get_green(), expander_color.get_blue());
cr->stroke();
Gtk::Requisition text_minimum, text_natural;
m_renderer_text.get_preferred_size(widget, text_minimum, text_natural);
const int text_x = background_area.get_x() + 22;
const int text_y = background_area.get_y() + background_area.get_height() / 2 - text_natural.height / 2;
const int text_w = text_natural.width;
const int text_h = text_natural.height;
Gdk::Rectangle text_cell_area(text_x, text_y, text_w, text_h);
static const auto color = Gdk::RGBA(Abaddon::Get().GetSettings().ChannelColor);
m_renderer_text.property_foreground_rgba() = color;
m_renderer_text.render(cr, widget, background_area, text_cell_area, flags);
m_renderer_text.property_foreground_set() = false;
}
// guild functions
void CellRendererChannels::get_preferred_width_vfunc_guild(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {

View File

@@ -6,6 +6,7 @@
#include "discord/snowflake.hpp"
enum class RenderType : uint8_t {
Folder,
Guild,
Category,
TextChannel,
@@ -39,6 +40,17 @@ protected:
const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags) override;
// guild functions
void get_preferred_width_vfunc_folder(Gtk::Widget &widget, int &minimum_width, int &natural_width) const;
void get_preferred_width_for_height_vfunc_folder(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const;
void get_preferred_height_vfunc_folder(Gtk::Widget &widget, int &minimum_height, int &natural_height) const;
void get_preferred_height_for_width_vfunc_folder(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const;
void render_vfunc_folder(const Cairo::RefPtr<Cairo::Context> &cr,
Gtk::Widget &widget,
const Gdk::Rectangle &background_area,
const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags);
// guild functions
void get_preferred_width_vfunc_guild(Gtk::Widget &widget, int &minimum_width, int &natural_width) const;
void get_preferred_width_for_height_vfunc_guild(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const;